Interscript

1. Interscript Version

This document describes Interscript version 1.0a8 build 1384 on ruby by root.It was generated by Interscript version 1.0a8, build 1383 on ruby by root at Mon Nov 30, 1998 at 05:02 AM (UTC).

1.1. Contents

   1. Interscript Version
      1.1. Contents
   2. Introduction
      2.1. Interscript
      2.2. Features
   3. Requirements
      3.1. Functionality
      3.2. Interface
      3.3. Management
      3.4. Implementation pragmatics
   4. Design Fundamentals
      4.1. Devices
      4.2. Processors
      4.3. Tanglers
      4.4. Lexical Scoping
      4.5. Weaver Control
      4.6. Source Tracking
      4.7. Parsing
      4.8. Documentation Constructions
      4.9. Microformatting shortcuts
      4.10. Weaver Architecture
   5. Tutorial
      5.1. Weaving a document
      5.2. Tangling code
      5.3. Scripting
      5.4. Unit tests
      5.5. Fonts
      5.6. Lists
      5.7. Tables
      5.8. Citations
      5.9. Cross References
      5.10. Including Files
      5.11. Translating Html
      5.12. Special constructions
      5.13. File Names
      5.14. Questions and Answers
   6. Implementation
      6.1. Interscript Module
      6.2. Core Subpackage
      6.3. Drivers Subpackage
      6.4. Weavers
      6.5. Weaver Filters
      6.6. Tanglers
      6.7. Tokenisers
      6.8. Html parser test
      6.9. LALR(1) Parser table generator
      6.10. Introduction to categories
      6.11. Felix Object protocol
      6.12. Felix Package
      6.13. Architecture
      6.14. Module getoptions
      6.15. Get Options
      6.16. Utility Modules
      6.17. Application and tool directory
      6.18. Test package
   7. Appendices
      7.1. Index of Identifiers
      7.2. Index of Classes
      7.3. File List
      7.4. Source List
      7.5. Include List
      7.6. Bugs (etc) for Version 1a7
      7.7. Installation Guide

2. Introduction

Interscript is a component of a new style of programming environment incorporating the ideas of literate programming and category theory. Literate programming was first embodied in significant code by Donald Knuth in a program called Web, to support publication of the sources for his TeX typesetting system.

The fundamental precept of literate programming is that documentation should not be written after software development, but be an integral part of it. A literate programming source is primarily a document in which source is embedded; the source is extracted by the literate programming tool by a process called tangling, while the file is typeset by a process called weaving.

Unlike traditional documentation, whether it be design specifications, or, code or user documentation, literate programming offers the opportunity for the documentation and software to remain synchronised because the two are lexically close and easy to maintain together. Furthermore, the published sources not only match the software exactly, but are sure to be complete.

2.1. Interscript

Interscript is a major breakthough in the design of literate programming tools. Other tools such as Web, C-Web, and FunnelWeb, have limited functionality, and are mainly restricted to partitioning code and documentation.

Interscript is different because it embodies a complete and fully functional programming language, namely Python. An Interscript source file consists of three, not two, kinds of source: the target source code, documentation, and executable Python script. Because of this feature, the user source can extend the tool in arbitrary ways at run time (without modifying the original tool).

In addition, the basic Interscript tool has an advanced object based design, including pluggable drivers for data sources and sinks, including automatic file downloading, tanglers for various programming languages including C, C++, Python, generic script , and raw data, and plugable weavers for various typesetting systems including HTML, TeX, Postscript, and plain text.

Interscript includes functionality designed to support building, testing, installation, and verion control of software. In particular, the standard system includes functionality designed to replace make.

2.2. Features

Interscript supports many powerful features.

2.2.1. Python Scripting

Interscript uses Python 1.5.1 both for its implementation and to supply scripting services to client sourceware.

2.2.2. Platform independent filenames

Are required in interscript sourceware. Filenames must be unix style relative filenames; interscript maps these to host operating system filenames automatically.

2.2.3. Documentation Constructions

Several specialised documentation constructions are provided apart from paragraphs and headings.

2.2.3.1. Automatic heading numbering

Headings are automatically numbered, and may be nested to any depth.

2.2.3.2. Cross references

References to any labelled part of the document can be cited. Headings may be labelled, and a label may be set within ordinary text.

2.2.3.3. Tables

Basic tables with headings are provided.

2.2.3.4. Nestable Lists

Lists are provided in bullet, numbered and keyed styles. Lists can be nested.

2.2.3.5. URL citation

A specialised contruction for citing a URL becomes an active link in HTML documents.

2.2.3.6. Code and Prose displays

Display constructions for quoting code and prose are provided. [There is no support for mathematics yet.]

2.2.3.7. Basic font selection

For emphasised, strong, italic, bold, or code fonts.

2.2.4. Advanced Web Weaving

The advanced web weaver supports many features.

2.2.4.1. Automatic pagination on headings

The web weaver spawns child pages on each heading.

2.2.4.2. Syntax Highlighting

For tokenising tanglers, syntax highlighting is supported by use of the SPAN tag with CLASS attribute.

2.2.4.3. CSS1 Cascading Style Sheets

A standard interscript style sheet, interscript.css is provided. A dummy style sheet, user.css, is provided to support client style overrides.

2.2.4.4. Folding Table of Contents

Using ECMAscript, operates conditionally on presence of Internet Explorer style document object model (DOM).

2.2.4.5. Frame presentation

A simple three frame presentation with a master index control panel, an index frame for holding various cross reference tables, and a document view frame.

2.2.4.6. Flexible navigation

Navigation is via a cross reference index, or via standard navigation links per page or per code section.

2.2.4.7. Table of classes

Points of definition of classes.

2.2.4.8. Table of functions

Points of definition of functions and methods.

2.2.4.9. Table of identifiers

Points of definition and use for identifiers.

2.2.4.10. Table of sections

List of sections making up a code file.

2.2.4.11. Table of tests

Table of tests with test results where applicable.

2.2.4.12. Convergence status

List of all output files with an indication of whether the file was changed.

2.2.4.13. Source tree

Heirachical list of all input files.

2.2.5. PerlPOD support

Perl POD is recognized and woven into documents.

2.2.6. Extensive Python Support

Specialised Python support includes numerous general purpose extension modules, a function generator supporting Eiffel style assertions including protocol verification, preconditions, postconditions, and per argument documentation.

2.2.7. Latex, Plain text and flat Html Weavers

Weavers are provided for Latex2e, plain text, and a single flat html file.

2.2.8. Html input filter

Allows simple Html to be processed as input.

2.2.9. XML support planned

XML is not currently supported, but and XML weaver and input filter is planned.

2.2.10. Unit testing

On the fly unit tests can be embedded in code and are marshalled in a table. Special support for Python is available to execute the tests.

2.2.10.1. Test output verification

Comparison of expected and actual output presented in a difference table if gnu diff is available.

2.2.11. Option help

Is provided with the --help command line option.

2.2.12. Tutorial

A tutorial is provided which covers some basic concepts.

2.2.13. Statement of Requirements

Discusses and tabulates some specific requirements.

2.2.14. Design Document

Discusses some design and implementation issues.

2.2.15. Full source listing

Interscript is literate programmed with itself, so that a full source listing is embedded in the implementation documentation.

3. Requirements

Interscript is a software component intended to assist in the publishing and development of software by providing integrated source code, documentation, testing and project management facilities.

The detailed requirements stem from fundamental design decisions including the choice of python as an implementation language, the decision to restrict the user interface to batch processing of text files, and the embodiment of the principal notions of literate programming.

The sections below discuss the requirements from the point of view of desired functionality, interface, implementation pragmatics, and management.

However, it is not possible to entirely separate discussion of requirements from design, because detailed requirements stem from design decisions, and guide more detailed design. Nor is it possible to separate implementation from design, since implementation details have design consequences -- and also provided unexpected opportunities for functionality not in the original requirements.

In other words you can expect some discussion of design and implementation in the section, although the emphasis is on requirements. See the next major section for a discussion focusing on design, and the following section for a detailed description of the implementation.

3.1. Functionality

This section discusses the functionality Interscript requires.

The overall functionality is easy to describe: interscript must process input source files and from them extract the target program files, and extract and format a suitable set of documentation files. In addition it must be able to compile and build the target software, execute test code, and present the results of all these processes in a comprehensible format.

We will call the goal of program code extraction tangling, that of document construction weaving, and that of compilation and test code execution building.

3.1.1. Tangling

This section describes the requirements of the tangling goal, and is by far the simplest to state (and implement).

The client will largely present files containing one or more program code files, separated by documentation sections. The tangler basically extracts this code, concatenates the sections sequentially, and writes the output verbatim to code files. Code sections targeting a single output file must be associated, and the target file identified and its location determined.

The detailed requirements for tangling, therefore, largely focus on deviations from normal processing.

3.1.1.1. Supported Programming Languages

Special parsers shall be supplied for C, C++, Python, Java, Eiffel, Pascal, Modula, Perl. Tcl, interscript, and Unix shell scripts are too quirky. Basic is too ugly :-) Cobol, Fortran and PL/1 are too archaic.

3.1.1.2. Source Tracking

Source tracking is the ability to determine where generated program and documentation sections came from in the original source files. It is vital at the building stage, so that errors can be corrected. Where target tools identify the source of errors, they should be guided if possible, to point at the original sources.
3.1.1.2.1. C and C++
For C and C++, interscript must generate #line preprocessing directives.

3.1.1.3. Chunking

The ability to build program files out of order is sometimes called chunking. It is sometimes useful, for example, to define functions after they are used even when the target programming language requires otherwise. However, chunking is not restricted to reordering code sections, but may be considered to include the ability to nest sections hierarchically. This permits the author to represent program structure in manner not provided by the target programming language.

There are some further variations on chunking. The first consideration is that code often has to be repeated, and so a section may be used more than once, possibly in distinct program files, but sometimes even in the same file. Because hierarchical chunking requires naming chunks, reuse is available automatically; the principal issue here is the converse: to ensure when required that a chunk is used exactly once.

Stemming from the use of labelled chunks is the need to be able to locate them: when a chunk is used, one needs to find where it is defined, and sometimes conversely.

More generally: a simple verbatim code file is a special case of breaking a code file into sections separated by documentation but without reordering, which is a special case of reorderable sections which is a special case of hierarchical chunking. Again, a tree is a special case of a directed acyclic graphs, which embodies the notion that a chunk may be used twice and also that it may not be used at all.

Some conventional literate programming tools go further in permitting what might be called macros: chunks containing unbound variables which can be bound at the point of use: a simple case of parameterized macro processing. Macros are particularly useful for generating repetitive forms such as tables.

In addition, we might consider conditional compilation, which is useful for controlling software variations such as platform dependencies and debugging versions. Conditional compilation is heavily used in C.

There is yet a more general form of chunking ... in which the notion of the chunk begins to degenerate, namely generation or arbitrary code by executable script. Such facility is essential, for example, where the code to be generated is sensitive to the environment, for example the inclusion of the current date. Perhaps more interesting is the ability of executable script to generate several files simultaneously, for example both the declaration in a header file and the definition in the body file, of a function in the C programming language. Building specialized scripts tailored to the client's requirement is an essential facility of literate programming tools because, although rarely used, it can save a lot of work and provide considerable coherence, as well as generating tabulated documentation.

To provide all these facilities, so the most specialized, and most common case integrates seamlessly with the most complex and general, interscript leverages the Python scripting engine. The most complex code generation is supported almost effortlessly by simply allowing the client to write arbitrary python script, while the more common simpler requirements are simply provided as pre-built routines: all the facilities are accessed in precisely the same way, by script execution.

This feature is central to the interscript design and cannot be isolation from a discussion of requirements, which can be recast, in some sense, to a discussion of the architectural framework in which such script executes, and the set of pre-built functions which ought be made available.

Macros with parameters, however, are not especially good at expression skeletons. A skeleton, or boilerplate, is essentially a macro with large arguments.

3.1.1.4. Parsing for reference tables

Where possible, interscript should tokenise and parse or partially parse program files to extract summary data.
3.1.1.4.1. Tokenisable Languages
The following languages can be tokenised easily: C, C++, Python, Java, Eiffel, Pascal, Modula. [Only the Python tokeniser has been written].
3.1.1.4.1.1. Identifier reference
For each language which can be tokenised, produce an identifier reference: C, C++, Python, Java, Eiffel. [Table generator done for web, html, latex]
3.1.1.4.2. Fully Parsable Languages
Python and Java. C and C++ cannot be fully parsed without semantic analysis, and even then, it is tricky: it is hard to determine if a statement is a function declaration, variable declaration, or executable. [Only partial python parsing has been implemented]
3.1.1.4.3. Partially Parsable Languages
C and C++ can be partially parsed: information extracted may not be completely correct.
3.1.1.4.3.1. Class reference
For each language which supports user defined types, particularly classes, provide a table of classes. Python, Java, C, C++, Eiffel, Pascal, Modula. [Table generator done for web, html, latex]
3.1.1.4.4. Function reference
For languages supporting functions, provide a function reference. This includes methods/member functions. Provide for C++, Python, Java, Eiffel, Pascal, Modula. [Table generator done for web, html]

3.1.1.5. Parsing for embedded documentation

3.1.1.5.1. Perl DOC
Perl DOC is arbitrary documentation provided in comments, to be converted to interscript method calls. [Done]
3.1.1.5.2. Java DOC
Java DOC is a commenting protocol, and depends on parsing to identify the entity to which the documentation refers. [Not implemented]
3.1.1.5.3. Eiffel
Eiffel provides dedicated documentation constructions. [Not implemented]
3.1.1.5.4. Python Doc strings
Python supports Doc strings with a standard protocol for module and class documentation. Although the Python runtime supports module, class, and function Doc strings, there is no standard way to relate Doc strings to functions. [Not implemented]

3.1.1.6. Internationalisation

Interscript tanglers should provide support for multiple human languages. There are two kinds of support determined by the binding time:
Interscript time binding
Interscript time binding allows generating target code for a specified language. If multiple languages are specified, multiple versions of the target code are generated.
Run time binding
Run time binding allows generating target code for a specified language set. Even if multiple languages are specified, only a single version of the target code is generated.
There are two levels of support which can be provided, which are not independent of binding time.
Identifiers
Using names in the programmers native language to aid maintenance. This is clearly an interscript time option.
Strings
Using strings in the client native language to aid use. This can be done either at interscript time or target software run time.
See also document_internationalisation for details on the documentation aspects of internationalisation.

3.1.2. Weaving

Weaving is the most complex subsystem.

3.1.2.1. Individual Weavers

There shall be weavers producing plain text [done], simple HTML 4 (html) [done], advanced HTML 4 multi page (web) [done], XML [not implemented], latex2e [done].

3.1.2.2. Individual weaver capabilities

These capabilities must be provided in each separate weaver.
3.1.2.2.1. Fonts
Weavers should support italic, bold, emphasized, strong and code fonts.
3.1.2.2.2. Lists
Weavers shall support bullet, numbered, and keyed lists.
3.1.2.2.3. Displays
Weavers shall support displays for code and prose, both inline and from a separate source. Latex, shall support math display.
3.1.2.2.4. Tables
Weavers shall support simple tables with horizontal spanning and column headings.
3.1.2.2.5. Headings
Weavers shall support multilevel headings with automatic heading number generation, and labels (anchors).
3.1.2.2.6. Code echo
Weavers shall provide a method to displayed line numbered code lines with labels (anchors).
3.1.2.2.7. Citations
Weavers shall support citation of URLs, print media, code files, and interscript generated documents.

3.1.2.3. Internationalisation

Internationalisation of documentation consists of two facets: automatic substitution of fixed literals such as the titles of tables, and providing for alternate translations of client documentary text.

The former requirement should be met by run time tangler binding of interscript itself, see tangler_internationalisation for details.

3.1.3. Building

3.1.3.1. Python hosting

Interscript shall be able to host python script, optionally capturing standard output.

3.1.3.2. Compilers

Interscript shall host system compilers.
3.1.3.2.1. CPython
For CPython, C and C++ compilers shall be hosted. Both executable applications and dynamically loadable python modules shall be supported.
3.1.3.2.2. JPython
For JPython, the javac compiler shall be hosted.

3.1.3.3. Diff/Patch

Interscript shall provide a file comparison/change tool similar to Unix Diff and patch. The tools must provide/apply reversible differentials.

3.1.3.4. Executing external tools

Interscript shall host external applications.

3.2. Interface

The normal understanding of this topic requires discussion of how interscript is launched. As a command line tool it provides a standard interface, an equivalent GUI hosted tool would be little different. Interscript also provides a Python callable API, which is more interesting, but largely unimportant to most users who will not be embedding it.

As a batch oriented text file processing tool, the secondary interface requirements which describe the organization and format of the input source files, are considerably more important, since it is this interface that most clients will use most of the time.

However, we cannot relegate the presentation of outputs -- both documents and program files -- to discussion of functionality because, as a specialized tool, interscript must constrain -- or at least guide -- presentation to suit its purpose as a development environment.

Finally, we cannot omit consideration of how the implementation interfaces to the underlying operating system and its tools, because, in the development process, the client must use interscript to host the launching and management of these tools.

In summary: interscript interfacing involves everything which has visual appearance including input source files, output documents and program files, and presentation of client tool interfaces, especially error output.

3.2.1. Unified command interface

One of the principal goals of interface design is to provide an API which is simple and comprehensible, while at the same time providing comprehensive access to the underlying functionality.

It is a basic lesson of software modelling that interfaces reflect architectural structure (or conversely that the API design influences the system architecture.)

Interscript maintains a current state analogous to a graphics device context: instead of pens, brushes, and canvases, the state can be partitioned into objects like the current weaver and current tangler.

Thus, as for graphics state, interscript provides a @select() command, to select objects into the current context.

Interscript requires clients construct individual tanglers, and provides the @tangler() command to facilitate this. In addition, some tanglers provide specialised tanglers for parts of the target programming language, such as strings and comments, or for extensions to the programming language.

On the other hand, weavers are generally not constructed individually by the LP author. Instead, the command line processor, or other launch script which invokes interscript, determines which documents formats the client desires: a default of none makes sense as this effectively turns the interscript process into tangle only mode.

The command line then constructs weavers for each desired format and hooks these weavers onto a multiplexor device, called a weaver loom, which delegates method calls to each of these weavers.

By contrast, typesetting different versions of a document requires that the user construct and manage a multiple looms. For example, if a document is written in one language and a translation into another is also provided, we need two looms, one of which is selected when a translation is available. When common text, such as code, is typeset, both weaver looms are selected.

It is necessary that the author construct these looms, and do so in a way that depends on the formats selected by the command line options. Furthermore, user command line options must be available to determine which whether to typeset the document in English, French, both, or neither: it is not the job of the author to make this decision.

3.3. Management

All software projects, even small ones, can benefit from good management; and management depends on availability not only of technical documentation, but also meta-information.

Project management meta-information includes statistical measures of volume and complexity (so-called software metrics),

3.3.1. Software Metrics

Interscript shall provide some built-in reporting of project meta-information, including conventional statistics reporting the number of lines of code (LOC) for inputs, tangled code, and documentation, number of classes, functions, and other constructions defined.

Perhaps more significant, however, are measures of unit test results.

3.3.1.1. Change Impact Analysis

It is my personal opinon, that these primitive metrics are only of minimal utility: theyre provided because theyre easy to compute, rather than because they're particularly useful.

In my opinion, the kind of metric which is actually a useful measure of progress and software quality is what I'll call a change impact analysis.

Extensive changes are indicators of poor software quality. Basically, if a programmer is changing many files, the system is unstable and poorly structured.

If, on the other hand, changes are intensive, and isolated, the system is likely to be robust and well structured. The intense work being done indicates new functionality, improved performance, or correction of a bug, rather than tediously re-engineering many interfaces as a consequence of a minor change to one module.

The theory behind this kind of metric is based on notions of coupling and modular dependencies: if, according to principles of loose coupling, as espoused by Bertrand Meyer in Object Oriented Software Construction, a program is well modularised, then changes to a module should have a limited impact on other modules. Indeed, a fundamental tenant of the Open/Closed principal (again from Meyer), and notions of information hiding, is that variations in the implementation of an interface should have no impact on other modules at all.

These indicators include documentation. Therefore, traditional development technology is certain to get a lousy rating by an impact change analysis: requirements are written first, then the system designed, then implemented, then tested, and finally documented (if there is any time left).

This is a woeful strategy. I subscribe to the philosophy most strongly emphasised by Robert Martin: that all aspects of software development should be done together, because they feed back into each other.

Interscript is especially designed to support this superior strategy by providing integrated documentation, design, programming, and testing facilities, along with progress indicators: it is designed to support ongoing simultaneous development of requirements, analysis, design, implementation, testing, and management. As such, there is no notion of maintenance: the same strategy is used throught the lifetime of the software, although the investment of resources will likely vary over this period.

Change impact analysis is best based on interscript sources, because target programming languages provide dubious support for proper localisation. For example, C and C++ require separate header and body files: parallel maintenance of function signatures is an impediement to quality imposed by the language. An interscript programmer will write generating tools to unify declaration and definition of a C function, so the parallel maintenance will be handled by the computer system.

It would be entirely wrong to interpret extensive changes as bad practice, however. On the contrary, historical impact change analysis ought to show alternating phases of intensive and extensive changes. The reason is that while extensive changes indicate poor software quality and lack of robustness, such indication is a good thing if the changes are followed by intensive changes, because they may indicate the programmer has recognized poor structure, devised a solution, and implemented it.

On multi-programmer projects, it is essential to coordinate the extensive change phase; whereas during times of intensive development, programmers can largely be left to work independently.

Any sizeable project which fails to go through at least one complete reorganisation is likely to be of very dubious quality. For example: interscript went through a complete reoganisation before 1.0a7 was released; the original single file was restructured into a package of separate modules, and the single global scope was partitioned into several distinct frames.

3.3.1.2. Measuring Change Impact

Interscript shall provide change impact metrics. It isn't clear to me at this time exactly what to measure and how. The basic idea is to compare all the source files before each run, and record which ones have been changed. If, after some time period, one observes changes to a small number of files, the development is intensive, whereas if one observes changes to a large number of files, the development is extensive. If there are a large number of changes, the project is in a development phase, whereas if there are a small number of changes, debugging or tuning is indicated.

Management should correlate these predictors with oral communication and written status reports. Furthermore, examining the particular location of changes may help pinpoint a problem and suggest reallocation of human resources.

3.3.2. Programming metrics

Because projects and management styles differ, and any notion of software metrics is new enough to be classed a black art rather than a science, interscript shall support user programmable metrics. Just as programmers can use the Python scripting engine to generate code or documentation, in accordance with their needs, so too can new software metrics be devised and programmed.

For this reason, interscript shall provide a basic statistical analysis package. In addition, apart from standard metrics, interscript shall provide hooks for gleaning other data required for computation of these new metrics. [It is not clear at this time how to do this.]

3.4. Implementation pragmatics

This section discusses requirements in terms of the constraints imposed by an implementation. There are several requirements all software must meet:
Performance
Interscript must be very fast because it must be executed after every change to program source code or documentation. If this additional processing time is significant compared to the time other build components such as compilers take, it is likely to be an impediment to practical software development, especially that for which documentation is not as highly rated as functionality.
Portability
Interscript must be highly portable: it must at least be able to execute on Unix, Windows, and Mac platforms with minimal installation and maintenance hassles. The installation and configuration must be manageable by people who are specialists in some computing field -- not necessarily the interscript implementation language or the host platform.
Accessibility
Interscript must be easy to get hold of.
Client side maintenance
Because the repertoire of facilities a literate programming tool could provide are huge, upgrades must be easy to install, must not compromise client configuration, and must remain largely compatible with sources already developed by interscript.
Third party development
Interscript must provide third party development opportunities. This is essential when required functionality is certain to be highly deviant, and also very specific.

4. Design Fundamentals

This part looks at various issues in the design of Interscript.

4.1. Devices

A device is an object representing an actual input, output, or execution stream such as a disk file. Devices are simple objects which read, write, or execute data without parsing or interpretation. Instead, they interface to actual system device objects such as disk files, remote files, or text stored in memory. In Interscript parlance, an input device is called a source, an output device is called a _sink_, and a device which acts first as sink, and subsequently sources data that was sunk into it, is called a store.

The input to interscript is represented by a source driver object. Both the tanglers and weavers write output via sink driver objects.

Currently implemented sources:

named_file_source
The most commonly used source driver reads a disk file named by a native filename.
ftp_file_source
This device initially reads files from an FTP host and creates a local copy. The local copy is read until it is deemed too old, at which point it is fetched again by FTP.
http_file_source
This device initially reads files from an HTTP host and creates a local copy. The local copy is read until it is deemed too old, at which point it is fetched again by HTTP.
url_file_source
Reads a file given a URL. Currently, ftp, http, gopher, and local files are supported. There is no caching.
stdin_source
Reads a file from standard input.
null_sink
Throws away data.
simple_named_file_sink
Writes a disk file given a native filename.
named_file_sink
This device writes a temporary disk file, and copies it to a nominated file if the two differ, both to prevent touching unchanged files, and to ensure the previous file is available during parsing, allowing generated files to be included back into the document.
stdout_sink
Writes to standard output.
memory
Writes and reads from memory.
disk
Writes and reads to disk (with separate read and write heads).

Under development are patch readers and writers. A patch writer compares two files, and, instead of replacing the old file with the new one if they differ, writes a patch file instead. The corresponding reader applies the patches to a copy of the old file and reads that instead. This mechanism provides rudimentary version control, allows stable files to be write protected, and permits posting and using patches by email or news.

Writers for news and email are also in the works. The email sink device is particularly useful to allow automatic regular updates (run as chron jobs) to send advice to the client.

The URL reader currently doesn't use a cache, because it uses the standard Python function urlopen, which doesn't use a cache. Hopefully this function will be upgraded to check expiration headers on http servers, and cache files locally.

A tee writer --- a device which writes to several other devices -- is planned.

4.1.1. File names

Common interscript commands always refer to files using Unix relative filename convention, even on non-Unix platforms; the interscript command line processor also requires master filenames given on the command line to follow this convention. These filenames are converted to the native format internally. The purpose of this mechanism is to ensure distributed source documents are platform independent.

Interscript requires the native operating system support long case sensitive filenames including the upper and lower case latin-1 (ASCII) letters, digits, and underscore, and a heirarchical directory system with some kind of current directory concept: these features are supported by all modern Unix , Windows, and Macintosh platforms. Note that interscript cannot operate on DOS or Win3.x platforms.

4.1.1.1. Named File Source Names

Interscript named_file_source takes two arguments identifying a local disk file. The first, mandatory, component is name in Unix relative filename format, and the second, optional, component, is a prefix in native operating system format.

This pair of names is the interscript file name convention. If the prefix is empty, it is replaced by the absolute pathname of the current directory in native operating system format, including a trailing directory separator. Then the Unix filename is converted to a native operating system filename, and appended to the prefix.

Commands such as include_file which refer to sources supply the directory of the current file as the prefix so that the argument filename is relative to the location of the including input file. All such arguments must be relative filenames in Unix format for this reason.

Note that the command line provides the --source-prefix= option for the same reason: a filename given on the command line as a master source file must be given as a relative filename in Unix format, even on non-Unix systems. The source-prefix option permits the native operating system name of the directory containing the file to be specified.

4.1.1.2. Named File Sink Names

Interscript named_file_sink takes two arguments identifying a local disk file. The first, mandatory, component is name in Unix relative filename format, and the second, optional, component, is a prefix in native operating system format.

This pair of names is the interscript file name convention. If the prefix is empty, it is replaced by the absolute pathname of the current directory in native operating system format, including a trailing directory separator. The the Unix filename is then converted to a native operating system filename, and appended to the prefix.

The command line supports four options, --tangler-prefix=, --tangler-directory=, --weaver-prefix=, and --weaver-directory=, which facilitate placement of outputs.

The two directory options allow a Unix relative filename (or other prefixing characters) to be prepended to all filenames used for tangler or weaver outputs, respectively.

The two prefix options allow a native operating system format filename to specify the output directory for tangler and weaver files. If the prefix is empty, the absolute pathname of the current directory, including trailing directory separator, is used. The Unix filename is converted to native operating system format and appended to the prefix.

4.2. Processors

A _processor_ is an object that performs some processing function. Processors are generally hooked up to to devices to read or write data. The separation of processing data streams, and sourcing and sinking those streams, is the traditional operating system facility known as device independence.

Whereas a file, denoted by a filename, is used in an operating system to implement device independence, in Interscript, a Python object is used instead.

The design of Interscript consists of four processors: the input, the code tangler, the document weaver, and the Python engine.

The Interscript parser reads and parses the input and sends lines to one of the three outputs. If the line begins with the special warning character @ it is sent to Python, otherwise if the tangler is not None it is sent to the tangler, otherwise it is sent to the weaver. If the tangler receives the line, it is written to a code file and echoed to the weaver.

The main source of power in this system is the ability to execute arbitrary Python script. Interscript has some builtin commands and data structures to facilitate control.

4.3. Tanglers

A tangler is an object that is designed to process source code in some programming language for which the tangler is specialised. Tanglers are generally selected by the @select() command in the source. Output to a tangler is disabled by most documentation commands, so the system reverts to generating documentation.

Tanglers can be stacked. Typically, test code or header code will be embedded in files containing definitions.

Interscript comes with specialised tanglers for, several languages. The list below shows the currently implemented special features of these tanglers.

data
No special features.
C
Tracks source with #linedirectives. Associated string and comment tanglers. Parses identifiers (badly).
C++
Tracks source with #line directives. Associated string and comment tanglers. Parses identifiers (badly).
python
Tracks source with #line directives. Associated comment tangler. Parses identifiers properly.
perl
Tracks source with #line directives. Parses and processes Plain Old Documentation constructions.
java
Associated string and comment tanglers.
interscript
No special features.

4.4. Lexical Scoping

The system maintains a stack of objects called input frames to track input sources. Input can be stacked using the @include_file() command, which is equivalent to a subroutine call. The stack is popped when the included file is exhausted.

The commands @begin() and @end() can also be used to push and pop the input stack, this is equivalent to a nested block.

User defined symbols are lexically scoped. The system currently maintains a dictionary of user symbols with each stack frame: all assignments enter the symbol into the dictionary of the top of stack frame.

When the stack is pushed, the new top of stack dictionary is initialised by a copy of the old top of stack dictionary. User symbols are searched for first in the top of stack user dictionary, and then in the global interscript namespace.

As well as supporting scoped symbols, the parser is scoped. That is, changes to lexicology or processing mode made by modifying the parser tables are lost when the frame is dropped. This ensures that, for example, a change to the warning character in an included file does not affect the interpretation of the including file.

4.5. Weaver Control

Weaver control is the most complex. Weavers can be stacked, for example to allow summary files or notes to be built incrementally. For HTML, detail pages can be stacked on a master, with hypertext links in the master to access them.

More than one weaver can be active at once, so that, for example, a HTML Web site, a LaTeX book text, and a plain text news article can be generated simultaneously. Document lines are sent to all the active weavers for processing.

Some typesetting constructions are too complex or specialised to be represented in all weavers. In this case, verbatim text can be sent to a particular weaver, or sent to any active weavers obeying a specific protocol.

4.6. Source Tracking

In the beginning, every system is a collection of original source files, one of which is designated as the initial (master) source. Interscript begins processing the initial source, and may switch to another source as a result of executing some command such as include_file. This can be done to break a long work into sections, or to include common macros (python script).

Each source must have a definite name, and each line read is counted. This allows references to the original source to be generated in the code (and documentation) files, so that errors reported by language processors can be corrected. The code files cannot be edited, because they are generated by Interscript and any changes would be overwritten by the next processing run.

A related reason for source tracking is to generate cross reference tables. For example some tanglers generate an identifier cross reference, which can be used, for example, to disentangle duplicated names. The tables can also be used to generate vi editor tags, for example.

Every line of output must have an associated original source. That includes code that is saved temporarily (in memory, or to a disk file), and it includes generated code.

In order to accurately track original source lines, each input driver must have a name, usually the input file name, and must count lines read. When a line is read by the parser, the filename and line number are returned as well. The parser passes this information on to the relevant processor, usually the executor, tangler, or weaver.

In turn, the tangler, for example, will check the sink driver to see if the otput is synchronised with the original source, and then store the source filename and line number in the sink driver.

If since the last write to the sink, not necessarily by this tangler, the original source filename has changed, or the line number is not one more than last time, then a section header is written to the sink file before the data. In C and C++ a #line directive is generated, in languages not supporting such directives (such as HTML and Python), a comment is generated instead. (Coincidentally, many scripting languages use a leading # for a comment and so the C style #line directives is generated)

4.7. Parsing

Interscript is a language, and needs a parser. Parsing is a complex task. The main control algorithm, however, uses a very simple syntax driven parsing engine. The parser table is a Python list of pairs. Each pair is a tuple consisting of a compiled regular expression and a function. The parser gets one line at a time from the source, and runs through the list, attempting to match the line against a regular expression. When a match is found, the corresponding function is called with the match and source reference data as an argument.

Because this scheme is very simple, it can be extended or modified easily by the end user.

Because the function invoked can read further lines from the input, more sophisticated parsing can be programmed. For example, the Python suite execution function matches against a line starting with an @ and ending with an : or other character that indicates an incomplete suite. The function reads further lines up to the end of the script before executing the lot as a single Python suite.

4.8. Documentation Constructions

Interscript supplies uses with various documentation constructions. These include standard constructions such as a title, multilevel document headings, page headings, table of contents, index, nestable enumerated, bulletted, and keyed lists, displays (long quotations), footnotes, and tables. For a full list of supported constructions see below.

The requirements here are to support a rich enough set of constructions, with a fine enough level of control of details, to do handle the bulk of work which would be required by a serious author, while at the same time providing the casual programmer simple enough tools to typeset basic program documentation.

In addition, Interscript supplies constructions specialised to literate programming. Naturally, there is a specialised construction for source code display, and some tables such as a list of files, and identifier index unique to literate programmed code. In addition, it is necessary to be able to typeset code fragments for examples of use, even though literate programming discourages this. (Give real examples!)

These requirements have to balanced against the efficiency of the translator, the ease of implementation of the constructions, and the availability of features in typesetting systems. How do you typeset diagrams in plain text? (With difficulty) What about diagrams, colour, pictures, and font control?

4.9. Microformatting shortcuts

By microformatting, I mean things like emphasising a single word. Most typsetters can set a plain, bold, italic, underlined, and mono-spaced font (but not plain text). Support for mathematics, however, is more limited.

The general solution to microformatting is to have specialised parsers. Just as the line by line parser can be extended by the user, specialised microformatting can be provided by the end user by writing a parser to further translate document source. Naturally, the weavers to be used will have to be support the constructions.

Weavers already perform some parsing. For example the Latex weaver has to translate the characters #$%^_ into the Latex macros that produce them, since they're reserved characters in standard Latex.

The biggest problem here is to specify a standard microformatting language. It is not too onerous to reserve the @ character at the beginning of a line, but how does one designate three special fonts (bold, italic and monospaced) and the scope they apply to? What about font size? For something more difficult, mathematics?

Any such language must eat up characters which can be typeset as is: the fewer such reserved characters, the more cluttered the source will become, whereas if more are reserved, the more likely the user is to forget to quote them properly when the character itself is required instead of magic.

HTML reserves <> and uses tag pairs to do detailed markup, and uses & to allow quoting. Latex reserves #$%^&_\. Interscript reserves @ at the beginning of the line.

It is possible to do all formatting using lines. But that leads to a troff like solution, which is extremely ugly. It should be possible to write normal text and have it print properly -- and for a programmer that will include setting special characters. Typesetting C code documentation in plain Latex is a pain because underscore means subscript and is an error outside maths mode: but underscore is more or less the C version of a hyphen, and more or less an alphabetic character.

The characters we can afford to reserve are those not commonly used in program documentation. There arent any. Heres the proof by analogy: if we reserve @, for example, then in the very documentation describing the construction implemented using the @ character, the most commonly used special character will, of course, be @.

The solution I have adopted to this intransigent problem is as follows. First, all the constructions have to be provided as commands. That means that irrespective of other details, all the constructions are available, even if it is a pain to typeset them.

Secondly, we provide regular expression matching technology to extract microformatting details using some standard forms, but we will not enable it by default.

Ill call these things shortcuts'. For example, the first shortcut for code is an @ followed by a C identifier. An @ in any other context is typeset as an @.

Shortcuts are implemented by weavers. (The control loop never sees them). To provide typesetter independent shortcuts, we need a special kind of weaver: a filter. A filtering weaver translates shortcuts and then calls the normal weaver.

Interscript comes with a standard filtering weaver, and is equipped with a user programmable table of shortcuts based on regular expression matching. The default version of this weaver does not do any shortcuts, however. Shortcuts must be explicitly enabled by the programmer. However, there is a table of standard shortcuts prepared, and a command to enable them.

4.10. Weaver Architecture

Interscript operates on the assumption that there is exactly one weaver that can process all weaver commands.

4.10.1. Multiple Typesetters

Often, we want to weave the same document in different formats, for example, using Latex for book output, HTML for a web, and plain text for email and news.

This facility is provided by a weaver front end called a multiplexor. The multiplexor keeps a list of active weavers, and sends every method call to all weavers in the list that supports that method. Its not an error if the weaver doesnt have the method, but it certainly is an error if it does, but the call fails.

4.10.1.1. Raw output

When Interscript does not support detailed constructions, it is necssary to hard code them into the document. For example, if you really want frames in HTML, or category theory diagrams in LaTex, you have to code raw HTML or LaTex (probably XYpic) because Interscript doesn't provide a generic interface to support.

The principal mechanism for raw output is to put it between a @rawif(protocol) command, and a @translate() command. The rawif command disables a target weaver unless it supports the nominated protocol, in which case, it is put in raw mode, whereas the enable command enables the weaver and put it in translating mode.

If the weaver is the multiplexor, it dispatches these commands to all the weavers attached to it, thereby allowing raw output to be written to the subset of weavers supporting it.

Generally, you should provide raw typesetter data for every possible typesetter so that _something_ is typeset in every format of the document. (even if it is just paste the diagram here :-)

Every weaver constructs a protocol list when it is created, but the method add_tag can be called to add another protocol to a weaver. The standard protocol names are html, latex, and text for the html and web weavers, the latex weaver, and the plain text weaver, respectively.

This mechanism is design to be used in documents of parts of documents without requiring knowledge of which weavers are active. If a particular weaver is active and accessible, it can be controlled directly instead, but this is recommended only for specialised documents.

4.10.2. Multiple Human Languages

Sometimes, we want to prepare the same document in several human languages. Interscript cannot translate English to German, for example, so it is necessary to provide documentation text in both languages. The program codes, however, are usually in common, except possibly for comments.

Interscript can generate a multiple versions of a single document (and each version will be generated in all the selected formats) using the same tagging mechanism that is used to control raw output. You can write sections of English documentation after that command @enableif(English) and sections of German version after the command @enableif(German), and this will disable all weavers not supporting the nominated protocol.

This mechanism applies to interscript program code comment commands. The commands generate ordinary woven text, but are also inserted into the tangled output files. In this case, comments will be inserted in the selected language or languages. Be aware that while this will not change program semantics it will change the physical source file.

It is also possible to generate string constants in different human languages with interscript, but this is a tangler function, having no special effect on weaving: because of the complexities of this issue, it must be effected using python script crafted by the author for this purpose ... in other words there are no special commands for it :-)

4.10.3. Multiple Documents

Sometimes, we wish to construct several documents simultaneously. For example, we may have a short and long version of a document. We need to select which weavers to write to. It is easy to do this in simple cases by just assigning the weaver. For example:
  @both = multiplexor((long, short))
  @weaver = both
  This document describes Interscript.
  @weaver = long
  Here are some gory details.
Because a multiplexor represents a set of documents, and because one can multiplex multiplexors, it is easy to create small sets of weavers, and then create various unions of these sets.

4.10.4. Cumulated Appendices

Sometimes it is useful to accumulate the text for a document thru the source: the table of contents is an example of this. Another important example is an issues list: details of bugs or issues are written near the relevant source, collected, and printed as an appendix.

Other examples include footnotes, which are usually printed all togther at the end of articles or chapters in some styles, summaries of test results, etc. [To be continued and stuff implemented]

5. Tutorial

An easy introduction to the Interscript literate programming tool and environment. Please note Interscript is still experimental, and the command set and architecture are not frozen.

5.1. Weaving a document

To create a plain document is easy. First, you should create a heading like this, then type documentation. On-the-fly interscript for test 1 follows.
Start interscript section from tutorial.pak
    12: @head(1,'My Document')
    13: This is a document describing Interscript, which
    14: is a literate programming tool. You can use
    15: any characters you like in the document,
    16: such as ~!@#$%^&*(), with one exception:
    17: you should not start a documentation line with @ in
    18: column 1. The @ character in column 1 is used to flag a command.
End interscript section from tutorial.pak
Test output at ../tests/output/test_1.html. Logfile at ../tests/output/test_1.log.

5.1.1. Headings

You can create sub-headings, and sub-subheadings, just use a @head(n,'Heading') command with n set to the heading level you want. Headings are numbered from 1, level 1 is the biggest heading. (Technically, the document title is a level 0 heading.)

Heading levels should go up consecutively, because Interscript numbers all headings automatically. Here's a document with several headings. On-the-fly interscript for test 2 follows.

Start interscript section from tutorial.pak
    33: @head(1,'Several Headings')
    34: Test with several headings.
    35: 
    36: @head(2,'First Subheading')
    37: Under the first subheading is a subsubheading.
    38: 
    39: @head(3,'First Subsubheading')
    40: Some details here.
    41: 
    42: @head(3,'Second Subsubheading')
    43: Some more details here.
    44: 
    45: @head(2,'Second Subheading')
    46: Here's the second subhead. And the last
    47: text in the document.
End interscript section from tutorial.pak
Test output at ../tests/output/test_2.html. Logfile at ../tests/output/test_2.log.

5.1.2. Separating paragraphs

You can separate paragraphs with the command
  @p()
Blanks lines do not separate paragraphs. This is deliberate. Any number of blank lines translates to a single space. This allows you to separate parts of your Interscript document with vertical white space. It is particularly useful to add blank lines before headings. For example: On-the-fly interscript for test 3 follows.
Start interscript section from tutorial.pak
    61: @head(1,'A document')
    62: We are flying to the moon today.
    63: @p()
    64: But not just any moon. The moon of Mars.
    65: 
    66: @head(1,'Phobos')
    67: Actually, there are two Martian moons.
    68: @p()
    69: @p()
    70: @p()
    71: 
    72: @p()
    73: 
    74: @p()
    75: One of them is Phobos.
End interscript section from tutorial.pak
Test output at ../tests/output/test_3.html. Logfile at ../tests/output/test_3.log.

You should note that @p() is idempotent, which is a fancy way of saying two or more of them in a row are the same as one. You can't add extra space between paragraphs. Not even by putting dummy blank lines in between.

5.1.3. Line and Page breaks

You can force a line and page break with the commands
  @line_break()
  @page_break()
respectively. On-the-fly interscript for test 4 follows.
Start interscript section from tutorial.pak
    90: @head(1,'A break test')
    91: Here is a short line
    92: @line_break()
    93: and another
    94: @line_break()
    95: and another.
    96: End of page.
    97: @page_break()
    98: Now a new page.
End interscript section from tutorial.pak
Test output at ../tests/output/test_4.html. Logfile at ../tests/output/test_4.log.

5.1.4. Displaying code examples

In this tutorial, I've been showing you some example code. That is something most documentation writers want to do. You can do it too, like this: On-the-fly interscript for test 5 follows.
Start interscript section from tutorial.pak
   107: @head(1,'Code displays')
   108: Here is a code display:
   109: @begin_displayed_code()
   110:   while 1:
   111:     print 'Hello again and again'
   112: @end_displayed_code()
End interscript section from tutorial.pak
Test output at ../tests/output/test_5.html. Logfile at ../tests/output/test_5.log.

5.1.5. Running Interscript

Well, you should try an example file. To process a file we'll say:
  python iscr.py --weaver=html example.pak
where 'example.pak' is the name of the Interscript document. This will create a single file "example.html". Try it!

If you prefer HTML split into lots of little pages, try:

  python iscr.py --weaver=web example.pak
This produces a file "example_top.html", and a number of auxiliary files, and a file for each heading.

You can also generate latex2e and plain text with the commands:

  python iscr.py --weaver=latex example.pak
which produces a file "example.tex", and,
  python iscr.py --weaver=text example.pak
which produces a file example.txt. you can put more than one file name at the end too. Each such document will be processed separately.

5.1.5.1. Option help

If you type:
  python iscr.py --help
you will get a complete list of available options.

5.1.5.2. Passes

The passes options causes Interscript to process files more than once. This is sometimes necessary to get cross reference information right. The default is currently 1.
  python iscr.py --weaver=text --passes=2 example.pak
Interscript may stop before running the specified number of passes. It will do this if, and only if, every buffered disk file ("named_file_sink") would write an output the same as the existing file. In that case, it assumes further passes wouldn't change anything, and stops. This is called convergence.

5.1.5.3. Tangling parts

If you construct your Interscript sources as a tree, using the "@include_file()" command, and you follow certain rules, you can run Interscript on the included file to extract the code, for just that file. The Interscript sources are constructed this way. This feature is vital for building big systems because it allows you to extract the code from files you have changed, without extracting code from those that have not.

You must ensure that code files are lexically contained entirely in a single include file. More generally, the include file does not rely on any context from its parent (except for that which is determined from the command line).

If you weave an include file, you will get a separate document for that include file which will, in general, not be linked to the master document: it will be in a separate file, named after the include file, and headings will be numbered separately.

[There is currently no simple way to require a separate source be built entirely independently so that the master document can link to it. This would be especially useful, because it would also permit time stamps to be checked and avoid unnecessary processing.]

5.2. Tangling code

So far, we have just produced a document. What about programming? Here's a sample document with tangling. On-the-fly interscript for test 6 follows.
Start interscript section from tutorial.pak
   196: @py = python_output('interscript/tests/output/mymodule.py')
   197: @head(1,'My Module')
   198: This is my very own module.
   199: @select(py)
   200: import sys
   201: class myclass:
   202:   def __init__(self, name):
   203:     self.name = name
   204: @head(2,'hello method')
   205: Just says hello.
   206: @select(py)
   207:   def hello(self):
   208:     print 'hello','self.name
   209: @doc()
   210: And now back to doco.
End interscript section from tutorial.pak
Test output at ../tests/output/test_6.html. Logfile at ../tests/output/test_6.log.

5.2.1. Original Source References

Here's the code from the previous example again:
Start python section to interscript/tests/output/mymodule2.py[1] 1
     1: #line 217 "tutorial.pak"
     2: import sys
     3: class myclass:
     4:   def __init__(self, name):
     5:     self.name = name
     6:   def hello(self):
     7:     print 'hello','self.name
End python section to interscript/tests/output/mymodule2.py[1]
Notice the #line directives. They're called original source references because they refer to the original, editable, source file containing the code. If you are creating C programs, the compiler will recognize them and report compiler errors in the original file. Integrated development environments will put the cursor right in the middle of the Interscript source. This is necessary, you must not edit the code file. Your changes will get clobbered next time you run Interscript on the original source.

5.2.2. Code sections

As you can see, the code is displayed with line numbers, and the file is named at the beginning and ending of each chunk. Interscript calls these chunks code sections and the doco between them document sections. So basically, Interscript allows you to interleave code and document sections. This is called gathering in some other literate programming tools. You can end a code section with an @head() command, or a @doc() command, which switches back to document mode.

Just so you can see it again, here is some code interleaved with documentation.

Start python section to interscript/tests/output/mymodule3.py[1] 1 2
     1: #line 266 "tutorial.pak"
     2: import sys
     3: class myclass:
     4:   def __init__(self, name):
     5:     self.name = name
End python section to interscript/tests/output/mymodule3.py[1]
And now for the hello method:
Start python section to interscript/tests/output/mymodule3.py[2] 1 2
     6: #line 273 "tutorial.pak"
     7:   def hello(self):
     8:     print 'hello','self.name
End python section to interscript/tests/output/mymodule3.py[2]
You should see two code sections, embedded in documentation.

5.3. Scripting

Traditional literate programming tools have two conceptual processes: weaving (a document) and tangling (a code file) which separate out interleaved document and code sections (respectively).

Interscript has a third kind of section, the script section. In case you're wondering what script sections look like, well, you've already used them. All those lines starting with @ are just executable python script. They aren't really special magical commands, just function calls to predefined python functions.

You can write any python script you like in a script section. On-the-fly interscript for test 7 follows.

Start interscript section from tutorial.pak
   303: @name = 'John Skaller'
   304: @print 'Hello',name
   305: @print 'Running Python',sys.version
   306: @head(1,'Hello World from '+name)
   307: This is a scripting test.
   308: @weave('Written by '+name+'.')
End interscript section from tutorial.pak
Test output at ../tests/output/test_7.html. Logfile at ../tests/output/test_7.log.

Notice you don't have to import sys: it is already imported, because it is used in Interscript. [Add list of imported modules here]

You will also notice the

  @weave(text)
command, which weaves its argument: use this when you want to calculate text, as in the example. For more information on the weave command, see weave command.

You should be careful with this feature. It is immensely powerful! You can use it to test programs, and to extend Interscript for you needs in a particular document -- without changing the actual source code for Interscript. See http://www.python.org to find out more about python.

5.3.1. Long script sections

You can code long script sections such as a class definition. The rule is: a long script section is started by a line starting with @ and ending with :,( or one of the characters that python would recognize that signifies that there is more to come. You must then indent the code with exactly one extra space. A long script section is ended by the first line not having a space character in column 1 (or the end of file).

The whole of a long script section is collected and then executed at once. On-the-fly interscript for test 8 follows.

Start interscript section from tutorial.pak
   349: @head(1,'Long script sections')
   350: Here is a long script. We define a class MyClass.
   351: @class MyClass:
   352:    def __init__(self, name):
   353:      self.name = name
   354:    def hello(self):
   355:      print 'Hello',self.name
   356: 
   357:  # test it
   358:  me = MyClass('John')
   359:  me.hello()
   360:  deliberate error
   361: @doc()
   362: After all that, the deliberate error is ignored.
End interscript section from tutorial.pak
Test output at ../tests/output/test_8.html. Logfile at ../tests/output/test_8.log.

Errors in script sections are reported with a traceback to the logfile, but do not halt processing. You cannot terminate an Interscript processing run inside a script section, not even with sys.exit(). [Interscript can be terminated with a keyboard interrupt or system abort signal, however.]

5.3.2. Very Long script sections

There's a better way to code long script sections, using the "python()" command. Here's an example: On-the-fly interscript for test 9 follows.
Start interscript section from tutorial.pak
   376: @head(1,'Long Script test')
   377: Some script should generate a string of 3 'My names',
   378: separated by 3 dashes.
   379: @python('//')
   380: x = 2
   381: y = 3
   382: z = 'My name'
   383: weave((z + '-' * x) * y)
   384: //
End interscript section from tutorial.pak
Test output at ../tests/output/test_9.html. Logfile at ../tests/output/test_9.log.

The 'python' command accepts a string argument which is a terminator line for the script section. The whole section is gathered, without any processing, and then executed. There is a danger to be aware of: if you don't put the terminator in correctly, the command will read all the way to the end of the file.

5.4. Unit tests

It is possible to test python script 'on the fly' as in the example: On-the-fly interscript for test 10 follows.
Start interscript section from tutorial.pak
   396: @head(1,'A python test')
   397: Test the test_python function.
   398: @test_python(hlevel=2,descr='A simple test',source_terminator='//')
   399: print 'A simple test'
   400: //
End interscript section from tutorial.pak
Test output at ../tests/output/test_10.html. Logfile at ../tests/output/test_10.log.

The test is also registered in a table of tests.

It is also possible to provide expected output: Interscript will verify your code by comparing the expected and actual output, and print a difference table if the test failed. Note that the difference table is only available if the module "interscript.utilities.diff" is available and operates correctly: the current implementation uses GNU diff invoked using "os.system()". Here's an example that veifies OK: On-the-fly interscript for test 11 follows.

Start interscript section from tutorial.pak
   413: @head(1,'A diff OK test')
   414: Test the test_python function.
   415: @test_python(hlevel=2,\
   416:   descr='A diff OK test',source_terminator='//', expected_terminator='//')
   417: print 'A simple diff test'
   418: print 'A simple diff test line 2'
   419: print 'A simple diff test line 3'
   420: //
   421: A simple diff test
   422: A simple diff test line 2
   423: A simple diff test line 3
   424: //
End interscript section from tutorial.pak
Test output at ../tests/output/test_11.html. Logfile at ../tests/output/test_11.log.

And here's one that should fail: On-the-fly interscript for test 12 follows.

Start interscript section from tutorial.pak
   428: @head(1,'A diff fail test')
   429: Test the test_python function.
   430: @test_python(hlevel=2,\
   431:   descr='A diff test',source_terminator='//', expected_terminator='//')
   432: print 'A simple diff test'
   433: print 'A simple diff test line 2'
   434: print 'A simple diff test line 3'
   435: //
   436: A simple diff test
   437: A simple diff test line 2 CHANGED
   438: A simple diff test line 3
   439: //
End interscript section from tutorial.pak
Test output at ../tests/output/test_12.html. Logfile at ../tests/output/test_12.log.

5.4.1. Weaver Control

The python function 'get_weaver()' refers to the current weaver. You can use it to call methods directly on the weaver. For example:
  @weaver = get_weaver()
  @weaver.write('Antidis')
  @weaver.begin_bold()
  @weaver.write('establishmentarianism')
  @weaver.end_bold()
   is a long word. Note the space on this line!
which comes out as Antidisestablishmentarianism is a long word. Note the space on this line!

You can also set the weaver. Suppose you have a weaver mynotes_weaver, then you can write:

  @old_weaver = get_weaver()
  @set_weaver(mynotes_weaver)
  This is woven into notes.
  @set_weaver(old_weaver)

To make this more convenient, the set_weaver function returns the current weaver so you can write:

  @old_weaver = set_weaver(mynotes_weaver)
  This is woven into notes.
  @set_weaver(old_weaver)

Even more convenient, you can push and pop weavers onto a stack using

  @push_weaver(mynotes_weaver)
  This is woven into notes.
  @pop_weaver()

The current weaver is lexically scoped.

5.4.2. Perl hates @

If you are programming Perl (or Interscript!) you will hate having @ as the warning character for script sections. There are two ways around this.

You can use two @ characters at the beginning of a line.

  @@p = @x
or you can use a command like:
  @set_warning_character(python='!')
which will set the python warning character to ! instead of @. Advanced Note. This change applies only to the current file, and only to the end of the containing block, if any. The effect will not be passed up to an including file, and it won't be inherited by an included file either.

5.5. Fonts

The following commands change font. Note that begin/end pairs must be balanced, and nesting may or may not be supported, depending on the weaver.
  @begin_emphasize()
  @end_emphasize()

  @begin_strong()
  @end_strong()

  @begin_code()
  @end_code()

  @begin_small()
  @end_small()

  @begin_big()
  @end_big()

  @begin_italic()
  @end_italic()

  @begin_bold()
  @end_bold()

5.6. Lists

The following commands build lists. Note that begin/end pairs must be balanced, and nesting is supported. There are three kinds of lists: numbered lists, which are numbered automatically, bullet lists, which display some special bullet symbol, and keyed lists, which display a string of text for each item.
  @begin_numbered_list(start=1):
  @end_numbered_list():
  @begin_numbered_list_item():
  @end_numbered_list_item():

  @begin_bullet_list():
  @end_bullet_list():
  @begin_bullet_list_item():
  @end_bullet_list_item():

  @begin_keyed_list():
  @end_keyed_list():
  @begin_keyed_list_item(key):
  @end_keyed_list_item():
Here's an example:
  @begin_keyed_list()
  @begin_keyed_list_item('bullet')
  A bullet or similar character at the start of each item.
  @end_keyed_list_item()
  @begin_keyed_list_item('numbered')
  A number at the start of each item.
  @end_keyed_list_item()
  @begin_keyed_list_item('keyed')
  A key, or definition term, at the start of each item.
  @end_keyed_list_item()
  @end_keyed_list()
which comes out like:
bullet
A bullet or similar character at the start of each item.
numbered
A number at the start of each item.
keyed
A key, or definition term, at the start of each item.

5.6.1. Easier lists

By default, Interscript installs a special weaver called 'multiplexor' which delegates commands to zero, one, or more weavers. This weaver also supports simplified list definitions. Here's the example above, simplified.
  @begin_list('keyed')
  @item('bullet')
  A bullet or similar character at the start of each item.
  @item('numbered')
  A number at the start of each item.
  @item('keyed')
  A key, or definition term, at the start of each item.
  @end_list()

5.7. Tables

Interscript supports tables, although currently the support is fairly primitive. Here's how to create a table:
  @begin_table('Column 1','Column 2','Column 3')
  @table_row('Data 11', 'Data 12','Data13')
  @table_row('Data 21', 'Data 22','Data23')
  @end_table()
which looks like this:
Column 1Column 2Column 3
Data 11
Data 12
Data13
Data 21
Data 22
Data23

5.8. Citations

You can cite a URL like:
  @cite_url('http://www.triode.net.au/~skaller')
which will appear as a hyper link in HTML files like http://www.triode.net.au/~skaller.

5.9. Cross References

Interscript supports intra-document (internal) cross referencing using the commands:
  @set_anchor('MyLabel')
  ...
  please see
  @ref_anchor('MyLabel')
   for details.
The label must be a string, and is currently required to be a valid identifier since it is used literally by the HTML weaver in an anchor tag. Latex imposes no such restrictions, nor does the plain text weaver. For HTML, the label is set as an anchor; for latex, the page number is given, for plain text the line number.

Note that inter-document (external) cross references are different to intra-document cross references. For truly external references to existing published works, use citations or bibliographic references. References across volumes of a work or project are not yet supported.

5.10. Including Files

Interscript allows you to include Interscript files with the command
  @include_file(filename)
When you do this, you should be aware that it is treated like a subroutine call: a stack frame is created, and any symbols bound in script sections are local to the file. In addition, various parameters are localized. Therefore, you cannot define a new command or variable in an include file and expect it to persist past the end of the file.

5.10.1. Including code

You can include existing code directly to the current tangler like:
  @select(py)
  @include_code(filename)
This is not the same as including an Interscript file. The contents of the code inclusion 'filename' are copied verbatim to the tangler 'py'. Leading @ characters are not detected. The contents of the file are still woven into the document.

5.10.2. Displaying Code

You can display a file as code like this:
  @display_code(filename)
This is very useful for printing the results of a processing run, or weaving example programs into a book.

5.11. Translating Html

Interscript normally reads Interscript. But it can also read (a small subset of) HTML. The command:
  @include_html(filename)
will read an HTML file and translate the tags to Interscript. In this manner, you can convert flat HTML into stacked HTML, or into Latex or plain text.

5.12. Special constructions

5.12.1. Table of Contents

To print the table of contents, you can say:
  @print_table_of_contents()
For Latex, the native table of contents construction is used. For flat HTML, the weaver generates a hyper linked table of headings, but two passes are required to get it right. For plain text, two passes are also required.

For stacked HTML, a separate contents page is created automatically. For this reason, the table of contents command is disabled for that weaver.

5.12.2. Identifier Index

This is table of all the identifiers used in your programs. For HTML, the entries are hyper linked to each occurrence of the identifier. Finding identifiers is the task of tanglers. At this time, the Python tangler can find most of them by tokenising python script. None of the other tanglers support this feature properly yet.
  @print_identifier_cross_reference()

5.12.3. File list

A list of all the generated files. Use
  @print_file_list()
to generate it. You can use this to assemble the generated files into a tar ball.

5.12.4. Source list

A list of all the input files. Use
  @print_source_file_list()
to generate it. This command is useful so you know what files are required for a package.

5.12.5. The Web Weaver

Here are some special features of the 'web' weaver.

5.12.5.1. Automatic table generation

As of version 1.0a6, the web weaver automatically produces a number of tables: the table of contents, index of classes, index of functions, index of identifiers, index of unit tests, and file convergence status report. None of these tables can be disabled at present.

5.12.5.2. Mandatory Frames

The web weaver also produces several framesets. There is no 'noframes' option at present.

5.12.5.3. Internet Explorer DHTML support

In addition, the table of contents uses ECMAscript to determine if it is running on a version Microsoft Internet Explorer; if so, it enables dynamic HTML features unique to the Microsoft object model which permit dynamic expansion or contraction of the table of contents tree at each branch.

5.12.5.4. Cascading Style Sheets

Both the web and html weavers uses CLASS attributes in tags, and the web weaver in particular makes fairly heavy use of the generic DIV and SPAN tags.

A standard Cascading Style Sheet called Interscript.css can be found in the directory interscript/doc. It colours various elements in a suggestive way. Do not change interscript.css; instead, supply user.css; it should override interscript.css even if your browser finds both files.

5.13. File Names

The names of files used in interscript documents should be relative pathnames obeying the Unix convention, even on other platforms such as NT or the Mac: separate components with a / character. Don't use silly characters such as : in components names.

I plan to upgrade the file naming convention to use URLs with 'interscript' addressing scheme, in which the 'network' component is treated as a logical location identifier; the client will map these locations to physical ones.

The current version of interscript does not provide this mechanism yet. Instead, there are four command line options:

  --weaver-prefix=nativepath
  --tangler-prefix=nativebspath
  --weaver-directory=relpath
  --tangler-directory=relpath
where the nativepath is a prefix in native operating system format, and the relpath is a prefix in Unix format. For an interscript file given as 'basename', the resulting actual filename is:
  abspath+ (string.join(string.split(relpath+basename,'/').os.sep)
Note that if you use 'a' and 'b' as the prefix and directory a filename base will be called 'abbase': no separators are put between the prefix, directory and base. Here's an example for Windows:
  python iscr.py                        \
    --tangler-prefix=c:\mydevelopment\  \
    --tangler-directory=code/           \
    example.pak

Note that interscript creates directories automatically for the 'Unix' part of the filename, but _not_ the native prefix. Thus in the example 'c:\mydevelopment' must exist, whereas 'code'is created within it automatically. If example.pak tangles a file 'package/module.py', then 'package' is also created automatically.

5.14. Questions and Answers

5.14.1. Why are HTML tags printed verbatim, even by the html weaver?

Weavers are _supposed_ to print all printable characters literally. So tagged text such as <EM>tagged</EM> is printed exactly as you wrote it.

5.14.2. OK, so how do I put HTML into a document?

If you want to write specialised HTML and put it into a document, there are several ways to do it.

5.14.2.1. Tag method

This is the prefered method. You say:
  @weaver.rawif('html')
  '<B>raw html</B>'
  @weaver.enable()
What this does is disable the weaver except unless it is tagged 'html'. Then you raw-write the html, and finally re-enable the weaver. This works even when you have multiple weavers configured with filters, because the multiplexor and markup filters delegate these commands to their clients.

You add tags to a weaver with anything by saying

  @weaver.add_tag(something)
The built in weavers are tagged 'text', 'html' 'latex' and 'raw' as appropriate.

I plan to make raw writing a bit more convenient!

5.14.2.2. Cheat method 1

If you know you have a particular weaver set, you can just raw write to it like
  @weaver._write('<B>raw html</B>')
and that will go straight to the output device. It will look funny if you have a Latex weaver set! You can also say:
  @weaver.raw()
  '<B>raw html</B>'
  @weaver.translate()
to force the current weaver into raw mode and back to translation mode.

5.14.2.3. Cheat method 2

What you do is construct a raw weaver bound to the same sink device as your html weaver, and then set it to be the current weaver. This weaver thinks it is writing a raw data file, and copies all input straight to the sink device. So your HTML tags will go straight through to the output file, uninterpreted.

5.14.3. How can I use existing HTML as a source?

You can construct an _input filter_ that parses HTML, translating into to Interscript. The Interscript parser then processes this data, calling the current weaver with appropriate methods. If the weaver is an html weaver, it will then translate the calls back to html tags.

The advantage of this method, however, is that if the current weaver is, say, a Latex weaver, then the output will be the Latex equivalent of the original HTML. In other words, you will have translated the original HTML into Latex.

5.14.4. Isn't it hard to create an HTML filter?

No, it is very easy, because a class, html_input_filter, to do exactly this is standard in Interscript. This class uses the Python standard library module htmllib to parse the input.

5.14.5. Why are blank lines ignored?

They're not, they're converted to spaces, which is the HTML convention.

5.14.6. Why do I get multiple spaces in my document?

This is probably a bug in Interscript. In general, multiple spaces in input files are passed on to the typesetter 'as is'. HTML and Latex will reduce these to a single space automatically, but not all typesetters do this.

Generally, weavers write lines out as they came in, in other words, a word at the end of one line will be separated from a word starting the next line because the weaver writes out two lines, and the typesetter replaces them with a space.

However, there are some nasty cases. In the html weaver, the @begin_bold() and @end_bold() commands write out the <B> and </B> tags without any spaces before or after. But the text to be boldened is always a sequence of lines, so there will always be a newline before the </B> tag. So there's no easy way to bold a single letter of a word using the bold command in an Interscript input.

However, this is _not_ the case if you implement a filter, because the filter can write out the argument using the weaver method write(), rather than writeline().

5.14.7. The indentation of my programs is all wrong. Why?

Interscript does not allow tabs. You should never ever use tabs, they're an extremely stupid idea. Interscript replaces tabs by spaces automatically. This feature _cannot_ be disabled (without hackery), because it is implemented in the main control loop.

The variable g.tabwidth can be changed from the default value of 2 (which is suitable for publication) to some other value (such as 8) with a command like @g.tabwidth = 8.

You can, and sometimes must, generate tabs in code files. For example, tabs are required in 'make' files. You can do this in many ways, for example by implementing a front end for a tangler that replaces leading spaces, or perhaps \t sequence, by tabs.

5.14.8. How do I get existing code into Interscript?

Generally, commands turn off tangling. However, the command @include_code(filename) leaves the current tangler enabled. This causes the contents of the file to be typeset as code (even if it contains leading @ characters) _and_ included in the output for the tangler.

5.14.9. What if I just want to print it?

If you don't want to write code to any output file, just use a tangler with a null sink device. That device just throws away all the data written to it. For example:
Start C section to null sink[1] 1
     1: #line 128 "faq.ipk"
     2: @from interscript.tanglers.c import c_tangler
     3: @from interscript.drivers.sinks.null import null_sink
     4: @dummy = c_tangler(null_sink(), weaver)
     5: @select(dummy)
     6: /* These comments do not get written out */

5.14.10. How do I debug Interscript

This is a very hard question. With some vexation, I have decided to make Interscript robust rather than fragile. (Generally, this is a bad idea).

First, the standard weaver is an object of the class multiplexor. That object is a proxy which dispatches method calls to every weaver in a list of delegates, but only if the delegate supports that method.

This means that the default behaviour of a method is to do nothing, which seems appropriate for weavers. For example the plain text weaver cannot do bolding, so rather than implement a 'pass' method, you just don't bother to implement the method at all.

When the Python engine detects an unexpected exception, usually coming from Python script in your document, but sometimes from I/O failures, and sometimes from bugs, Interscript attempts to put debugging information into the current document and continue. So, for example, if you try to include a file that doesn't exist, you'll get a message in the current document.

There are two excuses for doing this. The first is that it allows the rest of the process to continue, in particular, it prevents errors in documentation constructions holding up code development.

This feature was crucial in developing Interscript itself for the following interesting reason: when I added a new feature to a weaver I would have to use the existing version of Interscript to tangle the code containing the implementation of that feature. If I tried to use that feature in the documentation, it would always crash, because the feature wasn't implemented in the old version.

So, I would build the new version, then start using the new constructions. The problem was that there would be bugs in the implementation. If I just fixed the bugs, I'd be trying to tangle the code using the old bugged version, which would crash. On the other hand, if I used an older backup version of the program, it would also crash because there was _no_ implementation of the construction.

Developing a program generator which generates itself is an excellent way to test the program generator -- but there it is sometimes difficult to recover from faults!

So, I decided that documentation errors shouldn't stop the system generating code, as, in my case, the fixes would be in the code I was trying to generate!

Instead, error messages are printed in the documentation if possible. One excuse for this is that such messages are easy to find, and where they occur is a good indication of the fault. Separate logs are much harder to use, and if the process is to continue in the presence of a documentation fault, there's no harm from corrupting an already corrupt document.

One downside of this features comes if you don't read your documents: you may not notice an error. Another downside is that a corrupt weaver may not be able to print the error into the document, and it may not be there to read.

I'd be very interested hearing reports of how this facility trips people up: I'm sure it will, but not sure of the details. (Putting errors after a corrupt '</HTML>' tag, for example, means some browsers will never show the error!)

Most diagnostics are also written to a log file and standard output.

NOTE: the details described herein are currently not properly implemented!

6. Implementation

Literate programmed by itself, of course!

6.1. Interscript Module

The top level interscript module.
Start data section to interscript.README[1] 1
     1: The literate programming tool Interscript
     2:  version '1.0a8'
     3:  has been unpacked here.
     4: It consists of two text files, and a directory:
     5: 
     6:   interscript.README (this file)
     7:   interscript.pth    (the Python package control file)
     8:   interscript/       (the interscript package directory)
     9: 
    10: Find the basic HTML documentation at
    11: 
    12:   interscript/doc/iscrp.html
    13: 
    14: Find the enhanced HTML documentation at
    15: 
    16:   interscript/doc/iscr_top.html
    17: 
    18: Find the text documentation at
    19: 
    20:   interscript/doc/iscr.txt
    21: 
    22: Find the latex2e documentation at
    23: 
    24:   interscript/doc/iscr.tex
    25: 
    26: Find the interscript home page at
    27: 
    28:   http://www.triode.net.au/~skaller/interscript
    29: 
End data section to interscript.README[1]
Start data section to interscript.pth[1] 1
     1: interscript
End data section to interscript.pth[1]
Start python section to interscript/__init__.py[1] 1 2 3
     1: #line 237 "iscr.pak"
     2: # interscript package
End python section to interscript/__init__.py[1]

6.1.1. Construct Global Frame

This frame is shared between all processes, and is initialised at module load time. It hooks crucial resources and identification information. The attributes of the global frame class are used as the globals() dictionary for executing user scripts.

[This is probably a bad idea, because it allows the user to change the attributes using the global declaration. On the other hand, it provides a method for sharing between processes.]

For some weird reason, the global frame is a python class, not a module, and not a class instance. It's not a plain module, because python termination is somewhat indeterminate, and it isn't an instance, because there's only ever one of them. Clients of the global frame keep a reference to it explicitly to prevent premature deletion by the python run time on program termination.

The global fram in turn keeps references to a set of important resources, so that they're not deleted prematurely either. I'm doing this because interscript __del__ methods are often used to do substantial work, and it's imperative that system resources are available until all dynamically created objects are destroyed.

Start python section to interscript/__init__.py[2] 1 2 3
     3: #line 268 "iscr.pak"
     4: class global_frame:
     5: 
     6:   from interscript.drivers.sinks.bufdisk import named_file_sink
     7:   from interscript.drivers.sinks.disk import simple_named_file_sink
     8:   from interscript.drivers.sinks.null import null_sink
     9:   from interscript.drivers.sinks.cache import cache_sink
    10: 
    11:   from interscript.drivers.sources.base import eoi, eof
    12:   from interscript.drivers.sources.disk import named_file_source
    13:   from interscript.drivers.sources.url import url_source
    14:   from interscript.drivers.sources.ftp import ftp_file_source
    15:   from interscript.drivers.sources.http import http_file_source
    16:   from interscript.drivers.sources.cache import cache_source
    17: 
    18:   from interscript.drivers.storage.memory import memory
    19: 
    20:   from interscript.weavers.text import plain_text_weaver
    21:   from interscript.weavers.latex import latex_weaver
    22:   from interscript.weavers.html import html_weaver
    23:   from interscript.weavers.raw import raw_weaver
    24:   from interscript.weavers.web import stacking_weaver
    25:   from interscript.weavers.auto import auto_weaver
    26:   from interscript.weavers.filter import markup_filter
    27:   from interscript.weavers.multiplexor import multiplexor
    28: 
    29:   from interscript.parsers.html import sgml_wrapper, html_filter
    30: 
    31:   from interscript.tanglers.c import c_tangler
    32:   from interscript.tanglers.cpp import cpp_tangler
    33:   from interscript.tanglers.java import java_tangler
    34:   from interscript.tanglers.perl import perl_tangler
    35:   from interscript.tanglers.data import data_tangler
    36:   from interscript.tanglers.python import python_tangler
    37:   from interscript.tanglers.null import null_tangler
    38:   from interscript.tanglers.doc import doc_tangler
    39:   from interscript.tanglers.tcl import tcl_tangler
    40: 
    41:   import sys
    42:   import os
    43:   import string
    44:   import re
    45:   import time
    46:   from interscript.utilities import commands
    47:   from interscript.core.sets import set
    48:   from interscript.core.stacks import stack
    49:   import interscript.core.protocols
    50:   protocol = interscript.core.protocols
    51:   import getoptions
    52: 
    53:   import __builtin__
    54:   __builtins__ = __builtin__
    55:   del __builtin__
    56: 
    57:   try:
    58:     import thread
    59:     #print 'thread available'
    60:   except:
    61:     #print 'thread NOT available'
    62:     pass
    63: 
End python section to interscript/__init__.py[2]

6.1.2. Set version

This is an experimental release only, intended as an act of advocacy and to solicit comments and support.

The code below is tricky to understand. There are three distinct sets of version information: data describing the version being generated, data describing the version doing the generating, and data describing the version which generated the generator.

Python script at the top of this file computes or fixes the version information for the version being generated, that information is bound into the source of the generated version.

When that version is itself used to generated yet another version the data bound into it by the previous generation describes the currently executing version, which is now the generator.

When the version being generated is yet again used to generate another version, the original data now describes the version that generated the version generating the new version.

In order to make it easy to add or change identification attributes, they're initialised to dummy values, in case the generating version doesn't has the same set of values. This is always the case when a new attribute is introduced: the attribute won't make it into the generating version until a second pass is executed and the version being generated itself becomes the generator.

Note that knowing the version that generated the executing version is important for bug tracking, since a problem may be due to a bug in the source for the version, or in the generator which processed it: a bug can persist even when the source is correct for many generations if it is not processed correctly by the generator. Bootstrapped code can be a real nightmare to debug.

Start python section to interscript/__init__.py[3] 1 2 3
    64: #line 366 "iscr.pak"
    65: # first a hack to help bootstrapping work
    66: # if any of the variable in the second section don't exist.
    67: # then the at least some value is set in the generated code.
    68: # Iterated bootstrapping should eventually fix the problem.
    69: 
    70:   buildno=0
    71:   version=0
    72:   hostname="unknown"
    73:   username="unknown"
    74:   buildtime="unknown"
    75:   generator_buildno=0
    76:   generator_hostname="unknown"
    77:   generator_username="unknown"
    78:   generator_version="unknown"
    79:   generator_buildtime="unknown"
    80: 
    81: # now the real data
    82:   buildno=1384
    83:   version='1.0a8'
    84:   hostname='ruby'
    85:   username='root'
    86:   buildtime='Mon Nov 30, 1998 at 08:56 AM (UTC)'
    87:   generator_buildno=1383
    88:   generator_hostname='ruby'
    89:   generator_username='root'
    90:   generator_version='1.0a8'
    91:   generator_buildtime='Mon Nov 30, 1998 at 05:02 AM (UTC)'
    92: 
    93: # now print the current version information
    94: # wrapped in try/except clause in case any of the variables didn't get set
    95: try:
    96:   print 'Interscript version',global_frame.version,
    97:   print 'build',global_frame.buildno
    98:   print 'Built by',global_frame.username,
    99:   print 'on',global_frame.hostname,
   100:   print 'at',global_frame.buildtime
   101:   print 'Generated by',global_frame.generator_version,
   102:   print 'buildno',global_frame.generator_buildno,
   103:   print 'host',global_frame.generator_hostname
   104:   print 'at',global_frame.buildtime
   105: except: pass
   106: 
   107: # This is a utility function that makes it easy to use interscript
   108: # givem options in a standard form. The arguments are a list as
   109: # would be entered on a unix or nt command line.
   110: # Mac (or Tkinter) users can create a GUI interface to set the options
   111: # and then call this function to run interscript.
   112: 
   113: def run_from_options(arguments):
   114:   from interscript.getframes import getoption_frames
   115:   from interscript.frames.processf import process_frame
   116:   process_options, master_options = getoption_frames(arguments)
   117:   process = process_frame(global_frame, process_options, master_options)
   118:   process.run()
   119:   del process
   120: 
End python section to interscript/__init__.py[3]

6.1.3. Listing of iscr.pak source

Here is the fully listings of the top level interscript source file, iscr.pak.
@# Interscript

@# set to 1/0 to enable/disable debugging
@debug_version = 0

@# --------------------------------------------------------------------
@# Get standard modules.
@import os
@import time
@from interscript.weavers.multiplexor import multiplexor

@# --------------------------------------------------------------------
@# Set the source version.
@gen_version = '1.0a8'

@# --------------------------------------------------------------------
@# Get the build number. Update it, but only in pass 0.
@try:
   gen_buildno = 0
   print 'Trying to open iscrbldn.dat, which contains the build number..'
   temp = open('iscrbldn.dat','r')
   line = temp.readline()
   line = line[:-1]
   gen_buildno = int(line)
   temp.close()
   print 'OK, got last build number',gen_buildno
 except:
   print "Couldn't open build number file. Must be a virgin build."
   pass

@if get_pass_frame().passno == 0:
   gen_buildno = gen_buildno + 1
   temp = open('iscrbldn.dat','w')
   temp.write(str(gen_buildno)+'\n')
   temp.close()
   del temp

@# --------------------------------------------------------------------
@# Try to get the hostname.
@# Should work on Unix, but don't worry if it fails.
@gen_hostname = 'unknown'
@try:
   print 'Tring to get host name with "hostname" command'
   f = os.popen('hostname','r')
   gen_hostname = string.strip(f.readline())
   f.close()
   print 'Got hostname',gen_hostname
 except:
   print "Couldn't get hostname, probably not Unix."
   pass

@# --------------------------------------------------------------------
@# Try to get the username.
@# Should work on Unix, but don't worry if it fails.
@gen_username = 'unknown'
@try:
   print 'Trying to get username from environment variable USERNAME'
   gen_username = os.environ['USERNAME']
   print 'Got username',gen_username
 except:
   print "Couldn't get username, probably not Unix."
   pass

@# --------------------------------------------------------------------
@# Print the current working directory.
@try:
   print 'Current Directory is',os.getcwd()
 except:
   pass

 #print 'Python Path is'
 #for path in sys.path:
 #  if path == '': print '  '+os.curdir+' ('+os.getcwd()+')'
 #  else: print ' ',path

@# --------------------------------------------------------------------
@# Get the build time, but only during pass 0.
@if get_pass_frame().passno == 0:
   get_master_frame().now = time.time()
@now = get_master_frame().now
@localtime = time.localtime(now)
@utctime = time.gmtime(now)
@lfmtime = time.strftime('%a %b %d, %Y at %I:%M %p (%Z)',localtime)
@ufmtime = time.strftime('%a %b %d, %Y at %I:%M %p (UTC)',utctime)

@# --------------------------------------------------------------------
@# Get the identification information from the currently
@# executing version of interscript.
@global_frame = get_process_frame().global_frame
@print 'This is Interscript',global_frame.version,'build',global_frame.buildno
@print 'built on',global_frame.generator_hostname,'by',global_frame.generator_username
@print
@print 'Running on',gen_hostname,'by',gen_username,'at',lfmtime
@print "and building Interscript",gen_version,'build',gen_buildno
@print

@author = 'John Max Skaller'
@title = 'Interscript'
@pfx = get_master_frame().weaver_directory

@# --------------------------------------------------------------------
@# Use the 'weavers' user option to decide whether to generate documentation
@# of not. Issue a warning to the user if no weaver is set.
@# Also, warn if '--weaver=' is used instead of '--weavers'

@weavers = []
@weaver_opt = []
@def print_weaver_help():
   print '  Please use "--weavers=[\'html\',\'latex\']" (etc) instead of "--weaver=".'
   print '  Note: you may need to escape the quotes (or quote the argument).'
   print '  The argument must be an evaluable python list of strings,'
   print '  or the string "all".'

@if get_master_frame().autoweave != []:
   print 'WARNING: Interscript source uses document defined weavers.'
   print_weaver_help()
 else:
   useropt = get_master_frame().useropt
   if not useropt.has_key('weavers'):
     print 'No Weaver in use.'
     print_weaver_help()
   else:
     weaver_opt  = useropt['weavers']
     try:
       weaver_opt = eval(weaver_opt)
     except:
       print ' ERROR: The argument "'+weaver_opt+'" to --weavers= must be a python list of strings.'
       print_weaver_help()

@if weaver_opt == 'all':
   weaver_opt = ['html','text','web','latex']

@if 'text' in weaver_opt:
   plain_text_output = named_file_sink(get_pass_frame(),pfx+'interscript/doc/iscr.txt')
   plain = plain_text_weaver(get_pass_frame(),plain_text_output,title=title,author=author)
   weavers.append(plain)
   print 'Generating text document.'

@if 'html' in weaver_opt:
   simple_html_output = named_file_sink(get_pass_frame(),pfx+'interscript/doc/iscrp.html')
   simple_html = html_weaver(get_pass_frame(),simple_html_output,title=title,author=author)
   weavers.append(simple_html)
   print 'Generating simple HTML document.'

@if 'web' in weaver_opt:
   stacked_html_output = named_file_sink(get_pass_frame(),pfx+'interscript/doc/iscrs.html')
   stacked_html = html_weaver(get_pass_frame(),stacked_html_output,title=title,author=author)
   stacked = stacking_weaver(stacked_html,'iscr_%s.html',(1,2,3,4,5,6,7,99),toc_depth=3)
   weavers.append(stacked)
   print 'Generating complex WEB/HTML document.'

@if 'latex' in weaver_opt:
   latex_output = named_file_sink(get_pass_frame(),pfx+'interscript/doc/iscr.tex')
   latex = latex_weaver(get_pass_frame(),latex_output,title=title,author=author, heading_level_offset=1)
   weavers.append(latex)
   print 'Generating latex document.'

@# terminate the if :-)
@multiplex = multiplexor(get_pass_frame(),weavers)
@emph = markup_filter(get_pass_frame(),"'([^']+)'",'begin_emphasize','end_emphasize',[multiplex])
@code = markup_filter(get_pass_frame(),'"([^"]+)','begin_code','end_code',[emph])
@master_weaver = code
@set_weaver(master_weaver)

@# --------------------------------------------------------------------
@# Begin construction of the new version of interscript.
@head(1,'Interscript Version')
@# --------------------------------------------------------------------
@# Print information identifying the version of intercsript which
@# is being generated, and the version which is generating it.
@try:
   weave('This document describes Interscript version '+gen_version)
   weave(' build '+str(gen_buildno))
   weave(' on '+gen_hostname+' ')
   weave(' by '+gen_username+'.')

   weave('It was generated by Interscript version '+global_frame.version+', build '+str(global_frame.buildno))
   weave(' on '+global_frame.hostname)
   weave(' by '+global_frame.username)
   weave(' at '+global_frame.buildtime+'.')
 except: pass

@# --------------------------------------------------------------------
@# Print various tables.
@p()
@print_contents(hlevel=2,maxlev=2)

@# --------------------------------------------------------------------
@# Print the introduction and design principles chapters.
@include_file('introduction.ipk')
@include_file('requirements.ipk')
@include_file('design.ipk')
@include_file('tutorial.pak')


@# --------------------------------------------------------------------
@# Generate the source code and program documentation.
@head(1,'Implementation')
Literate programmed by itself, of course!

@head(2,'Interscript Module')
The top level interscript module.
@select(data_output('interscript.README'))
The literate programming tool Interscript
@tangle(' version '+repr(gen_version))
 has been unpacked here.
It consists of two text files, and a directory:

  interscript.README (this file)
  interscript.pth    (the Python package control file)
  interscript/       (the interscript package directory)

Find the basic HTML documentation at

  interscript/doc/iscrp.html

Find the enhanced HTML documentation at

  interscript/doc/iscr_top.html

Find the text documentation at

  interscript/doc/iscr.txt

Find the latex2e documentation at

  interscript/doc/iscr.tex

Find the interscript home page at

  http://www.triode.net.au/~skaller/interscript

@select(data_output('interscript.pth'))
interscript
@iscr_pkg = python_output('interscript/__init__.py')
@select(iscr_pkg)
# interscript package
@if debug_version:
  # announce the version when the module is imported.
  tangle('print "Interscript Package: version '+gen_version+'",')
  tangle('print "build '+str(gen_buildno)+'"')

@head(3,'Construct Global Frame')
This frame is shared between all processes, and is initialised
at module load time. It hooks crucial resources and identification
information. The attributes of the global frame class are used
as the globals() dictionary for executing user scripts.
@p()
[This is probably a bad idea, because it allows the user to change
the attributes using the global declaration. On the other hand,
it provides a method for sharing between processes.]
@p()
For some weird reason, the global frame is a python class,
not a module, and not a class instance. It's not a plain module,
because python termination is somewhat indeterminate, and it isn't
an instance, because there's only ever one of them. Clients of the
global frame keep a reference to it explicitly to prevent
premature deletion by the python run time on program termination.
@p()
The global fram in turn keeps references to a set of important resources,
so that they're not deleted prematurely either.
I'm doing this because interscript __del__ methods are often used to
do substantial work, and it's imperative that system resources are
available until all dynamically created objects are destroyed.


@select(iscr_pkg)
class global_frame:

  from interscript.drivers.sinks.bufdisk import named_file_sink
  from interscript.drivers.sinks.disk import simple_named_file_sink
  from interscript.drivers.sinks.null import null_sink
  from interscript.drivers.sinks.cache import cache_sink

  from interscript.drivers.sources.base import eoi, eof
  from interscript.drivers.sources.disk import named_file_source
  from interscript.drivers.sources.url import url_source
  from interscript.drivers.sources.ftp import ftp_file_source
  from interscript.drivers.sources.http import http_file_source
  from interscript.drivers.sources.cache import cache_source

  from interscript.drivers.storage.memory import memory

  from interscript.weavers.text import plain_text_weaver
  from interscript.weavers.latex import latex_weaver
  from interscript.weavers.html import html_weaver
  from interscript.weavers.raw import raw_weaver
  from interscript.weavers.web import stacking_weaver
  from interscript.weavers.auto import auto_weaver
  from interscript.weavers.filter import markup_filter
  from interscript.weavers.multiplexor import multiplexor

  from interscript.parsers.html import sgml_wrapper, html_filter

  from interscript.tanglers.c import c_tangler
  from interscript.tanglers.cpp import cpp_tangler
  from interscript.tanglers.java import java_tangler
  from interscript.tanglers.perl import perl_tangler
  from interscript.tanglers.data import data_tangler
  from interscript.tanglers.python import python_tangler
  from interscript.tanglers.null import null_tangler
  from interscript.tanglers.doc import doc_tangler
  from interscript.tanglers.tcl import tcl_tangler

  import sys
  import os
  import string
  import re
  import time
  from interscript.utilities import commands
  from interscript.core.sets import set
  from interscript.core.stacks import stack
  import interscript.core.protocols
  protocol = interscript.core.protocols
  import getoptions

  import __builtin__
  __builtins__ = __builtin__
  del __builtin__

  try:
    import thread
    #print 'thread available'
  except:
    #print 'thread NOT available'
    pass

@head(3,'Set version')
This is an experimental release only,
intended as an act of advocacy and to solicit comments and support.
@p()
The code below is tricky to understand. There are three distinct
sets of version information: data describing the version
being generated, data describing the version doing the generating,
and data describing the version which generated the generator.
@p()
Python script at the top of this file computes or fixes
the version information for the version being generated,
that information is bound into the source of the generated
version.
@p()
When that version is itself used to generated yet another
version the data bound into it by the previous generation
describes the currently executing version, which is now
the generator.
@p()
When the version being generated is yet again used to generate
another version, the original data now describes the version
that generated the version generating the new version.
@p()
In order to make it easy to add or change identification attributes,
they're initialised to dummy values, in case the generating version
doesn't has the same set of values. This is always the case
when a new attribute is introduced: the attribute won't make it into
the generating version until a second pass is executed and the version
being generated itself becomes the generator.
@p()
Note that knowing the version that generated the executing version
is important for bug tracking, since a problem may be due to a bug
in the source for the version, or in the generator which processed
it: a bug can persist even when the source is correct for many generations
if it is not processed correctly by the generator.
Bootstrapped code can be a real nightmare to debug.

@select(iscr_pkg)
# first a hack to help bootstrapping work
# if any of the variable in the second section don't exist.
# then the at least some value is set in the generated code.
# Iterated bootstrapping should eventually fix the problem.

@tangle('  buildno=0')
@tangle('  version=0')
@tangle('  hostname="unknown"')
@tangle('  username="unknown"')
@tangle('  buildtime="unknown"')
@tangle('  generator_buildno=0')
@tangle('  generator_hostname="unknown"')
@tangle('  generator_username="unknown"')
@tangle('  generator_version="unknown"')
@tangle('  generator_buildtime="unknown"')

# now the real data
@tangle('  buildno='+str(gen_buildno))
@tangle('  version='+repr(gen_version))
@tangle('  hostname='+repr(gen_hostname))
@tangle('  username='+repr(gen_username))
@tangle('  buildtime='+repr(ufmtime))
@tangle('  generator_buildno='+str(global_frame.buildno))
@tangle('  generator_hostname='+repr(global_frame.hostname))
@tangle('  generator_username='+repr(global_frame.username))
@tangle('  generator_version='+repr(global_frame.version))
@tangle('  generator_buildtime='+repr(global_frame.buildtime))

# now print the current version information
# wrapped in try/except clause in case any of the variables didn't get set
try:
  print 'Interscript version',global_frame.version,
  print 'build',global_frame.buildno
  print 'Built by',global_frame.username,
  print 'on',global_frame.hostname,
  print 'at',global_frame.buildtime
  print 'Generated by',global_frame.generator_version,
  print 'buildno',global_frame.generator_buildno,
  print 'host',global_frame.generator_hostname
  print 'at',global_frame.buildtime
except: pass

# This is a utility function that makes it easy to use interscript
# givem options in a standard form. The arguments are a list as
# would be entered on a unix or nt command line.
# Mac (or Tkinter) users can create a GUI interface to set the options
# and then call this function to run interscript.

def run_from_options(arguments):
  from interscript.getframes import getoption_frames
  from interscript.frames.processf import process_frame
  process_options, master_options = getoption_frames(arguments)
  process = process_frame(global_frame, process_options, master_options)
  process.run()
  del process

@head(3,'Listing of iscr.pak source')
Here is the fully listings of the top level interscript source file, iscr.pak.
@display_code('iscr.pak')

@head(2,'Core Subpackage')
@select(python_output('interscript/core/__init__.py'))
# interscript core modules

@push_head(2)
@include_file('sets.ipk')     # sets
@include_file('stacks.ipk')   # stacks
@include_file('protocols.ipk')# protocols
@pop_head(2)

@push_head()
@include_file('drivers.ipk')  # drivers
@include_file('weavers.ipk') # weavers
@include_file('weaver_filters.ipk') # weaver filters
@include_file('tanglers.ipk')  # tanglers
@include_file('tokenizers.ipk')  # tokenisers
@include_file('parsers.ipk') # parsers
@include_file('felix.pak') # felix category stuff
@include_file('frames.ipk') # architecture
@include_file('options.ipk') # generic option processing
@include_file('interscript_options.ipk') # interscript option processing
@pop_head()


@head(2,'Utility Modules')
@select(python_output('interscript/utilities/__init__.py'))
# interscript utilities

@push_head(2)
@include_file('compilers.ipk')
@include_file('diff.ipk')
@include_file('commands.ipk')
@pop_head(2)


@head(2,'Application and tool directory')
This is where the interscript mainline and any other shell commands go.
@select(python_output('interscript/bin/__init__.py'))
# dummy interscript.bin

@head(3,'Stand alone unix/nt mainline')
Command line stub.

@select(python_output('interscript/bin/iscr.py'))
#!/usr/bin/env python
import sys
args = sys.argv[1:]
if len(args)>0 and args[0]=='--test':
  print 'Interscript test mode, loading interscript from current directory'
  if sys.path[0]!='':
    sys.path = ['']+ sys.path
  args = args[1:]
import interscript
interscript.run_from_options(args)

@head(3,'Windows launcher')
A batch file to launch interscript.
You will need to edit the file!
@select(python_output('interscript/bin/iscr.bat'))
python iscr.py %1 %2 %3 %4 %5 %6 %7 %8 %9

@p()
There's a better way in Windows NT!
(SOMEONE CHECK THIS!)
Using the 'ASSOC' and 'FTYPE' commands,
you can specify the type of .pak files, and what to do with them:
@begin_displayed_code()
  ASSOC .pak=Interscript.Master.Document
  FTYPE Interscript.Master.Document=D:\interscript\interscript\bin\iscr.py %*
@end_displayed_code()
and then you can just type the name of the interscript
file with options to process it. This should already
have been done for python .py files if you ran a recent
version of the Windows installer. If you also do:
@begin_displayed_code()
  set PATHEXT=.pak;%PATHEXT%
@end_displayed_code()
you won't need to type the extension. To make this persistent,
you can use the Control Panel System/Environment editor.

@head(2,'Test package')
@select(python_output('interscript/tests/__init__.py'))
# dummy interscript/test

@head(1,'Appendices')
@# --------------------------------------------------------------------
@# Print the table of identifiers and class reference
@print_identifier_cross_reference(hlevel=2)
@print_class_reference(hlevel=2)
@print_file_list(hlevel=2)
@print_source_list(hlevel=2)
@print_include_list(hlevel=2)
@push_head()
@include_file('bugs.ipk')
@include_file('installation.ipk')
@pop_head()

6.2. Core Subpackage

Start python section to interscript/core/__init__.py[1] 1
     1: #line 428 "iscr.pak"
     2: # interscript core modules
     3: 

6.2.1. Sets

This class implements mathematical sets using a dictionary.
Start python section to interscript/core/sets.py[1] 1
     1: #line 6 "sets.ipk"
     2: class set:
     3:   __class_protocols__= ['sequence','mutable','set']
     4:   def __init__(self,*args):
     5:     self.s = {}
     6:     for e in args: self.s[e]=None
     7: 
     8:   # set contains element
     9:   def contains(self,e):
    10:     return self.s.has_key(e)
    11: 
    12:   # we're an improper subset of the rhs
    13:   def le(self,rhs):
    14:     for e in self.s.keys():
    15:       if e not in rhs: return 0
    16:     return 1
    17: 
    18:   # the rhs is an improper subset of us
    19:   def ge(self,rhs):
    20:     for e in rhs:
    21:       if not self.s.has_key(e): return 0
    22:     return 1
    23: 
    24:   def eq(self,rhs):
    25:     return self.le(rhs) and self.ge(rhs)
    26: 
    27:   def ne(self,rhs):
    28:     for e in rhs:
    29:       if not self.s.has_key(e): return 1
    30:     for e in self.s.keys():
    31:       if not e in rhs: return 1
    32:     return 0
    33: 
    34:   def gt(self,rhs):
    35:     return self.ne(rhs) and self.ge(rhs)
    36: 
    37:   def lt(self,rhs):
    38:     return self.ne(rhs) and self.le(rhs)
    39: 
    40:   def min(self):
    41:     return min(self.s.keys())
    42: 
    43:   def max(self):
    44:     return max(self.s.keys())
    45: 
    46:   def index(self,e):
    47:     return self.s.keys().index(e)
    48: 
    49:   def count(self,e):
    50:     return self.s.has_key(e)
    51: 
    52:   # ensure set contains element; no error if already in set
    53:   def insert(self,e):
    54:     self.s[e]=None
    55: 
    56:   # remove element, must be in set or error
    57:   def remove(self,e):
    58:     del self.s[e]
    59: 
    60:   # remove element if in set
    61:   def excise(self,e):
    62:     if self.s.has_key(e): del self.s[e]
    63: 
    64:   # append all the elements in the sequence
    65:   def append_sequence(self,seq):
    66:     for e in seq: self.s[e]=None
    67: 
    68:   # get list of elements
    69:   def list(self):
    70:     return self.s.keys()
    71: 
    72:   # get tuple of elements
    73:   def tuple(self):
    74:     return tuple(self.s.keys())
    75: 
    76:   # get dictionary of elements
    77:   def dict(self):
    78:     return self.s.copy()
    79: 
    80:   # return a copy of this set
    81:   def copy(self):
    82:     s = set()
    83:     s.s = self.s.copy()
    84:     return s
    85: 
    86:   # repr is set(e1, e2, e3) etc
    87:   def __repr__(self):
    88:     keys = self.s.keys()
    89:     p = 'set('
    90:     if keys: p = p + repr(keys[0])
    91:     for key in keys[1:]: p = p + ', ' + repr(key)
    92:     p = p + ')'
    93:     return p
    94: 
    95:   # 0 if empty, 1 otherwise
    96:   def __nonzero__(self):
    97:     return len(s)!=0
    98: 
    99:   # lexicographical comparison!
   100:   # a < b does NOT mean a is a subset of b!!!
   101: 
   102:   def __cmp__(self,other):
   103:     right = set()
   104:     for e in other: right.insert(e)
   105:     k1 = self.s.keys()
   106:     k1.sort()
   107:     k2 = right.s.keys()
   108:     k2.sort()
   109:     return cmp(k1,k2)
   110: 
   111:   def __len__(self):
   112:     return len(self.s)
   113: 
   114:   def __getitem__(self,index):
   115:     return self.s.keys()[index]
   116: 
   117:   def __delitem__(self,index):
   118:     k = self.s.keys()[index]
   119:     del self.s[k]
   120: 
   121:   def __getslice__(self,i,j):
   122:     return apply(set,tuple(self.s.keys()[i:j]))
   123: 
   124:   def __and__(self,right):
   125:     s = set()
   126:     for e in self.s.keys():
   127:       if e in right: s.insert(e)
   128:     return s
   129: 
   130:   def __or__(self,right):
   131:     s = set()
   132:     s.s = self.s.copy()
   133:     for e in right: s.s[e]=None
   134:     return s
   135: 
   136:   def __xor__(self,right):
   137:     s = set()
   138:     for e in right: s.insert(e)
   139:     for e in self.s.keys():
   140:       if s.s.has_key(e): del s.s[e]
   141:       else: s.s[e]=None
   142:     return s
   143: 
   144:   def __add__(self,right):
   145:     return self.__or__(right)
   146: 
   147:   def __sub__(self,right):
   148:     s = set()
   149:     for e in self.s.keys():
   150:       if e not in right: s.insert(e)
   151:     return s
   152: 

6.2.1.1. Test source

A simple test of sets.
Start python section to interscript/tests/test_sets.py[1] 1
     1: #line 163 "sets.ipk"
     2: import interscript.core.sets
     3: set = interscript.core.sets.set
     4: 
     5: s1 = set(1,2,3,1,2)
     6: s2 = set(10,20,30,3)
     7: print 's1=',s1
     8: print 's2=',s2
     9: print 's1|s2=',s1 | s2
    10: print 's1&s2=',s1 & s2
    11: print 's1^s2=',s1 ^ s2
    12: print 's1+s2=',s1 + s2
    13: print 's1-s2=',s1 - s2
    14: print 's1==s1=',s1 == s1.copy()
    15: assert (s1 ^ s2) == ((s1 | s2) - (s1 & s2))
    16: print 's1[:]=',s1[:]
    17: print 's1[1:-1]=',s1[1:-1]
    18: 
    19: print 's1==s2=',s1 == s2
    20: print 's1<s2=',s1 < s2
    21: print 's1>s2=',s1 > s2
    22: 
    23: print 's1.le(s2)=',s1.le(s2)
    24: print 's1.lt(s2)=',s1.lt(s2)
    25: print 's1.ge(s2)=',s1.ge(s2)
    26: print 's1.gt(s2)=',s1.gt(s2)
    27: 
    28: s1 = set(1,2,3,4,5,6,7,8,9)
    29: s2 = set(1,3,5,7,9)
    30: print 's1=',s1
    31: print 's2=',s2
    32: print 's1.le(s2)=',s1.le(s2)
    33: print 's1.lt(s2)=',s1.lt(s2)
    34: print 's1.ge(s2)=',s1.ge(s2)
    35: print 's1.gt(s2)=',s1.gt(s2)
    36: 

6.2.1.2. Test output

The result of running the test.
Start output section of "/usr/local/bin/python" interscript/tests/test_sets.py
     1: Interscript version 1.0a8 build 1378
     2: Built by root on ruby at Sun Nov 29, 1998 at 08:48 PM (UTC)
     3: Generated by 1.0a8 buildno 1376 host ruby
     4: at Sun Nov 29, 1998 at 08:48 PM (UTC)
     5: s1= set(3, 2, 1)
     6: s2= set(30, 20, 3, 10)
     7: s1|s2= set(10, 30, 20, 3, 2, 1)
     8: s1&s2= set(3)
     9: s1^s2= set(30, 20, 10, 1, 2)
    10: s1+s2= set(10, 30, 20, 3, 2, 1)
    11: s1-s2= set(2, 1)
    12: s1==s1= 1
    13: s1[:]= set(3, 2, 1)
    14: s1[1:-1]= set(2)
    15: s1==s2= 0
    16: s1<s2= 1
    17: s1>s2= 0
    18: s1.le(s2)= 0
    19: s1.lt(s2)= 0
    20: s1.ge(s2)= 0
    21: s1.gt(s2)= 0
    22: s1= set(9, 8, 7, 6, 5, 4, 3, 2, 1)
    23: s2= set(7, 5, 3, 9, 1)
    24: s1.le(s2)= 0
    25: s1.lt(s2)= 0
    26: s1.ge(s2)= 1
    27: s1.gt(s2)= 1
End output section to "/usr/local/bin/python" interscript/tests/test_sets.py

6.2.2. Stack

Simple stack class.
Start python section to interscript/core/stacks.py[1] 1
     1: #line 5 "stacks.ipk"
     2: class stack:
     3:   __class_protocols__ = ['sequence','mutable']
     4:   def __init__(self, *args): self.s = list(args)
     5:   def __del__(self):
     6:     # unbind in FILO order!
     7:     while len(self.s): del self.s[-1]
     8: 
     9:   def pop(self):
    10:     tmp = self.s[-1]
    11:     del self.s[-1]
    12:     return tmp
    13:   def push(self,x): self.s.append(x)
    14:   def append(self,x): self.s.append(x)
    15:   def __len__(self): return len(self.s)
    16:   def __nonzero__(self): return len(self.s)!=0
    17:   def __getitem__(self,index): return self.s[index]
    18:   def __setitem__(self,index,value): self.s[index]=value
    19:   def __delitem__(self,index): del self.s[index]
    20:   def __getslice__(self,i,j): return self.s[i:j]
    21:   def __setslice__(self,i,j,seq): self.s[i:j]=seq
    22:   def __delslice__(self,i,j): del self.s[i:j]
    23:   def __mul__(self,i): return apply(stack, tuple(self.s * i))
    24:   def __rmul__(self,i): return apply(stack, tuple(self.s * i))
    25:   def __add__(self,s): return apply(stack, tuple(self.s + s.s))
    26:   def __cmp__(self, other): return cmp(self.s,other.s)
    27:   def __repr__(self):
    28:     s = 'stack('
    29:     if self.s: s = s + repr(self.s[0])
    30:     for i in self.s[1:]: s = s + ', '+repr(i)
    31:     return s+')'
    32: 
    33:   def __setattr__(self,attr,value):
    34:     if attr == 'top':
    35:       self.s[-1]=value
    36:     else:
    37:       self.__dict__[attr]=value
    38: 
    39:   def __getattr__(self,attr):
    40:     if attr=='top':
    41:       return self.s[-1]
    42:     else:
    43:       raise AttributeError,attr
    44: 
    45:   def __delattr__(self,attr):
    46:     if attr=='top':
    47:       del self.s[-1]
    48:     else:
    49:       raise AttributeError,attr
    50: 
    51:   def copy(self): return apply(stack,tuple(self.s))
    52:   def count(self, item): return self.s.count(item)
    53:   def index(self, item): return self.s.index(item)
    54:   def sort(self, order=None):
    55:     if order == None:
    56:       self.s.sort()
    57:     else:
    58:       self.s.sort(order)
    59:   def insert(self,index,item): self.s.insert(index,item)
    60:   def remove(self,item): self.s.remove(item)
    61:   def reverse(self): self.s.reverse()
    62: 

6.2.3. protocol module

This modules implements protocols. Install in site-packages.

6.2.3.1. Standard Protocol Rules

Every object o has the protocol type(o). Every instance of class X, has protocol X. An object has protocol p, if p is a class protocol of its class, or any direct or indirect base of that class.

An object o of type t has protcol p if add_type_proto(t,p) has_been called. An object o which is an instance of class c, has protocol p if add_class_protol(b,p) has been called, where b is c or one of its direct or indirect bases.

An object o has protocol p if add_obj_proto(o,p) has been called and returned normally.

It is not possible to attach protocols to an object using add_obj_proto unless the object either has a readable attribute '__protocols__' which is a mutable sequence, or will set an attribute '__protocols__' (which can subsequently be read).

Please note the crucial distinction between the protocols of a class object c, which include c.__protocols__, and the protocols of instances of c, which include c.__class_protocols__. A class object is an object in its own right and obeys protocols distinct from its instances.

Similarly, note that a type object has different protocols than the instances of that type.

6.2.3.2. Source

Start python section to interscript/core/protocols.py[1] 1
     1: #line 38 "protocols.ipk"
     2: #-------------- protocol.py ---------------------------
     3: import types
     4: 
     5: type_protocols = {
     6:   types.NoneType : [],
     7:   types.TypeType : ['type','immutable'],
     8:   types.IntType : ['integer','number','immutable'],
     9:   types.LongType : ['integer','number','immutable'],
    10:   types.FloatType : ['number','immutable'],
    11:   types.StringType : ['string','immutable','filename','url'],
    12:   types.TupleType : ['sequence','immutable'],
    13:   types.ListType : ['sequence','mutable'],
    14:   types.DictType : ['map','mutable'],
    15:   types.FunctionType : ['function'],
    16:   types.LambdaType : ['function'],
    17:   types.CodeType : ['code'],
    18:   types.ClassType : ['class'],
    19:   types.InstanceType : ['instance'],
    20:   types.MethodType : ['function'],
    21:   types.BuiltinFunctionType: ['function'],
    22:   types.ModuleType: ['module'],
    23:   types.FileType: ['file'],
    24:   types.XRangeType: ['range'],
    25:   types.TracebackType: ['traceback'],
    26:   types.FrameType: ['frame'],
    27:   types.SliceType: ['slice'],
    28:   types.EllipsisType: ['ellipsis']
    29: }
    30: try:
    31:   type_protocols[types.ComplexType]='number'
    32: except NameError:
    33:   pass
    34: 
    35: class provides_attr:
    36:   def __init__(self,name):
    37:     self.name = name
    38: 
    39: def isclass(obj):
    40:   return type(obj) is types.ClassType
    41: 
    42: def isinstancetype(obj):
    43:   return type(obj) is types.InstanceType
    44: 
    45: def classof(obj):
    46:   if isinstancetype(obj):
    47:     return obj.__class__
    48:   else:
    49:     return None
    50: 
    51: def add_obj_proto(object,protocol):
    52:   if hasattr(object,'__protocols__'):
    53:     getattr(object,'__protocols__').append(protocol)
    54:   else:
    55:     setattr(object,'__protocols__',[protocol])
    56: 
    57: def add_obj_protos(object,protocols):
    58:   for p in protocols: add_obj_protos(object,p)
    59: 
    60: def add_class_proto(cls,protocol):
    61:   if hasattr(cls,'__class_protocols__'):
    62:     getattr(cls,'__class_protocols__').append(protocol)
    63:   else:
    64:     setattr(cls,'__class_protocols__',[protocol])
    65: 
    66: def add_class_protos(object,protocols):
    67:   for p in protocols: add_class_protos(object,p)
    68: 
    69: def add_type_protos(object,protocols):
    70:   for p in protocols: add_type_protos(object,p)
    71: 
    72: def add_type_proto(typ, protocol):
    73:   if type_protocols.has_key(typ):
    74:     type_protocols[typ].append(protocol)
    75:   else:
    76:     type_protocols[typ] = [protocol]
    77: 
    78: def has_class_proto(cls,protocol):
    79:   if cls is protocol: return 1
    80:   if hasattr(cls,'__class_protocols__'):
    81:     if protocol in getattr(cls,'__class_protocols__'): return 1
    82:   return 0
    83: 
    84: def has_type_proto(object,protocol):
    85:   typ = type(object)
    86:   if typ is protocol: return 1
    87:   if type_protocols.has_key(typ):
    88:     if protocol in type_protocols[typ]: return 1
    89:   return 0
    90: 
    91: def has_protocol(object,protocol):
    92:   if hasattr(object,'__protocols__'):
    93:     if protocol in getattr(object,'__protocols__'): return 1
    94: 
    95:   cls = classof(object)
    96:   if cls:
    97:     v = has_class_proto(cls, protocol)
    98:     if v: return 1
    99:     for base in cls.__bases__:
   100:       if has_class_proto(base,protocol): return 1
   101:   if has_type_proto(object,protocol): return 1
   102:   if type(protocol) is types.InstanceType:
   103:     if protocol.__class__ is provides_attr:
   104:       if hasattr(object,protocol.name): return 1
   105:   return 0
   106: 
   107: def has_protocols(object,protocols):
   108:   for p in protocols:
   109:     if not has_protocol(object,p): return 0
   110:   return 1
   111: 
End python section to interscript/core/protocols.py[1]

6.2.3.3. Test

Start python section to interscript/tests/test_protocol.py[1] 1
     1: #line 151 "protocols.ipk"
     2: #-------------- test_protocol.py ---------------------------
     3: import types
     4: import interscript.core.protocols
     5: protocol = interscript.core.protocols
     6: assert protocol.has_protocol(types.IntType,types.TypeType)
     7: assert protocol.has_protocol(1,types.IntType)
     8: assert protocol.has_protocol(1,'integer')
     9: 
    10: class B:
    11:   def __init__(self):
    12:     self.fred = 1
    13: 
    14: class D(B): pass
    15: d = D()
    16: 
    17: protocol.add_class_proto(B,'B')
    18: protocol.add_class_proto(D,'D')
    19: protocol.add_obj_proto(d,'d')
    20: protocol.add_type_proto(types.InstanceType,'my instance')
    21: 
    22: assert protocol.has_protocol(d,'B')
    23: assert protocol.has_protocol(d,'D')
    24: assert protocol.has_protocol(d,'d')
    25: assert protocol.has_protocol(d,'instance')
    26: assert protocol.has_protocol(d,'my instance')
    27: assert protocol.has_protocol(d,protocol.provides_attr('fred'))
    28: 
End python section to interscript/tests/test_protocol.py[1]
Start output section of "/usr/local/bin/python" interscript/tests/test_protocol.py
     1: Interscript version 1.0a8 build 1378
     2: Built by root on ruby at Sun Nov 29, 1998 at 08:48 PM (UTC)
     3: Generated by 1.0a8 buildno 1376 host ruby
     4: at Sun Nov 29, 1998 at 08:48 PM (UTC)
End output section to "/usr/local/bin/python" interscript/tests/test_protocol.py
     4: #line 435 "iscr.pak"
     5: 

6.3. Drivers Subpackage

There are three classes of drivers: source drivers, sink drivers, and storage drivers.
Start python section to interscript/drivers/__init__.py[1] 1
     1: #line 6 "drivers.ipk"
     2: # drivers package

6.3.1. Source Drivers Subpackage

This subpackage contains components to read lines from various sources. Note that an interscript line is not terminated by a newline, and it never ends in spaces. Control characters are not permitted in lines.

It should be noted that it is the responsibility of the driver to translate the underlying file into a source of whole lines according to these requirements.

Source drivers supply the following standard python methods:

read(size=None)
Return the whole file as a single string with lines terminated by newline characters. Whitespace is stripped from the end of each line before the newline is appended. At least one line will be returned, and there will always be a newline at the end of the string. The optional size argument is ignored. This method throws an eof exception if there are no lines in the file. An exception is thrown if the file is has been closed.
readline(sizehint=None)
Read a up to the end of a line, return the read data with a newline appended. Whitespace is stripped from the end of the line before the newline is appended. This method throws an eof exception if there are no lines in the file. An exception is thrown if the file is has been closed.
readlines(sizehint=None)
Read to the end of the file, returning a list of lines, each of which has had trailing whitespace stripped and a newline character appended. An empty list is returned if there are no lines in the file. An exception is thrown if the file is has been closed.
flush()
May flush input device.

In addition, the following methods are provided:

raw_readline()
Return next line. The line has trailing whitespace stripped, no newline character is appended. Throws an exception if there are no lines left in the file.
raw_readlines()
Return a list of all lines to the end of the file, with trailing whitespace stripped and no newlines added. Returns an empty list if there are no lines in the file. This routine is intended to be supplied by derivers of subclasses of the standard base.

6.3.1.1. Source Drivers Module

The source drivers module contains the class for the exception to be thrown when a source resource cannot be acquired, usually a file which cannot be opened because it doesn't exist.
Start python section to interscript/drivers/sources/__init__.py[1] 1
     1: #line 64 "source_drivers.ipk"
     2: #--- source package ---
     3: class source_open_error(Exception): pass
     4: 
End python section to interscript/drivers/sources/__init__.py[1]

6.3.1.2. Source Base

6.3.1.2.1. End Exceptions
A class to be used as an end of file exception, and a class to be used as an end of information exception. The distinction is: any input driver (source) file could throw an eof. An eoi is thrown by a higher level routine to indicate end of logical input frame.

These exceptions, when thrown, do not represent an error, they're just used to facilitate alternate block exits.

Start python section to interscript/drivers/sources/base.py[1] 1 2
     1: #line 80 "source_drivers.ipk"
     2: class eof(Exception): pass
     3: class eoi(Exception): pass
     4: 
End python section to interscript/drivers/sources/base.py[1]
6.3.1.2.2. Source Base Class
Interscript source drivers provide all the facilities required of standard python file objects opened for input.
Start python section to interscript/drivers/sources/base.py[2] 1 2
     5: #line 88 "source_drivers.ipk"
     6: #---------------------------------------------------------
     7: # source base
     8: import string
     9: class source:
    10:   __class_protocols__ = ['file','source']
    11:   def __init__(self, **kwds):
    12:     self.lines_read = 0
    13:     self.mode = 'r'
    14:     for k in kwds.keys():
    15:       self.__dict__[k]=kwds[k]
    16:     self.closed = 1
    17: 
    18:   def get_source_name(self):
    19:     return self.name
    20: 
    21:   def get_lines_read(self):
    22:     return self.lines_read
    23: 
    24:   def raw_readlines(self):
    25:     if self.closed: raise eof
    26:     lines = []
    27:     try:
    28:       while 1: lines.append(self.raw_readline())
    29:     except eof:
    30:       pass
    31:     return lines
    32: 
    33:   def readline(self, sizehint=None):
    34:     return self.raw_readline()+'\n'
    35: 
    36:   def read(self, sizehint=None):
    37:     return string.join(self.raw_readlines())+'\n'
    38: 
    39:   def readlines(self, sizehint=None):
    40:     x = []
    41:     for line in self.raw_readlines():
    42:       x.append(line+'\n')
    43:     return x
    44: 
    45:   def isatty(self):
    46:     return 0
    47: 
    48:   def close(self):
    49:     if not self.closed:
    50:       self._close()
    51:       self.closed = 1
    52: 
    53:   def _close(self): pass
    54:   def flush(self): pass
    55:   def __del__(self): self.close()
    56: 
    57: class file_source(source):
    58:   def __init__(self, *args, **kwds):
    59:     apply(source.__init__, (self,)+args, kwds)
    60: 
    61:   def _close(self):
    62:     self.file.close()
    63: 
    64:   def raw_readline(self):
    65:     if self.closed: raise eof
    66:     line = self.file.readline()
    67:     if len(line)==0: raise eof
    68:     self.lines_read = self.lines_read + 1
    69:     return string.rstrip(line)
    70: 
    71:   def get_filename(self):
    72:     return self.name
    73: 
End python section to interscript/drivers/sources/base.py[2]

6.3.1.3. Disk File Input

This driver uses a filename in your local operating system's convention.
Start python section to interscript/drivers/sources/disk.py[1] 1
     1: #line 162 "source_drivers.ipk"
     2: #---------------------------------------------------------
     3: # gets input from a named file
     4: from interscript.drivers.sources import source_open_error
     5: from interscript.drivers.sources.base import file_source
     6: from interscript.drivers.sources.base import eof
     7: import string
     8: import os
     9: 
    10: # this routine is a utility which loads data directly
    11: # from an operating system level file
    12: 
    13: def loadfile(filename):
    14:    "return a list of lines, trailing whitespace removed"
    15:    try:
    16:      f = open(filename)
    17:    except:
    18:      raise source_open_error,filename
    19:    data = f.readlines()
    20:    f.close()
    21:    for i in range(len(data)):
    22:      data[i]=string.rstrip(data[i])
    23:    return data
    24: 
    25: def parse_source_filename(filename, prefix):
    26:   pathlist = string.split(filename,'/')
    27:   if prefix == '':
    28:     prefix = os.getcwd()
    29:     if prefix[-1] != os.sep:
    30:       prefix = prefix + os.sep
    31:   directory = prefix + string.join(pathlist[:-1],os.sep)
    32:   if directory[-1] != os.sep:
    33:     directory = directory + os.sep
    34:   basename = pathlist[-1]
    35:   full_filename = directory + basename
    36:   return pathlist, basename, directory, full_filename
    37: 
    38: class named_file_source(file_source):
    39:   def __init__(self,pass_frame,filename, prefix='', **kwds):
    40:     apply(file_source.__init__,(self,), kwds)
    41:     pass_frame.iflist.append(filename)
    42:     self.name = filename
    43: 
    44:     pathlist, self.basename, self.directory, self.filename =\
    45:       parse_source_filename(filename, prefix)
    46: 
    47:     try:
    48:       self.file = open(self.filename,'r')
    49:       self.closed = 0
    50:     except:
    51:       raise source_open_error,filename
    52: 
    53: 
End python section to interscript/drivers/sources/disk.py[1]

6.3.1.4. URL input

This driver accepts a URL. Since it uses the Python urllib library, it has the same limitations. From the manual:
  • Currently, only the following protocols are supported: HTTP, (versions 0.9 and 1.0), Gopher (but not Gopher-+), FTP, and local files.
  • The caching feature of urlretrieve() has been disabled until I find the time to hack proper processing of Expiration time headers.
  • There should be a function to query whether a particular URL is in the cache.
  • For backward compatibility, if a URL appears to point to a local file but the file can't be opened, the URL is re-interpreted using the FTP protocol. This can sometimes cause confusing error messages.
  • The urlopen() and urlretrieve() functions can cause arbitrarily long delays while waiting for a network connection to be set up. This means that it is difficult to build an interactive web client using these functions without using threads.
  • The data returned by urlopen() or urlretrieve() is the raw data returned by the server. This may be binary data (e.g. an image), plain text or (for example) HTML. The HTTP protocol provides type information in the reply header, which can be inspected by looking at the Content-type header. For the Gopher protocol, type information is encoded in the URL; there is currently no easy way to extract it. If the returned data is HTML, you can use the module htmllib to parse it.
  • Although the urllib module contains (undocumented) routines to parse and unparse URL strings, the recommended interface for URL manipulation is in module urlparse.
Start python section to interscript/drivers/sources/url.py[1] 1
     1: #line 260 "source_drivers.ipk"
     2: # gets input from a URL
     3: from interscript.drivers.sources.base import file_source
     4: from interscript.drivers.sources.base import eof
     5: import string
     6: class url_source(file_source):
     7:   def __init__(self,filename,**kwds):
     8:     apply(file_source.__init__,(self,), kwds)
     9:     self.name = filename
    10:     self.file = urllib.urlopen(filename)
    11:     self.closed = 0
    12: 
    13: 
End python section to interscript/drivers/sources/url.py[1]

6.3.1.5. FTP input

This object fetches a file by ftp on construction. The file is then read from the local copy. The host name and remote filename arguments are mandatory. Optional arguments given by keywords are:
port
The port number of the host to use for FTP. Defaults to 21.
user
User name. Defaults to 'anonymous'.
account
User's account name.
password
User's password. If user is anonymous, the default password is `realuser@host' where realuser is the real user name (glanced from the `LOGNAME' or `USER' environment variable) and host is the hostname as returned by socket.gethostname().
remote_directory
The directory to 'cd' to to get the nominated file. If not specified, no 'cd' is done and the file is expected in the FTP root.
local_filename
The name of the file to which the download should be written. Defaults to 'remote_filename'.
refresh_interval
The is the number of days old the local file can be before ftp is done. The default is 28. If this value is set to 0, a download is always done. If the value is set to -1, a download is done only if the local file does not exist; delete the file to force another download.
An exception is thrown if there is no local file, and the attempt to ftp the remote file fails. No exception is thrown if the local file exists, even if it is out of date.
Start python section to interscript/drivers/sources/ftp.py[1] 1
     1: #line 317 "source_drivers.ipk"
     2: #---------------------------------------------------------
     3: # gets input by FTP
     4: import ftplib
     5: import time
     6: import os
     7: from interscript.drivers.sources.base import file_source
     8: from interscript.drivers.sources.base import eof
     9: import string
    10: 
    11: class ftp_file_source(file_source):
    12:   def __init__(self,host,remote_filename,**kwds):
    13:     apply(file_source.__init__, (self,), kwds)
    14:     self.name = remote_filename
    15:     self.remote_filename = remote_filename
    16:     self.host = host
    17:     self.g = g
    18:     for k in kwds.keys():
    19:       self.__dict__[k]=kwds[k]
    20:     if not hasattr(self,'local_filename'):
    21:       self.local_filename = self.remote_filename
    22:     self.os = os
    23:     self.fetch()
    24:     self.file = open(self.local_filename,'r')
    25:     self.closed = 0
    26: 
    27:   def transfer(self,data):
    28:     self.file.write(data+'\n')
    29: 
    30:   def fetch(self):
    31:     if not hasattr(self,'refresh_interval'):
    32:       self.refresh_interval = 28
    33:     if self.refresh_interval < 0: self.refresh_interval = 100000
    34:     self.local_file_exists = 1
    35:     try:
    36:       f = open(self.local_filename)
    37:       f.close()
    38:       if verbosity>=4: print 'local file',self.local_filename,'exists'
    39:     except:
    40:       if verbosity>=4: print 'local file',self.local_filename,'does NOT exist'
    41:       self.local_file_exists = 0
    42: 
    43:     if self.local_file_exists:
    44:       self.local_file_modify_time = os.stat(self.local_filename)[stat.ST_MTIME]
    45:       now = time.time()
    46:       age = (now - self.local_file_modify_time)/ (24 * 60 * 60)
    47:       download = age > self.refresh_interval
    48:     else:
    49:       download = 1
    50: 
    51:     if hasattr(self.g,'download'):
    52:       if self.g.download == 'always': download = 1
    53:       if self.g.download == 'never': download = 0
    54: 
    55:     if download:
    56:       try:
    57:         if verbosity>=2: print 'downloading',self.remote_filename
    58:         # create FTP object
    59:         ftp = ftplib.FTP()
    60: 
    61:         # connect to server
    62:         if hasattr(self,'port'):
    63:           ftp.connect(self.host,self.port)
    64:         else:
    65:           ftp.connect(self.host)
    66:         print 'connected to',self.host
    67: 
    68:         # login to server
    69:         if hasattr(self,'user'):
    70:           if hasattr(self,'password'):
    71:             if hasattr(self,'account'):
    72:               ftp.login(self.user,self.password,self.account)
    73:             else: ftp.login(self.user,self.password)
    74:           else: ftp.login(self.user)
    75:         else: ftp.login()
    76:         if verbosity>=4: print 'logged in'
    77: 
    78:         # set remote directory
    79:         if hasattr(self,'remote_directory'):
    80:           ftp.cwd(self.remote_directory)
    81:           print 'changed to remote directory',self.remote_directory
    82: 
    83:         # get file to a temporary
    84:         try:
    85:           tmp_filename = tempfile.mktemp()
    86:           self.file= open(tmp_filename,'w')
    87:           print 'opened',tmp_filename,'for download'
    88:           ftp.retrlines('RETR '+self.remote_filename, self.transfer)
    89:           self.file.close()
    90:           ftp.quit()
    91:           if verbosity>=2: print 'download complete'
    92: 
    93:           file = open(tmp_filename,'r')
    94:           newlines = file.readlines()
    95:           file.close()
    96: 
    97:           if self.local_file_exists:
    98:             file = open(self.local_filename,'r')
    99:             oldlines = file.readlines()
   100:             file.close()
   101: 
   102:             if newlines != oldlines:
   103:               if verbosity>=4: print 'Local file',self.local_filename,'UPDATED from',self.remote_filename
   104:             else:
   105:               if verbosity>=4: print 'Local file',self.local_filename,'unchanged'
   106:           else:
   107:             if verbosity>=4: print 'Writing new local file',self.local_filename
   108: 
   109:           # note that the local file is written even if it isn't changed
   110:           # to update the time stamp
   111:           file = open(self.local_filename,'w')
   112:           file.writelines(newlines)
   113:           file.close()
   114:           self.os.remove(self.tmp_filename)
   115: 
   116:         except:
   117:           print 'Cannot download',self.remote_filename,
   118:           if hasattr(self,'remote_directory'):
   119:             print 'from directory',self.remote_directory
   120:           else: print 'of',self.host
   121:           file.close()
   122:           self.os.remove(tmp_filename)
   123:           ftp.quit()
   124: 
   125:       except:
   126:         pass # ignore errors from ftp attempt
   127:     else:
   128:       print 'Skipping ftp download'
   129: 
End python section to interscript/drivers/sources/ftp.py[1]

6.3.1.6. HTTP input

This object fetches a file by http on construction. The file is then read from the local copy. The host name and remote filename arguments are mandatory. Optional arguments given by keywords are:
port
The port number of the host to use for FTP. Defaults to 21.
local_filename
The name of the file to which the download should be written. Defaults to 'remote_filename'.
refresh_interval
This is the number of days old the local file can be before ftp is done. The default is 28. If this value is set to 0, a download is always done. If the value is set to -1, a download is done only if the local file does not exist; delete the file to force another download.
An exception is thrown if there is no local file, and the attempt to ftp the remote file files. No exception is thrown if the local file exists, even if it is out of date.
Start python section to interscript/drivers/sources/http.py[1] 1
     1: #line 472 "source_drivers.ipk"
     2: #---------------------------------------------------------
     3: # gets input by HTTP
     4: from interscript.drivers.sources.base import file_source
     5: from interscript.drivers.sources.base import eof
     6: import os
     7: import time
     8: import httplib
     9: import string
    10: 
    11: class http_file_source(file_source):
    12:   def __init__(self,host,remote_filename,**kwds):
    13:     appy(file_source.__init__, (self,), kwds)
    14:     self.name = remote_filename
    15:     self.remote_filename = remote_filename
    16:     self.host = host
    17:     self.g = g
    18:     for k in kwds.keys():
    19:       self.__dict__[k]=kwds[k]
    20:     if not hasattr(self,'local_filename'):
    21:       self.local_filename = self.remote_filename
    22:     self.os = os
    23:     self.fetch()
    24:     self.file = open(self.local_filename,'r')
    25:     self.closed = 0
    26: 
    27:   def fetch(self):
    28:     if not hasattr(self,'refresh_interval'):
    29:       self.refresh_interval = 28
    30:     if self.refresh_interval < 0: self.refresh_interval = 100000
    31:     self.local_file_exists = 1
    32:     try:
    33:       f = open(self.local_filename)
    34:       f.close()
    35:       print 'local file',self.local_filename,'exists'
    36:     except:
    37:       print 'local file',self.local_filename,'does NOT exist'
    38:       self.local_file_exists = 0
    39: 
    40:     if self.local_file_exists:
    41:       self.local_file_modify_time = os.stat(self.local_filename)[stat.ST_MTIME]
    42:       now = time.time()
    43:       age = (now - self.local_file_modify_time)/ (24 * 60 * 60)
    44:       download = age > self.refresh_interval
    45:     else:
    46:       download = 1
    47: 
    48:     if hasattr(self.g,'download'):
    49:       if self.g.download == 'always': download = 1
    50:       if self.g.download == 'never': download = 0
    51: 
    52:     if download:
    53:       try:
    54:         print 'downloading',self.remote_filename
    55:         # create HTTP object
    56:         http = httplib.HTTP()
    57: 
    58:         # connect to server
    59:         if hasattr(self,'port'):
    60:           http.connect(self.host+':'+str(self.port))
    61:         else:
    62:           ftp.connect(self.host)
    63:         print 'connected to',self.host
    64: 
    65:         # set remote directory
    66:         to_download = self.remote_filename
    67:         if hasattr(self,'remote_directory'):
    68:           to_download = to_download + '/' + self.remote_directory
    69: 
    70:         # get file to a temporary
    71:         try:
    72:           http.putrequest('GET',to_download)
    73:           http.putheader('Accept','text/html')
    74:           http.putheader('Accept','text/plain')
    75:           http.endheaders()
    76:           errcode, errmsg, headers = http.getreply()
    77:           if errcode != 200: raise 'http error '+str(errcode)+'; '+errmsg
    78:           file = http.getfile()
    79:           newlines = file.readlines()
    80:           file.close()
    81:           print 'download complete'
    82: 
    83:           if self.local_file_exists:
    84:             file = open(self.local_filename,'r')
    85:             oldlines = file.readlines()
    86:             file.close()
    87: 
    88:             if newlines != oldlines:
    89:               print 'Local file',self.local_filename,'UPDATED from',self.remote_filename
    90:             else:
    91:               print 'Local file',self.local_filename,'unchanged'
    92:           else:
    93:             print 'Writing new local file',self.local_filename
    94: 
    95:           # note that the local file is written even if it isn't changed
    96:           # to update the time stamp
    97:           file = open(self.local_filename,'w')
    98:           file.writelines(newlines)
    99:           file.close()
   100: 
   101:         except:
   102:           print 'Cannot download',self.remote_filename,
   103:           if hasattr(self,'remote_directory'):
   104:             print 'from directory',self.remote_directory
   105:           else: print 'of',self.host
   106:           try:
   107:             print 'code',errcode,'msg',errmsg
   108:           except:
   109:             pass
   110:       except:
   111:         pass # ignore errors from ftp attempt
   112:     else:
   113:       print 'Skipping http download'
   114: 
   115:     self.file = open(self.local_filename,'r')
   116: 
End python section to interscript/drivers/sources/http.py[1]

6.3.1.7. Standard Input

Start python section to interscript/drivers/sources/stdin.py[1] 1
     1: #line 590 "source_drivers.ipk"
     2: #---------------------------------------------------------
     3: # gets input from _python_ sys.stdin object
     4: # same as named_file_source, except named 'standard input'
     5: # and doesn't close file on destruction
     6: import sys
     7: from interscript.drivers.sources.base import source
     8: from interscript.drivers.sources.base import eof
     9: import string
    10: 
    11: class stdin_source(source):
    12:   def __init__(self, **kwds):
    13:     apply(source.__init__,(self,) kwds)
    14:     self.name = 'standard input'
    15:     self.closed = 0
    16: 
    17:   def raw_readline(self):
    18:     if self.closed:
    19:       raise eof
    20:     line = sys.stdin.readline()
    21:     if len(line)==0: raise eof
    22:     self.lines_read = self.lines_read + 1
    23:     return string.rstrip(line)
    24: 
End python section to interscript/drivers/sources/stdin.py[1]

6.3.1.8. Cache

Start python section to interscript/drivers/sources/cache.py[1] 1
     1: #line 616 "source_drivers.ipk"
     2: from interscript.drivers.sources.base import source
     3: from interscript.drivers.sources.base import eof
     4: import string
     5: 
     6: class cache_source(source):
     7:   def __init__(self, name, master_frame):
     8:     source.__init__(self)
     9:     self.name = name
    10:     self.saved = ''
    11:     macros = master_frame.get_persistent_frame('macros')
    12:     self.list = macros.get(name,[])
    13:     self.closed = 0
    14: 
    15:   def raw_readline(self):
    16:     if len(self.list)>self.lines_read:
    17:       line = self.list[self.lines_read]
    18:     else:
    19:       raise eof
    20:     self.lines_read = self.lines_read + 1
    21:     return line
    22: 
    23:   def rewind_source(self):
    24:     self.lines_read = 0
    25: 

6.3.2. Sink Drivers

Sink drivers support the standard Python file protocol for output of text. They supply the standard python file methods:
write
Write text to output device. Repeatedly raw_write characters upto either the end of the string, or a newline character. If a newline character is found, increment the line count amd call raw_eol. Precondition: no control characters other than newline in the input.
writelines
Accepts a list of strings which are concatenated and passed to the write method. No newline characters are added. Precondition: no control characters other than newline in the input.
close
If the sink is not flagged as closed, flag the sink as closed for access to the device and call raw_close. Note this need not close the underlying device.
flush
May flush data to the device.
isatty
May return 1 if the underlying device is a tty type device.

The methods read, readline and readlines are note provided because a sink need not support read operations. The methods seek and tell are not provided because sinks need not support positioning. The method truncate is not provided because a sink need not be storage device. There is no mode attribute, sinks support writing, but need not be files.

The following methods augment the standard python methods.

writeline
Append a newline character to the argument and pass to write method.
raw_writelines
Accepts a list of strings which are written in turn using writeline. Use with a list of printable strings; that is, without trailing newlines.
The following methods should be provided by subclass derivers, if the default implementation (if it exists) is inappropriate. They are intended as private implementation details, not to be called by the user.
raw_write
Write raw text to the device. Precondition: only printable characters in the input (space is allowed). [All characters are written verbatim to the underlying device without incrementing the line count.]
raw_close
May close the underlying device. Called by the close method if the closed flag is false.
raw_flush
May flush the underlying device device.
raw_eol
Ends a line on the underlying device.
In addition, the following attributes are available:
lines_written
The total number of calls to writeline.
last_source_file
Provided for the client to store the name of the original source of the last line written.
last_source_line
Provided for the client to store the line number of the last line written in the original source file.
last_inhibit_sref
Provided for the client to store whether source referencing was disabled on the last write.
closed
Indicates if close was called.
Start python section to interscript/drivers/sinks/__init__.py[1] 1
     1: #line 96 "sink_drivers.ipk"
     2: #--- sink package ---
     3: class sink_open_error(Exception): pass
     4: 
     5: 
End python section to interscript/drivers/sinks/__init__.py[1]
Start python section to interscript/drivers/sinks/util.py[1] 1
     1: #line 102 "sink_drivers.ipk"
     2: import os
     3: posixpath = os.path
     4: import errno
     5: 
     6: # OS dependent routines.
     7: # Note: we use some posixpath functions, but don't trust them
     8: 
     9: # make the given directory, no error if it exists
    10: # this is posix specific, and should be moved to a platform
    11: # dependent place in the code
    12: 
    13: def create_directory(dir):
    14:   if not posixpath.isdir(dir):
    15:     try: os.mkdir(dir)
    16:     except os.error, data:
    17:       if data[0]!=errno.EEXIST: # File Exists is OK, everything else is fatal
    18:         raise os.error, (data[0],data+': directory "'+dir+'"')
    19:   if not posixpath.isdir(dir):
    20:     raise os.error, (errno.ENOENT, 'Created a directory '+dir+', but it is not there!')
    21: 
    22: # given an os specific prefix and a list of component names,
    23: # make the directory structure in which the last component is contained
    24: # and synthesise and return its full os specific pathname
    25: 
    26: def mk_dir(prefix, pathlist):
    27:   if len(pathlist)>1:
    28:     # there's more than one component in the list
    29:     # so create directories for all but the last component
    30: 
    31:     pathname = prefix+pathlist[0]
    32:     create_directory(pathname)
    33:     for component in pathlist[1:-1]:
    34:       pathname = pathname + os.sep + component
    35:       create_directory(pathname)
    36:     pathname = pathname + os.sep + pathlist[-1]
    37: 
    38:   else:
    39:     # only one component on the list
    40:     pathname = prefix+pathlist[0]
    41: 
    42:   if pathname[0]!=os.sep:
    43:     # the pathname isn't absolute, so make it so
    44:     # get current directory
    45:     curdir = os.getcwd()
    46: 
    47:     # strip trailing separator
    48:     # note this should fix cases like '/' (unix) or 'd:\' (nt)
    49:     # as well as cope with systems that return a trailing separator
    50:     if curdir[-1] == os.sep: curdir = curdir[:-1]
    51: 
    52:     # append a separator and the pathname: there will only be one
    53:     # separator at the join point unless the current directory
    54:     # ends with two separators (like the URL: http://)
    55:     pathname = curdir + os.sep + pathname
    56:   return pathname
    57: 
    58: # this routine checks is a file exists and is readable
    59: # (in the sense that it can be opened for read)
    60: # it returns 1 if the file exist and can be read, 0 if the file
    61: # doesn't exist, and throws an exception if anything else goes wrong
    62: 
    63: def file_exists(pathname):
    64:   try:
    65:     # note this leaks a file if it is opened but not closed :-))
    66:     open(pathname,'r').close()
    67:     return 1
    68:   except IOError, data:
    69:     if data[0] == errno.ENOENT:
    70:       return 0
    71:     raise IOError, data
    72: 
    73: # Note: the intention is to apply mk_dir to ensure the file has a
    74: # parent directory, creating it if necessary, then test if the file
    75: # already exists or has to be created. Even if it exists, it may have
    76: # to be replaced.
    77: 
End python section to interscript/drivers/sinks/util.py[1]

6.3.2.1. Sink Base Class

Start python section to interscript/drivers/sinks/base.py[1] 1
     1: #line 181 "sink_drivers.ipk"
     2: import string
     3: class sink_base:
     4:   __class_protocols__ = ['sink','file']
     5:   def __init__(self, **kwds):
     6:     self.lines_written = 0
     7:     self.last_source_file = ''
     8:     self.last_source_line = -1
     9:     self.last_inhibit_sref = 1
    10:     self.closed = 0
    11:     for k in kwds.keys():
    12:       self.__dict__[k]=kwds[k]
    13: 
    14:   def raw_close(self): pass
    15:   def raw_flush(self): pass
    16:   def raw_eol(self): self.raw_write('\n')
    17:   def isatty(self): return 0
    18: 
    19:   def raw_writeline(self,line):
    20:     self.raw_write(line)
    21:     self.raw_eol()
    22:     self.lines_written = self.lines_written  + 1
    23: 
    24:   def writeline(self,line):
    25:     self.write(line + '\n')
    26: 
    27:   def raw_writelines(self,lines):
    28:     for line in lines: self.raw_writeline(line)
    29: 
    30:   def writelines(self,lines):
    31:     self.write(string.join(lines,''))
    32: 
    33:   def get_sink_name(self):
    34:     return self.name
    35: 
    36:   def write(self,text):
    37:     lines = string.split(text,'\n')
    38:     for line in lines[:-1]:
    39:       self.raw_writeline(line)
    40:     self.raw_write(lines[-1])
    41: 
    42:   def close(self):
    43:     self.closed = 1
    44:     self.raw_close()
    45: 
    46:   def flush(self):
    47:     self.raw_flush
    48: 
End python section to interscript/drivers/sinks/base.py[1]

6.3.2.2. Null Sink

Start python section to interscript/drivers/sinks/null.py[1] 1
     1: #line 231 "sink_drivers.ipk"
     2: from interscript.drivers.sinks.base import sink_base
     3: class null_sink(sink_base):
     4:   def __init__(self):
     5:     sink_base.__init__(self,name='null sink')
     6: 
     7:   def raw_write(self,line):
     8:     pass
     9: 
End python section to interscript/drivers/sinks/null.py[1]

6.3.2.3. Tee Sink

Start python section to interscript/drivers/sinks/tee.py[1] 1
     1: #line 242 "sink_drivers.ipk"
     2: from interscript.drivers.sinks.base import sink_base
     3: class tee_sink(sink_base):
     4:   def __init__(self, *args, **kwds):
     5:     sink_base.__init__(self)
     6: 
     7:   def raw_write(self,line):
     8:     pass
     9: 
End python section to interscript/drivers/sinks/tee.py[1]

6.3.2.4. Simple Disk File Sink

Start python section to interscript/drivers/sinks/disk.py[1] 1
     1: #line 253 "sink_drivers.ipk"
     2: import string
     3: from interscript.drivers.sinks.base import sink_base
     4: from interscript.drivers.sinks import sink_open_error
     5: from interscript.drivers.sinks.util import mk_dir
     6: 
     7: class simple_named_file_sink(sink_base):
     8:   def __init__(self,pass_frame,input_filename, prefix='', eol='\n'):
     9:     self.eol = eol
    10: 
    11:     # compute absolute pathname, and create directories if necessary
    12:     # we don't use posixpath because we're enforcing an _interscript_
    13:     # pathname convention here
    14:     pathlist = string.split(input_filename,'/')
    15:     self.basename = pathlist[-1]
    16:     pathname = mk_dir(prefix, pathlist)
    17:     try:
    18:       file = open(pathname,'w')
    19:     except:
    20:       raise sink_open_error,pathname
    21:     sink_base.__init__(self, name = input_filename, file = file)
    22:     pass_frame.flist.append(pathname)
    23: 
    24:   def __del__(self):
    25:     self.file.close()
    26: 
    27:   def raw_write(self,line): self.file.write(line)
    28:   def raw_eol(self): self.raw_write(self.eol)
    29: 
End python section to interscript/drivers/sinks/disk.py[1]

6.3.2.5. Complex Disk File Sink

This class provides more advanced facilities than the simple disk file. Output is written to a temporary file until the driver is closed. At that point, the temporary file is compared line by line with the target file, and if the files differ, the temporary file is copied onto the target, and then, in either case the temporary deleted.

This mechanism has several purposes. First, it is used to prevent 'make' systems recompiling unchanged code files. Second, it is used so that the output of a previous run can be read back in while the current run is generating a new copy. Finally, the comparisons on all these files can be used to determine if the literate programming process has converged to a stable point or may require another pass.

Please note that some care is required to ensure convergence is possible. Note also that when line numbers are generated, a single change to the source file will cause comparisons to fail for all files with sections defined after that point, often causing an apparently redundant rebuild. This is not alsways the case, for example, in C, the assert macro reports line numbers at run time, and the rebuild is necessary. It may be useful to turn off line number generation for files once they have compiled successfully (until the production build).

Finally, note that if you put the time into an output file, it is likely to be different each run!

Start python section to interscript/drivers/sinks/bufdisk.py[1] 1
     1: #line 311 "sink_drivers.ipk"
     2: import string
     3: from interscript.drivers.sinks.base import sink_base
     4: from interscript.drivers.sinks import sink_open_error
     5: from interscript.drivers.sinks.util import mk_dir, file_exists
     6: import tempfile
     7: import os
     8: 
     9: class named_file_sink(sink_base):
    10:   def __init__(self,pass_frame,input_filename, prefix='', eol='\n'):
    11:     self.pass_frame = pass_frame
    12:     self.process = pass_frame.process
    13:     self.verbosity = self.pass_frame.verbosity
    14:     self.eol = eol
    15: 
    16:     # compute absolute pathname, and create directories if necessary
    17:     # we don't use posixpath because we're enforcing an _interscript_
    18:     # pathname convention here
    19:     pathlist = string.split(input_filename,'/')
    20:     self.basename = pathlist[-1]
    21:     pathname = mk_dir(prefix, pathlist)
    22: 
    23:     if file_exists(pathname):
    24:       self.tmp_filename = tempfile.mktemp()
    25:       if self.verbosity>=4:
    26:         print 'Generating temporary',self.tmp_filename,'for',input_filename
    27:       try:
    28:         file =open(self.tmp_filename,'w')
    29:         self.pass_frame.fdict[input_filename]='temporary'
    30:       except:
    31:         raise sink_open_error, self.tmp_filename
    32:       sink_base.__init__(self, filename = pathname, name = input_filename, file = file )
    33:       self.os = os
    34:       self.pass_frame.flist.append(input_filename)
    35:     else:
    36:       if self.verbosity>=3:
    37:         print 'Generating original',input_filename
    38:       try:
    39:         file = open(pathname,'w')
    40:         self.pass_frame.fdict[input_filename]='original'
    41:       except:
    42:         raise sink_open_error,pathname
    43:       sink_base.__init__(self, filename = pathname, name = input_filename, file = file)
    44:       self.pass_frame.flist.append(input_filename)
    45: 
    46:   def __del__(self):
    47:     if self.verbosity>=5: print 'closing', self.name
    48:     self.file.close()
    49:     if hasattr(self,'tmp_filename'):
    50:       if self.process.update_files:
    51:         original_file = open(self.filename,'r')
    52:         original_lines = original_file.readlines()
    53:         original_file.close()
    54: 
    55:         new_file = open(self.tmp_filename,'r')
    56:         new_lines = new_file.readlines()
    57:         new_file.close()
    58: 
    59:         if not original_lines == new_lines:
    60:           if self.verbosity>=1: print 'File',self.filename,'is CHANGED'
    61:           self.pass_frame.fdict[self.name]='changed'
    62:           file = open(self.filename,'w')
    63:           file.writelines(new_lines)
    64:           file.close()
    65:         else:
    66:           if self.verbosity>=4: print 'File',self.filename,'is unchanged'
    67:           self.pass_frame.fdict[self.name]='unchanged'
    68:       else:
    69:         if self.verbosity>=1: print '*** System error inhibiting file update for',self.filename,'***'
    70:         self.pass_frame.fdict[self.name]='cancelled'
    71:       self.os.remove(self.tmp_filename)
    72: 
    73:   def raw_write(self,line): self.file.write(line)
    74:   def raw_eol(self): self.raw_write(self.eol)
    75: 
End python section to interscript/drivers/sinks/bufdisk.py[1]

6.3.2.6. Standard Output Sink

Start python section to interscript/drivers/sinks/stdout.py[1] 1
     1: #line 388 "sink_drivers.ipk"
     2: import sys
     3: from interscript.drivers.sinks.base import sink_base
     4: class stdout_sink(sink_base):
     5:   def __init__(self):
     6:     sink_base.__init__(self,name='standard output')
     7: 
     8:   def raw_write(self,line):
     9:     sys.stdout.write(line)
    10: 
End python section to interscript/drivers/sinks/stdout.py[1]

6.3.2.7. Persistent Storage Sink

This is really the same as a disk file, except the data is stored in an array, and stashed into the cache.
Start python section to interscript/drivers/sinks/cache.py[1] 1
     1: #line 402 "sink_drivers.ipk"
     2: import sys
     3: from interscript.drivers.sinks.base import sink_base
     4: class cache_sink(sink_base):
     5:   def __init__(self, name, master_frame):
     6:     sink_base.__init__(self,name=name)
     7:     self.saved = ''
     8:     self.list = []
     9:     self.closed = 0
    10:     self.master_frame = master_frame
    11: 
    12:   def raw_eol(self):
    13:     self.list.append(self.saved)
    14:     self.saved = ''
    15: 
    16:   def raw_write(self,data):
    17:     self.saved = self.saved + data
    18: 
    19:   def __del__(self):
    20:     macros = self.master_frame.get_persistent_frame('macros')
    21:     macros[self.name]=self.list

6.3.3. Storage Drivers

These drivers support both reading and writing operations.
Start python section to interscript/drivers/storage/__init__.py[1] 1
     1: #line 4 "storage_drivers.ipk"
     2: # storage drivers
     3: 
End python section to interscript/drivers/storage/__init__.py[1]

6.3.3.1. Memory Driver

The memory driver is both a source and sink and can is used as a simple form of macro. By tangling sections of code into memory, a sction can be built which is later emitted in a single block. In this sense the tangler driving the memory device is defining a macro, and its later inclusion in te source stream can be considered expanding the macro.
Start python section to interscript/drivers/storage/memory.py[1] 1
     1: #line 16 "storage_drivers.ipk"
     2: from interscript.drivers.sources.base import source
     3: from interscript.drivers.sources.base import eof
     4: from interscript.drivers.sinks.base import sink_base
     5: 
     6: class memory(source,sink_base):
     7:   def __init__(self,name,**kwds):
     8:     source.__init__(self)
     9:     sink_base.__init__(self)
    10:     self.name = name
    11:     self.saved = ''
    12:     self.list = []
    13:     for k in kwds.keys():
    14:       self.k = kwds[k]
    15:     self.closed = 0
    16: 
    17:   def raw_readline(self):
    18:     if len(self.list)>self.lines_read:
    19:       line = self.list[self.lines_read]
    20:     else:
    21:       raise eof
    22:     self.lines_read = self.lines_read + 1
    23:     return line
    24: 
    25:   def raw_eol(self):
    26:     self.list.append(self.saved)
    27:     self.saved = ''
    28: 
    29:   def rewind_source(self):
    30:     self.lines_read = 0
    31: 
    32:   def raw_write(self,data):
    33:     self.saved = self.saved + data
    34: 
End python section to interscript/drivers/storage/memory.py[1]

6.3.3.2. Disk Driver

The disk driver is also both a source and sink and can is used as a simple form of macro. By tangling sections of code onto disk, a section can be built which is emitted in a single block.

By using differential files drivers, and performing multiple passes on the source, disk based macros can be emitted before they are defined, or even in the middle of their definition: the result will be the filw written from the last run.

Start python section to interscript/drivers/storage/disk.py[1] 1
     1: #line 61 "storage_drivers.ipk"
     2: from interscript.drivers.sources.base import source
     3: from interscript.drivers.sinks.base import sink_base
     4: #---------------------------------------------------------
     5: # This object is both a reader and a writer!
     6: 
     7: class disk(source,sink_base):
     8:   pass
     9:   # not implemented yet :-(
    10: 
     3: #line 11 "drivers.ipk"
     4: 

6.4. Weavers

Start python section to interscript/weavers/__init__.py[1] 1
     1: #line 3 "weavers.ipk"
     2: # weavers package
     3: 
End python section to interscript/weavers/__init__.py[1]

6.4.1. Weaver Base

Start python section to interscript/weavers/base.py[1] 1
     1: #line 8 "weavers.ipk"
     2: class weaver_base:
     3:   __class_protocols = ['weaver']
     4:   def __init__(self, pass_frame):
     5:     self.enabled = 1
     6:     self.translating = 1
     7:     self.tags = []
     8:     self.pass_frame = pass_frame
     9:     self.master = pass_frame.master
    10: 
    11:     self.sequence = self.pass_frame.get_new_sequence_number()
    12:     self.persistent_frame = self.master.get_persistent_frame(self.sequence)
    13: 
    14:   def enable(self): self.enabled = 1
    15:   def disable(self): self.enabled = 0
    16:   def translate(self): self.translating = 1
    17:   def raw(self): self.translating = 0
    18:   def add_tag(self,tag): self.tags.append(tag)
    19:   def rawif(self,tag):
    20:     if tag in self.tags: self.raw()
    21:     else: self.disable()
    22: 
    23:   def writeline(self,line=''):
    24:     self.write(line + '\n')
    25: 
    26:   def write(self,line):
    27:     self.sink.write(line)
    28: 
    29: 
End python section to interscript/weavers/base.py[1]

6.4.2. Raw weaver

The raw weaver outputs text exactly as it is input, special characters included. It cannot do any formatting.

Use of raw weavers is vital for output of typesetter specialised constructions. For example, If you are generating output for both HTML and Latex, and you have a complex table to print, you can set the weaver to a raw weaver attached to the same sink file as the HTML weaver and write HTML directly, then you can do the same for Latex. In that way, you get tables optimised for the various typesetting systems.

Start python section to interscript/weavers/raw.py[1] 1
     1: #line 50 "weavers.ipk"
     2: from interscript.weavers.base import weaver_base
     3: class raw_weaver(weaver_base):
     4:   def __init__(self, pass_frame, writer ,**kwds):
     5:     weaver_base.__init__(self, pass_frame)
     6:     if verbosity>=3: print 'initialising raw weaver, writer',writer.get_sink_name()
     7:     self.protocol = 'raw'
     8:     self.tags = ['raw']
     9:     self.sink = writer
    10:     self.name = 'raw weaver v1 for '+self.sink.name
    11: 
    12: 
End python section to interscript/weavers/raw.py[1]

6.4.3. Multiplex Weaver

This class is used as a base for classes that represent multiple weavers. It supports only one operation: method call with no return value, because only this functionality is transparent; that is, operates the same for a single object, or a set for which the multiplexor is a proxy.

The multiplex weaver also supports list shortcuts.

The technology is unfortunately not re-entrant, the multiplex call method return must be invoked immediately. This makes multi-threaded calls to multiplexed objects unsafe. (Python lacks appropriate categorical constructions.) We could use a thread lock to fix this, but it doesn't seem worth the effort.

Start python section to interscript/weavers/multiplexor.py[1] 1
     1: #line 78 "weavers.ipk"
     2: import traceback
     3: class multiplexor:
     4:   __class_protocols__ = ['weaver']
     5:   def __init__(self,pass_frame,base):
     6:     self.pass_frame = pass_frame
     7:     self.base=base
     8:     self.name = 'multiplexor v1'
     9:     self.debug_missing_methods = 0
    10:     self.list_stack = []
    11: 
    12:   def __nonzero__(self):
    13:     return 1
    14: 
    15:   def callit(self,*args, **kwds):
    16:     self._callit(self.temp,args,kwds)
    17: 
    18:   def _callit(self,at,args, kwds):
    19:     for b in self.base:
    20:       if hasattr(b,at):
    21:         try:
    22:           apply(getattr(b,at),args,kwds)
    23:         except KeyboardInterrupt:
    24:           raise KeyboardInterrupt
    25:         except:
    26:           protocol = 'No protocol attribute'
    27:           name = 'No name attribute'
    28:           if hasattr(b,'protocol'): protocol = b.protocol
    29:           if hasattr(b,'name'): name = b.name
    30:           print 'Error in call!'
    31:           print '  Method',at
    32:           print '  Args  ',args
    33:           print '  Kwds  ',kwds
    34:           print '  of    ',b.protocol,'weaver',b.name,'ignored'
    35:           traceback.print_exc()
    36:       elif self.debug_missing_methods:
    37:         protocol = 'No protocol attribute'
    38:         sinkname = 'No sink attribute'
    39:         if hasattr(b,'protocol'): protocol = b.protocol
    40:         if hasattr(b,'sink'):
    41:           sinkname = 'no sink name'
    42:           sink = b.sink
    43:           if hasattr(sink,'name'):
    44:             sinkname = sink.name
    45:         print 'Warning: missing method',at,'of weaver type',protocol,'for',sinkname,'ignored'
    46: 
    47:   def __getattr__(self,x):
    48:     self.temp = x
    49:     return self.callit
    50: 
    51:   def begin_list(self,style='bullet'):
    52:      if not style in ('bullet','numbered','keyed'):
    53:        style = 'bullet'
    54:      self.list_stack.append([style,0])
    55:      self._callit('begin_'+style+'_list',(),{})
    56: 
    57:   def end_list(self):
    58:     style, open_item = self.list_stack[-1]
    59:     del self.list_stack[-1]
    60:     if open_item:
    61:       self._callit('end_'+style+'_list_item',(),{})
    62:     self._callit('end_'+style+'_list',(),{})
    63: 
    64:   def item(self, *args, **kwds):
    65:     style, open_item = self.list_stack[-1]
    66:     if open_item:
    67:       self._callit('end_'+style+'_list_item',(),{})
    68:     else:
    69:       self.list_stack[-1][1]=1
    70:     self._callit('begin_'+style+'_list_item',args,kwds)
    71: 

6.4.4. Plain text weaver

This nasty weaver tries to output plain text that can be published on the Internet. It can underline headings, and flow text with left justification (and should be able to format tables), but the results are rather crude. Right justification is possible, but not implemented because, in my experience, the results are woeful.
Start python section to interscript/weavers/text.py[1] 1 2 3 4 5 6 7 8 9 10 11
     1: #line 11 "text_weaver.ipk"
     2: from interscript.weavers.base import weaver_base
     3: import string
     4: 
     5: class table_rule_object: pass
     6: 
     7: class plain_text_weaver(weaver_base):
     8:   def __init__(self, pass_frame,writer ,**kwds):
     9:     weaver_base.__init__(self, pass_frame)
    10:     self.verbosity = pass_frame.verbosity
    11:     if self.verbosity>=3:
    12:       print 'initialising plain text weaver, writer',writer.get_sink_name()
    13:     self.protocol = ('text/plain',1)
    14:     self.width = 55
    15:     self.c = 0
    16:     self.buffer = ''
    17:     self.strong = 0
    18:     self.string = string
    19:     self.code = 0
    20:     self.sink = writer
    21:     self.name = 'plain text weaver v1 for '+self.sink.name
    22:     self.tags = ['text']
    23:     self.margin = 0
    24:     self.numbered_list_stack = []
    25:     self.sop = 1
    26:     self.hcount = []
    27:     self.toc = []
    28: 
    29:   def _write(self,line):
    30:     if self.enabled:
    31:       self.sink.write(line)
    32:       self.c = self.c + len(line)
    33:     if line:
    34:       self.sop = 0
    35: 
    36:   def _writeline(self,line=''):
    37:     if self.enabled:
    38:       self._write(line+'\n')
    39:       self.c = 0
    40: 
    41:   def _goto(self,column):
    42:     if self.enabled:
    43:       if column < 0: column = self.width + column
    44:       if column < self.c: self._writeline()
    45:       if column > self.c: self._write(' '*(column-self.c))
    46: 
End python section to interscript/weavers/text.py[1]

6.4.4.1. reference processor

Start python section to interscript/weavers/text.py[2] 1 2 3 4 5 6 7 8 9 10 11
    47: #line 58 "text_weaver.ipk"
    48:   def set_original_filename(self, filename):
    49:     self.original_filename = filename
    50: 
    51:   def set_anchor(self, label):
    52:     if not self.persistent_frame.has_key('anchors'):
    53:       self.persistent_frame['anchors']  = {}
    54:     self.persistent_frame['anchors'][label]=self.sink.lines_written+1
    55: 
    56:   def get_anchor(self, label):
    57:     href = None
    58:     if self.persistent_frame.has_key('anchors'):
    59:       if self.persistent_frame['anchors'].has_key(label):
    60:         href =self.persistent_frame['anchors'][label]
    61:     return href
    62: 
    63:   def ref_anchor(self, label):
    64:     href = self.get_anchor(label)
    65:     if href:
    66:       self._write('line '+str(href))
    67:     else:
    68:       self._write('Unknown Label:'+label)
    69: 
End python section to interscript/weavers/text.py[2]

6.4.4.2. Table of Contents

Start python section to interscript/weavers/text.py[3] 1 2 3 4 5 6 7 8 9 10 11
    70: #line 82 "text_weaver.ipk"
    71:   def print_contents(self, hlevel=2, maxlev=3, *args, **kwds):
    72:     if hlevel>0:
    73:       self.head(hlevel,'Contents')
    74:     toc = self.persistent_frame.get('contents',[])
    75:     for level, line, lineno in toc:
    76:       if level <=maxlev:
    77:         prefix = ' '*(level*3)+line+' '
    78:         suffix = ' '+str(lineno+1)
    79:         mid = '.' * (self.width - len(prefix) - len(suffix))
    80:         self._writeline(prefix + mid + suffix)
    81:     self.par()
    82: 
End python section to interscript/weavers/text.py[3]

6.4.4.3. Code File List

Start python section to interscript/weavers/text.py[4] 1 2 3 4 5 6 7 8 9 10 11
    83: #line 96 "text_weaver.ipk"
    84:   def print_file_list(self,hlevel=2, *args, **kwds):
    85:     if hlevel>0:
    86:       self.head(hlevel,'File List')
    87:     if self.master.flist:
    88:       for line in self.master.flist:
    89:         self._writeline(line)
    90:     else:
    91:       self._writeline('No data available in pass '+str(self.pass_frame.passno)+'.')
    92:     self.par()
    93: 
End python section to interscript/weavers/text.py[4]

6.4.4.4. Code File Status

Start python section to interscript/weavers/text.py[5] 1 2 3 4 5 6 7 8 9 10 11
    94: #line 108 "text_weaver.ipk"
    95:   def print_file_status(self,hlevel=2, *args, **kwds):
    96:     passno = self.pass_frame.passno
    97:     h = 'File Status for pass '+str(passno-1)
    98:     if hlevel>0:
    99:       self.head(hlevel,h)
   100:     if self.master.fdict:
   101:       skeys = self.master.fdict.keys()
   102:       skeys.sort()
   103: 
   104:       h = 'Unchanged Files'
   105:       if hlevel>0:
   106:         self.head(hlevel+1,h)
   107:       else:
   108:         self._writeline(h)
   109:       for key in skeys:
   110:         status,change_passno = self.master.fdict[key]
   111:         if status == 'unchanged' and change_passno==0:
   112:           self._writeline(key)
   113: 
   114:       h = 'Changed Files'
   115:       if hlevel>0:
   116:         self.head(hlevel+1,h)
   117:       else:
   118:         self._writeline(h)
   119:       for key in skeys:
   120:         status,change_passno = self.master.fdict[key]
   121:         if status == 'unchanged' and change_passno == 1:
   122:           self._writeline(key)
   123: 
   124:       h = 'Files which required 2 or more passes to converge'
   125:       if hlevel>0:
   126:         self.head(hlevel+1,h)
   127:       else:
   128:         self._writeline(h)
   129:       for key in skeys:
   130:         status,change_passno = self.master.fdict[key]
   131:         if status == 'unchanged' and change_passno > 1:
   132:           self._writeline(key+' (converged in '+str(change_passno)+' passes)')
   133: 
   134:       h = 'Unstable Files'
   135:       if hlevel>0:
   136:         self.head(hlevel+1,h)
   137:       else:
   138:         self._writeline(h)
   139:       for key in skeys:
   140:         status,change_passno = self.master.fdict[key]
   141:         if status == 'changed':
   142:           self._writeline(key)
   143: 
   144:     else:
   145:       self._writeline('No data available in pass '+str(passno)+'.')
   146:     self.par()
   147: 
End python section to interscript/weavers/text.py[5]

6.4.4.5. Input File List

Start python section to interscript/weavers/text.py[6] 1 2 3 4 5 6 7 8 9 10 11
   148: #line 163 "text_weaver.ipk"
   149:   def print_source_list(self, hlevel=2, *args, **kwds):
   150:     if hlevel>0:
   151:       self.head(hlevel,'Source List')
   152:     if self.master.iflist:
   153:       for line in self.master.iflist:
   154:         self._writeline(line)
   155:     else:
   156:       self._writeline('No data available in pass '+str(self.pass_frame.passno)+'.')
   157:     self.par()
   158: 
End python section to interscript/weavers/text.py[6]

6.4.4.6. Include List

Start python section to interscript/weavers/text.py[7] 1 2 3 4 5 6 7 8 9 10 11
   159: #line 175 "text_weaver.ipk"
   160:   def print_include_list(self, hlevel=2, *args, **kwds):
   161:     if hlevel>0:
   162:       self.head(hlevel,'Include List')
   163:     if self.master.include_files:
   164:       for level, type, name in self.master.include_files:
   165:         self._writeline(' '*(level*3)+' '+type+': '+name)
   166:     else:
   167:       self._writeline('No data available in pass '+str(self.pass_frame.passno)+'.')
   168:     self.par()
   169: 
End python section to interscript/weavers/text.py[7]

6.4.4.7. Tables

Start python section to interscript/weavers/text.py[8] 1 2 3 4 5 6 7 8 9 10 11
   170: #line 187 "text_weaver.ipk"
   171:   def __htabrule(self,colw):
   172:     self._write('+')
   173:     for w in colw:
   174:       self._write('-'*(w+2)+'+')
   175:     self._writeline()
   176: 
   177:   def __tabrow(self,colw,data):
   178:     self._write('|')
   179:     for i in range(len(colw)):
   180:       w = colw[i]
   181:       entry = ' '* w
   182:       if i<len(data):
   183:         entry = (data[i]+entry)[:w]
   184:       self._write(' '+entry+' |')
   185:     self._writeline()
   186: 
   187:   def begin_table(self,*headings, **kwds):
   188:     self.table_headings = headings
   189:     self.table_data = []
   190: 
   191:   def table_row(self,data):
   192:     self.table_data.append(data)
   193: 
   194:   def table_rule(self):
   195:     self.table_data.append(table_rule_object)
   196: 
   197:   def end_table(self):
   198:     width = len(self.table_headings)
   199:     for row in self.table_data:
   200:       if row is not table_rule_object:
   201:         w = len(row)
   202:         if w>width : width = w
   203:     colw = [0] * width
   204:     for i in range(len(self.table_headings)):
   205:       w = len(self.table_headings[i])
   206:       if colw[i]<w: colw[i]=w
   207:     for row in self.table_data:
   208:       if row is not table_rule_object:
   209:         for i in range(len(row)):
   210:           w = len(row[i])
   211:           if colw[i]<w: colw[i]=w
   212:     self._flush()
   213:     self._writeline()
   214:     self.__htabrule(colw)
   215:     self.__tabrow(colw,self.table_headings)
   216:     self.__htabrule(colw)
   217:     for data in self.table_data:
   218:       if data is table_rule_object:
   219:         self.__htabrule(colw)
   220:       else:
   221:         self.__tabrow(colw,data)
   222:     self.__htabrule(colw)
   223:     del self.table_headings
   224:     del self.table_data
   225: 
End python section to interscript/weavers/text.py[8]

6.4.4.8. Code Output

Start python section to interscript/weavers/text.py[9] 1 2 3 4 5 6 7 8 9 10 11
   226: #line 244 "text_weaver.ipk"
   227:   def writecode(self,line):
   228:     self._flush()
   229:     self._writeline(line)
   230: 
   231:   def echotangle(self,count,data):
   232:     self.writecode("%6d: %s" % (count,data))
   233: 
   234:   def _write_word(self,word):
   235:     if self.c == 0:
   236:       self._write((' '*self.margin)+word)
   237:     elif self.c + len(word) < self.width:
   238:       self._write(' '+word)
   239:     else:
   240:       self._writeline()
   241:       self._write((' '*self.margin)+word)
   242: 
   243:   def _flush(self):
   244:     words = self.string.split(self.buffer)
   245:     for w in words:
   246:       self._write_word(w)
   247:     self.buffer = ''
   248: 
   249:   def write(self,line):
   250:     if self.translating:
   251:       if self.strong: line = string.upper(line)
   252:       self.buffer = self.buffer + line
   253:     else:
   254:       self._write(line)
   255: 
   256:   def writeline(self,line = ''):
   257:     if self.translating:
   258:       self.write(line)
   259:       if self.code:
   260:         self._writeline(self.buffer)
   261:         self.buffer = ''
   262:       else:
   263:         self._flush()
   264:     else:
   265:       self._writeline(line)
   266: 
   267:   def par(self):
   268:     self.line_break()
   269:     if not self.sop:
   270:       self._writeline()
   271:       self.sop = 1
   272: 
   273:   def line_break(self):
   274:     self._flush()
   275:     if self.c != 0: self._writeline()
   276: 
   277:   def page_break(self):
   278:     self.par()
   279:     self._writeline()
   280:     self._writeline('-' * self.width)
   281:     self._writeline()
   282:     self.sop = 1
   283: 
   284:   def begin_emphasize(self):
   285:     self.write('_')
   286: 
   287:   def end_emphasize(self):
   288:     self.write('_')
   289: 
   290:   def begin_strong(self):
   291:     self.strong = 1
   292: 
   293:   def end_strong(self):
   294:     self.strong = 0
   295: 
   296:   def begin_displayed_code(self):
   297:     self.par()
   298:     self.code = 1
   299: 
   300:   def end_displayed_code(self):
   301:     self.par()
   302:     self.code = 0
   303: 
   304:   def begin_displayed_text(self):
   305:     self.par()
   306:     self.margin = self.margin + 4
   307: 
   308:   def end_displayed_text(self):
   309:     self.par()
   310:     self.margin = self.margin - 4
   311: 
   312:   def new_heading(self,level):
   313:     while level>len(self.hcount): self.hcount.append(0)
   314:     while level<len(self.hcount): del self.hcount[-1]
   315:     counter = self.hcount[level-1]+1
   316:     self.hcount[level-1] = counter
   317:     return counter
   318: 
   319:   def get_formatted_heading_number(self, sep):
   320:     hnumber = ''
   321:     for i in range(0,len(self.hcount)-1):
   322:       hnumber = hnumber + str(self.hcount[i])+sep
   323:     hnumber = hnumber + str(self.hcount[-1])
   324:     return hnumber
   325: 
   326:   def head(self,level, text, atext='', anchor=''):
   327:     self.par()
   328:     self.strong = 0
   329:     self.new_heading(level)
   330:     h = self.get_formatted_heading_number('.')+'. '+text
   331:     self.toc.append((level,text,self.sink.lines_written))
   332:     self._writeline(h)
   333:     self._writeline('-'*len(h))
   334:     self._writeline()
   335: 
   336:   def code_head(self,tangler, secno):
   337:     if tangler:
   338:       self.par()
   339:       language = tangler.get_language()
   340:       filename  =tangler.sink.get_sink_name()
   341:       self._writeline( 'Start '+language+' section to '+\
   342:         filename+'['+str(secno)+']')
   343:       self._writeline()
   344: 
   345:   def code_foot(self,tangler,secno):
   346:     if tangler:
   347:       self.par()
   348:       language = tangler.get_language()
   349:       filename  =tangler.sink.get_sink_name()
   350:       self._writeline()
   351:       self._writeline( 'End '+language+' section to '+filename+\
   352:         '['+str(secno)+']')
   353:       self.par()
   354: 
   355:   def test_output_head(self,command, status):
   356:     self.par()
   357:     self._writeline( 'Start output section of '+command)
   358:     if status:
   359:       self._writeline( 'Command returned '+str(status))
   360:     self.par()
   361: 
   362:   def test_output_foot(self,command,status):
   363:     self.par()
   364:     self._writeline('End output section of '+command)
   365:     self.par()
   366: 
   367:   def expected_head(self,command):
   368:     self.par()
   369:     self._writeline( 'Start expected section of '+command)
   370:     self.par()
   371: 
   372:   def expected_foot(self,command):
   373:     self.par()
   374:     self._writeline('End expected section of '+command)
   375:     self.par()
   376: 
   377:   def diff_head(self,command):
   378:     self.par()
   379:     self._writeline( 'Start diff section of '+command)
   380:     self.par()
   381: 
   382:   def diff_foot(self,command):
   383:     self.par()
   384:     self._writeline('End diff section of '+command)
   385:     self.par()
   386: 
   387:   def __del__(self):
   388:     self._flush()
   389:     if self.c != 0:
   390:       self._writeline()
   391:     self.persistent_frame['contents']=self.toc
   392: 
End python section to interscript/weavers/text.py[9]

6.4.4.9. Citations

Start python section to interscript/weavers/text.py[10] 1 2 3 4 5 6 7 8 9 10 11
   393: #line 412 "text_weaver.ipk"
   394:   def begin_keyed_list(self):
   395:     self.margin = self.margin + 4
   396: 
   397:   def begin_numbered_list(self,start=1):
   398:     self.margin = self.margin + 4
   399:     self.numbered_list_stack.append(start)
   400: 
   401:   def begin_bullet_list(self):
   402:     self.margin = self.margin + 4
   403: 
   404:   def end_keyed_list(self):
   405:     self.par()
   406:     self.margin = self.margin - 4
   407: 
   408:   def end_numbered_list(self):
   409:     self.par()
   410:     self.margin = self.margin - 4
   411:     del self.numbered_list_stack[-1]
   412: 
   413:   def end_bullet_list(self):
   414:     self.par()
   415:     self.margin = self.margin - 4
   416: 
   417:   def begin_keyed_list_item(self,key):
   418:     self.par()
   419:     self._goto(self.margin-4)
   420:     self._write(key+' ')
   421:     self._goto(self.margin)
   422: 
   423:   def begin_numbered_list_item(self):
   424:     self.par()
   425:     key = "%2d. " % self.numbered_list_stack[-1]
   426:     self.numbered_list_stack[-1] = self.numbered_list_stack[-1] + 1
   427:     self._goto(self.margin-4)
   428:     self._write(key)
   429: 
   430:   def begin_bullet_list_item(self):
   431:     self.par()
   432:     key = '*   '
   433:     self._goto(0)
   434:     self._goto(self.margin-4)
   435:     self._write(key)
   436: 
End python section to interscript/weavers/text.py[10]

6.4.4.10. Citations

Start python section to interscript/weavers/text.py[11] 1 2 3 4 5 6 7 8 9 10 11
   437: #line 457 "text_weaver.ipk"
   438:   def cite_url(self,url):
   439:     self.write(url)
   440: 
   441: 
    72: #line 151 "weavers.ipk"
    73: 
    74: 

6.4.5. HTML Weaver

The most commonly used weaver is sure to be the HTML weaver. This weaver attempts to generate HTML compliant with the proposed strict HTML 4.0 DTD. See http://www.w3.org/TR/REC/-html40

Interscript uses a different markup model to HTML. While interscript uses begin and end methods like many HTML tags, HTML paragraph elements are not indicated by such methods. Instead, text written in many places is implicitly a paragraph element, and interscript must detect these places and insert an appropriate start tag. Similarly, interscript paragraphs are separated by @p() commands, and terminated by some other block level construction like a heading or table.

On the other hand, not all text lines are paragraph content, for example list body content.

Start python section to interscript/weavers/html.py[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
     1: #line 21 "html_weaver.ipk"
     2: from interscript.weavers.base import weaver_base
     3: import string
     4: try:
     5:   import interscript.core.iscrcopt
     6:   cvt_code = interscript.core.iscrcopt.cvt_code
     7:   cvt_text = interscript.core.iscrcopt.cvt_text
     8:   #print 'Using iscrcopt'
     9: except:
    10:   #print 'iscrcopt NOT AVAILABLE'
    11:   def cvt_code(line):
    12:     l = ''
    13:     for ch in line:
    14:       if ch in '<>':
    15:         l = l + {'<':'<','>':'>'}[ch]
    16:       else:
    17:         l = l + ch
    18:     return l
    19: 
    20:   def cvt_text(line):
    21:     l = ''
    22:     for ch in line:
    23:       if ch in '<>&':
    24:         l = l + {'<':'<','>':'>','&':'&'}[ch]
    25:       else:
    26:         l = l + ch
    27:     return l
    28: 
    29: class html_weaver(weaver_base):
    30: 
End python section to interscript/weavers/html.py[1]

6.4.5.1. Initialisation

Start python section to interscript/weavers/html.py[2] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
    31: #line 52 "html_weaver.ipk"
    32:   def __init__(self, pass_frame,writer ,**kwds):
    33:     weaver_base.__init__(self,pass_frame)
    34:     self.verbosity = pass_frame.verbosity
    35:     if self.verbosity>3: print 'initialising html weaver, writer',writer.get_sink_name()
    36:     self.protocol = 'text/html'
    37:     self.sink = writer
    38:     self.acount = 1
    39:     self.hcount = [0]
    40:     self.mode = None
    41:     self.comments = 0
    42:     self.list = []
    43:     self.name = 'html weaver v1 for '+self.sink.name
    44:     self.heading_level_offset = 0
    45:     self.keywords = kwds
    46:     self.tags = ['html'] # this 'tags' has nothing to do with html tags!
    47:     self.toc = []
    48:     if kwds.has_key('title'):
    49:       self.title=kwds['title']
    50:     else:
    51:       title = self.sink.name
    52: 
    53:     self.prolog()
    54: 
End python section to interscript/weavers/html.py[2]

6.4.5.2. Termination

Start python section to interscript/weavers/html.py[3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
    55: #line 77 "html_weaver.ipk"
    56:   def __del__(self):
    57:     self.epilog()
    58:     self.persistent_frame['contents']=self.toc
    59: 
End python section to interscript/weavers/html.py[3]

6.4.5.3. Body Output and Mode Control

Start python section to interscript/weavers/html.py[4] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
    60: #line 83 "html_weaver.ipk"
    61:   def _setmode(self,mode):
    62:     self._write('\n<'+mode+'>')
    63:     self.mode = mode
    64: 
    65:   def _endmode(self):
    66:     if self.mode:
    67:       self._write('</'+self.mode+'>\n')
    68:       self.mode = None
    69: 
    70:   def _startmode(self,mode):
    71:     self._endmode()
    72:     self._setmode(mode)
    73: 
    74:   def _ensuremode(self,mode):
    75:     if self.mode != mode : self._startmode(mode)
    76: 
    77:   def _writeline(self,line=''):
    78:     if self.enabled: self.sink.writeline(line)
    79: 
    80:   def _write(self,line):
    81:     if self.enabled: self.sink.write(line)
    82: 
    83:   def writeline(self,line=''):
    84:     self.write(line + '\n')
    85: 
    86:   def write(self,line):
    87:     #hack to correct bug in popular broswers
    88:     #if not self.mode: self._setmode('P')
    89:     if self.translating:
    90:       self._write(cvt_text(line))
    91:     else:
    92:       self._write(line)
    93: 
    94:   def writecode(self,line):
    95:     self._ensuremode('PRE')
    96:     self._writeline(cvt_code(line))
    97: 
    98:   def begin_displayed_text(self):
    99:     self._ensuremode('P')
   100:     # note this is HTML 2, HTML 3 uses BQ instead
   101:     self.write('<BLOCKQUOTE>')
   102: 
   103:   def end_displayed_text(self):
   104:     self.write('</BLOCKQUOTE>')
   105: 
   106:   def begin_displayed_code(self):
   107:     self._write('<PRE>\n')
   108: 
   109:   def end_displayed_code(self):
   110:     self._write('</PRE>')
   111: 
   112:   def line_break(self):
   113:     self._writeline('<BR>')
   114: 
   115:   def page_break(self):
   116:     self._writeline('<BR><HR>')
   117: 
   118:   def write_tagged(self,tag, data):
   119:     self._write('<'+tag+'>')
   120:     self._writeline(data)
   121:     self._write('</'+tag+'>')
   122: 
   123:   def label_chunk(self, filename):
   124:     self._ensuremode('PRE')
   125:     self._write('<I>include</I> <STRONG>')
   126:     self._writeline(cvt_code(filename)+'</STRONG>')
   127: 
   128:   def _write_section_ref(self, filename, index):
   129:     name = filename + '['+str(index+1)+']'
   130:     anchor = '<A HREF="'+self.get_anchor(name)+'">'+str(index+1)+'</A>'
   131:     self._writeline (anchor+' ')
   132: 
   133:   def code_head(self,tangler, secno):
   134:     if tangler:
   135:       self._endmode()
   136:       filename =tangler.sink.get_sink_name()
   137:       language = tangler.get_language()
   138:       w = self._writeline
   139:       w ( '<DIV CLASS="CODE_SECTION_HEAD"><SMALL>Start <EM>'+\
   140:         language+'</EM> section to <STRONG>'+\
   141:         filename+'['+str(secno)+']</STRONG></SMALL>')
   142:       dict = self.master.section_index
   143:       if dict.has_key(filename):
   144:         nsections = len(dict[filename])
   145:         for i in range(nsections):
   146:           self._write_section_ref(filename, i)
   147:       w ('</DIV>')
   148:       w ( '<DIV CLASS="CODE">')
   149: 
   150: 
   151:   def code_foot(self,tangler, secno):
   152:     if tangler:
   153:       self._endmode()
   154:       filename =tangler.sink.get_sink_name()
   155:       language = tangler.get_language()
   156:       self._write( '</DIV><DIV CLASS="CODE_SECTION_FOOT"><SMALL>End <EM>'+\
   157:         language+'</EM> section to <STRONG>'+\
   158:         filename+'['+str(secno)+']</STRONG></SMALL></DIV>')
   159: 
   160:   def script_head(self,language,filename):
   161:       self._endmode()
   162:       self._writeline( '<DIV CLASS="CODE_SECTION_HEAD"><SMALL>Start <EM>'+\
   163:         language+'</EM> section from <STRONG>'+\
   164:         filename+'</STRONG></SMALL></DIV>')
   165:       self._writeline( '<DIV CLASS="CODE">')
   166: 
   167:   def script_foot(self,language,filename):
   168:       self._endmode()
   169:       self._write( '</DIV><DIV CLASS="CODE_SECTION_FOOT"><SMALL>End <EM>'+\
   170:         language+'</EM> section from <STRONG>'+\
   171:         filename+'</STRONG></SMALL></DIV>')
   172: 
   173:   def test_output_head(self,command, status):
   174:     self._endmode()
   175:     self._writeline( '<DIV CLASS="TEST_OUTPUT_SECTION_HEAD"><SMALL>Start <EM>'+\
   176:       'output</EM> section of <STRONG>'+\
   177:       command+'</STRONG></SMALL></DIV>')
   178:     if status:
   179:       self._writeline( '<DIV CLASS="TEST_OUTPUT_RESULT"><BIG>Command returned <STRONG>'+\
   180:         str(status)+'</STRONG></BIG></DIV>')
   181:     if status: div_class = 'BAD_TEST_OUTPUT'
   182:     else: div_class = 'TEST_OUTPUT'
   183:     self._writeline( '<DIV CLASS="'+div_class+'">')
   184: 
   185:   def test_output_foot(self,command,status):
   186:     self._endmode()
   187:     self._writeline( '</DIV><DIV CLASS="TEST_OUTPUT_SECTION_FOOT">')
   188:     self._writeline('<SMALL>End <EM>output</EM> section to <STRONG>'+command+'</STRONG></SMALL></DIV>')
   189: 
   190:   def expected_head(self,command):
   191:     self._endmode()
   192:     self._writeline( '<DIV CLASS="EXPECTED_OUTPUT_SECTION_HEAD"><SMALL>Start <EM>expected</EM> section of <STRONG>'+command+'</STRONG></SMALL></DIV>')
   193:     div_class = 'EXPECTED_OUTPUT'
   194:     self._writeline( '<DIV CLASS="'+div_class+'">')
   195: 
   196:   def expected_foot(self,command):
   197:     self._endmode()
   198:     self._writeline( '</DIV><DIV CLASS="EXPECTED_OUTPUT_SECTION_FOOT">')
   199:     self._writeline('<SMALL>End <EM>expected</EM> section to <STRONG>'+command+'</STRONG></SMALL></DIV>')
   200: 
   201:   def diff_head(self,command):
   202:     self._endmode()
   203:     self._writeline( '<DIV CLASS="DIFF_SECTION_HEAD"><SMALL>Start <EM>diff</EM> section of <STRONG>'+command+'</STRONG></SMALL></DIV>')
   204:     div_class = 'DIFF'
   205:     self._writeline( '<DIV CLASS="'+div_class+'">')
   206: 
   207:   def diff_foot(self,command):
   208:     self._endmode()
   209:     self._writeline( '</DIV><DIV CLASS="DIFF_SECTION_FOOT">')
   210:     self._writeline('<SMALL>End <EM>diff</EM> section to <STRONG>'+command+'</STRONG></SMALL></DIV>')
   211: 
End python section to interscript/weavers/html.py[4]

6.4.5.4. Reference Processor

Start python section to interscript/weavers/html.py[5] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   212: #line 236 "html_weaver.ipk"
   213:   def set_anchor(self, label):
   214:     self._write('<A NAME="#'+label+'"></A>')
   215: 
   216:   def get_anchor(self, label):
   217:     return '#'+label
   218: 
   219:   def ref_anchor(self, label):
   220:     href = self.get_anchor(label)
   221:     if href:
   222:       self._write('<A HREF="'+href+'">'+label+'</A>')
   223:     else:
   224:       self._write('<EM>Unknown Label:'+label+'</EM>')
   225: 
End python section to interscript/weavers/html.py[5]

6.4.5.5. Headings

Start python section to interscript/weavers/html.py[6] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   226: #line 251 "html_weaver.ipk"
   227:   def new_heading(self,level):
   228:     while level>len(self.hcount): self.hcount.append(0)
   229:     while level<len(self.hcount): del self.hcount[-1]
   230:     counter = self.hcount[level-1]+1
   231:     self.hcount[level-1] = counter
   232:     return counter
   233: 
   234:   def get_formatted_heading_number(self, sep):
   235:     hnumber = ''
   236:     for i in range(0,len(self.hcount)-1):
   237:       hnumber = hnumber + str(self.hcount[i])+sep
   238:     hnumber = hnumber + str(self.hcount[-1])
   239:     return hnumber
   240: 
   241: 
   242:   def head(self,level, text, atext='', anchor=''):
   243:     self._endmode()
   244:     myanchor = anchor
   245:     if myanchor == '': myanchor = atext
   246:     if myanchor == '':
   247:       myanchor = 'h'+str(self.acount)
   248:       self.acount = self.acount + 1
   249: 
   250:     self.new_heading(level)
   251:     hnumber = self.get_formatted_heading_number('.')+'. '
   252:     hprefix = ''
   253:     if self.keywords.has_key('heading_prefix'):
   254:       hprefix = self.keywords['heading_prefix']
   255:     ahref = '<A HREF=#'+anchor+'>'+hprefix+hnumber+str(text)+'</A>'
   256: 
   257:     html_level = level + self.heading_level_offset
   258:     if html_level > 6: html_level = 6
   259:     if anchor: atag = ' ID="'+anchor+'" TITLE="'+anchor+'"'
   260:     else: atag = ' ID="'+myanchor+'"'
   261:     self._writeline( '<H'+str(html_level)+atag+'>'+
   262:       hprefix+hnumber+str(text)+\
   263:       '</H'+str(html_level)+'>')
   264: 
   265:     counter = self.hcount[level-1]
   266:     self.toc.append((level,ahref))
   267: 
End python section to interscript/weavers/html.py[6]

6.4.5.6. Lists

Interscript has a problem here. HTML 4.0 allows the content of a list item to be either inline text or block elements.

Interscript has no way to distinguish between inline text and a paragraph block. Even if we look ahead, a plain text stream could be intended as either a paragraph or inline text.

Unfortunately, NS3 and IE4 put blank lines in on </P> tags, which is wrong: the presence or absence of an optional tag ought not affect rendering. For this reason, I've been forced to remove the wrapping of text in <P> and </P> tags; the @p() command inserts a plain <P> after the _first_ paragraph. Technically, this is invalid HTML, the first pargraph is not wrapped in start and end P tags.

6.4.5.6.1. Numbered Lists
Start python section to interscript/weavers/html.py[7] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   268: #line 311 "html_weaver.ipk"
   269:   def begin_numbered_list(self,start=1, type='1'):
   270:     self._endmode()
   271:     self._write('<OL SEQNUM="'+str(start)+'" TYPE="'+type+'">')
   272: 
   273:   def end_numbered_list(self):
   274:     self._write('</OL>')
   275: 
   276:   def begin_numbered_list_item(self):
   277:     self._write('<LI>')
   278: 
   279:   def end_numbered_list_item(self):
   280:     self._write('</LI>')
   281: 
End python section to interscript/weavers/html.py[7]
6.4.5.6.2. Bullet Lists
Start python section to interscript/weavers/html.py[8] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   282: #line 326 "html_weaver.ipk"
   283:   def begin_bullet_list(self):
   284:     self._endmode()
   285:     self._write('<UL>')
   286: 
   287:   def end_bullet_list(self):
   288:     self._write('</UL>')
   289: 
   290:   def begin_bullet_list_item(self):
   291:     self._write('<LI>')
   292: 
   293:   def end_bullet_list_item(self):
   294:     self._endmode()
   295:     self._write('</LI>')
   296: 
End python section to interscript/weavers/html.py[8]
6.4.5.6.3. Keyed Lists
Start python section to interscript/weavers/html.py[9] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   297: #line 342 "html_weaver.ipk"
   298:   def begin_keyed_list(self):
   299:     self._endmode()
   300:     self._write('<DL>')
   301: 
   302:   def end_keyed_list(self):
   303:     self._write('</DL>')
   304: 
   305:   def begin_keyed_list_item(self,key):
   306:     self._write('<DT><B>'+key+'</B></DT><DD>')
   307: 
   308:   def end_keyed_list_item(self):
   309:     self._write('</DD>')
   310: 
End python section to interscript/weavers/html.py[9]

6.4.5.7. Code Output

Start python section to interscript/weavers/html.py[10] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   311: #line 357 "html_weaver.ipk"
   312:   # default code line formatting
   313:   def echotangle(self,count,data):
   314:     if self.comments:
   315:       self._writeline(data)
   316:     else:
   317:       self.start_code_line(count)
   318:       self._writeline(cvt_code(data))
   319: 
   320:   def start_code_line(self, count=None):
   321:     self._ensuremode('PRE')
   322:     if count:
   323:       self._write('<SPAN CLASS="LINENO">%6d: </SPAN>' % count)
   324:     else:
   325:       self._write('<SPAN CLASS="LINENO">      + </SPAN>')
   326: 
   327:   def end_code_line(self): self._writeline()
   328: 
   329:   def write_code_fragment(self,fragment, kind=None):
   330:     if kind:
   331:       self._write('<SPAN CLASS="'+kind+'">')
   332:     self._write(cvt_code(fragment))
   333:     if kind:
   334:       self._write('</SPAN>')
   335: 
End python section to interscript/weavers/html.py[10]

6.4.5.8. Citations

Start python section to interscript/weavers/html.py[11] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   336: #line 383 "html_weaver.ipk"
   337:   def cite_url(self,url):
   338:     self._write('<A HREF="'+url+'">'+url+'</A>')
   339: 
End python section to interscript/weavers/html.py[11]

6.4.5.9. Paragraphs

Start python section to interscript/weavers/html.py[12] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   340: #line 388 "html_weaver.ipk"
   341:   def prose(self): # start of paragraph
   342:     self._ensuremode('P')
   343: 
   344:   def par(self): # paragraph separator
   345:     self._endmode()
   346:     self._ensuremode('P')
   347: 
   348:   def eop(self): # end of paragraph
   349:     self._endmode()
   350: 
   351:   def write_comment(self,v):
   352:     saved_mode = self.mode
   353:     self.write_tagged('SMALL',v)
   354:     self._ensuremode(saved_mode)
   355: 
End python section to interscript/weavers/html.py[12]

6.4.5.10. Fonts

Start python section to interscript/weavers/html.py[13] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   356: #line 405 "html_weaver.ipk"
   357:   def begin_code(self):
   358:     self._write('<CODE>')
   359: 
   360:   def end_code(self):
   361:     self._write('</CODE>')
   362: 
   363:   def begin_emphasize(self):
   364:     self._write('<EM>')
   365: 
   366:   def end_emphasize(self):
   367:     self._write('</EM>')
   368: 
   369:   def begin_strong(self):
   370:     self._write('<STRONG>')
   371: 
   372:   def end_strong(self):
   373:     self._write('</STRONG>')
   374: 
   375:   def begin_italic(self):
   376:     self._write('<I>')
   377: 
   378:   def end_italic(self):
   379:     self._write('</I>')
   380: 
   381:   def begin_bold(self):
   382:     self._write('<B>')
   383: 
   384:   def end_bold(self):
   385:     self._write('</B>')
   386: 
   387:   def begin_big(self):
   388:     self._write('<BIG>')
   389: 
   390:   def end_big(self):
   391:     self._write('</BIG>')
   392: 
   393:   def begin_small(self):
   394:     self._write('<SMALL>')
   395: 
   396:   def end_small(self):
   397:     self._write('</SMALL>')
   398: 
End python section to interscript/weavers/html.py[13]

6.4.5.11. Identifier Cross Reference Table

Start python section to interscript/weavers/html.py[14] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   399: #line 449 "html_weaver.ipk"
   400:   def identifier_reference(self, hlevel=2, *args, **kwds):
   401:     ids = self.master.ids
   402:     if not ids:
   403:       ids = self.pass_frame.ids
   404:     keys = ids.keys()
   405:     keys.sort()
   406:     if hlevel>0:
   407:       self.head(hlevel,'Index of Identifiers')
   408:     self._writeline('<TABLE COLS="2" BORDER="1" CELLPADDING="2">')
   409:     for k in keys:
   410:       refs = ids[k]
   411:       self._write('<TR><TD VALIGN="Top"><CODE> '+k+' </CODE></TD><TD> ')
   412:       old_df = ''
   413:       for sf,sc,df,dc in refs:
   414:         if old_df != '': self._write(', ')
   415:         if old_df != df:
   416:           self._write(df+': <A HREF=#'+sf+':'+str(sc)+'>'+str(dc)+'</A>')
   417:           old_df = df
   418:         else:
   419:           self._write('<A HREF=#'+sf+':'+str(sc)+'>'+str(dc)+'</A>')
   420:       self._write('</TD></TR>')
   421:     self._writeline('</TABLE>')
   422: 
End python section to interscript/weavers/html.py[14]

6.4.5.12. Class Reference Table

Start python section to interscript/weavers/html.py[15] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   423: #line 474 "html_weaver.ipk"
   424:   def class_reference(self, hlevel=2, *args, **kwds):
   425:     ids = self.master.classes
   426:     if not ids:
   427:       ids = self.pass_frame.classes
   428:     keys = ids.keys()
   429:     keys.sort()
   430:     if hlevel>0:
   431:       self.head(hlevel,'Index of Classes')
   432:     self._writeline('<TABLE COLS="2" BORDER="1" CELLPADDING="2">')
   433:     for k in keys:
   434:       refs = ids[k]
   435:       self._write('<TR><TD VALIGN="Top"><CODE> '+k+' </CODE></TD><TD> ')
   436:       old_df = ''
   437:       for sf,sc,df,dc in refs:
   438:         if old_df != '': self._write(', ')
   439:         if old_df != df:
   440:           self._write(df+': <A HREF=#'+sf+':'+str(sc)+'>'+str(dc)+'</A>')
   441:           old_df = df
   442:         else:
   443:           self._write('<A HREF=#'+sf+':'+str(sc)+'>'+str(dc)+'</A>')
   444:       self._write('</TD></TR>')
   445:     self._writeline('</TABLE>')
   446: 
   447:   # create an HTML anchor
   448:   def set_fc_anchor(self,file,count):
   449:     self._write('<A NAME="'+file+':'+str(count)+'"></A>')
   450: 
End python section to interscript/weavers/html.py[15]

6.4.5.13. Table of Contents

Start python section to interscript/weavers/html.py[16] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   451: #line 503 "html_weaver.ipk"
   452:   def print_contents(self, hlevel=2, maxlev=3, *args, **kwds):
   453:     if hlevel>0:
   454:       self.head(hlevel,'Contents')
   455:     toc = self.persistent_frame.get('contents',[])
   456:     self._write('<PRE>')
   457:     for level, line in toc:
   458:       if level <=maxlev:
   459:         self._writeline(' '*(level*3)+line)
   460:     self._writeline('</PRE>')
   461: 
End python section to interscript/weavers/html.py[16]

6.4.5.14. Code File List

Start python section to interscript/weavers/html.py[17] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   462: #line 515 "html_weaver.ipk"
   463:   def print_file_list(self,hlevel=2, *args, **kwds):
   464:     if hlevel>0:
   465:       self.head(hlevel,'File List')
   466:     if self.master.flist:
   467:       for line in self.master.flist:
   468:         self._writeline(line + '<BR>')
   469:     else:
   470:       self._writeline('<P>No data available in pass '+str(self.pass_frame.passno)+'.</P>')
   471: 
End python section to interscript/weavers/html.py[17]

6.4.5.15. Code File Status

Start python section to interscript/weavers/html.py[18] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   472: #line 526 "html_weaver.ipk"
   473:   def print_file_status(self,hlevel=2, *args, **kwds):
   474:     passno = self.pass_frame.passno
   475:     h = 'File Status for pass '+str(passno-1)
   476:     if hlevel>0:
   477:       self.head(hlevel,h)
   478:     if self.master.fdict:
   479:       skeys = self.master.fdict.keys()
   480:       skeys.sort()
   481: 
   482:       h = 'Unchanged Files'
   483:       if hlevel>0:
   484:         self.head(hlevel+1,h)
   485:       else:
   486:         self._writeline('<STRONG>'+h+'<STRONG><BR>')
   487:       for key in skeys:
   488:         status,change_passno = self.master.fdict[key]
   489:         if status == 'unchanged' and change_passno==0:
   490:           self._writeline(key+'<BR>')
   491: 
   492:       h = 'Changed Files'
   493:       if hlevel>0:
   494:         self.head(hlevel+1,h)
   495:       else:
   496:         self._writeline('<STRONG>'+h+'<STRONG><BR>')
   497:       for key in skeys:
   498:         status,change_passno = self.master.fdict[key]
   499:         if status == 'unchanged' and change_passno == 1:
   500:           self._writeline(key+'<BR>')
   501: 
   502:       h = 'Files which required 2 or more passes to converge'
   503:       if hlevel>0:
   504:         self.head(hlevel+1,h)
   505:       else:
   506:         self._writeline('<STRONG>'+h+'<STRONG><BR>')
   507:       for key in skeys:
   508:         status,change_passno = self.master.fdict[key]
   509:         if status == 'unchanged' and change_passno > 1:
   510:           self._writeline(key+' (converged in '+str(change_passno)+' passes)<BR>')
   511: 
   512:       h = 'Unstable Files'
   513:       if hlevel>0:
   514:         self.head(hlevel+1,h)
   515:       else:
   516:         self._writeline('<STRONG>'+h+'<STRONG><BR>')
   517:       for key in skeys:
   518:         status,change_passno = self.master.fdict[key]
   519:         if status == 'changed':
   520:           self._writeline(key+'<BR>')
   521: 
   522:     else:
   523:       self._writeline('<P>No data available in pass '+str(passno)+'.</P>')
   524: 
End python section to interscript/weavers/html.py[18]

6.4.5.16. Input File List

Start python section to interscript/weavers/html.py[19] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   525: #line 580 "html_weaver.ipk"
   526:   def print_source_list(self, hlevel=2, *args, **kwds):
   527:     if hlevel>0:
   528:       self.head(hlevel,'Source List')
   529:     if self.master.iflist:
   530:       for line in self.master.iflist:
   531:         self._writeline(line + '<BR>')
   532:     else:
   533:       self._writeline('<P>No data available in pass '+str(self.pass_frame.passno)+'.</P>')
   534: 
End python section to interscript/weavers/html.py[19]

6.4.5.17. Include List

Start python section to interscript/weavers/html.py[20] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   535: #line 591 "html_weaver.ipk"
   536:   def print_include_list(self, hlevel=2, *args, **kwds):
   537:     if hlevel>0:
   538:       self.head(hlevel,'Include List')
   539:     if self.master.include_files:
   540:       for level, type, name in self.master.include_files:
   541:         self._writeline(' '*(level*3)+' '+type+': '+name+ '<BR>')
   542:     else:
   543:       self._writeline('<P>No data available in pass '+str(self.pass_frame.passno)+'.</P>')
   544: 
End python section to interscript/weavers/html.py[20]

6.4.5.18. Tables

Start python section to interscript/weavers/html.py[21] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   545: #line 602 "html_weaver.ipk"
   546:   def begin_table(self, *headings, **kwds):
   547:     border=kwds.get('border',2)
   548:     tbclass = kwds.get('CLASS','DEFAULT_TABLE_CLASS')
   549:     self._writeline('<TABLE CLASS="'+tbclass+'" COLS="'+str(len(headings))+'" BORDER="'+str(border)+'"><TR>')
   550:     for h in headings:
   551:       self._write('<TH>')
   552:       self.write(h)
   553:       self._write('</TH>')
   554:     self._writeline('</TR>')
   555: 
   556:   def table_row(self,data):
   557:     self._write('<TR>')
   558:     for d in data:
   559:       self._write('<TD VALIGN="TOP">')
   560:       lines = string.split(d,'\n')
   561:       for line in lines:
   562:         self.write(line)
   563:         self._write('<BR>')
   564:       self._write('</TD>')
   565:     self._writeline('</TR>')
   566: 
   567:   def end_table(self):
   568:     self._writeline('</TABLE>')
   569: 
End python section to interscript/weavers/html.py[21]

6.4.5.19. HTML Header

Start python section to interscript/weavers/html.py[22] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
   570: #line 628 "html_weaver.ipk"
   571:   def prolog(self):
   572:     kwds = self.keywords
   573:     w = self._writeline
   574:     w('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">')
   575:     w( '<HTML>')
   576:     w( '<HEAD>')
   577: 
   578:     self.write_tagged('TITLE', self.title)
   579: 
   580:     w( '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">')
   581:     if kwds.has_key('author'):
   582:       author =kwds['author']
   583:       w( '<META NAME="Author" CONTENT="'+author+'">')
   584:     w( '<META NAME="Generator" CONTENT="Interscript">')
   585:     extra = kwds.get('head_extra','');
   586:     w('<LINK REL=STYLESHEET TYPE="text/css" HREF="interscript.css" TITLE="Interscript Standard">')
   587:     w(extra);
   588:     w('<LINK REL=STYLESHEET TYPE="text/css" HREF="user.css" TITLE="User Overrride">')
   589:     w( '</HEAD>')
   590:     w( '<BODY>')
   591:     if kwds.has_key('pagehead'):
   592:       self._write(kwds['pagehead'])
   593:     if kwds.has_key('title'):
   594:       if kwds.has_key('anchor') and kwds['anchor']!='':
   595:         atag = ' ID="'+kwds['anchor']+'" TITLE="'+kwds['anchor']+'" '
   596:       else: atag= ''
   597:       self._writeline('<H1 '+atag+'ALIGN="CENTER">'+self.title+'</H1>')
   598:     if kwds.has_key('heading_level_offset'):
   599:       self.heading_level_offset = kwds['heading_level_offset']
   600: 
   601:   def epilog(self):
   602:     kwds = self.keywords
   603:     self._endmode()
   604:     if kwds.has_key('pagefoot'):
   605:       self._write(kwds['pagefoot'])
   606:     self._writeline('</BODY>')
   607:     self._writeline('</HTML>')
   608: 
End python section to interscript/weavers/html.py[22]

6.4.5.20. Interscript Style Sheet

The file 'interscript/doc/interscript.css' is a CSS1 style sheet for interscript documents. It is <LINK>ed by interscript documentation, but is not currently copied to the weaver output directory.

HTML documents also <LINK> a stub file, 'user.css' which allows the user to override the interscript standard one.

Start data section to interscript/doc/interscript.css[1] 1
     1: BODY {
     2:   background-color : #FFFFF0;
     3: }
     4: BODY EM {
     5:   color: #A01010;
     6: }
     7: 
     8: BODY CODE {
     9:   color: #101080;
    10: }
    11: DIV.CODE {
    12:   color : #101080;
    13:   background-color: #E0FFFF;
    14:   margin-top: 0.0 ex;
    15:   padding-top: 0.4 ex;
    16:   padding-bottom: 0.2 ex;
    17:   margin-bottom: 0.0 ex;
    18:   margin-right: 2 ex;
    19:   border: thin solid gray;
    20:   display: block;
    21: }
    22: SPAN.LINENO {
    23:   color : #101010;
    24:   font-size: 80%;
    25: }
    26: 
    27: DIV.CODE SPAN.KEYWORD {
    28:   color : #000000;
    29:   font-weight: bold;
    30: }
    31: DIV.CODE SPAN.NAME {
    32:   color : #000000;
    33: }
    34: DIV.CODE SPAN.STRING{
    35:   color : #004000;
    36: }
    37: DIV.CODE SPAN.NUMBER {
    38:   color : #002020;
    39: }
    40: DIV.CODE SPAN.BRACKET {
    41:   color : #800000;
    42: }
    43: DIV.CODE SPAN.PUNCT {
    44:   color : #802000;
    45: }
    46: DIV.CODE SPAN.OP {
    47:   color : #400000;
    48: }
    49: DIV.CODE SPAN.COMMENT {
    50:   color : #000000;
    51:   background-color : #FFF0FF;
    52:   font-size: 80%;
    53:   font-family: sans-serif;
    54: }
    55: 
    56: TABLE.DEFAULT_TABLE_CLASS {
    57:   color: #101010;
    58:   background-color: #F0F0E0;
    59: }
    60: 
    61: TABLE.DIFF {
    62:   color: #204060;
    63:   background-color: #FFE0E0;
    64: }
    65: 
    66: DIV.CODE_SECTION_HEAD {
    67:   margin-top: 1 ex;
    68:   padding-top: 0.2 ex;
    69:   border-top: 0 ex;
    70:   padding-bottom: 0.0 ex;
    71:   border-bottom: 0 ex;
    72:   margin-bottom: -1 ex;
    73:   padding-left: 0.1 em;
    74:   display: block;
    75: }
    76: DIV.CODE_SECTION_FOOT {
    77:   margin-top: -1.0 ex;
    78:   padding-top: 0.0 em;
    79:   border-top-width: 0.0 em;
    80:   border-bottom-width: 0.0 em;
    81:   padding-bottom: 0.0 em;
    82:   margin-bottom: 0.0 em;
    83:   display: block;
    84:   display:none;
    85: }
    86: 
    87: DIV.CODE_SECTION_HEAD SMALL, DIV.CODE_SECTION_FOOT SMALL{
    88:   color : #503020;
    89:   font-size: 80%;
    90:   display: inline;
    91:   color: #101080;
    92: }
    93: DIV.CODE_SECTION_HEAD STRONG, DIV.CODE_SECTION_FOOT STRONG {
    94:   font-family : monospace, courier;
    95:   font-weight: normal;
    96:   font-size: 100%;
    97:   display: inline;
    98:   color : black;
    99: }
   100: DIV.CODE_SECTION_HEAD EM, DIV.CODE_SECTION_FOOT EM {
   101:   display: inline;
   102: }
   103: 
   104: DIV.TEST_OUTPUT {
   105:   color : #101080;
   106:   background-color: #E0FFE0;
   107:   margin-top: 0.0 ex;
   108:   padding-top: 0.4 ex;
   109:   padding-bottom: 0.2 ex;
   110:   margin-bottom: 0.0 ex;
   111:   margin-right: 2 ex;
   112:   border: thin solid gray;
   113:   display: block;
   114: }
   115: DIV.BAD_TEST_OUTPUT {
   116:   color : #101080;
   117:   background-color: #FFE0E0;
   118:   margin-top: 0.0 ex;
   119:   padding-top: 0.4 ex;
   120:   padding-bottom: 0.2 ex;
   121:   margin-bottom: 0.0 ex;
   122:   margin-right: 2 ex;
   123:   border: thin solid gray;
   124:   display: block;
   125: }
   126: DIV.TEST_OUTPUT_RESULT {
   127:   margin-top: 1.5 ex;
   128:   padding-top: 0.2 ex;
   129:   border-top: 0 ex;
   130:   padding-bottom: 0.0 ex;
   131:   border-bottom: 0 ex;
   132:   margin-bottom: -1 ex;
   133:   padding-left: 0.1 em;
   134:   display: block;
   135: }
   136: DIV.TEST_OUTPUT_SECTION_HEAD {
   137:   margin-top: 1 ex;
   138:   padding-top: 0.2 ex;
   139:   border-top: 0 ex;
   140:   padding-bottom: 0.0 ex;
   141:   border-bottom: 0 ex;
   142:   margin-bottom: -1 ex;
   143:   padding-left: 0.1 em;
   144:   display: block;
   145: }
   146: 
   147: DIV.TEST_OUTPUT_SECTION_FOOT {
   148:   margin-top: -1.0 ex;
   149:   padding-top: 0.0 em;
   150:   border-top-width: 0.0 em;
   151:   border-bottom-width: 0.0 em;
   152:   padding-bottom: 0.0 em;
   153:   margin-bottom: 0.0 em;
   154:   display: block;
   155:   display:none;
   156: }
   157: 
   158: DIV.TEST_OUTPUT_SECTION_HEAD SMALL, DIV.TEST_OUTPUT_SECTION_FOOT SMALL{
   159:   color : #503020;
   160:   font-size: 80%;
   161:   display: inline;
   162:   color: #101080;
   163: }
   164: DIV.TEST_OUTPUT_SECTION_HEAD STRONG, DIV.TEST_OUTPUT_SECTION_FOOT STRONG {
   165:   font-family : monospace, courier;
   166:   font-weight: normal;
   167:   font-size: 100%;
   168:   display: inline;
   169:   color : black;
   170: }
   171: DIV.TEST_OUTPUT_SECTION_HEAD EM, DIV.TEST_OUTPUT_SECTION_FOOT EM {
   172:   display: inline;
   173: }
   174: 
   175: DIV.EXPECTED_OUTPUT {
   176:   color : #101080;
   177:   background-color: #E0FFFF;
   178:   margin-top: 0.0 ex;
   179:   padding-top: 0.4 ex;
   180:   padding-bottom: 0.2 ex;
   181:   margin-bottom: 0.0 ex;
   182:   margin-right: 2 ex;
   183:   border: thin solid gray;
   184:   display: block;
   185: }
   186: 
   187: DIV.EXPECTED_OUTPUT_SECTION_HEAD {
   188:   margin-top: 1 ex;
   189:   padding-top: 0.2 ex;
   190:   border-top: 0 ex;
   191:   padding-bottom: 0.0 ex;
   192:   border-bottom: 0 ex;
   193:   margin-bottom: -1 ex;
   194:   padding-left: 0.1 em;
   195:   display: block;
   196: }
   197: 
   198: DIV.EXPECTED_OUTPUT_SECTION_FOOT {
   199:   margin-top: -1.0 ex;
   200:   padding-top: 0.0 em;
   201:   border-top-width: 0.0 em;
   202:   border-bottom-width: 0.0 em;
   203:   padding-bottom: 0.0 em;
   204:   margin-bottom: 0.0 em;
   205:   display: block;
   206:   display:none;
   207: }
   208: 
   209: DIV.EXPECTED_OUTPUT_SECTION_HEAD SMALL, DIV.EXPECTED_OUTPUT_SECTION_FOOT SMALL{
   210:   color : #503020;
   211:   font-size: 80%;
   212:   display: inline;
   213:   color: #101080;
   214: }
   215: DIV.EXPECTED_OUTPUT_SECTION_HEAD STRONG, DIV.EXPECTED_OUTPUT_SECTION_FOOT STRONG {
   216:   font-family : monospace, courier;
   217:   font-weight: normal;
   218:   font-size: 100%;
   219:   display: inline;
   220:   color : black;
   221: }
   222: DIV.EXPECTED_OUTPUT_SECTION_HEAD EM, DIV.EXPECTED_OUTPUT_SECTION_FOOT EM {
   223:   display: inline;
   224: }
   225: 
   226: DIV.DIFF {
   227:   color : #101080;
   228:   background-color: #E0FFE0;
   229:   margin-top: 0.0 ex;
   230:   padding-top: 0.4 ex;
   231:   padding-bottom: 0.2 ex;
   232:   margin-bottom: 0.0 ex;
   233:   margin-right: 2 ex;
   234:   border: thin solid gray;
   235:   display: block;
   236: }
   237: 
   238: DIV.DIFF_SECTION_HEAD {
   239:   margin-top: 1 ex;
   240:   padding-top: 0.2 ex;
   241:   border-top: 0 ex;
   242:   padding-bottom: 0.0 ex;
   243:   border-bottom: 0 ex;
   244:   margin-bottom: -1 ex;
   245:   padding-left: 0.1 em;
   246:   display: block;
   247: }
   248: 
   249: DIV.DIFF_SECTION_FOOT {
   250:   margin-top: -1.0 ex;
   251:   padding-top: 0.0 em;
   252:   border-top-width: 0.0 em;
   253:   border-bottom-width: 0.0 em;
   254:   padding-bottom: 0.0 em;
   255:   margin-bottom: 0.0 em;
   256:   display: block;
   257:   display:none;
   258: }
   259: 
   260: DIV.DIFF_SECTION_HEAD SMALL, DIV.DIFF_SECTION_FOOT SMALL{
   261:   color : #503020;
   262:   font-size: 80%;
   263:   display: inline;
   264:   color: #101080;
   265: }
   266: DIV.DIFF_SECTION_HEAD STRONG, DIV.DIFF_SECTION_FOOT STRONG {
   267:   font-family : monospace, courier;
   268:   font-weight: normal;
   269:   font-size: 100%;
   270:   display: inline;
   271:   color : black;
   272: }
   273: DIV.DIFF_SECTION_HEAD EM, DIV.DIFF_SECTION_FOOT EM {
   274:   display: inline;
   275: }
   276: 
End data section to interscript/doc/interscript.css[1]
Start data section to interscript/doc/user.css[1] 1
     1: // dummy: to be replaced by the user

6.4.6. Web Weaver

This weaver creates a _single_ document consisting of a heirarchy of HTML pages , using hyperlinks from parent pages to child pages. The control weaver maintains a stack of weavers, delegating most commands to the weaver on the top of the stack.

However, when a heading command at a specified level is trapped, a new weaver is created and pushed onto the stack. When a heading at that same level is trapped again, the weaver on the top of the stack is popped, and a new weaver pushed in its place.

In this way, all headings at a certain level in a document will create a new html document.

A stacking weaver requires a list of montonic increasing integers to determine when to spawn a child page. When a child is spawned by a level n heading, that heading becomes the title of the spawned page, and a heading of level n+m is sent to the child as a level m heading.

On the other hand, it has to create separate sinks for each new weaver, except the top level (main page). This is currently done by supplying a prefix for the child page filenames, the stacking weaver appends a number representing the child number, in order the children were spawned.

Implementation notes. We maintain a document stack. Each document is triggered by the corresponding heading level from the supplied trigger list (which had better be strictly montonic increasing).

When we get a heading level n, we pop off weavers until n is greater than the trigger level of that weaver. (The test is performed first).

Then, we push documents onto the stack, until n is greater than or equal to the document trigger level. (The test is performed first).

Then, if n is the trigger level of the document, we use it as a title and hyperlink the document into it's parent, otherwise we just typeset the heading.

Note that the first loop will destroy a document whose trigger level is equal to the heading level, and the second loop will create a new document at this level.

6.4.6.1. Bugs

Summary: This weaver is not as flexible as it should be.

Child document filenames are simply the given prefix plus a sequentially generated count. The child weaver is always the system html weaver.

Headings in child pages are adjusted to start at level 1. The 'print level' offset is not inherited from the parent or controllable in any way.

Heading numbers in child documents never reflect the position in the whole document, only the child page; that is, the first heading in a child spawned by 2.3.4 will be 1, not 2.3.4.1.

Each page will have it's own table of contents. There's no overall table for the document. (This will require links to pages other than 'self').

There are no 'next, previous, home' type links anywhere, these are necessary.

The spawning weaver assumes HTML. There's no 'in principle' reason it shouldn't be possible to generate other documents this way. Although, for example, 'hyperlinks' in printed documents as would be produced by LaTeX will be of the form, 'see page 99 of such and such', they're hyperlinks never the less, even if they have to be followed by the 'manual' browser. :-)

In light of these comments, one can say the current system confuses production of multi-page web documents, and production of distinct separate documents (which happen to be hyperlinked).

6.4.6.2. Code

Start python section to interscript/weavers/web.py[1] 1 2 3 4 5 6 7 8
     1: #line 87 "web_weaver.ipk"
     2: from interscript.weavers.multiplexor import multiplexor
     3: from interscript.weavers.html import html_weaver
     4: from interscript.weavers.html import cvt_code, cvt_text
     5: from interscript.drivers.sinks.bufdisk import named_file_sink
     6: from interscript.drivers.sinks.disk import simple_named_file_sink
     7: from interscript.core.sets import set
     8: import string
     9: import traceback
    10: 
    11: 
    12: class stacking_weaver(multiplexor):
    13:   def mk_head(self, sink):
    14:     w = sink.writeline
    15:     w('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">')
    16:     w( '<HTML>')
    17:     w( '<HEAD>')
    18: 
    19:     w('<TITLE>'+self.title+'</TITLE>')
    20: 
    21:     w( '<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">')
    22:     if self.keywords.has_key('author'):
    23:       author =self.keywords['author']
    24:       self.frames_sink.writeline( '<META NAME="Author" CONTENT="'+author+'">')
    25:     version = self.process.global_frame.version
    26: 
    27:     w( '<META NAME="Generator" CONTENT="Interscript '+version+'">')
    28:     w( '</HEAD>')
    29: 
    30:   def mk_frame(self,name, orientation, subframes):
    31:     filename = self.pattern % name
    32:     sink = named_file_sink(
    33:       self.pass_frame,
    34:       self.basedir+filename,
    35:       self.master.weaver_prefix,
    36:       eol=self.eol)
    37:     self.mk_head(sink)
    38:     pc = ''
    39:     for frame_name,frame_percent,frame_src in subframes:
    40:       pc = pc + str(frame_percent)+'%,'
    41:     pc = pc[:-1]
    42:     w = sink.writeline
    43:     w( '<FRAMESET '+orientation+'="'+pc+'" scrolling="yes">')
    44:     for frame_name,frame_percent,frame_src in subframes:
    45:       w( '<FRAME NAME="'+frame_name+'" SRC="'+frame_src+'">')
    46:     w( '</FRAMESET>')
    47:     w( '</HTML>')
    48: 
    49:   def mk_frames(self, doc):
    50:     top = self.pattern % 'top' # top level frame
    51:     indexview = self.pattern % 'indexview'
    52:     indexnav = self.pattern % 'indexnav'
    53:     contents = self.pattern % 'toc'
    54:     classref = self.pattern % 'classref'
    55:     funcref = self.pattern % 'funcref'
    56:     identref = self.pattern % 'identref'
    57:     testref = self.pattern % 'testref'
    58:     filestatus = self.pattern % 'filestatus'
    59:     sectionref = self.pattern % 'sectionref'
    60:     sourceref = self.pattern % 'sourceref'
    61: 
    62:     self.mk_frame('indexview','ROWS', (
    63:       ('indexnav',20,indexnav),
    64:       ('indexdat',80,contents)))
    65:     self.mk_frame('top','COLS',(
    66:       ('indexview',30,indexview),
    67:       ('docview',70,doc)))
    68: 
    69:     nav = '';
    70:     for filename, description in [
    71:       (contents, 'Contents'),
    72:       (classref, 'Classes'),
    73:       (funcref, 'Functions'),
    74:       (identref, 'Identifiers'),
    75:       (testref, 'Tests'),
    76:       (filestatus, 'Status'),
    77:       (sectionref, 'Sections'),
    78:       (sourceref, 'Sources')
    79:       ]:
    80:       nav = nav + '<A HREF="'+filename+'" TARGET="indexdat">'+description+'</A> '
    81:     ha = '<A HREF="'+self.home_file+'" TARGET="docview">Home</A>'
    82:     nav = '<DIV CLASS="NAVIGATION">'+nav+' '+ha+'</DIV>'
    83: 
    84:     filename = self.pattern % 'indexnav'
    85:     sink = named_file_sink(
    86:       self.pass_frame,
    87:       self.basedir+filename,
    88:       self.master.weaver_prefix,
    89:       eol=self.eol)
    90:     self.mk_head(sink)
    91:     w = sink.writeline
    92:     w ('<BODY>')
    93:     w (nav)
    94:     w ('</BODY>')
    95:     w ('</HTML>')
    96: 
    97: 
    98:   def print_table(self,dict,sink):
    99:     keys = dict.keys()
   100:     keys.sort()
   101:     w = sink.writeline
   102:     w('<TABLE COLS="2" BORDER="1" CELLPADDING="2">')
   103:     for k in keys:
   104:       refs = dict[k]
   105:       w('<TR><TD VALIGN="Top"><CODE> '+k+' </CODE></TD><TD> ')
   106:       old_df = ''
   107:       for sf,sc,df,dc in refs:
   108:         key = (sf, sc)
   109:         if self.anchor_file.has_key(key):
   110:           child = self.anchor_file[key]
   111:         else:
   112:           child = ''
   113:         anchor = '<A HREF='+child+'#'+sf+':'+str(sc)+' TARGET="docview">'+str(dc)+'</A>'
   114: 
   115:         if old_df != '': w(', ')
   116:         if old_df != df:
   117:           w(df+': '+ anchor )
   118:           old_df = df
   119:         else:
   120:           w(anchor)
   121:       w('</TD></TR>')
   122:     w('</TABLE>')
   123: 
   124:   def __init__(self,parent_weaver, pattern='', break_list=None, **kwds):
   125:     self.pass_frame = parent_weaver.pass_frame
   126:     self.master = self.pass_frame.master
   127:     self.process = self.pass_frame.process
   128: 
   129:     self.sequence = self.pass_frame.get_new_sequence_number()
   130:     self.persistent_frame = self.master.get_persistent_frame(self.sequence)
   131: 
   132:     self.verbosity = self.pass_frame.verbosity
   133:     self.debug_missing_methods = 0
   134:     self.keywords = kwds
   135: 
   136:     self.original_filename = 'Unknown'
   137: 
   138:     self.toc_depth = self.keywords.get('toc_depth',99)
   139:     self.base = [parent_weaver]
   140:     parent_sink = parent_weaver.sink.name
   141:     self.basedir = string.join(string.split(parent_sink,'/')[:-1],'/')+'/'
   142:     if self.basedir == '/': self.basedir = ''
   143:     #print 'Base directory for stacking weaver is',self.basedir
   144:     self.home_file = string.split(parent_sink,'/')[-1]
   145:     if kwds.has_key('title'):
   146:       self.title = kwds['title']
   147:     elif hasattr(parent_weaver,'title'):
   148:       self.title = parent_weaver.title
   149:     else:
   150:       self.title = self.home_file
   151:     self.pattern = pattern
   152:     if string.find(pattern,'%') == -1:
   153:       self.pattern = self.pattern+'_%s.html'
   154:     # break list
   155:     self.break_list = [0]
   156:     if break_list:
   157:       for b in break_list: self.break_list.append(b)
   158:     else:
   159:       for i in range(1,40): self.break_list.append(i)
   160: 
   161:     self.stack = [parent_weaver]
   162:     self.childcount = 0
   163:     self.debug = 0
   164:     self.protocol = 'stacking weaver'
   165:     self.hcount = [1,0]
   166:     self.acount = 0
   167:     self.anchor_file = {}
   168:     self.name = 'stacking weaver'
   169:     self.eol = parent_weaver.sink.eol
   170: 
   171:     # table of contents
   172:     self.toc = []
   173: 
   174:     self.home_anchor = '<A HREF="'+self.home_file+'">Home</A>'
   175:     self.home_nav = '<DIV CLASS="NAVIGATION">'+self.home_anchor+'<BR><HR></DIV>'
   176: 
   177:     self.mk_frames(self.home_file)
   178: 
   179:     # cheat here, guess next exists :-)
   180:     next = self.pattern%('%04d'%(self.childcount+1))
   181:     next = '<A HREF="'+next+'">Next</A>'
   182: 
   183:     nav = ''
   184:     if next : nav = nav + next+' '
   185: 
   186:     hnav = '<HR><DIV CLASS="NAVIGATION">'+nav+'<BR><HR></DIV>'
   187:     parent_weaver._writeline(hnav)
   188: 
End python section to interscript/weavers/web.py[1]
6.4.6.2.1. reference processor
Start python section to interscript/weavers/web.py[2] 1 2 3 4 5 6 7 8
   189: #line 276 "web_weaver.ipk"
   190:   def set_original_filename(self, filename):
   191:     self.original_filename = filename
   192: 
   193:   def set_anchor(self, label):
   194:     href = self.pattern%('%04d'%(self.childcount))+'#'+label
   195:     self._write('<A NAME="'+label+'"></A>')
   196:     self.register_anchor(label, href)
   197: 
   198:   def register_anchor(self, label, anchor):
   199:     if not self.persistent_frame.has_key('anchors'):
   200:       self.persistent_frame['anchors']  = {}
   201:     self.persistent_frame['anchors'][label]=anchor
   202: 
   203:   def get_anchor(self, label):
   204:     href = None
   205:     if self.persistent_frame.has_key('anchors'):
   206:       if self.persistent_frame['anchors'].has_key(label):
   207:         href =self.persistent_frame['anchors'][label]
   208:     return href
   209: 
   210:   def ref_anchor(self, label):
   211:     href = self.get_anchor(label)
   212:     if href:
   213:       self._write('<A HREF="'+href+'">'+label+'</A>')
   214:     else:
   215:       self._write('<EM>Unknown Label:'+label+'</EM>')
   216: 
End python section to interscript/weavers/web.py[2]
6.4.6.2.2. section processor
Process code sections.
Start python section to interscript/weavers/web.py[3] 1 2 3 4 5 6 7 8
   217: #line 306 "web_weaver.ipk"
   218:   def _write_section_ref(self, filename, i, text=None):
   219:     if not text: text = str(i)
   220:     name = filename + '['+str(i)+']'
   221:     anchor = self.get_anchor(name)
   222:     if anchor:
   223:       anchor = '<A HREF="'+anchor+'">'+text+'</A>'
   224:       self._writeline (anchor+' ')
   225: 
   226:   def code_head(self,tangler, secno):
   227:     dst_filename = tangler.sink.name
   228:     self.set_anchor(dst_filename+'['+str(secno)+']')
   229:     self._endmode()
   230:     filename =tangler.sink.get_sink_name()
   231:     language = tangler.get_language()
   232:     dict = self.master.section_index
   233:     if dict.has_key(filename):
   234:       nsections = len(dict[filename])
   235:     else: nsections = 0
   236:     w = self._write
   237:     wl = self._writeline
   238:     w ( '<DIV CLASS="CODE_SECTION_HEAD"><SMALL>Start <EM>'+\
   239:       language+'</EM> section to <STRONG>'+\
   240:       filename+'['+str(secno))
   241:     if nsections: w('/'+str(nsections))
   242:     w(']</STRONG></SMALL>')
   243: 
   244:     if nsections:
   245:       if secno != nsections:
   246:         self._write_section_ref(filename, secno+1, 'Next')
   247:       if secno!=1:
   248:         self._write_section_ref(filename, secno-1, 'Prev')
   249:       if secno !=1:
   250:         self._write_section_ref(filename, 0, 'First')
   251:       if secno != nsections:
   252:         self._write_section_ref(filename, nsections, 'Last')
   253:     wl ('</DIV>')
   254:     wl ( '<DIV CLASS="CODE">')
   255: 
End python section to interscript/weavers/web.py[3]
6.4.6.2.3. heading processor
The title of the main document is level 0. The top level content of that document is level 1. A heading inserted into the document is level 1. After a level 1 heading is inserted, the immediately following content is level 2.

The hcount list is a list of current heading numbers at each level, including 0. The current document level is the length of this list, minus 1. The last entry in the list is always 0, except briefly when a heading is being generated at that level.

Start python section to interscript/weavers/web.py[4] 1 2 3 4 5 6 7 8
   256: #line 355 "web_weaver.ipk"
   257:   def _current_level(self): return len(self.hcount)-1
   258:   def _pop_level(self): del self.hcount[-1]
   259:   def _push_level(self): self.hcount.append(0)
   260:   def _next_hnum(self): self.hcount[-1] = self.hcount[-1] + 1
   261: 
   262:   def head(self,level, text, atext='', anchor=''):
   263:     while level > self._current_level():
   264:       self._head(text, atext,anchor)  # synthesised dummy heading
   265:       self._push_level()
   266:     while level < self._current_level():
   267:       self._pop_level()
   268:       self._foot()
   269:     assert level == self._current_level()
   270:     self._next_hnum()
   271:     self._head(text, atext, anchor)
   272:     self._push_level()
   273:     assert self._current_level() == level + 1
   274: 
End python section to interscript/weavers/web.py[4]
6.4.6.2.4. document control
The break level of a page is the level of it title, so the top level content of that page is 1 more than its break level.
Start python section to interscript/weavers/web.py[5] 1 2 3 4 5 6 7 8
   275: #line 377 "web_weaver.ipk"
   276:   # if the current page has a break level equal to the current level pop it
   277:   # (we'd print a footer first if we used them)
   278:   def _foot(self):
   279:     if self._trig(0) == self._current_level():
   280:       self._popw()
   281: 
   282:   def _head(self,text, atext, anchor):
   283:     level = self._current_level()
   284:     if level == self._trig(1):
   285:       self._pushw(level,text,atext,anchor)
   286:     else:
   287:      self._ins_head(level,text,atext,anchor)
   288: 
   289:   def __del__(self):
   290:     try:
   291:       self.mk_funcref(self.pattern % 'funcref','docview')
   292:       self.mk_classref(self.pattern % 'classref','docview')
   293:       self.mk_identref(self.pattern % 'identref','docview')
   294:       self.mk_contents(self.pattern % 'toc','docview')
   295:       self.mk_testref(self.pattern % 'testref','docview')
   296:       self.mk_sectionref(self.pattern % 'sectionref','docview')
   297:       self.mk_sourceref(self.pattern % 'sourceref','docview')
   298:       self.mk_filestatus(self.pattern % 'filestatus')
   299:     except:
   300:       print 'Error in stacking weaver __del__ routine'
   301:       traceback.print_exc()
   302: 
   303:   def get_formatted_heading_number(self, sep):
   304:     hnumber = ''
   305:     for i in range(1,len(self.hcount)-1):
   306:       hnumber = hnumber + str(self.hcount[i])+'.'
   307:     hnumber = hnumber + str(self.hcount[-1])
   308:     return hnumber
   309: 
   310:   def _popw(self):
   311:     if self.debug or self.verbosity>=6 :
   312:       print 'Terminating weaver',self.stack[-1].name
   313:     del self.stack[-1]
   314:     self.base = [self.stack[-1]]
   315: 
   316:   def _new_child(self):
   317:     self.childcount = self.childcount + 1
   318:     last = self.persistent_frame.get('lastchild',-1)
   319:     self.persistent_frame['lastchild']=max(last,self.childcount)
   320:     return self.pattern % ('%04d' % self.childcount)
   321: 
   322:   def _pushw(self,level,text,atext,label):
   323:     filename = self._new_child()
   324:     if label:
   325:       anchor = self.pattern%('%04d'%(self.childcount))
   326:       self.register_anchor(label, anchor)
   327: 
   328:     #print 'Spawning Weaver',filename,'for',text
   329:     self.base = [self.stack[-1]]
   330:     hn = self.get_formatted_heading_number('.')+'.'
   331:     hnum = self.get_formatted_heading_number('_')
   332:     h = hn + ' '+text
   333:     self.toc.append([level,hnum,filename,h])
   334:     self._ensuremode('P')
   335:     self._writeline( '<BR><A HREF="'+filename+'">'+h+'</A>')
   336: 
   337:     # create navigation links (kludge!)
   338:     home = self.home_anchor
   339:     up = None
   340:     try:
   341:       up = string.split(self.base[0].sink.name,'/')[-1]
   342:       up_anchor = '<A HREF="'+up+'">Up</A>'
   343:     except: pass
   344: 
   345:     if self.childcount > 1:
   346:       prev = self.pattern % ('%04d'%(self.childcount-1))
   347:       prev_anchor= '<A HREF="'+prev+'">Prev</A>'
   348:     else: prev = None
   349: 
   350:     last = self.persistent_frame.get('lastchild',None)
   351:     if last and self.childcount == last:
   352:       next = None
   353:     else:
   354:       next = self.pattern%('%04d'%(self.childcount+1))
   355:       next_anchor = '<A HREF="'+next+'">Next</A>'
   356: 
   357:     this = self.pattern%('%04d'%(self.childcount))
   358:     this_anchor = '<A HREF="'+this+'">This</A>'
   359: 
   360:     nav = ''
   361:     if next : nav = nav + next_anchor+' '
   362:     if up : nav = nav + up_anchor+' '
   363:     if prev : nav = nav + prev_anchor+' '
   364:     if home: nav = nav + home+' '
   365:     nav = nav + this_anchor+' <SMALL>['+self.original_filename+']</SMALL>'
   366: 
   367:     hnav = '<DIV CLASS="NAVIGATION">'+nav+'<BR><HR></DIV>'
   368:     fnav = '<DIV CLASS="NAVIGATION"><BR><HR>'+nav+'</DIV>'
   369: 
   370:     extra = '<LINK type="text/html" rel="Contents" href="'+self.pattern % 'toc' +'">\r\n'
   371:     extra = '<LINK type="text/html" rel="Identifiers" href="'+self.pattern % 'identref'+'">\r\n'
   372:     extra = '<LINK type="text/html" rel="Classes" href="'+self.pattern % 'classref'+'">\r\n'
   373:     extra = '<LINK type="text/html" rel="Functions" href="'+self.pattern % 'funcref'+'">\r\n'
   374:     extra = extra + '<LINK type="text/html" rel="Start" href="'+self.home_file+'">\r\n'
   375:     if next: extra = extra + '<LINK type="text/html" rel="Next" href="'+next+'">\r\n'
   376:     if prev: extra = extra + '<LINK type="text/html" rel="Prev" href="'+prev+'">\r\n'
   377:     if up: extra = extra + '<LINK type="text/html" rel="Section" href="'+up+'">\r\n'
   378: 
   379:     sink = named_file_sink(self.pass_frame, self.basedir + filename, self.master.weaver_prefix, self.eol)
   380:     child = html_weaver(
   381:       self.pass_frame, sink,
   382:       title = h,
   383:       pagehead = hnav,
   384:       pagefoot=fnav,
   385:       heading_prefix=hn,
   386:       head_extra=extra,
   387:       anchor=label)
   388:     self.base = [child]
   389:     self.stack.append(child)
   390: 
   391:   def _trig(self,offset=0):
   392:     doc_level = len(self.stack)-1 # 0 origin
   393:     return self.break_list[doc_level+offset]
   394: 
   395:   def _ins_head(self,level,text,atext,anchor):
   396:     adjusted_level = level - self._trig()
   397:     if anchor == '':
   398:       anchor = 'a'+str(self.acount)
   399:       self.acount = self.acount + 1
   400:     hn = self.get_formatted_heading_number('.')+'.'
   401:     hnum = self.get_formatted_heading_number('_')
   402:     h = hn + ' '+text
   403:     filename = self.pattern%('%04d'%self.childcount)
   404:     self.toc.append([level,hnum,filename+'#'+anchor,h])
   405:     for weaver in self.base:
   406:       weaver.head(adjusted_level,text,atext,anchor)
   407: 
End python section to interscript/weavers/web.py[5]
6.4.6.2.5. Table of contents
6.4.6.2.5.1. MSIE DOM ECMAScript
ECMAscript for Microsoft Internet Explorer Docuement Object Model.
Start python section to interscript/weavers/web.py[6] 1 2 3 4 5 6 7 8
   408: #line 513 "web_weaver.ipk"
   409:   MSIE_treehandler = """
   410: <SCRIPT type="text/javascript">
   411: <!--
   412: function clickHandler() {
   413:   var targetId, srcElement, targetElement;
   414:   srcElement = window.event.srcElement;
   415:   if (srcElement.className == "Button") {
   416:     targetId = srcElement.id + "d";
   417:     targetElement = document.all(targetId);
   418:     if(targetElement.style.display == "none") {
   419:       targetElement.style.display = "";
   420:       srcElement.checked = true;
   421:     } else {
   422:       targetElement.style.display = "none";
   423:       srcElement.checked = false;
   424:     }
   425:   }
   426: }
   427: 
   428: // this function restores the status of the contents tree
   429: // IE4 preserves the buttons states, but not the visibility
   430: function loadHandler() {
   431:   for (var srcId in document.all) {
   432:     srcElement = document.all(srcId);
   433:     if (srcElement != null && srcElement.className == "Button") {
   434:       var targetId = srcId + "d";
   435:       var targetElement = document.all(targetId);
   436:       if(srcElement.checked == true) {
   437:         targetElement.style.display = "";
   438:       } else {
   439:         targetElement.style.display = "none";
   440:       }
   441:     }
   442:   }
   443: }
   444: document.onclick = clickHandler
   445: document.onload = loadHandler
   446: // -->
   447: </SCRIPT>
   448: """
   449: 
End python section to interscript/weavers/web.py[6]
6.4.6.2.5.2. Table of contents generator
Make the table of contents.
Start python section to interscript/weavers/web.py[7] 1 2 3 4 5 6 7 8
   450: #line 557 "web_weaver.ipk"
   451:   def mk_contents(self,toc_filename,target):
   452:     self.toc_sink = named_file_sink(
   453:       self.pass_frame,
   454:       self.basedir+toc_filename,
   455:       self.master.weaver_prefix,
   456:       eol=self.eol)
   457:     self.mk_head(self.toc_sink)
   458:     w = self.toc_sink.writeline
   459:     w( '<BODY onload="loadHandler()">')
   460:     if not target:
   461:       nav = '<DIV CLASS="NAVIGATION">'+self.home_anchor+' '+self.frames_anchor+'<BR><HR></DIV>'
   462:       self.toc_sink.writeline(nav)
   463:     w('<H1>Table of Contents</H1>')
   464:     w(stacking_weaver.MSIE_treehandler)
   465:     last_level = -1
   466:     if self.toc:
   467:       i = 0
   468:       level, hnum, href, text = self.toc[i]
   469:       next_level = 0
   470:       if len(self.toc) > i+1: next_level = self.toc[i+1][0]
   471:       self.emit_contents_line(level, hnum, href, text, level<next_level, target)
   472:       divid = 'h'+hnum+'d'
   473:       w('<DIV ID='+divid+' style="display:">')
   474:       last_level = level
   475:     for i in range(1, len(self.toc)):
   476:       level, hnum, href, text = self.toc[i]
   477:       next_level = 0
   478:       if len(self.toc) > i+1: next_level = self.toc[i+1][0]
   479:       while level <= last_level:
   480:         self.toc_sink.writeline('</DIV>')
   481:         last_level = last_level - 1
   482:       self.emit_contents_line(level, hnum, href, text, level<next_level, target)
   483:       divid = 'h'+hnum+'d'
   484:       w('<DIV ID='+divid+' style="display:">')
   485:       last_level = level
   486:     while 1 <= last_level:
   487:       w('</DIV>')
   488:       last_level = last_level - 1
   489:     w( '</BODY>')
   490:     w( '</HTML>')
   491:     del self.toc_sink
   492: 
   493:   def emit_contents_line(self, level, hnum, href, text, enabled, target):
   494:     self.toc_sink.writeline(' '*(3*level))
   495:     headid ='h'+hnum
   496:     flag = 'disabled'
   497:     if enabled: flag = ''
   498:     self.toc_sink.writeline('<INPUT ID='+headid+' CLASS="Button" TYPE="Radio" '+flag+'>')
   499:     if target:
   500:       self.toc_sink.writeline('<A HREF="'+href+'" TARGET="'+target+'">'+text+'</A>')
   501:     else:
   502:       self.toc_sink.writeline('<A HREF="'+href+'">'+text+'</A>')
   503: 
End python section to interscript/weavers/web.py[7]
6.4.6.2.6. Identifier Cross references
This is a bit hacky. When a tangler calls 'set_fc_anchor' with a file name and line number, an anchor with the name
  original_file_name + ':' + str(original_lineno)
is generated. Tanglers which call this function supply the original source file name and line number (not the file and line being written to).

Tanglers generate an entry for the identifier occurence which contains both the original source file and line number, and the output code file and line number.

The cross reference table the html weaver generates displays the output code file and line number (not the orginal file and line number), but it generates a reference of the form

  '#' + original_file_name + ':' + str(original_lineno)
using the original file name and line number.

The stacking weaver must trap calls to 'identifier_reference' because the hyperlinks the child weaver charged with generating this table would fail to refer to the specific html file containing the anchor. Instead, the stacking weaver must build the table.

To do that, the stacking weaver must know in which html child document the reference was generated so it can generate a hyperlink of the form:

  childname + '#' + original_file_name + ':' + str(original_lineno)
Unfortunately, the ids dictionary in the global frame currently being used to hold identifier cross references on a document wide basis, does not have this information available. It wouldn't make sense either, the information in that table is generated by tanglers, and has nothing to do with the weaver.

Therefore, the stacking weaver must _also_ intercept calls to 'set_fc_anchor', and create an entry in a dictionary keyed by the original filename and original line number, which tells in which html file the anchor was set: the stacking weaver knows that!

Start python section to interscript/weavers/web.py[8] 1 2 3 4 5 6 7 8
   504: #line 658 "web_weaver.ipk"
   505:   def mk_identref(self,filename,target):
   506:     sink = named_file_sink(
   507:       self.pass_frame,
   508:       self.basedir+filename,
   509:       self.master.weaver_prefix,
   510:       eol=self.eol)
   511:     self.mk_head(sink)
   512:     w = sink.writeline
   513:     w( '<BODY>')
   514: 
   515:     ids = self.master.ids
   516:     if len(ids) == 0:
   517:       ids = self.pass_frame.ids
   518:     w('<H1>Index of Identifiers</H1>')
   519:     self.print_table(ids,sink)
   520: 
   521:     w('</BODY>')
   522:     w('</HTML>')
   523: 
   524:   def mk_sectionref(self,filename,target):
   525:     sink = named_file_sink(
   526:       self.pass_frame,
   527:       self.basedir+filename,
   528:       self.master.weaver_prefix,
   529:       eol=self.eol)
   530:     self.mk_head(sink)
   531:     w = sink.writeline
   532:     w( '<BODY>')
   533: 
   534:     dict = self.pass_frame.section_index
   535:     w('<H1>Index of Sections</H1>')
   536:     keys = dict.keys()
   537:     keys.sort()
   538:     w = sink.writeline
   539:     w('<TABLE COLS="1" BORDER="1" CELLPADDING="2">')
   540:     for k in keys:
   541:       w('<TR><TD VALIGN="Top"><CODE> '+k+' </CODE>: ')
   542:       nsections = len(dict[k])
   543:       for i in range(nsections):
   544:         name = k + '['+str(i+1)+']'
   545:         anchor = '<A HREF="'+self.get_anchor(name)+\
   546:           '" TARGET="'+target+'">'+str(i+1)+'</A>'
   547:         w(anchor+' ')
   548:       w('</TD></TR>')
   549:     w('</TABLE>')
   550:     w('</BODY>')
   551:     w('</HTML>')
   552: 
   553:   def mk_classref(self,filename,target):
   554:     sink = named_file_sink(
   555:       self.pass_frame,
   556:       self.basedir+filename,
   557:       self.master.weaver_prefix,
   558:       eol=self.eol)
   559:     w = sink.writeline
   560:     self.mk_head(sink)
   561:     w( '<BODY>')
   562: 
   563:     ids = self.master.classes
   564:     if len(ids) == 0:
   565:       ids = self.pass_frame.classes
   566:     w('<H1>Index of Classes</H1>')
   567:     self.print_table(ids,sink)
   568:     w('</BODY>')
   569:     w('</HTML>')
   570: 
   571:   def mk_funcref(self,filename,target):
   572:     sink = named_file_sink(
   573:       self.pass_frame,
   574:       self.basedir+filename,
   575:       self.master.weaver_prefix,
   576:       eol=self.eol)
   577:     w = sink.writeline
   578:     self.mk_head(sink)
   579:     w( '<BODY>')
   580: 
   581:     ids = self.master.functions
   582:     if len(ids) == 0:
   583:       ids = self.pass_frame.functions
   584:     w('<H1>Index of Functions</H1>')
   585:     self.print_table(ids,sink)
   586: 
   587:     w('</BODY>')
   588:     w('</HTML>')
   589: 
   590:   def mk_sourceref(self,filename,target):
   591:     sink = named_file_sink(
   592:       self.pass_frame,
   593:       self.basedir+filename,
   594:       self.master.weaver_prefix,
   595:       eol=self.eol)
   596:     w = sink.writeline
   597:     self.mk_head(sink)
   598:     w( '<BODY>')
   599: 
   600:     w('<H1>Source tree</H1>')
   601:     data = self.master.include_files
   602:     if not data:
   603:       data = self.pass_frame.include_files
   604: 
   605:     for level, type, name in data:
   606:       w(' '*(level*3)+' '+type+': '+name+ '<BR>')
   607: 
   608:     w('</BODY>')
   609:     w('</HTML>')
   610: 
   611:   def mk_testref(self,filename,target):
   612:     sink = named_file_sink(
   613:       self.pass_frame,
   614:       self.basedir+filename,
   615:       self.master.weaver_prefix,
   616:       eol=self.eol)
   617:     w = sink.writeline
   618:     self.mk_head(sink)
   619:     w( '<BODY>')
   620: 
   621:     ids = self.master.tests
   622:     if len(ids) == 0:
   623:       ids = self.pass_frame.tests
   624:     w('<H1>Index of Tests</H1>')
   625:     w('<TABLE CLASS="TEST_SUMMARY_TABLE" COLS="4" BORDER="1">')
   626:     w('<TR><TH>No</TH><TH>Description</TH><TH>Kind</TH><TH>Result</TH><TR>')
   627:     keys = ids.keys()
   628:     keys.sort()
   629:     for key in keys:
   630:       descr, label, kind, result = ids[key]
   631:       href = self.get_anchor(label)
   632:       w('<TR><TD>'+str(key)+'</TD><TD><A TARGET="'+target+'" HREF="'+href+'">'+descr+'</A></TD><TD>'+kind+'</TD><TD>'+result+'</TD></TR>')
   633:     w('</TABLE>')
   634:     w('</BODY>')
   635:     w('</HTML>')
   636: 
   637:   def mk_filestatus(self,filename):
   638:     print 'Creating file status file:',filename
   639:     filestatus_output = simple_named_file_sink(
   640:       self.pass_frame,self.basedir+filename, self.master.weaver_prefix,eol='\r\n')
   641:     filestatus_weaver = html_weaver(
   642:       self.pass_frame,
   643:       filestatus_output,title='File Status')
   644:     filestatus_weaver.print_file_status(hlevel=1)
   645: 
   646:   def set_fc_anchor(self,file,count):
   647:     filename = self.base[0].sink.basename
   648:     self.anchor_file[(file,count)]=filename
   649:     for weaver in self.base:
   650:       weaver.set_fc_anchor(file,count)
   651: 
   652:   def heading_reference(self, *args, **kwds): pass # always generated
   653:   def identifier_reference(self, *args, **kwds): pass # always generated
   654:   def class_reference(self, *args, **kwds): pass # always generated
   655:   def function_reference(self, *args, **kwds): pass # always generated
   656:   def test_reference(self, *args, **kwds): pass # always generated
   657: 
   658: 
End python section to interscript/weavers/web.py[8]

6.4.6.3. Test Code

Start python section to interscript/tests/test_stacking_weaver.pak[1] 1
     1: #line 815 "web_weaver.ipk"
     2: @mysink = named_file_sink(get_pass_frame(),'interscript/tests/output/test_stacking_weaver.html',eol='\r\n')
     3: @weaver = html_weaver(get_pass_frame(),mysink, title='Stacking Weaver Test')
     4: @weaver = stacking_weaver(weaver,'swt_%s.html',[1,3,99,99,99])
     5: Simple test for stacking weaver : headings are:
     6: @begin_displayed_code()
     7: 1 (link)
     8:   1.1 (internal)
     9:   1.2 (internal)
    10:     1.2.1 (link)
    11:     1.2.2 (link)
    12:           1.2.2.1 (internal)
    13:           1.2.2.2 (internal)
    14:           1.2.2.3 (internal)
    15:     1.2.3
    16: 2
    17: 3.
    18: @end_displayed_code()
    19: Documents should be spawned at level 1 and 3.
    20: @head(1,'Heading 1')
    21: This is a stacking weaver test.
    22: @head(2,'Heading 1.1')
    23: This is a stacking weaver test.
    24: @head(2,'Heading 1.2')
    25: This is a stacking weaver test.
    26: @head(3,'Heading 1.2.1')
    27: This is a stacking weaver test.
    28: @head(3,'Heading 1.2.2')
    29: This is a stacking weaver test.
    30: @head(4,'Heading 1.2.2.1')
    31: This is a stacking weaver test.
    32: @head(4,'Heading 1.2.2.2')
    33: This is a stacking weaver test.
    34: @head(4,'Heading 1.2.2.3')
    35: This is a stacking weaver test.
    36: @head(3,'Heading 1.2.3')
    37: This is a stacking weaver test.
    38: @head(1,'Heading 2')
    39: This is a stacking weaver test.
    40: @head(1,'Heading 3')
    41: This is a stacking weaver test.
End python section to interscript/tests/test_stacking_weaver.pak[1]
Click interscript/tests/output/test_stacking_weaver.html for result. See diagnostics from the run below.
Start output section of "/usr/local/bin/python" interscript/bin/iscr.py --test interscript/tests/test_stacking_weaver.pak
     1: Interscript test mode, loading interscript from current directory
     2: Interscript version 1.0a8 build 1384
     3: Built by root on ruby at Mon Nov 30, 1998 at 08:56 AM (UTC)
     4: Generated by 1.0a8 buildno 1383 host ruby
     5: at Mon Nov 30, 1998 at 08:56 AM (UTC)
     6: 
     7: ---------------------------------
     8: Interscript 1.0a8[1384] Process Mon 30 Nov, 1998 20:44:56 (EST)
     9: Processing test_stacking_weaver.pak Pass 0
    10: Creating file status file: swt_filestatus.html
    11: Of 11 files, only 0 were stable on pass 0
    12: There were 11 new files,
    13: and 0 unstable files.
    14: Elapsed Process Time 0 seconds
    15: ================================
    16: 
End output section to "/usr/local/bin/python" interscript/bin/iscr.py --test interscript/tests/test_stacking_weaver.pak

6.4.7. LaTeX Weaver

This weaver generates LaTeX2e codes. You'll require a full LaTeX2e installation to typeset it, along with common standard packages such as makeidx.
Start python section to interscript/weavers/latex.py[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
     1: #line 8 "latex_weaver.ipk"
     2: from interscript.weavers.base import weaver_base
     3: import string
     4: 
     5: def cvt_code(line):
     6:   v = '\\verb+'
     7:   for ch in line:
     8:     if ch != '+': v = v + ch
     9:     else: v = v + '+\\verb-+-\\verb+'
    10:   v = v + '+'
    11:   return v
    12: 
    13: def cvt_text(line):
    14:   l = ''
    15:   for ch in line:
    16:     if ch in '$&%#_^{}\\': l = l + '\\'
    17:     l = l + ch
    18:   return l
    19: 
    20: class latex_weaver(weaver_base):
End python section to interscript/weavers/latex.py[1]

6.4.7.1. Initialisation

Start python section to interscript/weavers/latex.py[2] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
    21: #line 29 "latex_weaver.ipk"
    22:   def __init__(self, pass_frame, writer ,**kwds):
    23:     weaver_base.__init__(self, pass_frame)
    24:     self.verbosity = pass_frame.verbosity
    25:     self.sink = writer
    26:     if self.verbosity>=3:
    27:       print 'initialising latex weaver, writer',writer.get_sink_name()
    28:     self.protocol = 'LaTeX2e'
    29:     self.acount = 1
    30:     self.tag_stack = []
    31:     self.comments = 0
    32:     self.master = pass_frame.master
    33:     self.list = []
    34:     self.heading_level_offset = 0
    35:     self.name = 'latex2e weaver v1 for '+self.sink.name
    36:     self.verbatim = 0
    37:     self.prolog(kwds)
    38: 
End python section to interscript/weavers/latex.py[2]

6.4.7.2. Termination

Start python section to interscript/weavers/latex.py[3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
    39: #line 48 "latex_weaver.ipk"
    40:   def __del__(self):
    41:     self.epilog()
    42: 
End python section to interscript/weavers/latex.py[3]

6.4.7.3. Identifier Cross Reference Table

Start python section to interscript/weavers/latex.py[4] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
    43: #line 53 "latex_weaver.ipk"
    44:   def identifier_reference(self, hlevel=2, *args, **kwds):
    45:     ids = self.master.ids
    46:     keys = ids.keys()
    47:     keys.sort()
    48:     if hlevel >0:
    49:       self.head(hlevel,'Index of Identifiers')
    50:     self._writeline('\\begin{tabular}{ll}')
    51:     for k in keys:
    52:       refs = ids[k]
    53:       self._write(cvt_code(k)+'&')
    54:       old_df = ''
    55:       for sf,sc,df,dc in refs:
    56:         if old_df != '': self._write(', ')
    57:         if old_df != df:
    58:           self._writeline(cvt_code(df)+': '+str(dc)+'\\ref{'+sf+':'+str(sc)+'}')
    59:           old_df = df
    60:         else:
    61:           self._write(': '+str(dc)+'\\ref{'+sf+':'+str(sc)+'}')
    62:       self._write('\\\\\n')
    63:     self._writeline('\\end{tabular}\n')
    64: 
End python section to interscript/weavers/latex.py[4]

6.4.7.4. Class Reference Table

Start python section to interscript/weavers/latex.py[5] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
    65: #line 76 "latex_weaver.ipk"
    66:   def class_reference(self, hlevel=2, *args, **kwds):
    67:     ids = self.master.classes
    68:     keys = ids.keys()
    69:     keys.sort()
    70:     if hlevel >0:
    71:       self.head(hlevel,'Index of Classes')
    72:     self._writeline('\\begin{tabular}{ll}')
    73:     for k in keys:
    74:       refs = ids[k]
    75:       self._write('\\verb+'+k+'+&')
    76:       old_df = ''
    77:       for sf,sc,df,dc in refs:
    78:         if old_df != '': self._write(', ')
    79:         if old_df != df:
    80:           self._writeline(cvt_code(df)+': '+str(dc)+'\\ref{'+sf+':'+str(sc)+'}')
    81:           old_df = df
    82:         else:
    83:           self._writeline(': '+str(dc)+'\\ref{'+sf+':'+str(sc)+'}')
    84:       self._write('\\\\\n')
    85:     self._writeline('\\end{tabular}\n')
    86: 
    87:   # create a Latex anchor
    88:   def set_fc_anchor(self,file,count):
    89:     self._write('\\label{'+file+':'+str(count)+'}')
    90: 
End python section to interscript/weavers/latex.py[5]

6.4.7.5. Table of Contents

Start python section to interscript/weavers/latex.py[6] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
    91: #line 103 "latex_weaver.ipk"
    92:   def print_contents(self,*args,**kwds):
    93:     self._writeline('\\tableofcontents')
    94: 
End python section to interscript/weavers/latex.py[6]

6.4.7.6. Code File List

Start python section to interscript/weavers/latex.py[7] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
    95: #line 108 "latex_weaver.ipk"
    96:   def print_file_list(self, hlevel=2, *args, **kwds):
    97:     self.head(hlevel,'File List')
    98:     for line in self.master.flist:
    99:       self._writeline(cvt_code(line))
   100: 
End python section to interscript/weavers/latex.py[7]

6.4.7.7. Source List

Start python section to interscript/weavers/latex.py[8] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   101: #line 115 "latex_weaver.ipk"
   102:   def print_source_list(self, hlevel=2, *args, **kwds):
   103:     self.head(hlevel,'Source List')
   104:     for line in self.master.iflist:
   105:       self._writeline(cvt_code(line))
   106: 
End python section to interscript/weavers/latex.py[8]

6.4.7.8. Latex Preamble

This is a very complex section that provides the latex preamble and document front matter. The basic command is like: @w = latex_weaver(sink,documentclass='book', documentclass_options=['a4paper','11pt'],topmargin='4pt'). [Typeset this as a display .. when the code is done for that feature]
Start python section to interscript/weavers/latex.py[9] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   107: #line 127 "latex_weaver.ipk"
   108:   def prolog(self,kwds):
   109: 
   110:     # see Kopka pp25-27
   111:     # the default document class is for a book
   112:     # other standard classes include:
   113:     #   article report letter
   114: 
   115:     documentclass = 'book'
   116:     if kwds.has_key('documentclass'):
   117:       documentclass=kwds['documentclass']
   118: 
   119:     # the options are a python list of words
   120:     # for the standard book class they're from the set:
   121:     #   10pt 11pt 12pt
   122:     #   letterpaper legalpaper executivepaper
   123:     #   a4paper a5paper b5paper
   124:     #   landscape
   125:     #   onecolumn twocolumn
   126:     #   oneside twoside
   127:     #   openright openany
   128:     #   notitlepage titlepage
   129: 
   130:     # note: the default paper size Latex uses is
   131:     # american letterpaper. Don't count on this,
   132:     # I intend to make the ISO Standard A4 that everyone
   133:     # else uses the default!
   134: 
   135:     docopts = []
   136:     if kwds.has_key('documentclass_options'):
   137:       docopts =kwds['documentclass']
   138:     docoptstr=''
   139:     if docopts: docoptstr = docopts[0]
   140:     for opt in range(1,len(docopts)):
   141:      docoptstr = dosoptstr + ', ' + opt
   142:     self._writeline('\\documentclass['+docoptstr+']{'+documentclass+'}')
   143: 
   144:     if kwds.has_key('heading_level_offset'):
   145:       self.heading_level_offset = kwds['heading_level_offset']
   146: 
   147:     # page heading control
   148:     pagestyle = 'headings'
   149:     if kwds.has_key('pagestyle'):
   150:       pagestyle=kwds['pagestyle']
   151:     self._writeline('\\pagestyle{'+pagestyle+'}')
   152: 
   153:     pagenumbering= 'arabic'
   154:     if kwds.has_key('pagenumbering'):
   155:       pagenumbering=kwds['pagenumbering']
   156:     self._writeline('\\pagenumbering{'+pagenumbering+'}')
   157: 
   158:     # page layout
   159:     page_format_params = [
   160:       'topmargin','headheight','headsep','topskip','textheight','footskip',
   161:       'oddsidemargin','evensidemargin',
   162:       'textwidth']
   163:     for p in page_format_params:
   164:       if kwds.has_key(p):
   165:         param=kwds[p]
   166:         self._writeline('\\setlength{\\'+p+'}{'+param+'}')
   167: 
   168:     # lines and paragraphs
   169: 
   170:     # Note: we do _not_ permit indented paragraphs AT ALL.
   171:     # Don't even try it. FAR FAR too many things are broken
   172:     # by indentation.
   173: 
   174:     baselinestretch= 1
   175:     if kwds.has_key('baselinestretch'):
   176:       baselinestretch=kwds['baselinestretch']
   177:     self._writeline('\\renewcommand{\\baselinestretch}{'+str(baselinestretch)+'}')
   178: 
   179:     self._writeline('\\setlength{\\parskip 2mm plus 0.5mm minus 1mm}')
   180:     self._writeline('\\setlength{\\parindent 0mm}')
   181: 
   182:     self._writeline( '\\begin{document}')
   183:     if kwds.has_key('title'):
   184:       title=kwds['title']
   185:     else:
   186:       title = self.sink.pass_frame.master.filename
   187:     self._writeline('\\title{'+cvt_text(title)+'}')
   188:     if kwds.has_key('author'):
   189:       author =kwds['author']
   190:       self._writeline('\\author{'+cvt_text(author)+'}')
   191: 
   192:     self._writeline( '\\maketitle')
   193: 
   194:   def epilog(self):
   195:     self._writeline('\\end{document}')
   196: 
End python section to interscript/weavers/latex.py[9]

6.4.7.9. Body Output and Mode Control

Start python section to interscript/weavers/latex.py[10] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   197: #line 218 "latex_weaver.ipk"
   198:   def _writeline(self,line=''):
   199:     if self.enabled: self.sink.writeline(line)
   200: 
   201:   def _write(self,line):
   202:     if self.enabled: self.sink.write(line)
   203: 
   204:   def write(self,line):
   205:     if self.translating and not self.verbatim:
   206:       line = string.rstrip(line)
   207:       if line == '': return # don't print any blank lines
   208:       self._write(cvt_text(line))
   209:     else:
   210:       self._write(line)
   211: 
   212:   def writeline(self,line=''):
   213:     self.write(line);
   214:     self._writeline()
   215: 
   216:   def writecode(self,line):
   217:     self._writeline('\\hbox to 0pt{'+cvt_code(line)+'\\hss}\\\\')
   218: 
   219:   def begin_displayed_text(self):
   220:     self._write('\\begin{quote}\n')
   221: 
   222:   def end_displayed_text(self):
   223:     self._write('\\end{quote}\n')
   224: 
   225: 
   226:   def begin_displayed_code(self):
   227:     self._writeline('\\begin{verbatim}')
   228:     self.verbatim = 1
   229: 
   230:   def end_displayed_code(self):
   231:     self._writeline('\\end{verbatim}')
   232:     self.verbatim = 0
   233: 
   234:   def line_break(self):
   235:     self._writeline('\\newline')
   236: 
   237:   def page_break(self):
   238:     self._writeline('\\newpage')
   239: 
   240:   def write_tagged(self,tag, data):
   241:     self._write('{\\'+tag)
   242:     self._write(data)
   243:     self._write('}')
   244: 
   245: 
   246:   def code_head(self,tangler, secno):
   247:     if tangler:
   248:       self._write( '{\\par\\noindent\\small Start section to '+\
   249:         cvt_code(tangler.sink.get_sink_name())+\
   250:         '['+str(secno)+']}\\\\')
   251: 
   252:   def code_foot(self,tangler, secno):
   253:     if tangler:
   254:       self._write( '{\\small End section to '+\
   255:         cvt_code(tangler.sink.get_sink_name())+\
   256:         '['+str(secno)+']}')
   257: 
End python section to interscript/weavers/latex.py[10]

6.4.7.10. Headings

Start python section to interscript/weavers/latex.py[11] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   258: #line 280 "latex_weaver.ipk"
   259:   def head(self,level, text, atext='', anchor=''):
   260:     cmds = {
   261:       1:'\\part',
   262:       2:'\\chapter',
   263:       3:'\\section',
   264:       4:'\\subsection',
   265:       5:'\\subsubsection',
   266:       6:'\\paragraph',
   267:       7:'\\subparagraph'}
   268:     lev = level+self.heading_level_offset
   269:     if lev>7:lev=7
   270:     cmd = cmds[lev]
   271:     if anchor == '': anchor = atext
   272:     if anchor == '':
   273:       anchor = 'h'+str(self.acount)
   274:       self.acount = self.acount + 1
   275: 
   276:     if atext:
   277:       self._writeline(cmd+'['+atext+']{'+text+'}\\label{'+anchor+'}')
   278:     else:
   279:       self._writeline(cmd+'{'+text+'}\\label{'+anchor+'}')
   280: 
End python section to interscript/weavers/latex.py[11]

6.4.7.11. Tables

Start python section to interscript/weavers/latex.py[12] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   281: #line 304 "latex_weaver.ipk"
   282:   def begin_table(self, *headings, **kwds):
   283:     self._writeline('\\begin{table}[h]\\begin{tabular}{|'+'l|'*len(headings)+'}\hline')
   284:     self.write(headings[0])
   285:     for h in headings[1:]:
   286:       self._write('&')
   287:       self.write(h)
   288:     self._writeline(r'\\\hline')
   289: 
   290:   def table_row(self,data):
   291:     self.write(data[0])
   292:     for d in data[1:]:
   293:       self._write('&')
   294:       self.write(d)
   295:     self._writeline(r'\\')
   296: 
   297:   def table_rule(self):
   298:     self._writeline(r'\hline')
   299: 
   300:   def end_table(self):
   301:     self._writeline('\\hline\\end{tabular}\\end{table}')
   302: 
End python section to interscript/weavers/latex.py[12]

6.4.7.12. Lists

6.4.7.12.1. Numbered Lists
Start python section to interscript/weavers/latex.py[13] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   303: #line 328 "latex_weaver.ipk"
   304:   def begin_numbered_list(self,start=1, type='1'):
   305:     self._writeline('\\begin{enumerate}')
   306: 
   307:   def end_numbered_list(self):
   308:     self._writeline('\\end{enumerate}')
   309: 
   310:   def begin_numbered_list_item(self):
   311:     self._writeline('\\item ')
   312: 
   313:   def end_numbered_list_item(self):
   314:     pass
   315: 
End python section to interscript/weavers/latex.py[13]
6.4.7.12.2. Bullet Lists
Start python section to interscript/weavers/latex.py[14] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   316: #line 342 "latex_weaver.ipk"
   317:   def begin_bullet_list(self):
   318:     self._writeline('\\begin{itemize}')
   319: 
   320:   def end_bullet_list(self):
   321:     self._writeline('\\end{itemize}')
   322: 
   323:   def begin_bullet_list_item(self):
   324:     self._write('\\item ')
   325: 
   326:   def end_bullet_list_item(self):
   327:     pass
   328: 
End python section to interscript/weavers/latex.py[14]
6.4.7.12.3. Keyed Lists
Start python section to interscript/weavers/latex.py[15] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   329: #line 356 "latex_weaver.ipk"
   330:   def begin_keyed_list(self):
   331:     self._writeline('\\begin{description}')
   332: 
   333:   def end_keyed_list(self):
   334:     self._writeline('\\end{description}')
   335: 
   336:   def begin_keyed_list_item(self,key):
   337:     self._write('\\item[')
   338:     self.write(key)
   339:     self._write(']')
   340: 
   341:   def end_keyed_list_item(self):
   342:     pass
   343: 
End python section to interscript/weavers/latex.py[15]

6.4.7.13. Code Output

Start python section to interscript/weavers/latex.py[16] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   344: #line 372 "latex_weaver.ipk"
   345:   # default code line formatting
   346:   def echotangle(self,count,data):
   347:     if self.comments:
   348:       self._writeline(data)
   349:     else:
   350:       self.writecode("%6d: %s" % (count,data))
   351: 
End python section to interscript/weavers/latex.py[16]

6.4.7.14. Paragraphs

Start python section to interscript/weavers/latex.py[17] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   352: #line 381 "latex_weaver.ipk"
   353:   def prose(self): # start of paragraph
   354:     self._write('\\noindent ')
   355: 
   356:   def par(self): # paragraph separator
   357:     self._write('\\par\n\\noindent ')
   358: 
   359:   def eop(self): # end of paragraph
   360:     self._write('\\par\n')
   361: 
   362:   def write_comment(self,v):
   363:     self.write_tagged('small',v)
   364: 
End python section to interscript/weavers/latex.py[17]

6.4.7.15. Fonts

Start python section to interscript/weavers/latex.py[18] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   365: #line 395 "latex_weaver.ipk"
   366:   def begin_code(self):
   367:     self._write('{\\tt ')
   368: 
   369:   def end_code(self):
   370:     self._write('}')
   371: 
   372:   def begin_emphasize(self):
   373:     self._write('{\\em ')
   374: 
   375:   def end_emphasize(self):
   376:     self._write('}')
   377: 
   378:   def begin_strong(self):
   379:     self._write('{\\bfseries ')
   380: 
   381:   def end_strong(self):
   382:     self._write('}')
   383: 
   384:   def begin_italic(self):
   385:     self._write('{\\itshape ')
   386: 
   387:   def end_italic(self):
   388:     self._write('}')
   389: 
   390:   def begin_bold(self):
   391:     self._write('{\\bfseries ')
   392: 
   393:   def end_bold(self):
   394:     self._write('}')
   395: 
   396:   def begin_big(self):
   397:     self._write('{\\large ')
   398: 
   399:   def end_big(self):
   400:     self._write('}')
   401: 
   402:   def begin_small(self):
   403:     self._write('{\\small ')
   404: 
   405:   def end_small(self):
   406:     self._write('}')
   407: 
End python section to interscript/weavers/latex.py[18]

6.4.7.16. Citations

Start python section to interscript/weavers/latex.py[19] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   408: #line 439 "latex_weaver.ipk"
   409:   def cite_url(self,url):
   410:     self._write('{\\bfseries ')
   411:     self.write(url)
   412:     self._write('}')
   413: 
    75: #line 158 "weavers.ipk"
    76: 
End python section to interscript/weavers/multiplexor.py[1]

6.4.8. Unimplemented Weavers

In the following sections, I describe some weavers that are to be considered standard. Some ought to be implemented but haven't been yet, including Postscript, Nroff for man pages, and some Microsoft formats. There are some typesetting systems I don't think need support, however. I think texinfo is archaic, as is troff.

6.4.8.1. microsoft word weaver

isn't implemented yet. produces word files for some popular version of word. help please!

6.4.8.2. microsoft help weaver

isn't implemented yet. produces micorsoft help files.

6.4.8.3. nroff weaver

this unimplemented weaver is useful for producing man pages on unix systems. man pages are considered essential base documentation by some people.

6.4.8.4. lout weaver

this weaver isn't implemented yet.

6.4.8.5. postscript weaver

this weaver isn't implemented yet. it should output encapsulated postscript in some sensible format. it shouldn't be too hard to write, but the results will probably not be as pleasing as postscript produced from a proper typesetting system.

6.4.9. auto weaver

make a weaver loom from the list of descriptors.
Start python section to interscript/weavers/auto.py[1] 1
     1: #line 193 "weavers.ipk"
     2: from interscript.weavers.multiplexor import multiplexor
     3: from interscript.weavers.text import plain_text_weaver
     4: from interscript.weavers.latex import latex_weaver
     5: from interscript.weavers.html import html_weaver
     6: from interscript.weavers.web import stacking_weaver
     7: from interscript.drivers.sinks.bufdisk import named_file_sink
     8: 
     9: def mk_html(pass_frame,basename, directory, prefix, eol, title):
    10:   w = named_file_sink(pass_frame,directory+basename+'.html', prefix, eol=eol)
    11:   if not title: title = basename
    12:   return html_weaver(pass_frame,w,title=title)
    13: 
    14: def mk_web(pass_frame,basename, directory, prefix, eol, title):
    15:   w = named_file_sink(pass_frame,directory+basename+'.html', prefix, eol=eol)
    16:   w = html_weaver(pass_frame,w,title=title)
    17:   return stacking_weaver(w,basename+'_%s.html',(1,2,3,4,5,6,7,8,9,10))
    18: 
    19: def mk_latex(pass_frame,basename, directory, prefix, eol, title):
    20:   w = named_file_sink(pass_frame,directory+basename+'.tex', prefix)
    21:   if not title: title = basename
    22:   return latex_weaver(pass_frame,w, title=title)
    23: 
    24: def mk_text(pass_frame,basename, directory, prefix, eol, title):
    25:   w = named_file_sink(pass_frame,directory+basename+'.txt', prefix)
    26:   if not title: title = basename
    27:   return plain_text_weaver(pass_frame,w, title=title)
    28: 
    29: auto_weavers = {
    30:   'html': mk_html,
    31:   'web': mk_web,
    32:   'latex': mk_latex,
    33:   'text': mk_text
    34:   }
    35: 
    36: def auto_weaver(pass_frame,basename,autoweave,title):
    37:   prefix = pass_frame.master.weaver_prefix
    38:   eol = pass_frame.master.html_eol
    39:   directory = pass_frame.master.weaver_directory
    40:   weavers = []
    41:   for w in autoweave:
    42:     if auto_weavers.has_key(w):
    43:       weavers.append( auto_weavers[w](pass_frame, basename, directory, prefix, eol, title) )
    44:   return multiplexor(pass_frame, weavers)
    45: 

6.5. Weaver Filters

6.5.1. Markup filtering weaver

This weaver is a multiplexor with the additional facility to perform search for markup codes in input lines, and execute appropriate weaver constructions.

Note that only one regexp can be matched: chain filters together to parse multiple markups shortcuts. Note that the regexp must not be nullable, that is, it must never match an empty string.

Note that the start and end method must be weaver method names, not actual methods.

Start python section to interscript/weavers/filter.py[1] 1 2
     1: #line 17 "weaver_filters.ipk"
     2: from interscript.weavers.multiplexor import multiplexor
     3: import re
     4: class markup_filter(multiplexor):
     5:   def __init__(self,pass_frame,regexp,startmethod,endmethod,base=[]):
     6:     multiplexor.__init__(self,pass_frame,base)
     7:     self.regexp = re.compile(regexp)
     8:     self.startmethod = startmethod
     9:     self.endmethod = endmethod
    10:     self.protocol = ('regexp filter',regexp)
    11:     self.name = 'markup filter v1'
    12:     self.translating = 1
    13: 
    14:   def translate(self):
    15:     self.translating = 1
    16:     for weaver in self.base: weaver.translate()
    17: 
    18:   def raw(self):
    19:     self.translating = 0
    20:     for weaver in self.base: weaver.raw()
    21: 
    22:   def rawif(self, tag):
    23:     self.translating = 0
    24:     for weaver in base: weaver.rawif(tag)
    25: 
    26:   def write(self,data):
    27:      if not self.enabled: return
    28:      if not self.translating:
    29:        for weaver in self.base:
    30:          weaver.write(data)
    31:      else:
    32:        match = self.regexp.search(data)
    33:        startpos = 0
    34:        while match:
    35:          midpos = match.start(0)
    36:          endpos = match.end(0)
    37:          if midpos == endpos:
    38:            raise 'nullable regexp '+self.regexp.pattern
    39:          if startpos != midpos:
    40:            for weaver in self.base:
    41:              weaver.write(data[startpos:midpos])
    42:          for weaver in self.base:
    43:            exec 'weaver.'+self.startmethod+'()'
    44:            weaver.write(match.group(1))
    45:            exec 'weaver.'+self.endmethod+'()'
    46:          startpos = endpos
    47:          match = self.regexp.search(data,startpos)
    48:        if startpos != len(data):
    49:          for weaver in self.base:
    50:            weaver.write(data[startpos:])
    51: 
    52:   def writeline(self,data=''):
    53:     if not self.enabled: return
    54:     if data != '': self.write(data)
    55:     for weaver in self.base:
    56:       weaver.writeline()
    57: 
    58:   def begin_displayed_code(self):
    59:     self.translating = 0
    60:     for weaver in self.base:
    61:       try: weaver.begin_displayed_code()
    62:       except KeyboardInterrupt: raise
    63:       except: pass
    64: 
    65:   def end_displayed_code(self):
    66:     self.translating = 0
    67:     for weaver in self.base: weaver.end_displayed_code()
    68: 
End python section to interscript/weavers/filter.py[1]

6.5.2. Convenience commands

These functions are conveniences for creating filter chains. The function chain_filters chains a sequence of filters together, the first filter is called first, and calls the second filter, etc.

the function create filters takes a sequence of triples as an argument, and returns a sequence of filters: each triple should consist of a regexp, start method name, and end method name. The filters are not connected.

The function create_filter_chain combines these two functions, it takes a sequence of triples and constructs a filter chain. Such a connected chain is also known as a pipe.

Start python section to interscript/weavers/filter.py[2] 1 2
    69: #line 99 "weaver_filters.ipk"
    70: def chain_filters(filters):
    71:   for i in range(0,len(filters)-1):
    72:     filters[i].base = [filters[i+1]]
    73: 
    74: def create_filters(triples):
    75:   filters = []
    76:   for regexp,startmethod,endmethod in triples:
    77:     filters.append(markup_filter(regexp,startmethod,endmethod))
    78:   return filters
    79: 
    80: def create_filter_chain(triples):
    81:   return chain_filters(create_filters(triples))
    82: 

6.6. Tanglers

A tangler is a driver that accepts lines of code in a particular language or class of languages, writes it to a code file, possibly pretty printing it, and displays it in a weaver fixed at construction time.

Tanglers may also build tables of information about the code.

The main method of a tangler is writeline, which requires three arguments: the line of code to be tangled, and the name of the original file from which the line came, and the line number within the original file from which the line came.

If the target language supports original source references (like c's #line directive), the tangler should also insert a directive into the code file using the supplied arguments, unless the file name is the same as the previous line's original source file, or the line number is not one more than the previous line's original line number.

The tangler should attach the original filename and line number to it's sink device, since more than one tangler may write to the same sink.

A tangler may supply a write_comment method accepting a single argument, some text to be comments. The tangler may assume the text does not contain any end of line characters. It may write the text into the code file as comments, not necessarily on one line; however, it may not write anything which affects the semantics of the program being generated. The comment should be woven as ordinary program text.

A tangler may supply a method get_comment_tangler. If it does, then, when called with no arguments, it shall return a tangler which can be used to write a single block of comments to the same sink and weaver as itself.

A tangler may supply a method get_string_tangler. If it does, it shall accept two or more arguments, the first being an end of line string, and the second a width. A string tangler so returned shall produce a string in the target language, whose text in the target language shall have the same natural language interpretation as the text fed to the string tangler via calls to its writeline method.

The string tangler may strip trailing, leading, or interior whitespace from the data supplied via the writeline method, and it may insert the supplied end of line string in appropriate places. It may also translate the encoding of the input to another encoding, or translate the natural language input to another natural language.

The string tangler may not insert end of line markers other than the supplied marker. (The target operating system for execution of the code is not known to the string tangler. Also, the caller may supply a blank, to inhibit multi-line output, or may supply a null string, to force concatenation of non-blank text.

The width parameter is a hint to the string tangler indicating approximately how long lines should be if the string tangler is flowing, justifying, or otherwise formatting the text as lines of a paragraph.

Note: the purpose of string tanglers is simply to allow the programmer to write natural language text in Interscript source files without having to worry about escape characters, quoting, encodings, or line endings. Text so provided may be intended to be output for user help, as a message, or, as part of a run-time documentation system.

Although Python currently supports only strings of 8 bit characters, a Japanese programmer might construct a c string tangler that translated some multi-byte encoding of Japanese characters into a c 'wide' string literal with a 16 bit encoding.

Start python section to interscript/tanglers/__init__.py[1] 1
     1: #line 84 "tanglers.ipk"
     2: # tanglers
     3: 
End python section to interscript/tanglers/__init__.py[1]

6.6.1. Tangler Base class

Start python section to interscript/tanglers/base.py[1] 1
     1: #line 89 "tanglers.ipk"
     2: #---------------------------------------------------------
     3: # tangler base
     4: #---------------------------------------------------------
     5: class tangler_base:
     6:   __class_protocols__ = ['tangler']
     7:   def __init__(self,sink,weaver):
     8:     self.sink = sink
     9:     self.weaver = weaver
    10:     self.inhibit_sref = 0
    11:     self.pass_frame = weaver.pass_frame
    12:     self.master = self.pass_frame.master
    13:     self.process = self.master.process
    14:     self.language = 'data'
    15: 
    16:   def get_language(self): return self.language
    17: 
    18:   def write_comment(self,line):
    19:     pass
    20: 
    21:   def _writeline(self,data):
    22:     self.sink.writeline(data)
    23: 
    24:   def _write_and_echo(self,data):
    25:     self._writeline(data)
    26:     self.weaver.echotangle(self.sink.lines_written,data)
    27: 
    28:   def _handle_sref(self, file, count, inhibit_sref):
    29:     if not inhibit_sref and not self.inhibit_sref:
    30:       if (file != self.sink.last_source_file or
    31:         count != self.sink.last_source_count+1 or
    32:         self.sink.last_inhibit_sref):
    33:         self.start_section(file,count)
    34:       self.sink.last_inhibit_sref = 0
    35:     else:
    36:       self.sink.last_inhibit_sref = 1
    37:     self.sink.last_source_file = file
    38:     self.sink.last_source_count = count
    39: 
    40:   def writeline(self,data,file,count, inhibit_sref=0):
    41:     self._handle_sref(file,count,inhibit_sref)
    42:     self._write_and_echo(data)
    43: 
    44:   def start_section(self,file,count): pass
    45: 
    46: #---------------------------------------------------------
    47: # builtin tanglers: null, data, c, script
    48: #---------------------------------------------------------
    49: 
End python section to interscript/tanglers/base.py[1]

6.6.2. Null Tangler

A null tangler eats up input without writing it to either a sink file or the documentation file. Note that the start and end section markers are still written (showing something was skipped over).
Start python section to interscript/tanglers/null.py[1] 1
     1: #line 144 "tanglers.ipk"
     2: #---------------------------------------------------------
     3: # null tangler
     4: # NOTE: a null tangler is _not_ the same as
     5: # some other tangler with a null sink:
     6: # null tanglers do _not_ write to the weaver!
     7: # Use a null tangler to remove files from the
     8: # source _and_ documentation
     9: 
    10: from interscript.tanglers.base import tangler_base
    11: class null_tangler(tangler_base):
    12:   def __init__(self,weaver=None):
    13:     tangler_base.__init__(self,null_sink(),weaver)
    14:     self.language = 'None'
    15: 
    16:   def get_comment_tangler(self):
    17:     return self
    18: 
    19:   def writeline(self,data,file,count,inhibit_sref=0):
    20:     pass
    21: 
End python section to interscript/tanglers/null.py[1]

6.6.3. Document Tangler

A document tangler writes to the documentation file without actually writing any source file: it can be used to present examples or code snippets, for example.
Start python section to interscript/tanglers/doc.py[1] 1
     1: #line 170 "tanglers.ipk"
     2: #---------------------------------------------------------
     3: # document tangler: writes text as doco,
     4: # doesn't generate a file. Not the same as 'no' tangler
     5: from interscript.tanglers.base import tangler_base
     6: 
     7: class doc_tangler(tangler_base):
     8:   def __init__(self,weaver):
     9:     tangler_base.__init__(self,null_sink(),weaver)
    10:     self.language = 'document'
    11: 
    12:   def get_comment_tangler(self):
    13:     return self
    14: 
    15:   def writeline(self,data,file,count,inhibit_sref=0):
    16:     self.weaver.writeline(data,file,count)
    17: 
End python section to interscript/tanglers/doc.py[1]

6.6.4. Data Tangler

The data tangler simply write output to the attached sink file and weaver, it does not parse the input in any way or emit any line numbers. There is no associated comment tangler either.
Start python section to interscript/tanglers/data.py[1] 1
     1: #line 192 "tanglers.ipk"
     2: #--------------------------------------------------
     3: # data tangler: write to a file
     4: # can not emit source line cross references
     5: from interscript.tanglers.base import tangler_base
     6: 
     7: class data_tangler(tangler_base):
     8:   pass
     9: 
End python section to interscript/tanglers/data.py[1]

6.6.5. c Tangler

The c tangler is used to write c code. It supports #line directives refering to the original input.

The write_comment method can be used to insert comments into a code file without them appearing in the documentation file.

There is an associated comment tangler which writes text as block of comments to the same sink: the whole block is enclosed in a single /* */ pair and nicely formatted. (The c comment tangler cannot interleave comments).

Design note: The idea of comment tanglers was to get rid of a 'mode' for tanglers. But the idea seems to have problems.

There is also an associated string tangler which generates native strings.

Start python section to interscript/tanglers/c.py[1] 1 2 3
     1: #line 220 "tanglers.ipk"
     2: #---------------------------------------------------------
     3: # c tangler: write to a file, insert source line numbers
     4: # using '#line' pre-processor directives
     5: from interscript.tanglers.base import tangler_base
     6: import re
     7: import string
     8: class c_tangler(tangler_base):
     9:   def __init__(self,sink,weaver):
    10:     tangler_base.__init__(self,sink,weaver)
    11:     self.matchid = re.compile('^[^A-Za-z_]*([A-Za-z_][A-Za-z_0-9]*)(.*)$')
    12:     self.language = 'C'
    13: 
    14:   def write_comment(self,line,file,count):
    15:     self.writeline('/* '+line+'*/')
    16: 
    17:   def start_section(self, file, count):
    18:     data = '#line '+str(count)+' '+'"'+file+'"'
    19:     self._writeline(data)
    20:     if self.weaver:
    21:       self.weaver.echotangle(self.sink.lines_written,data)
    22: 
    23:   def get_comment_tangler(self):
    24:     return c_comment_tangler(self.sink)
    25: 
    26:   def get_string_tangler(self,eol='\\n',width=0):
    27:     return c_string_tangler(self.sink,self.weaver,eol,width)
    28: 
End python section to interscript/tanglers/c.py[1]

6.6.5.1. c comment tangler

Start python section to interscript/tanglers/c.py[2] 1 2 3
    29: #line 249 "tanglers.ipk"
    30: #---------------------------------------------------------
    31: class c_comment_tangler(tangler_base):
    32:   def __init__(self,sink,weaver):
    33:     tangler_base.__init__(self,sink,weaver)
    34: 
    35:   def writeline(self,data,file,count,inhibit_sref=0):
    36:     if self.count == 0:
    37:       self._writeline('/* '+data)
    38:     else:
    39:       self._writeline(' * '+data)
    40:     self.weaver.writeline(data)
    41: 
    42:   def __del__(self):
    43:     self._writeline(' */')
    44: 
End python section to interscript/tanglers/c.py[2]

6.6.5.2. c string tangler

Start python section to interscript/tanglers/c.py[3] 1 2 3
    45: #line 266 "tanglers.ipk"
    46: #---------------------------------------------------------
    47: class c_string_tangler(tangler_base):
    48:   def __init__(self,sink,weaver,eol,width):
    49:     print 'Initialising c string tangler, eol=',eol,'width=',width
    50:     tangler_base.__init__(self,sink,weaver)
    51:     self.eol=eol
    52:     self.width=width
    53:     self.language = 'C string'
    54: 
    55:   def writeline(self,data,file,count,inhibit_sref=0):
    56:     data = string.rstrip(data) # remove trailing spaces
    57:     if self.width > 0: data = string.ljust(data, self.width)
    58:     line = '"'
    59:     for ch in data:
    60:       if ch in '\\"': line = line + '\\' + ch
    61:       else: line = line + ch
    62:     line = line + self.eol + '"'
    63:     self._writeline(line)
    64:     self.weaver.writeline(data)
    65: 
End python section to interscript/tanglers/c.py[3]

6.6.6. c++ Tangler

The c++ tangler is the same as the c tangler except it writes c++ style comments and is associated with a corresponding c++ comment tangler.
Start python section to interscript/tanglers/cpp.py[1] 1 2 3
     1: #line 293 "tanglers.ipk"
     2: #---------------------------------------------------------
     3: # c++ tangler: write to a file, insert source line numbers
     4: # using '#line' pre-processor directives
     5: from interscript.tanglers.base import tangler_base
     6: import re
     7: 
     8: class cpp_tangler(tangler_base):
     9:   def __init__(self,sink,weaver):
    10:     tangler_base.__init__(self,sink,weaver)
    11:     self.matchid = re.compile('^[^A-Za-z_]*([A-Za-z_][A-Za-z_0-9]*)(.*)$')
    12:     self.language = 'C++'
    13: 
    14:   def write_comment(self,line):
    15:     self._writeline('// '+line)
    16: 
    17:   def start_section(self, file, count):
    18:     data = '#line '+str(count)+' '+'"'+file+'"'
    19:     self._writeline(data)
    20:     if self.weaver:
    21:       self.weaver.echotangle(self.sink.lines_written,data)
    22: 
    23:   def get_comment_tangler(self):
    24:     return cpp_comment_tangler(self.sink, weaver)
    25: 
    26:   def get_string_tangler(self,eol,width):
    27:     return c_string_tangler(self.sink,self.weaver,eol,width)
    28: 
    29: 
End python section to interscript/tanglers/cpp.py[1]

6.6.6.1. Hash Tangler

Start python section to interscript/tanglers/cpp.py[2] 1 2 3
    30: #line 323 "tanglers.ipk"
    31: class hash_comment_tangler(tangler_base):
    32:   def __init__(self, writer, weaver, prefix):
    33:     tangler_base.__init__(self,writer, weaver)
    34:     self.prefix = prefix
    35:     self.language = prefix+' comment'
    36: 
    37:   def writeline(self,data,file,count,inhibit_sref=0):
    38:     self.weaver.writeline(data)
    39:     self._writeline(self.prefix+line)
    40: 
End python section to interscript/tanglers/cpp.py[2]

6.6.6.2. c++ comment tangler

Start python section to interscript/tanglers/cpp.py[3] 1 2 3
    41: #line 335 "tanglers.ipk"
    42: class cpp_comment_tangler(hash_comment_tangler):
    43:   def __init__(self, writer,weaver):
    44:     hash_comment_tangler.__init__(self,writer,weaver,'// ')
    45: 
End python section to interscript/tanglers/cpp.py[3]

6.6.7. Java Tangler

The Java tangler is the same as the c++ tangler, except there are no #line directives. This is because I don't know enough about Java to write a Java tangler. Help!
Start python section to interscript/tanglers/java.py[1] 1
     1: #line 345 "tanglers.ipk"
     2: from interscript.tanglers.base import tangler_base
     3: from interscript.tanglers.cpp import cpp_comment_tangler
     4: from interscript.tanglers.c import c_string_tangler
     5: import re
     6: class java_tangler(tangler_base):
     7:   def __init__(self,sink,weaver):
     8:     tangler_base.__init__(self,sink,weaver)
     9:     self.matchid = re.compile('^[^A-Za-z_]*([A-Za-z_][A-Za-z_0-9]*)(.*)$')
    10:     self.language = 'java'
    11: 
    12:   def write_comment(self,line):
    13:     self._writeline('// '+line)
    14: 
    15:   def start_section(self, file, count):
    16:     data = '//#line '+str(count)+' '+'"'+file+'"'
    17:     self._writeline(data)
    18:     if self.weaver:
    19:       self.weaver.echotangle(self.sink.lines_written,data)
    20: 
    21:   def get_comment_tangler(self):
    22:     return cpp_comment_tangler(self.sink)
    23: 
    24:   def get_string_tangler(self,eol,width):
    25:     return c_string_tangler(self.sink,self.weaver,eol,width)
    26: 
End python section to interscript/tanglers/java.py[1]

6.6.8. Tcl Tangler

Start python section to interscript/tanglers/tcl.py[1] 1 2
     1: #line 373 "tanglers.ipk"
     2: from interscript.tanglers.base import tangler_base
     3: from interscript.tanglers.cpp import hash_comment_tangler
End python section to interscript/tanglers/tcl.py[1]
Start python section to interscript/tanglers/tcl.py[2] 1 2
     4: #line 376 "tanglers.ipk"
     5: 
     6: class tcl_tangler(tangler_base):
     7:   def __init__(self,sink,weaver):
     8:     tangler_base.__init__(self,sink,weaver)
     9:     self.language = 'tcl'
    10: 
    11:   def write_comment(self,line):
    12:     self._writeline('# '+line)
    13: 
    14:   def start_section(self, file, count):
    15:     data = 'line '+str(count)+' '+'"'+file+'"'
    16:     self._writeline(data)
    17:     if self.weaver:
    18:       self.weaver.echotangle(self.sink.lines_written,data)
    19: 
    20:   def get_comment_tangler(self):
    21:     return hash_comment_tangler(self.sink,weaver, '# ')
    22: 
    23:   def get_string_tangler(self,eol,width=0):
    24:     # This is _wrong_ and needs to be fixed!
    25:     return c_string_tangler(self.sink,self.weaver,eol,width)
    26: 
    27: 

6.6.9. Python Tangler

The Python tangler is particularly important for Interscript, because it is the native script language in which Interscript is written, in which commands are issued in source files, and with which it can be extended by the user.

This very document is itself the Python source for Interscript, and that leads to interesting bootstrappping problems in development.

6.6.9.1. Tokeniser interface

Start python section to interscript/tanglers/python.py[1] 1 2 3 4 5 6
     1: #line 14 "python_tangler.ipk"
     2: #---------------------------------------------------------
     3: # python tangler: write to a file, insert source line numbers
     4: # using '#line ' comments
     5: # works for Python
     6: from interscript.tanglers.base import tangler_base
     7: import re
     8: import string
     9: from interscript.tokenisers.python import python_tokeniser
    10: from interscript.tokenisers.python import COMMENT, \
    11:    MULTILINE_STRING_FIRST, \
    12:    MULTILINE_STRING_MIDDLE, \
    13:    MULTILINE_STRING_LAST
    14: import keyword
    15: import token
    16: 
    17: py_bracket_tokens = [
    18:   token.LPAR, token.RPAR,
    19:   token.LSQB, token.RSQB,
    20:   token.LBRACE, token.RBRACE]
    21: 
    22: py_punct_tokens = [
    23:   token.COLON, token.COMMA, token.SEMI]
    24: 
    25: py_op_tokens = [
    26:   token.OP,
    27:   token.PLUS, token.MINUS, token.STAR, token.SLASH,
    28:   token.VBAR, token.AMPER,
    29:   token.LESS, token.GREATER, token.EQUAL,
    30:   token.DOT, token.PERCENT,
    31:   token.BACKQUOTE, token.EQEQUAL,
    32:   token.NOTEQUAL, token.LESSEQUAL, token.GREATEREQUAL,
    33:   token.TILDE, token.CIRCUMFLEX,
    34:   token.LEFTSHIFT,  token.RIGHTSHIFT, token.DOUBLESTAR]
    35: 
End python section to interscript/tanglers/python.py[1]

6.6.9.2. Function generator

Start python section to interscript/tanglers/python.py[2] 1 2 3 4 5 6
    36: #line 50 "python_tangler.ipk"
    37: class argument:
    38:   def __init__(self,
    39:     name,
    40:     protocol=None,
    41:     description=None,
    42:     default=None):
    43:     self.name = name
    44:     self.protocol = protocol
    45:     self.description = description
    46:     self.default = default
    47: 
End python section to interscript/tanglers/python.py[2]

6.6.9.3. Code generator

Start python section to interscript/tanglers/python.py[3] 1 2 3 4 5 6
    48: #line 63 "python_tangler.ipk"
    49: def tangle_precondition(indent, precondition):
    50:   return ' ' * indent + 'assert ' + precondition + '\n'
    51: 
    52: def tangle_postcondition(indent, postcondition):
    53:   return ' ' * indent + 'assert ' + postcondition + '\n'
    54: 
    55: def tangle_argument_check(indent, argument):
    56:   code = ''
    57:   if argument.protocol:
    58:     code = code + ' '* indent + 'assert has_protocol('+\
    59:       argument.name + ', '+ argument.protocol + ')\n'
    60:   return code
    61: 
    62: def tangle_argument_checks(indent, arguments):
    63:   code = ''
    64:   for argument in arguments:
    65:     code = code + tangle_argument_check(indent, argument)
    66:   return code
    67: 
    68: def tangle_argument(argument):
    69:   code = argument.name
    70:   if argument.default: code = code + '='+argument.default
    71:   return code
    72: 
    73: def tangle_arguments(indent, arguments):
    74:   code = ''
    75:   for argument in arguments[:-1]:
    76:     code = code + ' '*indent + tangle_argument(argument)
    77:     code = code + ',\n'
    78:   code = code + ' '*indent + tangle_argument(arguments[-1])
    79:   return code
    80: 
    81: def tangle_result(indent, results):
    82:   code = ''
    83:   for result in results:
    84:     if result.protocol:
    85:       code = code + ' '*indent + 'assert has_protocol(' +\
    86:         result.name+', '+ result.protocol+')\n'
    87:   code = code + ' '*indent + 'return '
    88:   for result in results[:-1]:
    89:     code = code + result.name + ', '
    90:   code = code + results[-1].name+'\n'
    91:   return code
    92: 
    93: def tangle_function(
    94:   sink,
    95:   source_file,
    96:   source_line,
    97:   indent,
    98:   name,
    99:   description=None,
   100:   arguments=None,
   101:   precondition=None,
   102:   result=None,
   103:   postcondition=None,
   104:   initial=None,
   105:   final=None,
   106:   body=None):
   107: 
   108:   # argument list
   109:   code = ' '* indent + 'def '+name
   110:   if arguments:
   111:     code = code + '(\n'
   112:     code = code + tangle_arguments(indent+2, arguments)
   113:     code = code + '):\n'
   114:   else: code = code + '():\n'
   115: 
   116:   # argument checks
   117:   if arguments:
   118:     code = code + ' ' * (indent + 2) + '#check arguments\n'
   119:     code = code + tangle_argument_checks(indent+2, arguments)
   120: 
   121:   # precondition
   122:   if precondition:
   123:     code = code + ' ' * (indent + 2) + '#precondition\n'
   124:     code = code + tangle_precondition(indent+2, precondition)
   125: 
   126:   # begin try/finally block
   127:   code = code + ' '* (indent+2) + 'try:\n'
   128: 
   129:   # initial
   130:   if initial:
   131:     code = code + ' ' * (indent + 4) + '#initially\n'
   132:     for line in initial:
   133:       code = code + ' ' * (indent+4) + line + '\n'
   134: 
   135:   # begin try/except block
   136:   code = code + ' '* (indent+4) + 'try:\n'
   137: 
   138:   # body
   139:   if body:
   140:     code = code + ' ' * (indent + 6) + '#body\n'
   141:     for line in body:
   142:       code = code + ' ' * (indent+6) + line + '\n'
   143: 
   144: 
   145:   # exception
   146:   code = code + ' ' * (indent + 4) + '#transmit user exceptions\n'
   147:   code = code + ' ' * (indent +4) + 'except: raise\n'
   148:   code = code + ' ' * (indent +4) + 'else:\n'
   149: 
   150: 
   151:   # postcondition
   152:   if postcondition:
   153:     code = code + ' ' * (indent + 6) + '#postcondition\n'
   154:     code = code + tangle_postcondition(indent + 6, postcondition)
   155: 
   156: 
   157:   # result
   158:   if result:
   159:     code = code + ' ' * (indent + 6) + '#return result\n'
   160:     code = code + tangle_result(indent + 6, result)
   161:   else: code = code + ' ' * (indent+6) + 'pass\n'
   162: 
   163:   # finally
   164:   code = code + ' ' * (indent + 2) + '#cleanup\n'
   165:   code = code + ' '* (indent+2) + 'finally:\n'
   166:   if final:
   167:     for line in final:
   168:       code = code + ' ' * (indent+4) + line + '\n'
   169:   else:
   170:     code = code + ' ' * (indent+4) + 'pass\n'
   171: 
   172:   for line in string.split(code,'\n')[:-1]:
   173:     sink.writeline(line)
   174:   return code
   175: 
End python section to interscript/tanglers/python.py[3]

6.6.9.4. Document generator

Start python section to interscript/tanglers/python.py[4] 1 2 3 4 5 6
   176: #line 192 "python_tangler.ipk"
   177: #-------------------------------------------------
   178: def weave_argument(weaver, indent, argument):
   179:   weaver.write_code_fragment(' '* indent)
   180:   weaver.write_code_fragment(argument.name, 'NAME')
   181:   if argument.protocol:
   182:     weaver.write_code_fragment(':', 'PUNCT')
   183:     weaver.write_code_fragment(' ')
   184:     weaver.write_code_fragment(argument.protocol, 'NAME')
   185:   if argument.default:
   186:     weaver.write_code_fragment('=', 'PUNCT')
   187:     weaver.write_code_fragment(argument.default)
   188:   if argument.description:
   189:     weaver.write_code_fragment(' ')
   190:     weaver.write_code_fragment(repr(argument.description), 'COMMENT')
   191: 
   192: def weave_arguments(weaver, indent, arguments):
   193:   for argument in arguments[:-1]:
   194:     weaver.start_code_line()
   195:     weave_argument(weaver, indent, argument)
   196:     weaver.write_code_fragment(',','PUNCT')
   197:     weaver.end_code_line()
   198:   weaver.start_code_line()
   199:   weave_argument(weaver, indent, arguments[-1])
   200: 
   201: def weave_function(
   202:   weaver,
   203:   indent,
   204:   name,
   205:   description=None,
   206:   arguments=None,
   207:   precondition=None,
   208:   result=None,
   209:   postcondition=None,
   210:   initial=None,
   211:   final=None,
   212:   body=None):
   213: 
   214:   weaver.start_code_line()
   215:   weaver.write_code_fragment(' '*indent)
   216:   weaver.write_code_fragment('function','KEYWORD')
   217:   weaver.write_code_fragment(' ')
   218:   weaver.write_code_fragment(name,'NAME')
   219:   weaver.write_code_fragment(':','PUNCT')
   220:   weaver.write_code_fragment(' ')
   221:   weaver.write_code_fragment('# '+description,'COMMENT')
   222:   weaver.end_code_line()
   223: 
   224:   if arguments:
   225:     weaver.start_code_line()
   226:     weaver.write_code_fragment(' '*(indent+2))
   227:     weaver.write_code_fragment('accepts','KEYWORD')
   228:     weaver.write_code_fragment(':','PUNCT')
   229:     weaver.end_code_line()
   230:     weave_arguments(weaver,indent+4,arguments)
   231:     weaver.end_code_line()
   232: 
   233:   if precondition:
   234:     weaver.start_code_line()
   235:     weaver.write_code_fragment(' '*(indent+2),)
   236:     weaver.write_code_fragment('precondition','KEYWORD')
   237:     weaver.write_code_fragment(':','PUNCT')
   238:     weaver.write_code_fragment(' ')
   239:     weaver.write_code_fragment(precondition)
   240:     weaver.end_code_line()
   241: 
   242:   if result:
   243:     weaver.start_code_line()
   244:     weaver.write_code_fragment(' '*(indent+2))
   245:     weaver.write_code_fragment('returns','KEYWORD')
   246:     weaver.end_code_line()
   247:     weave_arguments(weaver,indent+4,result)
   248:     weaver.end_code_line()
   249: 
   250:   if postcondition:
   251:     weaver.start_code_line()
   252:     weaver.write_code_fragment(' '*(indent+2))
   253:     weaver.write_code_fragment('postcondition','KEYWORD')
   254:     weaver.write_code_fragment(':','PUNCT')
   255:     weaver.write_code_fragment(' ')
   256:     weaver.write_code_fragment(postcondition)
   257:     weaver.end_code_line()
   258: 
   259:   if body:
   260:     for line in body:
   261:       weaver.start_code_line()
   262:       weaver.write_code_fragment(' '*(indent+2))
   263:       weaver.write_code_fragment(line)
   264:       weaver.end_code_line()
   265: 
End python section to interscript/tanglers/python.py[4]

6.6.10. Python Tangler

Start python section to interscript/tanglers/python.py[5] 1 2 3 4 5 6
   266: #line 283 "python_tangler.ipk"
   267: #-------------------------------------------------
   268: class python_tangler(tangler_base):
   269:   def __init__(self,sink,weaver):
   270:     tangler_base.__init__(self,sink,weaver)
   271:     self.matchPOD = re.compile('^ *#@(.*)$')
   272:     self.matchcomment = re.compile('^([^#]*)#.*$')
   273:     self.excludeid = []
   274:     self.userdict = {}
   275:     self.tokeniser = python_tokeniser(report_comments = 1, split_multiline_strings=1)
   276:     self.language = 'python'
   277: 
   278:   def __del__(self):
   279:     try:
   280:       tokens = self.tokeniser.close()
   281:     except:
   282:         print 'Tokeniser error'
   283:         print 'closing tokeniser for',self.sink.name
   284: 
   285:   def writeline(self,data,file,count,inhibit_sref=0):
   286:     match = self.matchPOD.match(data)
   287:     if match:
   288:       command = match.group(1)
   289:       py_exec(command,file,count,globals(),self.userdict)
   290:     else:
   291:       self.weaver.set_fc_anchor(file,count)
   292:       # special hack to preserve leading #! line
   293:       if self.sink.lines_written == 0 and len(data)>2:
   294:         inhibit_sref = data[:2]=='#!'
   295:       self._handle_sref(file,count, inhibit_sref)
   296:       self._writeline(data)
   297: 
   298:       try:
   299:         tokens = self.tokeniser.tokenize(data+'\n')
   300:       except TokenError, e:
   301:         print 'Tokeniser error',e
   302:         print 'in file',file,'line',line
   303:         print 'data['+data+']'
   304: 
   305: 
   306:       # pretty printing
   307:       chars_written = 0
   308:       self.weaver.start_code_line(self.sink.lines_written)
   309:       if tokens:
   310:         for kind,id,lstart,lend,dummy in tokens:
   311:           first = lstart[1]
   312:           last = lend[1]
   313:           self.weaver.write_code_fragment(data[chars_written:first])
   314:           markup = None
   315:           if kind == token.NAME:
   316:             if keyword.iskeyword(id): markup = 'KEYWORD'
   317:           elif kind == COMMENT: markup = 'COMMENT'
   318:           elif kind in [token.STRING,
   319:             MULTILINE_STRING_FIRST,
   320:             MULTILINE_STRING_MIDDLE,
   321:             MULTILINE_STRING_LAST]: markup = 'STRING'
   322:           elif kind == token.NUMBER: markup = 'NUMBER'
   323:           elif kind in py_bracket_tokens : markup = 'BRACKET'
   324:           elif kind in py_punct_tokens : markup = 'PUNCT'
   325:           elif kind in py_op_tokens: markup = 'OP'
   326:           self.weaver.write_code_fragment(data[first:last], markup)
   327:           chars_written = last
   328:         self.weaver.write_code_fragment(data[chars_written:])
   329:       self.weaver.end_code_line()
   330: 
   331:       dst_count = self.sink.lines_written
   332:       dst_file = self.sink.name
   333:       class_name = 0
   334:       function_name = 0
   335:       level = 0
   336:       for kind,id,lstart,lend,dummy in tokens:
   337:         if kind == token.INDENT:
   338:           level = level + 1
   339:         elif kind == token.DEDENT:
   340:           level = level - 1
   341:         if kind is token.NAME:
   342:           if not (keyword.iskeyword(id) or id in self.excludeid):
   343:             if not self.pass_frame.ids.has_key(id): self.pass_frame.ids[id]=[]
   344:             self.pass_frame.ids[id].append((file,count,dst_file,dst_count))
   345:             if class_name:
   346:               #print 'class',id
   347:               if not self.pass_frame.classes.has_key(id): self.pass_frame.classes[id]=[]
   348:               self.pass_frame.classes[id].append((file,count,dst_file,dst_count))
   349:               class_name = 0
   350:             elif function_name:
   351:               if not self.pass_frame.functions.has_key(id): self.pass_frame.functions[id]=[]
   352:               self.pass_frame.functions[id].append((file,count,dst_file,dst_count))
   353:               function_name = 0
   354:           elif id == 'class':
   355:             class_name = 1
   356:           elif id == 'def':
   357:             function_name = 1
   358: 
   359:   def write_comment(self,line,file,count):
   360:     self.writeline('# '+line,file,count)
   361: 
   362:   def start_section(self, file, count):
   363:     data = '#line '+str(count)+' '+'"'+file+'"'
   364:     self._writeline(data)
   365:     if self.weaver:
   366:       self.weaver.echotangle(self.sink.lines_written,data)
   367: 
   368:   def get_comment_tangler(self):
   369:     return script_comment_tangler(self.sink)
   370: 
   371:   def get_string_tangler(self,eol,width):
   372:     return c_string_tangler(self.sink,self.get_weaver(),eol,width)
   373: 
   374:   def function(self,
   375:     name,
   376:     indent,
   377:     source_file,
   378:     source_line,
   379:     description=None,
   380:     arguments=None,
   381:     precondition=None,
   382:     result=None,
   383:     postcondition=None,
   384:     initial=None,
   385:     final=None,
   386:     body=None):
   387: 
   388:     tangle_function(
   389:       self.sink,
   390:       source_file,
   391:       source_line,
   392:       indent,
   393:       name,
   394:       description=description,
   395:       arguments=arguments,
   396:       precondition=precondition,
   397:       result=result,
   398:       postcondition=postcondition,
   399:       initial=initial,
   400:       final=final,
   401:       body=body)
   402: 
   403:     weave_function(
   404:       self.weaver,
   405:       indent,
   406:       name,
   407:       description=description,
   408:       arguments=arguments,
   409:       precondition=precondition,
   410:       result=result,
   411:       postcondition=postcondition,
   412:       initial=initial,
   413:       final=final,
   414:       body=body)
   415: 
End python section to interscript/tanglers/python.py[5]

6.6.11. Python comment tangler

Start python section to interscript/tanglers/python.py[6] 1 2 3 4 5 6
   416: #line 434 "python_tangler.ipk"
   417: class script_comment_tangler(tangler_base):
   418:   def writeline(self,data,file,count,inhibit_sref=0):
   419:     if self.weaver:
   420:       self.weaver.writeline(data)
   421:     self._writeline('# '+line)
   422: 

6.6.12. Perl Tangler

This tangler attempts to support Perl's POD constructions. It implements the commands pod, cut, head1, head2, over, back, item, for, begin, and end.

Contrary to the perlpod manpage, Interscript pod commands are terminated at the end of a line, not the end of a 'paragraph'. It shouldn't make the slightest bit of difference, however, since weavers ignore blank lines anyhow.

When the tangler is in paragraph mode, blank lines are translated to end of paragraph commands. Paragraph mode is triggered by any non-command non-blank data lines, so you won't get an end of paragraph after a command before the first text.

Currently, support for the for/begin/end pod constructions is a hack. Interscript uses a different (better!) mechanism.

Start python section to interscript/tanglers/perl.py[1] 1
     1: #line 22 "perl_tangler.ipk"
     2: from interscript.tanglers.base import tangler_base
     3: from interscript.tanglers.c import c_string_tangler
     4: import re
     5: import string
     6: 
     7: class perl_tangler(tangler_base):
     8:   def __init__(self,sink,weaver, heading_level_offset = 2):
     9:     tangler_base.__init__(self,sink,weaver)
    10:     self.language = 'perl'
    11: 
    12:     self.mode = 'code'
    13:     self.list_type = []
    14:     self.pod_re = re.compile('^=([A-Za-z][A-Za-z0-9_]*) *(.*)$')
    15:     self.heading_level_offset = heading_level_offset
    16:     self.esc_re = re.compile('^(.*?)(>|[IBSCLFXZE]<)(.*)$')
    17:     self.digits_re = re.compile('^([0-9]+)>(.*)$')
    18:     self.entity_re = re.compile('^([A-Za-z]+)>(.*)$')
    19:     # this is not a full list, we should in fact call a weaver routine.
    20:     self.html_entity = {
    21:       'amp':'&',
    22:       'lt':'<',
    23:       'gt':'>',
    24:       'quot':'"',
    25:       'copy':'C',
    26:       'trade':'T',
    27:       'reg':'R'}
    28: 
    29:   def __del__(self):
    30:     self.flow_escape()
    31:     self.end_lists()
    32: 
    33:   def flow_escape(self):
    34:     line = self.flow_text
    35:     if not line: return
    36:     self.flow_text = ''
    37:     # process balanced text,
    38:     # if there is an unbalanced >, the text after it is returned
    39:     # write a >, and then try again.
    40:     tail = self.flow_parse(line)
    41:     while tail:
    42:       if verbosity >=4: print 'Unbalanced > in perl POD text'
    43:       self.weaver.write('>')
    44:       tail = self.flow_parse(tail)
    45: 
    46:   # recursive descent parser
    47:   def flow_parse(self,tail):
    48:     if not tail: return ''
    49:     weaver = self.weaver
    50: 
    51:     match = self.esc_re.match(tail)
    52:     while match:
    53:       pre, cmd, tail = match.group(1,2,3)
    54:       if pre: weaver.write(pre)
    55:       if cmd=='>': return tail
    56: 
    57:       assert len(cmd)==2 and cmd[1]=='<'
    58:       cmd = cmd[0]
    59:       if cmd == 'I':
    60:         weaver.begin_italic()
    61:         tail = self.flow_parse(tail)
    62:         weaver.end_italic()
    63:       elif cmd == 'B':
    64:         weaver.begin_bold()
    65:         tail = self.flow_parse(tail)
    66:         weaver.end_bold()
    67:       elif cmd == 'S':
    68:         # should be non-breaking spaces, but interscript
    69:         # doesn't implement that
    70:         tail = self.flow_parse(tail)
    71:       elif cmd == 'C':
    72:         weaver.begin_code()
    73:         tail = self.flow_parse(tail)
    74:         weaver.end_code()
    75:       elif cmd == 'L':
    76:         # a link: we just hack it for now
    77:         weaver.write('[')
    78:         tail = self.flow_parse(tail)
    79:         weaver.write(']')
    80:       elif cmd == 'F':
    81:         # filename
    82:         weaver.begin_code()
    83:         tail = self.flow_parse(tail)
    84:         weaver.end_code()
    85:       elif cmd == 'X':
    86:         # index entry??  (Does this mean print it, or index it?)
    87:         # I'll just print it as code :-)
    88:         weaver.begin_code()
    89:         tail = self.flow_parse(tail)
    90:         weaver.end_code()
    91:       elif cmd == 'Z':
    92:         # zero width character? What's that mean?
    93:         tail = self.flow_parse(tail)
    94:       elif cmd == 'E':
    95:         match = self.digits_re.match(tail)
    96:         if match:
    97:           digits, tail = match.group(1,2)
    98:           n = chr(int(digits))
    99:           weaver.write(n)
   100:         else:
   101:           match = self.entity_re.match(tail)
   102:           if match:
   103:             entity, tail = match.group(1,2)
   104:             data = self.html_entity.get(entity,'E<'+entity+'>')
   105:             weaver.write(data)
   106:           else:
   107:             # nothing we recognize, print literally
   108:             weaver.write('E<')
   109:             tail = self.flow_parse(tail)
   110:             weaver.write('>')
   111: 
   112:       match = self.esc_re.match(tail)
   113: 
   114:     # no (more) matches, so just weave the tail
   115:     self.weaver.writeline(tail)
   116:     return ''
   117: 
   118: 
   119:   def end_list_item(self):
   120:     kind = self.list_type[-1]
   121:     weaver = self.weaver
   122:     if kind == 'keyed': weaver.end_keyed_list_item()
   123:     elif kind == 'bullet': weaver.end_bullet_list_item()
   124:     elif kind == 'numbered': weaver.end_numbered_list_item()
   125: 
   126:   def end_list(self):
   127:     kind = self.list_type[-1]
   128:     weaver = self.weaver
   129:     if kind == 'keyed': weaver.end_keyed_list()
   130:     elif kind == 'bullet': weaver.end_bullet_list()
   131:     elif kind == 'numbered': weaver.end_numbered_list()
   132:     del self.list_type[-1]
   133: 
   134:   def end_lists(self):
   135:     while self.list_type: self.end_list()
   136: 
   137:   def begin_list(self,kind):
   138:     # print '** list type:',kind
   139:     self.list_type.append(kind)
   140:     weaver = self.weaver
   141:     if kind == 'keyed': weaver.begin_keyed_list()
   142:     elif kind == 'bullet': weaver.begin_bullet_list()
   143:     elif kind == 'numbered': weaver.begin_numbered_list()
   144: 
   145:   def begin_list_item(self,key=None):
   146:     kind = self.list_type[-1]
   147:     weaver = self.weaver
   148:     if kind == 'keyed': weaver.begin_keyed_list_item(key)
   149:     elif kind == 'bullet': weaver.begin_bullet_list_item()
   150:     elif kind == 'numbered': weaver.begin_numbered_list_item()
   151: 
   152:   def writeline(self,data,file,count,inhibit_sref=0):
   153:     if not inhibit_sref and not self.inhibit_sref:
   154:       if (file != self.sink.last_source_file or
   155:         count != self.sink.last_source_count+1):
   156:         self.start_section(file,count)
   157:     self.sink.last_source_file = file
   158:     self.sink.last_source_count = count
   159:     tangler_base._writeline(self,data)
   160: 
   161:     # try to find a pod command
   162:     pod = self.pod_re.match(data)
   163: 
   164:     # if we're in code mode, and we didn't
   165:     # get a pod command, just echotangle as code
   166:     # otherwise, switch to pod mode
   167: 
   168:     if self.mode == 'code':
   169:       if pod: self.mode = 'pod'
   170:       else:
   171:         self.weaver.echotangle(self.sink.lines_written,data)
   172:         return
   173: 
   174:     # now we're in pod mode, if we didn't get a pod command,
   175:     # strip the line to see if it's blank.
   176:     # if not, weave it and switching pod end of para detection on
   177:     # otherwise, emit an end of paragraph if detection is on
   178:     # unless we're in litpar mode, in which case we have to
   179:     # emulate an 'end' cmd
   180:     # pod_par means: 0 - begin of para, 1 - flowing text, 2 - literal text
   181:     assert self.mode == 'pod'
   182:     if not pod:
   183:       line = string.rstrip(data)
   184:       if line:
   185:         if not self.pod_par:
   186:           self.pod_par = (line[0] in ' \t')+1
   187:           if self.pod_par == 1: self.flow_text = ''
   188:         if self.pod_par-1:
   189:           self.weaver.writecode(line)
   190:         else:
   191:           # we have to search for escapes here!
   192:           self.flow_text = self.flow_text + line + ' '
   193:       elif self.pod_par:
   194:         self.flow_escape()
   195:         self.weaver.par()
   196:         self.pod_par = 0 # beginning of paragraph
   197:       return
   198: 
   199:     # we've got a pod command, so turn para detection off
   200:     assert pod
   201:     self.pod_par = 0
   202:     cmd = pod.group(1)
   203: 
   204:     # if we're cuttiung back to code, terminate lists and list
   205:     # items correctly if nececcary and switch back to code mode
   206: 
   207:     if cmd == 'cut':
   208:       self.end_lists()
   209:       if hasattr(self,'pod_mode'):
   210:         if self.pod_mode in ['lit','litpar']:
   211:           self.weaver.enable() # disable rawmode
   212:           self.weaver.translate() # disable rawmode
   213:         del self.pod_mode
   214:       self.mode = 'code'
   215:       return
   216: 
   217:     # Otherwise, just process the command
   218: 
   219:     if cmd == 'head1':
   220:       self.end_lists()
   221:       self.weaver.head(1+self.heading_level_offset, pod.group(2))
   222: 
   223:     elif cmd == 'head2':
   224:       self.end_lists()
   225:       self.weaver.head(2+self.heading_level_offset, pod.group(2))
   226: 
   227:     elif cmd == 'over':
   228:       # list of unknown type pending, wait for =item
   229:       self.pod_mode = 'list'
   230: 
   231:     elif cmd == 'back':
   232:       self.end_list_item()
   233:       self.end_list()
   234: 
   235:     elif cmd == 'item':
   236:       if not hasattr(self,'pod_mode'):
   237:         if verbosity >=2: print 'POD: item before over'
   238:         self.pod_mode = 'list'
   239:       key = pod.group(2)
   240:       key = string.strip(key)
   241:       if self.pod_mode == 'item':
   242:         self.end_list_item()
   243:       else:
   244:         self.pod_mode = 'item'
   245:         list_type = 'keyed'
   246:         if len(key)==1:
   247:           if key in '*+.-':
   248:             list_type = 'bullet'
   249:         self.begin_list(list_type)
   250:       if self.list_type[-1] == 'keyed':
   251:         # interscript doesn't support formatting of any kind
   252:         # in keyed list keys (because LaTeX doesn't)
   253:         # we need another kind of list (LaTeX can be given one)
   254:         # For now, we remove any X<...> stuff
   255:         stripkey = ''
   256:         tail = key
   257:         match = self.esc_re.match(tail)
   258:         while match:
   259:           pre, cmd, tail = match.group(1,2,3)
   260:           stripkey = stripkey + pre
   261:           match = self.esc_re.match(tail)
   262:         if tail: stripkey = stripkey + tail
   263:         key = stripkey
   264: 
   265:       self.begin_list_item(key)
   266: 
   267:     elif cmd == 'for':
   268:       self.weaver.rawif(pod.group(2))
   269:       self.pod_mode = 'litpar'
   270:     elif cmd == 'begin':
   271:       self.weaver.rawif(pod.group(2))
   272:       self.pod_mode = 'lit'
   273:     elif cmd == 'end':
   274:       self.weaver.enable()
   275:       self.weaver.translate()
   276:       self.weaver.pod_mode = ''
   277: 
   278:   def write_comment(self,line):
   279:     self._writeline('# '+line)
   280: 
   281:   def start_section(self, file, count):
   282:     data = '#line '+str(count)+' '+'"'+file+'"'
   283:     self._writeline(data)
   284:     self.weaver.echotangle(self.sink.lines_written,data)
   285: 
   286:   def get_comment_tangler(self):
   287:     return hash_comment_tangler(self.sink,weaver, '# ')
   288: 
   289:   def get_string_tangler(self,eol,width):
   290:     # This is _wrong_ and needs to be fixed!
   291:     return c_string_tangler(self.sink,self.get_weaver(),eol,width)
   292: 
   293: 

6.7. Tokenisers

Tokenise various languages.
Start python section to interscript/tokenisers/__init__.py[1] 1
     1: #line 4 "tokenizers.ipk"
     2: # tokenisers package
     3: 

6.7.1. Python Tokeniser

This module was modified from tokenize.py of the standard library marked
  __version__ = "Ka-Ping Yee, 26 October 1997; patched, GvR 3/30/98'
The module provides tokenisation of python source code.

The module provides a class 'python_tokenize' and a function 'tokenize'.

The function tokenize is provided for compatibility with the original tokenize.py. It accepts up to four arguments. The first argument, readline, is required and is a callback function which fetches a line for tokenisation. It should return a line with a trailing newline character, or an empty string to indicate end of input. The second argument, tokeneater, is a callback which is called with each token as an argument. If omitted, it defaults to a pretty-printing routine which writes a formatted display of the token to sys.stdout.

The class constructor and function accept three optional arguments.

squashop
The argument squashop defaults to 0 for the class and 1 for the function. If set, all special tokens are reported as token OP.
report_comments
The argument report_comments defaults to 0 for the class and 1 for the function. If set, comments are reported as COMMENTS, and blanks lines and mid-statement end of lines are reported as NL.
split_multiline_strings
If set, multiline strings are reported using one token per line. The default is 0 because partial strings aren't really tokens.
If the optional arguments are zero, the result is a 'pure' token stream suitable for parsing, if they're all set the result is more suitable for pretty printing.

The class provides the following methods. The method reset() resets the tokenizer state. The method write accepts arbitrary text data. The method writeline shall be called with a single line including a trailing newline character, or with an empty string, indicating end of input. The method get_tokens is called to fetch tokens which have been produced and clears the token queue. The method close signals end of input and returns any trailing tokens. The method tokenize accepts any text data and returns the tokens from the queue. Tokens which span lines are report after the line in which they are terminated is processed.

The format of a token consists of an integer token index corresponding to python tokens as listed in the file token.py, the lexeme which the token represents, the starting and ending positions of the lexeme as (line, column) pairs, and the source containing the lexeme. Lines are numbered from 1.

Start python section to interscript/tokenisers/python.py[1] 1 2 3 4
     1: #line 57 "python_tokeniser.ipk"
     2: __version__ = "Ka-Ping Yee 1997/10/26; GvR 1998/3/20, Skaller 1998/11/21"
     3: 
     4: import string, re
     5: from token import *
     6: 
     7: COMMENT = N_TOKENS
     8: tok_name[COMMENT] = 'COMMENT'
     9: 
    10: NL = N_TOKENS + 1
    11: tok_name[NL] = 'NL'
    12: 
    13: WHITESPACE = N_TOKENS+2
    14: tok_name[WHITESPACE] = 'WHITESPACE'
    15: 
    16: MULTILINE_STRING_FIRST = N_TOKENS+3
    17: tok_name[MULTILINE_STRING_FIRST]= 'MULTILINE_STRING_FIRST'
    18: 
    19: MULTILINE_STRING_MIDDLE = N_TOKENS+4
    20: tok_name[MULTILINE_STRING_MIDDLE]= 'MULTILINE_STRING_MIDDLE'
    21: 
    22: MULTILINE_STRING_LAST = N_TOKENS+5
    23: tok_name[MULTILINE_STRING_LAST]= 'MULTILINE_STRING_LAST'
    24: 
    25: # Changes from 1.3:
    26: #     Ignore now accepts \f as whitespace.  Operator now includes '**'.
    27: #     Ignore and Special now accept \n or \r\n at the end of a line.
    28: #     Imagnumber is new.  Expfloat is corrected to reject '0e4'.
    29: # Note: to quote a backslash in a regex, it must be doubled in a r'aw' string.
    30: 
    31: def group(*choices): return '(' + string.join(choices, '|') + ')'
    32: def any(*choices): return apply(group, choices) + '*'
    33: def maybe(*choices): return apply(group, choices) + '?'
    34: 
    35: Whitespace = r'[ \f\t]*'
    36: Comment = r'#[^\r\n]*'
    37: Ignore = Whitespace + any(r'\\\r?\n' + Whitespace) + maybe(Comment)
    38: Name = r'[a-zA-Z_]\w*'
    39: 
    40: Hexnumber = r'0[xX][\da-fA-F]*[lL]?'
    41: Octnumber = r'0[0-7]*[lL]?'
    42: Decnumber = r'[1-9]\d*[lL]?'
    43: Intnumber = group(Hexnumber, Octnumber, Decnumber)
    44: Exponent = r'[eE][-+]?\d+'
    45: Pointfloat = group(r'\d+\.\d*', r'\.\d+') + maybe(Exponent)
    46: Expfloat = r'[1-9]\d*' + Exponent
    47: Floatnumber = group(Pointfloat, Expfloat)
    48: Imagnumber = group(r'0[jJ]', r'[1-9]\d*[jJ]', Floatnumber + r'[jJ]')
    49: Number = group(Imagnumber, Floatnumber, Intnumber)
    50: 
    51: Single = any(r"[^'\\]", r'\\.') + "'"
    52: Double = any(r'[^"\\]', r'\\.') + '"'
    53: Single3 = any(r"[^'\\]",r'\\.',r"'[^'\\]",r"'\\.",r"''[^'\\]",r"''\\.") + "'''"
    54: Double3 = any(r'[^"\\]',r'\\.',r'"[^"\\]',r'"\\.',r'""[^"\\]',r'""\\.') + '"""'
    55: Triple = group("[rR]?'''", '[rR]?"""')
    56: String = group("[rR]?'" + any(r"[^\n'\\]", r'\\.') + "'",
    57:                '[rR]?"' + any(r'[^\n"\\]', r'\\.') + '"')
    58: 
    59: Operator = group('\+', '\-', '\*\*', '\*', '\^', '~', '/', '%', '&', '\|',
    60:                  '<<', '>>', '==', '<=', '<>', '!=', '>=', '=', '<', '>')
    61: Bracket = '[][(){}]'
    62: Special = group(r'\r?\n', r'[:;.,`]')
    63: Funny = group(Operator, Bracket, Special)
    64: 
    65: PlainToken = group(Number, Funny, String, Name)
    66: Token = Ignore + PlainToken
    67: 
    68: ContStr = group("[rR]?'" + any(r'\\.', r"[^\n'\\]") + group("'", r'\\\r?\n'),
    69:                 '[rR]?"' + any(r'\\.', r'[^\n"\\]') + group('"', r'\\\r?\n'))
    70: PseudoExtras = group(r'\\\r?\n', Comment, Triple)
    71: PseudoToken = Whitespace + group(PseudoExtras, Number, Funny, ContStr, Name)
    72: 
    73: tokenprog, pseudoprog, single3prog, double3prog = map(
    74:     re.compile, (Token, PseudoToken, Single3, Double3))
    75: endprogs = {"'": re.compile(Single), '"': re.compile(Double),
    76:             "'''": single3prog, '"""': double3prog,
    77:             "r'''": single3prog, 'r"""': double3prog,
    78:             "R'''": single3prog, 'R"""': double3prog, 'r': None, 'R': None}
    79: 
    80: opdict = {
    81:   '(':LPAR,
    82:   ')':RPAR,
    83:   '[':LSQB,
    84:   ']':RSQB,
    85:   ':':COLON,
    86:   ',':COMMA,
    87:   ';':SEMI,
    88:   '+':PLUS,
    89:   '-':MINUS,
    90:   '*':STAR,
    91:   '/':SLASH,
    92:   '|':VBAR,
    93:   '&':AMPER,
    94:   '<':LESS,
    95:   '>':GREATER,
    96:   '=':EQUAL,
    97:   '.':DOT,
    98:   '%':PERCENT,
    99:   '`':BACKQUOTE,
   100:   '{':LBRACE,
   101:   '}':RBRACE,
   102:   '==':EQEQUAL,
   103:   '!=':NOTEQUAL,
   104:   '<>':NOTEQUAL,
   105:   '<=':LESSEQUAL,
   106:   '>=':GREATEREQUAL,
   107:   '~':TILDE,
   108:   '^':CIRCUMFLEX,
   109:   '<<':LEFTSHIFT,
   110:   '>>':RIGHTSHIFT,
   111:   '**':DOUBLESTAR
   112:   }
   113: 
   114: tabsize = 8
   115: TokenError = 'TokenError'
   116: def printtoken(type, token, (srow, scol), (erow, ecol), line): # for testing
   117:     print "%d,%d-%d,%d:\t%s\t%s" % \
   118:         (srow, scol, erow, ecol, tok_name[type], repr(token))
   119: 
End python section to interscript/tokenisers/python.py[1]

6.7.1.1. Callback Interface

This function does callbacks from a supplier to get data, and sends tokens to a consumer callback. State is preserved on the system stack.
Start python section to interscript/tokenisers/python.py[2] 1 2 3 4
   120: #line 180 "python_tokeniser.ipk"
   121: def tokenise(readline,
   122:   tokeneater=printtoken,
   123:   squashop=1, report_comments=1, split_multiline_strings=0):
   124:   t = python_tokeniser(squashop, report_comments, split_multiline_strings)
   125:   line = readline()
   126:   while line:
   127:     t.writeline(line)
   128:     for token in t.tokens:
   129:       apply(tokeneater,token)
   130:     t.tokens = []
   131:     line = readline()
   132:   t.writeline('')
   133:   for token in t.tokens:
   134:     apply(tokeneater,token)
   135:   t.tokens = []
   136: 
End python section to interscript/tokenisers/python.py[2]

6.7.1.2. Server Interface

This interface is driven by the client. State is preserved in a class instance. Tokens are buffered until the client fetches them.
Start python section to interscript/tokenisers/python.py[3] 1 2 3 4
   137: #line 200 "python_tokeniser.ipk"
   138: namechars, numchars = string.letters + '_', string.digits
   139: 
   140: class python_tokeniser:
   141:   def __init__(self, squashop=0, report_comments=0, split_multiline_strings=0):
   142:     self.squashop = squashop
   143:     self.report_comments = report_comments
   144:     self.split_multiline_strings = split_multiline_strings
   145:     self.reset()
   146: 
   147:   def reset(self):
   148:     self.lnum = self.parenlev = self.continued = 0
   149:     self.contstr, self.needcont = '', 0
   150:     self.contline = None
   151:     self.indents = [0]
   152:     self.tokens = []
   153:     self.buffer = ''
   154: 
   155:   def get_tokens(self):
   156:     tmp = self.tokens
   157:     self.tokens = []
   158:     return tmp
   159: 
   160:   def tokenize(self,data):
   161:     self.write(data)
   162:     return self.get_tokens()
   163: 
   164:   def tokeneater(self,*args):
   165:     self.tokens.append(args)
   166: 
   167:   def close(self):
   168:     if self.buffer:
   169:       self.writeline(self.buffer)
   170:       self.buffer = ''
   171:     self.writeline('')
   172:     return self.get_tokens()
   173: 
   174:   def write(self,data):
   175:     lines = string.split(data,'\n')
   176:     if lines:
   177:       lines[0]=lines[0]+self.buffer
   178:       self.buffer = ''
   179:     for line in lines[:-1]:
   180:       self.writeline(line+'\n')
   181:     self.buffer = lines[-1]
   182: 
End python section to interscript/tokenisers/python.py[3]
6.7.1.2.1. Main Routine
This is the main function to supply a line of data to the tokeniser. It was adapted from the original function by control inversion: when it runs out of data, instead of fetching more, it just returns.
Start python section to interscript/tokenisers/python.py[4] 1 2 3 4
   183: #line 251 "python_tokeniser.ipk"
   184:   def writeline(self,line):
   185:     lnum = self.lnum = self.lnum + 1
   186:     pos, max = 0, len(line)
   187:     tokeneater = self.tokeneater
   188: 
   189:     if self.contstr:                                   # continued string
   190:         if not line:
   191:             raise TokenError, ("EOF in multi-line string", self.strstart)
   192:         endmatch = self.endprog.match(line)
   193:         if endmatch:
   194:             pos = end = endmatch.end(0)
   195:             if self.split_multiline_strings:
   196:               tokeneater(MULTILINE_STRING_LAST,
   197:                 line[:end], (lnum,0),(lnum,end), line)
   198:             else:
   199:               tokeneater(STRING, self.contstr + line[:end],
   200:                 self.strstart, (lnum, end), self.contline + line)
   201:             self.contstr, self.needcont = '', 0
   202:             self.contline = None
   203:         elif self.needcont and line[-2:] != '\\\n' and line[-3:] != '\\\r\n':
   204:             tokeneater(ERRORTOKEN, self.contstr + line,
   205:                        self.strstart, (lnum, len(line)), self.contline)
   206:             self.contstr = ''
   207:             self.contline = None
   208:             return
   209:         else:
   210:             self.contstr = self.contstr + line
   211:             self.contline = self.contline + line
   212:             if self.split_multiline_strings:
   213:               tokeneater(MULTILINE_STRING_MIDDLE,
   214:                 line, (lnum, 0), (lnum, len(line)), line)
   215:             return
   216: 
   217:     elif self.parenlev == 0 and not self.continued:    # new statement
   218:         if not line: self._close(); return
   219: 
   220:         column = 0
   221:         while pos < max:                               # measure leading whitespace
   222:             if line[pos] == ' ': column = column + 1
   223:             elif line[pos] == '\t': column = (column/tabsize + 1)*tabsize
   224:             elif line[pos] == '\f': column = 0
   225:             else: break
   226:             pos = pos + 1
   227:         if pos == max: self._close(); return           # omitted newline
   228: 
   229:         if line[pos] in '#\r\n':                       # skip comments or blank lines
   230:             if self.report_comments:
   231:               tokeneater((NL, COMMENT)[line[pos] == '#'], line[pos:],
   232:                        (lnum, pos), (lnum, len(line)), line)
   233:             return
   234: 
   235:         if column > self.indents[-1]:                  # count indents or dedents
   236:             self.indents.append(column)
   237:             tokeneater(INDENT, line[:pos], (lnum, 0), (lnum, pos), line)
   238:         while column < self.indents[-1]:
   239:             self.indents = self.indents[:-1]
   240:             tokeneater(DEDENT, '', (lnum, pos), (lnum, pos), line)
   241: 
   242:     else:                                              # continued statement
   243:         if not line:
   244:             raise TokenError, ("EOF in multi-line statement", (lnum, 0))
   245:         self.continued = 0
   246: 
   247:     while pos < max:
   248:         pseudomatch = pseudoprog.match(line, pos)
   249:         if pseudomatch:                                # scan for tokens
   250:             start, end = pseudomatch.span(1)
   251:             spos, epos, pos = (lnum, start), (lnum, end), end
   252:             token, initial = line[start:end], line[start]
   253: 
   254:             if initial in numchars \
   255:                 or (initial == '.' and token != '.'):  # ordinary number
   256:                 tokeneater(NUMBER, token, spos, epos, line)
   257:             elif initial in '\r\n':
   258:                 if self.parenlev == 0:
   259:                   tokeneater(NEWLINE, token, spos, epos, line)
   260:                 elif self.report_comments:
   261:                   tokeneater(NL, token, spos, epos, line)
   262: 
   263:             elif initial == '#':
   264:                 if self.report_comments:
   265:                   tokeneater(COMMENT, token, spos, epos, line)
   266:             elif token in ("'''", '"""',               # triple-quoted
   267:                            "r'''", 'r"""', "R'''", 'R"""'):
   268:                 self.endprog = endprogs[token]
   269:                 endmatch = self.endprog.match(line, pos)
   270:                 if endmatch:                           # all on one line
   271:                     pos = endmatch.end(0)
   272:                     token = line[start:pos]
   273:                     tokeneater(STRING, token, spos, (lnum, pos), line)
   274:                 else:
   275:                     if self.split_multiline_strings:
   276:                       token = line[start:]
   277:                       tokeneater(MULTILINE_STRING_FIRST,
   278:                         token, spos, (lnum, len(line)), line)
   279:                     self.strstart = (lnum, start)    # multiple lines
   280:                     self.contstr = line[start:]
   281:                     self.contline = line
   282:                     break
   283:             elif initial in ("'", '"') or \
   284:                 token[:2] in ("r'", 'r"', "R'", 'R"'):
   285:                 if token[-1] == '\n':                  # continued string
   286:                     self.strstart = (lnum, start)
   287:                     self.endprog = endprogs[initial] or endprogs[token[1]]
   288:                     self.contstr, self.needcont = line[start:], 1
   289:                     self.contline = line
   290:                     if self.split_multiline_strings:
   291:                       tokeneater(MULTILINE_STRING_FIRST,
   292:                         line[start:], (lnum, start), (lnum, len(line)), line)
   293:                     break
   294:                 else:                                  # ordinary string
   295:                     tokeneater(STRING, token, spos, epos, line)
   296:             elif initial in namechars:                 # ordinary name
   297:                 tokeneater(NAME, token, spos, epos, line)
   298:             elif initial == '\\':                      # continued stmt
   299:                 self.continued = 1
   300:             else:
   301:                 if initial in '([{': self.parenlev = self.parenlev + 1
   302:                 elif initial in ')]}': self.parenlev = self.parenlev - 1
   303:                 if self.squashop:
   304:                   tokeneater(OP, token, spos, epos, line)
   305:                 else:
   306:                   op = opdict[token]
   307:                   tokeneater(op, token, spos, epos, line)
   308:         else:
   309:             tokeneater(ERRORTOKEN, line[pos],
   310:                        (lnum, pos), (lnum, pos+1), line)
   311:             pos = pos + 1
   312: 
   313: 
   314:   def _close(self):
   315:       for indent in self.indents[1:]:          # pop remaining indent levels
   316:           self.tokeneater(DEDENT, '', (self.lnum, 0), (self.lnum, 0), '')
   317:       self.tokeneater(ENDMARKER, '', (self.lnum, 0), (self.lnum, 0), '')
   318: 
   319: if __name__ == '__main__':                     # testing
   320:     import sys
   321:     if len(sys.argv) > 1: tokenise(open(sys.argv[1]).readline)
   322:     else: tokenise(sys.stdin.readline)
   323: 
     4: #line 8 "tokenizers.ipk"
     5: 
     6: 

6.7.2. Parsers

While a tangler is used to 'pretty print' code in some language, a parser, or 'meta-tangler' is used to actually execute it. A meta-tangler has a writeline method just like any other tangler object, however instead of writing output to a code file and weaver, it translates the input and executes it.
Start python section to interscript/parsers/__init__.py[1] 1
     1: #line 12 "parsers.ipk"
     2: # input parsers

6.7.2.1. HTML Parser

We provide an HTML meta tangler. The sgml_wrapper class maps writeline calls from the control algorithm to feed calls of on the parser.

Construction of an html_filter object feeds the parser with an initial <HTML> tag. Termination semantics are as follows: if the external data source becomes exhausted, processing of buffered data should be forced by calling the close method of the sgml_wrapper or html_filter object.

If a </HTML> ending tag is detected, an eoi exception is thrown.

In either case, reset() me be called to reinitialise the object state, or the object can be destroyed. Note that the current implementation dispatches tags to global methods, rather than to a weaver bound to the object. This is to permit bindings to Interscript operations other than weaving.

Embedded Python and Tcl (if supported) can be executed in the Interscript environment using the <SCRIPT> tag as follows:

  <SCRIPT LANGUAGE="Python"><!--
    print "Hello World"
  #-->
  </SCRIPT>
  <SCRIPT LANGUAGE="Tcl"><!--
    puts "Hello World"
  #-->
Note that the used of comments is _not_ optional. If an error is detected during execution, a diagnostic will be printed but will not terminate continued processing of the document beyond the ending SCRIPT tag.

Start python section to interscript/parsers/html.py[1] 1
     1: #line 39 "html_parser.ipk"
     2: from interscript.drivers.sources.base import eoi
     3: import string
     4: import traceback
     5: class sgml_wrapper:
     6:   def __init__(self, sgml):
     7:     self.sgml = sgml
     8: 
     9:   def writeline(self,data,file,count):
    10:     self.sgml.feed(data)
    11: 
    12:   def close():
    13:     self.sgml.close(self)
    14: 
    15:   def reset(self):
    16:     self.sgml.reset()
    17: 
    18: # this is a hack: sgmllib needs to be imported here
    19: # so the class SGMLParser defined in it can be used as a base
    20: import sgmllib
    21: 
    22: class html_filter(sgmllib.SGMLParser):
    23:   def __init__(self, input_frame):
    24:     sgmllib.SGMLParser.__init__(self)
    25:     self.save_data = 0
    26:     self.script_language = ''
    27:     self.input_frame = input_frame
    28:     self.weaver = input_frame.get_weaver()
    29:     self.verbosity = input_frame.verbosity
    30: 
    31:     # feeding <HTML> in here is a hack to get around a bug in sgmllib,
    32:     # which fails to process unbalanced end tags correctly
    33:     self.feed('<HTML>')
    34: 
    35:   def _save(self):
    36:     self.save_data = 1
    37:     self.saved_data = ''
    38:   def _saved(self):
    39:     self.save_data = 0
    40:     return self.saved_data
    41: 
    42:   def handle_data(self,data):
    43:     new_data = ''
    44:     for ch in data:
    45:       if ch == '\n': ch = ' \n'
    46:       new_data = new_data + ch
    47:     if self.save_data:
    48:       self.saved_data = self.saved_data + new_data
    49:     else:
    50:       self.weaver.write(new_data)
    51: 
    52:   def handle_comment(self,data):
    53:     if self.verbosity>=5: print 'SGML comment',data
    54:     if self.script_language != '':
    55:       self.saved_comments = self.saved_comments + data
    56: 
    57:   def start_html(self, attributes): pass
    58:   def start_head(self, attributes): pass
    59:   def end_head(self): pass
    60:   def start_body(self, attributes): pass
    61:   def end_body(self): pass
    62:   def end_html(self):
    63:     del self.input_frame
    64:     del self.weaver
    65:     raise eoi
    66: 
    67: # fonts
    68:   def start_b(self,attributes): self.weaver.begin_bold()
    69:   def end_b(self): self.weaver.end_bold()
    70: 
    71:   def start_i(self,attributes): self.weaver.begin_italic()
    72:   def end_i(self): self.weaver.end_italic()
    73: 
    74:   def start_em(self,attributes): self.weaver.begin_emphasize()
    75:   def end_em(self): self.weaver.end_emphasize()
    76: 
    77:   def start_strong(self,attributes): self.weaver.begin_strong()
    78:   def end_strong(self): self.weaver.end_strong()
    79: 
    80:   def start_small(self,attributes): self.weaver.begin_small()
    81:   def end_small(self): self.weaver.end_small()
    82: 
    83:   def start_big(self,attributes): self.weaver.begin_big()
    84:   def end_big(self): self.weaver.end_big()
    85: 
    86:   def start_code(self,attributes): self.weaver.begin_code()
    87:   def end_code(self): self.weaver.end_code()
    88: 
    89: # paragraphs
    90:   def start_p(self,attributes): self.weaver.prose()
    91:   def end_p(self): self.weaver.eop()
    92: 
    93: # displays
    94:   def start_pre(self,attributes): self.weaver.begin_displayed_code()
    95:   def end_pre(self): self.weaver.end_displayed_code()
    96: 
    97: #lists
    98:   def start_ol(self,attributes):
    99:     self.weaver.begin_numbered_list()
   100:     self.list_kind = 'ol'
   101:   def end_ol(self):
   102:     self.weaver.end_numbered_list()
   103: 
   104:   def start_dl(self,attributes):
   105:     self.weaver.begin_keyed_list()
   106:     self.list_kind = 'dl'
   107:   def end_dl(self):
   108:     self.weaver.end_keyed_list()
   109: 
   110:   def start_ul(self,attributes):
   111:     self.weaver.begin_bullet_list()
   112:     self.list_kind = 'ul'
   113:   def end_ul(self):
   114:     self.weaver.end_bullet_list()
   115: 
   116: #list items
   117:   def start_li(self,attributes):
   118:     if self.list_kind == 'ol':
   119:       self.weaver.begin_numbered_list_item()
   120:     else:
   121:       self.weaver.begin_bullet_list_item()
   122: 
   123:   def end_li(self):
   124:     if self.list_kind == 'ol':
   125:       self.weaver.end_numbered_list_item()
   126:     else:
   127:       self.weaver.end_bullet_list_item()
   128: 
   129:   def start_dt(self,attributes): self._save()
   130:   def end_dt(self):
   131:     self.weaver.begin_keyed_list_item(self._saved())
   132: 
   133:   def start_dd(self,attributes): pass
   134:   def end_dd(self): self.weaver.end_keyed_list_item()
   135: 
   136: #headings
   137:   def start_h1(self,attributes): self._save()
   138:   def end_h1(self): self.weaver.head(1,self._saved())
   139: 
   140:   def start_h2(self,attributes): self._save()
   141:   def end_h2(self): self.weaver.head(2,self._saved())
   142: 
   143:   def start_h3(self,attributes): self._save()
   144:   def end_h3(self): self.weaver.head(3,self._saved())
   145: 
   146:   def start_h4(self,attributes): self._save()
   147:   def end_h4(self): self.weaver.head(4,self._saved())
   148: 
   149:   def start_h5(self,attributes): self._save()
   150:   def end_h5(self): self.weaver.head(5,self._saved())
   151: 
   152:   def start_h6(self,attributes): self._save()
   153:   def end_h6(self): self.weaver.head(6,self._saved())
   154: 
   155:   def unknown_starttag(self,tag,attributes):
   156:     print 'UNKNOWN START TAG',tag,attributes
   157: 
   158:   def unknown_endtag(self,tag):
   159:     print 'UNKNOWN END TAG',tag
   160: 
   161:   def unknown_charref(self,ref):
   162:     print 'BAD CHAR REF',ref
   163: 
   164:   def unknown_entityref(self,ref):
   165:     print 'UNKNOWN ENTITY REF',ref
   166: 
   167:   # due to a bug in sgmllib, this routine will
   168:   # never be called
   169:   def report_unbalanced(self,tag):
   170:     print 'LONELY ENDTAG',tag
   171: 
   172:   def start_script(self,attributes):
   173:     if self.verbosity>=6: print 'start of script'
   174:     for param, value in attributes:
   175:       if string.lower(param) == 'language':
   176:         self.script_language = string.lower(value)
   177:         self.saved_comments = ''
   178: 
   179:   def end_script(self):
   180:     if self.verbosity>=6: print 'end of script'
   181:     if self.script_language == 'python':
   182:       try:
   183:         exec self.saved_comments in globals(),self.input_frame.userdict
   184:       except:
   185:         print "Error executing python <SCRIPT>"
   186:         traceback.print_exc()
   187:     else:
   188:       print 'Sorry',self.script_language,'not available'
End python section to interscript/parsers/html.py[1]

6.8. Html parser test

This is an Html test for bold and italicsand strong, emphasised and code.Sizes too: big and small.

We can also do lists: an ordered list

  1. an ordered list item
  2. another ordered list item
and an unordered list
  • an unordered list item
  • another unordered list item
and a description list:
dl key 1
description 1
dl key 2
description 2
Here's a code display, using PRE tag:
A code example.With PRE tags.
Now for some script.print "Python script"weave("Some Python script made this.")

6.9. LALR(1) Parser table generator

6.9.1. Credits

This code is heavily adapted from the original by
  mailto:scott@chronis.icgroup.com
__version__ = "$Id: Grammar.py,v 0.2 1997/12/13 03:02:13 scott Exp scott $"
Scott has all the credit for implementing the very complex LALR parser table generator. The algorithms are from the Dragon Book, 'Compilers: Principles, Techniques and Tools' by Aho Sethi and Ullman, Addison Wesley. Mine has ISBN 0-201-10194-7, but is an old (1987) edition. Page numbers herein refer to that.

6.9.1.1. Dependencies

This module requires the Maxtal 'sets' module which contains the class 'set', used to represent a set. See 'sets.pak'.
Start python section to interscript/parsers/lalr1.py[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
     1: #line 21 "lalr1_parser.ipk"
     2: import sets
     3: import stacks
     4: set = sets.set
     5: gstack = stacks.stack
     6: 
End python section to interscript/parsers/lalr1.py[1]

6.9.1.2. Reserved Symbols

The following symbols are reserved by the system. EPS is a nonterminal which derives nothing, commonly called epsilon. It can be used in the client grammar, but must not be the LHS of a production.

EOF is a terminal, marking the end of the input stream. It must not be used in the client grammar. Some parsers may prohibit the inclusion of this symbol in the input stream, others may require it, and others may require an infinite stream of them at the end of the input.

In addition, the empty string and -1 are reserved as symbols by the system.

Note: this is ugly. We should use a class, but the repr() of a class is ugly.

Start python section to interscript/parsers/lalr1.py[2] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
     7: #line 42 "lalr1_parser.ipk"
     8: EPS = "<EPS>"
     9: EOF = "<EOF>"
    10: 
End python section to interscript/parsers/lalr1.py[2]

6.9.1.3. Grammar Productions

A production of a grammar is any object with two attributes, 'LHS' and 'RHS' where LHS is a nonterminal of the grammar, and the RHS is a sequence of grammar symbols, possibly empty.

There is no restriction on what kind of sequence is used, nor on what kind of objects the grammar symbols are, except that the string "<EPS>" may not be the LHS symbol of a production, and "<EOF>" and None may not be used at all.

It is recommended that interned strings or integers be used as grammar symbols. Strings make debugging easy because they can be read. Integers are commonly produced by other generating software.

Note that a production may have other attributes. In particular, the attribute 'func' may be used by parsers as a function to be invoked when deriving a nonterminal, thus implementing syntax directed parsing for S-attributed grammars.

Note: There may be a prohibition against using -1 as a grammar symbol. This should be fixed, it should be permitted.

Start python section to interscript/parsers/lalr1.py[3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
    11: #line 67 "lalr1_parser.ipk"
    12: class Production:
    13:   def __init__(self, LHS, RHS, **kwds):
    14:     self.LHS = LHS
    15:     self.RHS = RHS
    16:     for k in kwds.keys():
    17:       setattr(self,k,kwds[k])
    18: 
    19:   def __len__(self):
    20:     return len(self.RHS)
    21: 
    22:   def __repr__(self):
    23:     d = self.__dict__.copy()
    24:     del d['LHS']
    25:     del d['RHS']
    26:     return `self.LHS` + " -> " + `self.RHS`+' '+`d`
    27: 
End python section to interscript/parsers/lalr1.py[3]

6.9.1.4. Grammar

A grammar object is initialised by a nonempty sequence of productions, and a start symbol. The start symbol is required and must equal the LHS of at least one production.

An optional argument with keyword 'verbosity' defaults to 0, and may be used to control the amount of debugging information output during the initialisation process.

The sequence of productions is copied, but the productions objects are not.

The constructor builds some tables of auxilliary information about the grammar. After construction the following attributes are defined:

symbols
The set of symbols used in the client grammar, excluding "<EPS>". These are called the client symbols.
nonterms
The set of symbols found on the LHS of some production.
terms
The set of client symbols of the grammar excluding those found on the LHS of a production.
epslhs
The subset of client nonterminals which directly derive either nothing or "<EPS>".
lhsdereps
The subset of client nonterminals which derive nothing. This is a (possibly improper) superset of 'epslhs'.
lhsprods
A dictionary of keyed by client nonterminals, returning the set of productions of the nonterminal.
productions
A list of productions in the same order as the sequence passed to the constructor.
start
The nonterminal which the client denoted as the start symbol of the grammar.
firstmap
A dictionary keyed by grammar symbols, defining the FIRST set of that symbol. The dictionary includes entried for "<EOF>", "<EPS>", and a special entry for -1 (which is used internally as an error state).

The elements of the FIRST sets will be either client terminals or "<EOF>".

The FIRST set of a symbol is defined as follows: for a terminal, the singleton set containing just that terminal, for a nonterminal, the set of terminals which could be the first symbol of a derivation of the nonterminal, and including "<EPS>" if the nonterminal can derive nothing. See the Dragon book [4.4 p188].

followmap
A dictionary keyed by client nonterminals defining the FOLLOW set of that nonterminal.

The FOLLOW set is defined as the set of terminals which can follow the nonterminal in some sentential form of the grammar, and including "<EOF>" if the nonterminal can appear at the right of a sentential form. See the Dragon book [4.4 p189].

Start python section to interscript/parsers/lalr1.py[4] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
    28: #line 154 "lalr1_parser.ipk"
    29: class Grammar:
    30:   DummyLA = -1
    31: 
End python section to interscript/parsers/lalr1.py[4]
6.9.1.4.1. Constructor
Start python section to interscript/parsers/lalr1.py[5] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
    32: #line 159 "lalr1_parser.ipk"
    33:   def __init__(self, prods, start,verbosity=0):
    34:     self.verbosity = verbosity
    35:     self.start = start
    36:     self.productions = prods[:]
    37: 
    38:     if verbosity>1:
    39:       for i in range(len(self.productions)):
    40:         print i,':',self.productions[i]
    41: 
    42:     # calculate set of symbols, nonterminals, terminals
    43:     # and non-terminals directly deriving epsilon
    44:     self.symbols = set()
    45:     self.nonterms = set()
    46:     self.epslhs = set()
    47:     self.lhsprods = {}
    48:     for p in self.productions:
    49:       if not self.lhsprods.has_key(p.LHS): self.lhsprods[p.LHS]=set()
    50:       self.lhsprods[p.LHS].insert(p)
    51:       self.nonterms.insert(p.LHS)
    52:       if len(p.RHS)==1:
    53:         if p.RHS[0] is EPS: self.epslhs.insert(p.LHS)
    54:       elif len(p.RHS)==0: self.epslhs.insert(p.LHS)
    55: 
    56:       for sym in p.RHS:
    57:         if sym != EPS: self.symbols.insert(sym)
    58: 
    59:     self.terms = self.symbols - self.nonterms
    60: 
    61:     if verbosity>1:
    62:       print 'Symbols',self.symbols
    63:       print 'Terminals',self.terms
    64:       print 'NonTerminals',self.nonterms
    65:       print 'Directly Derive epsilon',self.epslhs
    66: 
    67:     self.calc_lhsdereps()
    68:     if verbosity>1:
    69:       print 'Derive epsilon',self.lhsdereps
    70: 
    71:     self.calc_firstmap()
    72:     if verbosity>1:
    73:       print 'First Sets:'
    74:       for nt in self.firstmap.keys():
    75:         print nt,'->',self.firstmap[nt]
    76: 
    77:     self.calc_followmap()
    78:     if verbosity>1:
    79:       print 'Follow Sets:'
    80:       for nt in self.followmap.keys():
    81:         print nt,'->',self.followmap[nt]
    82: 
    83: 
End python section to interscript/parsers/lalr1.py[5]
6.9.1.4.2. Find Nullable NonTerminals
Non-optimal!
Start python section to interscript/parsers/lalr1.py[6] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
    84: #line 213 "lalr1_parser.ipk"
    85:   def calc_lhsdereps(self):
    86:     res = self.epslhs.copy()
    87:     wnts = self.nonterms - res
    88: 
    89:     converged = 0
    90:     while not converged:
    91:       converged = 1
    92:       for nt in wnts:
    93:         for p in self.lhsprods[nt]:
    94:           p_nullable = 1
    95:           for sym in p.RHS:
    96:             if not res.contains(sym):
    97:               p_nullable = 0
    98:               break
    99:           if p_nullable:
   100:             res.insert(nt)
   101:             wnts = wnts.remove(nt)
   102:             converged = 0
   103:             break
   104:         if not converged: break
   105:     self.lhsdereps = res
   106: 
   107: 
End python section to interscript/parsers/lalr1.py[6]
6.9.1.4.3. Find FIRST sets
Calculcate FIRST(sym) for each symbol in the grammar, including epsilon, EOF, and DummyLA (whatever that is).
Start python section to interscript/parsers/lalr1.py[7] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   108: #line 240 "lalr1_parser.ipk"
   109:   def calc_firstmap(self):
   110:       res = {}
   111:       for sym in self.terms + [EPS, EOF, Grammar.DummyLA]:
   112:           res[sym] = set(sym)
   113:       while 1:
   114:           added = 0
   115:           for nt in self.nonterms:
   116:               firsts = res.get(nt, set())
   117:               for p in self.lhsprods[nt]:
   118:                   if not p.RHS:
   119:                       if not firsts.contains(EPS):
   120:                           added = 1
   121:                           firsts.insert(EPS)
   122:                       continue
   123:                   i = 0
   124:                   while i < len(p.RHS):
   125:                       f = res.get(p.RHS[i], set())
   126:                       for t in f:
   127:                           if not firsts.contains(t):
   128:                               added = 1
   129:                               firsts.insert(t)
   130:                       if self.lhsdereps.contains(p.RHS[i]):
   131:                           i = i + 1
   132:                       else: break
   133:               res[nt] = firsts
   134:           if not added:
   135:               break
   136:       self.firstmap = res
   137: 
   138: 
   139:   #
   140:   # these function are used as the grammar produces the tables (or writes them
   141:   # to a file)
   142:   #
   143:   def firstofstring(self, gs_list):
   144:     tmpres = {}
   145:     allhaveeps = 1
   146:     for x in range(len(gs_list)):
   147:       tmp = self.firstmap[gs_list[x]]
   148:       for s in tmp: tmpres[s] = 1
   149:       if EPS in tmp: del tmpres[EPS]
   150:       else:
   151:           allhaveeps = 0
   152:           break
   153:     if allhaveeps: tmpres[EPS] = 1
   154:     return tmpres.keys()
   155: 
   156: 
End python section to interscript/parsers/lalr1.py[7]
6.9.1.4.4. Augment grammar
This function adds a production S' -> S to the grammar where S was the start symbol.
Start python section to interscript/parsers/lalr1.py[8] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   157: #line 292 "lalr1_parser.ipk"
   158:   def augment(self):
   159:     lhss = map(lambda x: x.LHS, self.productions)
   160:     newsym = self.start
   161:     while newsym in lhss: newsym = newsym + "'"
   162:     self.productions.insert(0, Production(newsym, [self.start]))
   163: 
   164:   def unaugment(self):
   165:     del self.productions[0]
   166: 
End python section to interscript/parsers/lalr1.py[8]
6.9.1.4.5. Find FOLLOW sets
Calculcate FOLLOW(sym) for each symbol in the grammar, including epsilon,
Start python section to interscript/parsers/lalr1.py[9] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   167: #line 304 "lalr1_parser.ipk"
   168:   def calc_followmap(self):
   169:       eof = EOF
   170:       follow = {}
   171:       startsym = self.productions[0].LHS
   172:       follow[startsym] = set(eof)
   173:       nts = self.nonterms
   174:       for p in self.productions:
   175:           cutoff = range(len(p.RHS))
   176:           cutoff.reverse()
   177:           for c in cutoff[:-1]:  # all but the first of the RHS elements
   178:               f = self.firstmap[p.RHS[c]].copy()
   179:               f.excise(EPS)
   180:               if follow.has_key(p.RHS[c - 1]):
   181:                   if p.RHS[c -1] in nts:
   182:                       follow[p.RHS[c -1]] = follow[p.RHS[c - 1]] + f[:]
   183:               else:
   184:                   if p.RHS[c -1] in nts:
   185:                       follow[p.RHS[c - 1]] = f[:]
   186:       for p in self.productions:
   187:           if not p.RHS: continue
   188:           cutoff = range(len(p.RHS))
   189:           cutoff.reverse()
   190:           if p.RHS[-1] in nts:
   191:               if follow.has_key(p.LHS):
   192:                   add = follow[p.LHS]
   193:               else:
   194:                   add = []
   195: 
   196:               if follow.has_key(p.RHS[-1]):
   197:                   follow[p.RHS[-1]] = follow[p.RHS[-1]] + add
   198:               else:
   199:                   follow[p.RHS[-1]] = add
   200:           for c in cutoff[:-1]:
   201:               f = self.firstmap[p.RHS[c]].copy()
   202:               if EPS in f:
   203:                   if follow.has_key(p.LHS):
   204:                       add = follow[p.LHS]
   205:                   else:
   206:                       add = set()
   207:                   if follow.has_key(p.RHS[c-1]):
   208:                       follow[p.RHS[c-1]] = follow[p.RHS[c-1]] + add
   209:                   elif add:
   210:                       follow[p.RHS[c - 1]] = add
   211:       for k in follow.keys():
   212:           d = set()
   213:           for i in follow[k]: d.insert(i)
   214:           follow[k] = d
   215:       self.followmap = follow
   216: 
End python section to interscript/parsers/lalr1.py[9]
6.9.1.4.6. LALR Closure
Compute the LALR Closure. An 'item' is logically a pair consisting of a production and an indictor of a position in the RHS. It is represented here as a pair of integers: an index into the sequence of productions, and an integer between 0 and the length of the RHS of the production, inclusive.
Start python section to interscript/parsers/lalr1.py[10] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   217: #line 360 "lalr1_parser.ipk"
   218:   def closure(self, items):
   219:       res = items[:]
   220:       todo = items[:]
   221:       while 1:
   222:           more = []
   223:           for (prodind, rhsind), term in todo:
   224:               if rhsind >= len(self.productions[prodind].RHS):
   225:                   continue
   226:               for p in self.lhsprods.get(self.productions[prodind].RHS[rhsind], []):
   227:                   try:
   228:                       newpart = self.productions[prodind].RHS[rhsind + 1]
   229:                   except IndexError:
   230:                       newpart = EPS
   231:                   stringofsyms = [newpart, term]
   232:                   for t in self.firstofstring(stringofsyms):
   233:                       if ((self.productions.index(p), 0), t) not in res:
   234:                           more.append(((self.productions.index(p), 0), t))
   235:                   if term == EOF and newpart == EPS:
   236:                       if ((self.productions.index(p), 0), EOF) not in res:
   237:                           more.append(((self.productions.index(p), 0), EOF))
   238:           if more:
   239:               res = res + more
   240:               todo = more
   241:           else:
   242:               break
   243:       return res
   244: 
   245: 
   246: #  def goto(self, items, sym):
   247: #      itemset = []
   248: #      for (prodind, rhsind), term in items:
   249: #          try:
   250: #              if self.productions[prodind].RHS[rhsind] == sym and ((prodind, rhsind+1), term) not in itemset:
   251: #                  itemset.append( ((prodind, rhsind +1), term))
   252: #          except IndexError:
   253: #              pass
   254: #      return self.closure(itemset)
   255: 
End python section to interscript/parsers/lalr1.py[10]

6.9.2. LALR Parser Table generator

This is the efficient LALR parser generator described in the Dragon book.
Start python section to interscript/parsers/lalr1.py[11] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   256: #line 401 "lalr1_parser.ipk"
   257: class LALRGrammar(Grammar):
   258: 
   259:   def __init__(self, prods, start, verbosity=0):
   260:     Grammar.__init__(self, prods, start, verbosity)
   261:     self.calc_ntfirstmap()
   262:     self.calc_tfirstmap()
   263:     self.augment()
   264:     self.calc_LALR1items()
   265:     self.calc_action_table()
   266:     self.calc_goto_table()
   267:     self.unaugment()
   268: 
End python section to interscript/parsers/lalr1.py[11]

6.9.3. mkntfirstmap

Computes all nonterms A, first of (strings n) such that some nonterminal B derives [A, n] in zero or more steps of (rightmost) derivation. used to help make epsilon productions quickly calculable. (B may == A)

This is to help mak epsilon productions work with kernel items and to compute goto transitions from kernel.

Start python section to interscript/parsers/lalr1.py[12] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   269: #line 422 "lalr1_parser.ipk"
   270:   def calc_ntfirstmap(self):
   271:     res = {}
   272:     for p in self.productions:
   273:       if p.RHS and p.RHS[0] in self.nonterms:
   274:         fos = self.firstofstring(p.RHS[1:])
   275:         fos.sort()
   276:         if not res.has_key(p.LHS):
   277:           res[p.LHS] = {}
   278:         if not res[p.LHS].has_key(p.RHS[0]):
   279:           res[p.LHS][p.RHS[0]] = []
   280:         for i in fos:
   281:           if i not in res[p.LHS].get(p.RHS[0], []):
   282:             res[p.LHS][p.RHS[0]] = fos
   283: 
   284:     while 1:
   285:       foundmore = 0
   286:       reskeys = res.keys()
   287:       for nt in reskeys:
   288:         rhsdict = res[nt]
   289:         for rnt in rhsdict.keys():
   290:           if rnt in reskeys:
   291:             d = res[rnt]
   292:             for k in d.keys():
   293:               if not res[nt].has_key(k):
   294:                 fos = self.firstofstring(d[k]+ res[nt][rnt])
   295:                 foundmore = 1
   296:                 fos.sort()
   297:                 res[nt][k] = fos
   298:               else:
   299:                 fos = self.firstofstring(d[k] + res[nt][rnt])
   300:                 fos.sort()
   301:                 if fos != res[nt][k]:  # then res[nt][k] is contained in fos
   302:                   foundmore = 1
   303:                   res[nt][k] = fos
   304:       if not foundmore: break
   305:     #
   306:     # this part accounts for the fact that a nonterminal will
   307:     # produce exactly itself in zero steps
   308:     #
   309:     for p in self.productions:
   310:       if res.has_key(p.LHS):
   311:         res[p.LHS][p.LHS] = [EPS]
   312:       else:
   313:         res[p.LHS] = {p.LHS: [EPS]}
   314:     self.ntfirstmap = res
   315: 
End python section to interscript/parsers/lalr1.py[12]

6.9.3.1. newmkntfirstmap

computes all nonterms A, first of (strings n) such that some nonterminal B derives [A, n] in zero or more steps of (rightmost) derivation. used to help make epsilon productions quickly calculable. (B may == A)
Start python section to interscript/parsers/lalr1.py[13] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   316: #line 473 "lalr1_parser.ipk"
   317:   def newmkntfirstmap(self):
   318:     res = {}
   319:     pi = 0
   320:     for p in self.productions:
   321:       if p.RHS and p.RHS[0] in self.nonterms:
   322:         if not res.has_key(p.LHS):
   323:           res[p.LHS] = {}
   324:         if not res[p.LHS].has_key(p.RHS[0]):
   325:           res[p.LHS][p.RHS[0]] = 1
   326: 
   327:     while 1:
   328:       foundmore = 0
   329:       reskeys = res.keys()
   330:       for nt in reskeys:
   331:         rhsdict = res[nt]
   332:         for rnt in rhsdict.keys():
   333:           if rnt in reskeys:
   334:             d = res[rnt]
   335:             for k in d.keys():
   336:               if not res[nt].has_key(k):
   337:                 foundmore = 1
   338:                 res[nt][k] = 1
   339:       if not foundmore:
   340:         break
   341:     #
   342:     # this part accounts for the fact that a nonterminal will
   343:     # produce exactly itself in zero steps
   344:     #
   345:     for p in self.productions:
   346:       if res.has_key(p.LHS):
   347:         res[p.LHS][p.LHS] = 1
   348:       else:
   349:         res[p.LHS] = {p.LHS: 1}
   350:     self.ntfirstmap = res
   351: 
End python section to interscript/parsers/lalr1.py[13]

6.9.3.2. mktfirstmap

This is to help make shifts work with only kernel items.

For each nonterminal C, compute the set of all terminals a, such that C derives ax in zero or more steps of (rightmost) derivation where the last derivation is not an epsilon (empty) production.

assumes .mkfirstntmap() has been run and has already produced self.ntfirstmap

Start python section to interscript/parsers/lalr1.py[14] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   352: #line 517 "lalr1_parser.ipk"
   353:   def calc_tfirstmap(self):
   354:     res = {}
   355:     for p in self.productions:
   356:       if not res.has_key(p.LHS):
   357:         res[p.LHS] = []
   358:       if p.RHS and p.RHS[0] in self.terms:
   359:         res[p.LHS].append(p.RHS[0])
   360:     while 1:
   361:       foundmore = 0
   362:       reskeys = res.keys()
   363:       for nt in self.ntfirstmap.keys():
   364:         arrows = self.ntfirstmap[nt]
   365:         for k in arrows.keys():
   366:           for t in res[k]:
   367:             if t not in res[nt]:
   368:               foundmore = 1
   369:               res[nt].append(t)
   370:       if not foundmore: break
   371:     self.tfirstmap = res
   372: 
   373: 
End python section to interscript/parsers/lalr1.py[14]

6.9.3.3. goto

Start python section to interscript/parsers/lalr1.py[15] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   374: #line 540 "lalr1_parser.ipk"
   375:   def goto(self, itemset, sym):
   376:     res = []
   377:     for (pi, ri) in itemset:
   378:       if ri == len(self.productions[pi].RHS):
   379:         continue
   380:       s = self.productions[pi].RHS[ri]
   381:       if s == sym:
   382:         res.append((pi, ri+1))
   383:       d = self.ntfirstmap.get(s, {})
   384:       for k in d.keys():
   385:         for p in self.lhsprods[k]:
   386:           if p.RHS and p.RHS[0] == sym:
   387:             i = self.productions.index(p)
   388:             if (i, 1) not in res: res.append((i, 1))
   389:     res.sort()
   390:     return res
   391: 
End python section to interscript/parsers/lalr1.py[15]

6.9.3.4. lookaheads

Start python section to interscript/parsers/lalr1.py[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
   392: #line 559 "lalr1_parser.ipk"
   393:   def lookaheads(self, itemset):
   394:     setsofitems = kernels = self.kernelitems
   395:     spontaneous = []
   396:     propagates = {}
   397:     gotomap = {}
   398:     for (kpi, kri) in itemset:
   399:       C = self.closure([((kpi, kri), Grammar.DummyLA)])
   400:       for (cpi, cri), t in C:
   401:         if (cri) == len(self.productions[cpi].RHS):
   402:           continue
   403:         s = self.productions[cpi].RHS[cri]
   404:         if gotomap.has_key(s):
   405:           newstate = gotomap[s]
   406:         else:
   407:           newstate = setsofitems.index(self.goto(itemset, s))
   408:           gotomap[s] = newstate
   409:         if t != Grammar.DummyLA:
   410:           spontaneous.append((newstate, (cpi, cri+1), t))
   411:         else:
   412:           if propagates.has_key((kpi, kri)):
   413:             propagates[(kpi, kri)].append((newstate, (cpi, cri+1)))
   414:           else:
   415:             propagates[(kpi, kri)]=[(newstate, (cpi, cri+1))]
   416:     return spontaneous, propagates
   417: 
   418: 
End python section to interscript/parsers/lalr1.py[16]

6.9.3.5. kernelsoflalr1items

Start python section to interscript/parsers/lalr1.py[17] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   419: #line 587 "lalr1_parser.ipk"
   420:   def kernelsoflalr1items(self):
   421:     res = [[(0, 0)]]
   422:     todo = [[(0, 0)]]
   423:     while 1:
   424:       newtodo = []
   425:       for items in todo:
   426:         for s in self.terms + self.nonterms + [EOF]:
   427:           g = self.goto(items, s)
   428:           if g and g not in res:
   429:             newtodo.append(g)
   430:       if not newtodo:
   431:         break
   432:       else:
   433:         if self.verbosity>1:
   434:           print "found %d more kernels" % (len(newtodo))
   435:         res = res + newtodo
   436:         todo = newtodo
   437:     res.sort()
   438:     return res
   439: 
   440: 
End python section to interscript/parsers/lalr1.py[17]

6.9.3.6. Calculate LALR1items

Start python section to interscript/parsers/lalr1.py[18] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   441: #line 610 "lalr1_parser.ipk"
   442:   def initLALR1items(self):
   443:       self.kernelitems = kernels = self.kernelsoflalr1items()
   444:       props = {}
   445:       la_table = []
   446:       for x in range(len(kernels)):
   447:           la_table.append([])
   448:           for y in range(len(kernels[x])):
   449:               la_table[x].append([])
   450:       la_table[0][0] = [EOF]
   451:       if self.verbosity>1:
   452:           print "initLALR1items, kernels done, calculating propagations and spontaneous lookaheads"
   453:       state_i = 0
   454:       for itemset in kernels:
   455:           if self.verbosity>1:
   456:               print ".",
   457:           sp, pr = self.lookaheads(itemset)
   458:           for ns, (pi, ri), t in sp:
   459:               inner = kernels[ns].index((pi, ri))
   460:               la_table[ns][inner].append(t)
   461:           props[state_i] = pr
   462:           state_i = state_i + 1
   463:       return la_table, props
   464: 
   465: 
   466:   def calc_LALR1items(self):
   467:       la_table, props = self.initLALR1items()
   468:       if self.verbosity>1:
   469:           print "done init LALR1items"
   470:       soi = self.kernelitems
   471:       while 1:
   472:           added_la = 0
   473:           state_i = 0
   474:           for state in la_table:
   475:               ii = 0
   476:               for propterms in state:
   477:                   if not propterms:
   478:                       ii = ii + 1
   479:                       continue
   480:                   item = soi[state_i][ii]
   481:                   ii = ii + 1
   482:                   try:
   483:                       proplist = props[state_i][item]
   484:                   except KeyError:
   485:                       continue
   486:                   for pstate, pitem in proplist:
   487:                       inner = soi[pstate].index(pitem)
   488:                       for pt in propterms:
   489:                           if pt not in la_table[pstate][inner]:
   490:                               added_la = 1
   491:                               la_table[pstate][inner].append(pt)
   492:               state_i = state_i + 1
   493:           if not added_la:
   494:               break
   495:       #
   496:       # this section just reorganizes the above data
   497:       # to the state it's used in later...
   498:       #
   499:       if self.verbosity>1:
   500:           print "done with lalr1items, reorganizing the data"
   501:       res = []
   502:       state_i = 0
   503:       for state in soi:
   504:           item_i = 0
   505:           inner = []
   506:           for item in state:
   507:               for term in la_table[state_i][item_i]:
   508:                   if (item, term) not in inner:
   509:                       inner.append((item, term))
   510:               item_i = item_i + 1
   511:           inner.sort() # keeps productions in order!
   512:           res.append(inner)
   513:           state_i = state_i + 1
   514:       self.LALRitems = res
   515: 
End python section to interscript/parsers/lalr1.py[18]

6.9.3.7. Calculate Action Table

Start python section to interscript/parsers/lalr1.py[19] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   516: #line 686 "lalr1_parser.ipk"
   517:   def pr_conflict(self,state,sym,rej,acc):
   518:     if rej[0]=='r' and acc[0]=='s':
   519:       print "Shift/Reduce Conflict, Use Shift [%d,%s]:" % (state, repr(sym)), rej, "->", acc
   520:     elif rej[0]=='s' and acc[0]=='r':
   521:       print "WARNING! Shift/Reduce Conflict, Use Reduce [%d,%s]:" % (state, repr(sym)), rej, "->", acc
   522:     elif rej[0]=='s' and acc[0]=='s':
   523:       print "WARNING! Shift/Shift Conflict[%d,%s]:" % (state, repr(sym)), rej, "->", acc
   524:     elif rej[0]=='r' and acc[0]=='r':
   525:       print "WARNING! Reduce/Reduce Conflict[%d,%s]:" % (state, repr(sym)), rej, "->", acc
   526:     else:
   527:       print "WARNING! WEIRD Conflict[%d,%s]:" % (state, repr(sym)), rej, "->", acc
   528: 
   529:   def resolve(self,at,sym,new,state_i):
   530:     old = at.get(sym)
   531:     # new entry
   532:     if not old:
   533:       at[sym] = new
   534:       return
   535: 
   536:     # same entry
   537:     if old == new: return
   538: 
   539:     # resolve shift/reduce conflict in favour of shift
   540:     if old[0]=='s' and new[0] =='r':
   541:       self.pr_conflict(state_i,sym,new,old)
   542:       return
   543:     if old[0]=='r' and new[0] =='s':
   544:       self.pr_conflict(state_i,sym,old,new)
   545:       at[sym] = new
   546:       return
   547: 
   548:     if old[0]=='r' and new[0]=='r':
   549:       oldp = self.productions[old[1]]
   550:       newp = self.productions[new[1]]
   551:       oldpri = None
   552:       newpri = None
   553:       if hasattr(oldp,'priority'): oldpri = oldp.priority
   554:       if hasattr(newp,'priority'): newpri = newp.priority
   555:       if oldpri > newpri: return
   556:       elif newpri > oldpri:
   557:         at[sym]=new
   558:         return
   559: 
   560:       # resolve reduce/reduce conflict in favour of earlier production
   561:       if old[1] > new[1]:
   562:         at[sym]=new
   563:         self.pr_conflict(state_i,sym,old,new)
   564:       else:
   565:         self.pr_conflict(state_i,sym,new,old)
   566:       return
   567: 
   568:     self.pr_conflict(state_i,sym,old,new)
   569:     at[sym] = new
   570: 
   571:   def calc_action_table(self):
   572:     items = self.LALRitems
   573:     res = []
   574:     state_i = 0
   575:     terms = self.terms.list()
   576:     terms.append(EOF)
   577:     for state in items:
   578:       at = {}
   579:       res.append(at)
   580:       for (prodind, rhsind), term in state:
   581:         if (rhsind ) == len(self.productions[prodind].RHS):
   582:             if prodind != 0: new = ("r", prodind)
   583:             else: new = ("a", None)
   584:             self.resolve(at,term,new,state_i)
   585:         # calculate reduction by epsilon productions
   586:         #
   587:         elif self.productions[prodind].RHS[rhsind] in self.nonterms:
   588:           nt = self.productions[prodind].RHS[rhsind]
   589:           ntfirst = self.firstmap[nt]
   590:           ntfirsts = self.ntfirstmap.get(nt, {})
   591:           for k in ntfirsts.keys():
   592:             if self.epslhs.contains(k):
   593:               reduceterms = self.followmap[k]
   594:               print `((prodind, rhsind), term)`, reduceterms
   595:               for r in reduceterms:
   596:                 new = ("r", self.epslhs[k])
   597:                 self.resolve(at,r,new,state_i)
   598:           #
   599:           # calculate the shifts that occur but whose normal items aren't in the kernel
   600:           #
   601:           tfirsts = self.tfirstmap[nt]
   602:           for t in tfirsts:
   603:             g = self.goto(self.kernelitems[state_i], t)
   604:             try:
   605:               news = self.kernelitems.index(g)
   606:             except ValueError:
   607:               continue
   608:             new = ("s", news)
   609:             self.resolve(at,t,new,state_i)
   610:         #
   611:         # compute the rest of the shifts that occur 'normally' in the kernel
   612:         #
   613:         else:
   614:           t = self.productions[prodind].RHS[rhsind]
   615:           gt = self.goto(self.kernelitems[state_i], t)
   616:           if gt in self.kernelitems:
   617:             news = self.kernelitems.index(gt)
   618:             new = ("s", news)
   619:             self.resolve(at,t,new,state_i)
   620:       state_i = state_i + 1
   621:     self.action_table = res
   622: 
End python section to interscript/parsers/lalr1.py[19]

6.9.3.8. Calculate goto table

Start python section to interscript/parsers/lalr1.py[20] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   623: #line 794 "lalr1_parser.ipk"
   624:   def calc_goto_table(self):
   625:       items = self.kernelitems
   626:       res = []
   627:       nonterms = self.nonterms.list()
   628:       for state in items:
   629:         gt = {}
   630:         for nt in nonterms:
   631:           goto = self.goto(state, nt)
   632:           if goto in items: gt[nt] = items.index(goto)
   633:         res.append(gt)
   634:       self.goto_table = res
   635: 
   636: 
End python section to interscript/parsers/lalr1.py[20]

6.9.3.9. Parser

As described in the Dragon book, 4.7 Fig 4.30. p219, but with the addition of action functions on reduce corresponding to evaluation of S-attributes.

We hope to upgrade this to L-attributes later.

Start python section to interscript/parsers/lalr1.py[21] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   637: #line 814 "lalr1_parser.ipk"
   638:   def parse(self, data, reduce='func'):
   639:     act = self.action_table
   640:     go = self.goto_table
   641:     stack = gstack()
   642: 
   643:     stack.push(0)
   644:     n = len(data)
   645:     ip = 0
   646: 
   647:     while 1:
   648:       s = stack.top
   649:       if ip < len(data): token = data[ip]
   650:       else: token = (EOF,None)
   651:       a = token[0]
   652:       action = act[s][a]
   653:       #print 'Symbol',a,'Value',token[1],'State',s,'Action',action
   654:       if action[0]=='s':
   655:         s = action[1]
   656:         ip = ip + 1
   657:         stack.push(token)
   658:         stack.push(s)
   659:       elif action[0]=='r':
   660:         prodn = action[1]-1
   661:         prod = self.productions[prodn]
   662:         nt = prod.LHS
   663:         #print 'Reduce ',nt,'-->',
   664:         #for sym in prod.RHS: print sym,
   665:         #print
   666:         n = len(prod.RHS)
   667:         vals = []
   668:         while n:
   669:           stack.pop()
   670:           vals.insert(0,stack.pop())
   671:           n = n -1
   672:         vals.insert(0,prod)
   673:         args = tuple(vals)
   674:         #print 'args=',args
   675:         res = None
   676:         if hasattr(prod,reduce):
   677:           if callable(getattr(prod,reduce)):
   678:             res = apply(getattr(prod,reduce),args)
   679:         s = stack.top
   680:         stack.push((nt,res))
   681:         stack.push(go[s][nt])
   682:       elif act[s][a][0]=='a':
   683:         stack.pop()
   684:         res = stack.pop()
   685:         stack.pop()
   686:         assert not stack.s
   687:         print 'Accept'
   688:         return res
   689:       else:
   690:         raise 'Parse Error'
   691: 
End python section to interscript/parsers/lalr1.py[21]

6.9.4. LR parser engine

The 'parse' function is a temporary test parser to checkout the tables produced by LR parser generators.
data
A sequence of pairs. The first item in each pair should usually be a terminal symbol of the grammar, and the second item some value or other data associated with it.
gram
A sequence of productions.
tab
A pair (action, goto) containing LR parsing tables as follows: each table consists of a sequence of rows, one row for each non-error state of the parser. Each row is a single dictionary, keyed by a grammar symbol.

For the action table, the keys are terminals of the grammar, and the values are pairs consisting of an action indicator and an integer. The action indicator must be an empty string for an error, the letter 'r' for a reduce operation, the letter 's' for a shift operation, or the letter 'a' for an accept operation.

For a reduce, the integer is the index of the production in the grammar to be reduced, plus one. (The plus one is an artefact of the use of an augmented grammar in the LALR1 parser generator. This needs to be fixed.)

For a shift, the integer is a state to be shifted.

For the goto table, the keys are nonterminals of the grammar, the value is simply an integer denoting the state to be shifted.

start
The initial state of the parser. Defaults to 0.
reduce
The reduction functor to use.

This is the name of the attribute of a production which will be used to locate a function to be executed when the production is reduced, and defaults to 'func'. This facility is useful to allow a single grammar to have multiple action categories. For example, a grammar for expressions could build a parse tree, emit the input in reverse polish order, evaluate the expression, or generate code to evaluate the expression.

6.9.5. Test function

This is a very simple test. Much more is needed.
Start python section to interscript/parsers/lalr1.py[22] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   692: #line 921 "lalr1_parser.ipk"
   693: 
   694: def pr_tab(p):
   695:   at = p.action_table
   696:   gt = p.goto_table
   697:   print 'actions'
   698:   for i in range(len(at)):
   699:     print i,':',at[i]
   700:   print 'gotos'
   701:   for i in range(len(gt)):
   702:     print i,':',gt[i]
   703: 
   704: def _test1():
   705:     # the token interface will be defined in
   706:     # a wrapper module and in the lexer.
   707:     # this is the format the information will be stored in
   708:     #
   709:     # first, define the tokens
   710:     #
   711:     #(id, plus, times, lparen, rparen, eof) = range(6)
   712:     #
   713:     # then, define how you want them to appear
   714:     # in the documentation of the output file
   715:     #
   716:     toks = ["id", "+", "*", "(", ")","$"]
   717:     (id, plus, times, lparen, rparen, eof) = toks
   718: 
   719:     #
   720:     # define the productions (LHS=left hand side, RHS=right hand side)
   721:     #
   722:     prods = map(lambda x: Production(x[0], x[1]), [("E", ["E", plus, "T"]),
   723:                                                    ("E", ["T"]),
   724:                                                    ("T", ["T", times, "F"]),
   725:                                                    ("T", ["F"]),
   726:                                                    ("F", [lparen, "E", rparen]),
   727:                                                    ("F", [id])])
   728:     g = LALRGrammar(prods, "E")
   729:     #
   730: 
   731:     #
   732:     # define functions for the parser to use
   733:     #
   734:     def fadd(prod,*args):
   735:         print "adding %d with %d" % (args[0][1], args[2][1])
   736:         return args[0][1] + args[2][1]
   737: 
   738:     def fdummy(prod,*args):
   739:         print "calling fdummy with args %s" % `args`
   740:         return args[0][1]
   741: 
   742:     def ftimes(prod,*args):
   743:         print "multiplying %d with %d" % (args[0][1], args[2][1])
   744:         return args[0][1] * args[2][1]
   745: 
   746:     def fparens(prod,*args):
   747:         print "handling parens, returning whats in between"
   748:         return args[1][1]
   749: 
   750: 
   751:     #
   752:     # register the functions
   753:     #
   754:     for i in range(len(g.productions)):
   755:         if len(g.productions[i].RHS) == 1:
   756:             g.productions[i].func=fdummy
   757:     g.productions[0].func=fadd
   758:     g.productions[2].func=ftimes
   759:     g.productions[4].func=fparens
   760:     #
   761:     # produce the parser
   762:     #
   763:     pr_tab(g)
   764: 
   765:     #
   766:     # this is the input as would be returned by the Lexer
   767:     # (3+(4*2))*2*5 =110
   768:     input = [(lparen, "("), (id, 3), (plus, "+"),
   769:              (lparen, "("), (id, 4), (times, "*"), (id, 2),  (rparen, ")"),
   770:              (rparen, ")"), (times, "*"),
   771:              (id, 2), (times, "*"), (id, 5) ]
   772: 
   773:     res = g.parse(input)
   774:     print 'RESULT=',res
   775: 
End python section to interscript/parsers/lalr1.py[22]

6.9.6. Bootstrapping

The function below is used to bootstrap the parser. We use the standard Python tokeniser, and contruct a grammar by hand to recognize grammars. The reduction functor is used to build a list of productions, the functions named in the grammar are attached to these productions. The grammar we will use is:
  G -> Plist
  Plist -> Plist newline P
  Plist -> P
  P -> LHS = RHS { func }
  RHS -> RHS sym
  RHS -> sym
We will immediately test the generated parser to parse a string representing a grammar, namely, the same grammar, which should generate an equivalent parser.
  G = Plist { build_grammar }
  Plist = Plist newline P { add_production_to_list }
  Plist = P { new_production_list }
  P = LHS = RHS "{" func "}" { build_production }
  RHS = RHS sym { add_sym_to_list }
  RHS = sym { new_RHS_list}

6.9.6.1. Test Tokeniser

Start python section to interscript/parsers/lalr1.py[23] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   776: #line 1032 "lalr1_parser.ipk"
   777: 
   778: import string
   779: def tokenise(s):
   780:   i = 0
   781:   s = s + '\0'
   782:   toks = []
   783:   while 1:
   784:     while s[i] == ' ': i = i + 1
   785:     if s[i] in '#\0': return toks
   786:     lexeme = ''
   787:     if s[i] in string.letters+'_':
   788:       while s[i] in string.letters+'_'+string.digits:
   789:         lexeme = lexeme+s[i]
   790:         i = i + 1
   791:       toks.append(('NAME',lexeme))
   792:       continue
   793:     if s[i] == '"':
   794:       i = i + 1
   795:       while s[i] not in '"\0':
   796:         lexeme = lexeme + s[i]
   797:         i = i + 1
   798:       toks.append(('STRING',lexeme))
   799:       if s[i]=='\0': return toks
   800:       i = i + 1
   801:       continue
   802:     if s[i] == "'":
   803:       i = i + 1
   804:       while s[i] not in "'\0":
   805:         lexeme = lexeme + s[i]
   806:         i = i + 1
   807:       toks.append(('STRING',lexeme))
   808:       if s[i]=='\0': return toks
   809:       i = i + 1
   810:       continue
   811:     if s[i] in '{}=':
   812:       toks.append((s[i],s[i]))
   813:       i = i + 1
   814:       continue
   815:     if s[i] in '#\n':
   816:       toks.append(('NEWLINE','\n'))
   817:       i = i + 1
   818:       continue
   819:     if s[i]=='\\':
   820:       i = i + 1
   821:       if s[i] == '\0': return toks
   822:       toks.append(('STRING',s[i]))
   823:       i = i + 1
   824:       continue
   825:     toks.append(('STRING',s[i]))
   826:     i = i + 1
   827:     continue
   828: 
End python section to interscript/parsers/lalr1.py[23]

6.9.6.2. Bootstrapping test

Start python section to interscript/parsers/lalr1.py[24] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
   829: #line 1086 "lalr1_parser.ipk"
   830: def _test2():
   831:     def dummy(prod,*args):
   832:       print 'dummy:reduce',prod,'args=',args
   833:       return None
   834: 
   835:     def new_production_list(prod, *args):
   836:       return [args[0][1]]
   837: 
   838:     def add_production_to_list(prod, *args):
   839:       return args[0][1]+[args[1][1]]
   840: 
   841:     def build_production(prod, *args):
   842:       return Production(args[0][1],args[2][1],func=args[4][1])
   843: 
   844:     def new_symbol_list(prod, *args):
   845:       return [args[0][1]]
   846: 
   847:     def add_symbol_to_list(prod, *args):
   848:       return args[0][1]+[args[1][1]]
   849: 
   850:     def name_as_symbol(prod, *args):
   851:       return args[0][1]
   852: 
   853:     def string_as_symbol(prod, *args):
   854:       return args[0][1]
   855: 
   856:     def just_copy(prod, *args):
   857:       return args[0][1]
   858: 
   859:     bootgram = [
   860:       ('G',    ['Plist'], just_copy),
   861:       ('Plist', ['Plist','P'], add_production_to_list),
   862:       ('Plist', ['P'], new_production_list),
   863:       ('P', ['NAME','=','RHS','{','NAME','}','NEWLINE'],build_production),
   864:       ('RHS',['RHS','SYM'],add_symbol_to_list),
   865:       ('RHS',['SYM'],new_symbol_list),
   866:       ('SYM',['NAME'],name_as_symbol),
   867:       ('SYM',['STRING'],string_as_symbol)
   868:     ]
   869:     print 'bootgram=',bootgram
   870:     prods = map(lambda x: Production(x[0], x[1], func=x[2]), bootgram)
   871: 
   872:     g = LALRGrammar(prods, "G", verbosity=1)
   873:     pr_tab(g)
   874: 
   875:     print
   876:     print '---------------------------------------------------'
   877:     print '  TABLES FOR MANUALLY CONSTRUCTED GRAMMAR GENERATED'
   878:     print '---------------------------------------------------'
   879:     print
   880: 
   881:     input = """G       = Plist { just_copy }
   882: Plist   = Plist P { add_production_to_list }
   883: Plist   = P { new_production_list }
   884: P       = NAME \= RHS \{ NAME \} NEWLINE { build_production }
   885: RHS     = RHS SYM { add_symbol_to_list }
   886: RHS     = SYM { new_symbol_list }
   887: SYM     = NAME { name_as_symbol }
   888: SYM     = STRING { string_as_symbol }
   889: """
   890:     tokens = tokenise(input)
   891:     print 'tokens=',tokens
   892:     for t in tokens: print t[1],
   893:     print
   894: 
   895:     res = g.parse(tokens)
   896:     prods = res[1]
   897:     print 'RESULT=',prods
   898: 
   899:     for p in prods: p.func = eval(p.func)
   900:     print 'BOUND=',prods
   901: 
   902:     g = LALRGrammar(prods, "G", verbosity=2)
   903:     pr_tab(g)
   904: 
   905:     print
   906:     print '--------------------------------------------------------'
   907:     print '  TABLES FOR AUTOMATICALLY CONSTRUCTED GRAMMAR GENERATED'
   908:     print '--------------------------------------------------------'
   909:     print
   910: 
   911:     res = g.parse(tokens)
   912:     prods = res[1]
   913:     print 'RESULT=',prods
   914: 
   915:     print '--------------------------------------------------------'
   916:     print ' IF THAT WORKED, WE HAVE A BOOTSTRAP                    '
   917:     print '--------------------------------------------------------'
   918: 
   919:     input = """G = S {dummy}
   920: S = if E then S else S {dummy}
   921: S = if E then S {dummy}
   922: S = X {dummy}
   923: E = X {dummy}
   924: """
   925:     tokens = tokenise(input)
   926:     res = g.parse(tokens)
   927:     prods = res[1]
   928:     print 'RESULT=',prods
   929: 
   930:     for p in prods: p.func = eval(p.func)
   931:     print 'BOUND=',prods
   932: 
   933:     ifthenelse = LALRGrammar(prods, "G", verbosity=2)
   934:     pr_tab(ifthenelse)
   935:     input = """if X then X else X"""
   936:     tokens = tokenise(input)
   937:     toks = []
   938:     for tok in tokens[:]:
   939:       toks.append((tok[1],tok[1]))
   940:     print toks
   941:     res = ifthenelse.parse(toks)
   942:     prods = res[1]
   943:     print 'RESULT=',prods
   944: 
   945: 
Start python section to interscript/tests/tgram.py[1] 1
     1: #line 1205 "lalr1_parser.ipk"
     2: import interscript.parsers.lalr1
     3: interscript.parsers.lalr1._test1()
     4: interscript.parsers.lalr1._test2()
Start output section of "/usr/local/bin/python" interscript/tests/tgram.py
     1: Interscript version 1.0a8 build 1378
     2: Built by root on ruby at Sun Nov 29, 1998 at 08:48 PM (UTC)
     3: Generated by 1.0a8 buildno 1376 host ruby
     4: at Sun Nov 29, 1998 at 08:48 PM (UTC)
     5: actions
     6: 0 : {'id': ('s', 11), '(': ('s', 9)}
     7: 1 : {'+': ('s', 3), '<EOF>': ('a', None)}
     8: 2 : {'+': ('s', 3), ')': ('s', 10)}
     9: 3 : {'id': ('s', 11), '(': ('s', 9)}
    10: 4 : {'<EOF>': ('r', 1), '*': ('s', 6), '+': ('r', 1), ')': ('r', 1)}
    11: 5 : {'<EOF>': ('r', 2), '*': ('s', 6), '+': ('r', 2), ')': ('r', 2)}
    12: 6 : {'id': ('s', 11), '(': ('s', 9)}
    13: 7 : {'<EOF>': ('r', 3), '*': ('r', 3), '+': ('r', 3), ')': ('r', 3)}
    14: 8 : {'<EOF>': ('r', 4), '*': ('r', 4), '+': ('r', 4), ')': ('r', 4)}
    15: 9 : {'id': ('s', 11), '(': ('s', 9)}
    16: 10 : {'<EOF>': ('r', 5), '*': ('r', 5), '+': ('r', 5), ')': ('r', 5)}
    17: 11 : {'<EOF>': ('r', 6), '*': ('r', 6), '+': ('r', 6), ')': ('r', 6)}
    18: gotos
    19: 0 : {'F': 8, 'T': 5, 'E': 1}
    20: 1 : {}
    21: 2 : {}
    22: 3 : {'F': 8, 'T': 4}
    23: 4 : {}
    24: 5 : {}
    25: 6 : {'F': 7}
    26: 7 : {}
    27: 8 : {}
    28: 9 : {'F': 8, 'T': 5, 'E': 2}
    29: 10 : {}
    30: 11 : {}
    31: calling fdummy with args (('id', 3),)
    32: calling fdummy with args (('F', 3),)
    33: calling fdummy with args (('T', 3),)
    34: calling fdummy with args (('id', 4),)
    35: calling fdummy with args (('F', 4),)
    36: calling fdummy with args (('id', 2),)
    37: multiplying 4 with 2
    38: calling fdummy with args (('T', 8),)
    39: handling parens, returning whats in between
    40: calling fdummy with args (('F', 8),)
    41: adding 3 with 8
    42: handling parens, returning whats in between
    43: calling fdummy with args (('F', 11),)
    44: calling fdummy with args (('id', 2),)
    45: multiplying 11 with 2
    46: calling fdummy with args (('id', 5),)
    47: multiplying 22 with 5
    48: calling fdummy with args (('T', 110),)
    49: Accept
    50: RESULT= ('E', 110)
    51: bootgram= [('G', ['Plist'], <function just_copy at 8176c58>), ('Plist', ['Plist', 'P'], <function add_production_to_list at 8172860>), ('Plist', ['P'], <function new_production_list at 817ad10>), ('P', ['NAME', '=', 'RHS', '{', 'NAME', '}', 'NEWLINE'], <function build_production at 8186350>), ('RHS', ['RHS', 'SYM'], <function add_symbol_to_list at 8172500>), ('RHS', ['SYM'], <function new_symbol_list at 8172820>), ('SYM', ['NAME'], <function name_as_symbol at 80ba370>), ('SYM', ['STRING'], <function string_as_symbol at 80ba848>)]
    52: actions
    53: 0 : {'NAME': ('s', 5)}
    54: 1 : {'<EOF>': ('a', None)}
    55: 2 : {'<EOF>': ('r', 1), 'NAME': ('s', 5)}
    56: 3 : {'<EOF>': ('r', 2), 'NAME': ('r', 2)}
    57: 4 : {'<EOF>': ('r', 3), 'NAME': ('r', 3)}
    58: 5 : {'=': ('s', 6)}
    59: 6 : {'NAME': ('s', 14), 'STRING': ('s', 15)}
    60: 7 : {'{': ('s', 8), 'NAME': ('s', 14), 'STRING': ('s', 15)}
    61: 8 : {'NAME': ('s', 9)}
    62: 9 : {'}': ('s', 10)}
    63: 10 : {'NEWLINE': ('s', 11)}
    64: 11 : {'<EOF>': ('r', 4), 'NAME': ('r', 4)}
    65: 12 : {'{': ('r', 5), 'NAME': ('r', 5), 'STRING': ('r', 5)}
    66: 13 : {'{': ('r', 6), 'NAME': ('r', 6), 'STRING': ('r', 6)}
    67: 14 : {'{': ('r', 7), 'NAME': ('r', 7), 'STRING': ('r', 7)}
    68: 15 : {'{': ('r', 8), 'NAME': ('r', 8), 'STRING': ('r', 8)}
    69: gotos
    70: 0 : {'G': 1, 'Plist': 2, 'P': 4}
    71: 1 : {}
    72: 2 : {'P': 3}
    73: 3 : {}
    74: 4 : {}
    75: 5 : {}
    76: 6 : {'RHS': 7, 'SYM': 13}
    77: 7 : {'SYM': 12}
    78: 8 : {}
    79: 9 : {}
    80: 10 : {}
    81: 11 : {}
    82: 12 : {}
    83: 13 : {}
    84: 14 : {}
    85: 15 : {}
    86: 
    87: ---------------------------------------------------
    88:   TABLES FOR MANUALLY CONSTRUCTED GRAMMAR GENERATED
    89: ---------------------------------------------------
    90: 
    91: tokens= [('NAME', 'G'), ('=', '='), ('NAME', 'Plist'), ('{', '{'), ('NAME', 'just_copy'), ('}', '}'), ('NEWLINE', '\012'), ('NAME', 'Plist'), ('=', '='), ('NAME', 'Plist'), ('NAME', 'P'), ('{', '{'), ('NAME', 'add_production_to_list'), ('}', '}'), ('NEWLINE', '\012'), ('NAME', 'Plist'), ('=', '='), ('NAME', 'P'), ('{', '{'), ('NAME', 'new_production_list'), ('}', '}'), ('NEWLINE', '\012'), ('NAME', 'P'), ('=', '='), ('NAME', 'NAME'), ('STRING', '='), ('NAME', 'RHS'), ('STRING', '{'), ('NAME', 'NAME'), ('STRING', '}'), ('NAME', 'NEWLINE'), ('{', '{'), ('NAME', 'build_production'), ('}', '}'), ('NEWLINE', '\012'), ('NAME', 'RHS'), ('=', '='), ('NAME', 'RHS'), ('NAME', 'SYM'), ('{', '{'), ('NAME', 'add_symbol_to_list'), ('}', '}'), ('NEWLINE', '\012'), ('NAME', 'RHS'), ('=', '='), ('NAME', 'SYM'), ('{', '{'), ('NAME', 'new_symbol_list'), ('}', '}'), ('NEWLINE', '\012'), ('NAME', 'SYM'), ('=', '='), ('NAME', 'NAME'), ('{', '{'), ('NAME', 'name_as_symbol'), ('}', '}'), ('NEWLINE', '\012'), ('NAME', 'SYM'), ('=', '='), ('NAME', 'STRING'), ('{', '{'), ('NAME', 'string_as_symbol'), ('}', '}'), ('NEWLINE', '\012')]
    92: G = Plist { just_copy }
    93: Plist = Plist P { add_production_to_list }
    94: Plist = P { new_production_list }
    95: P = NAME = RHS { NAME } NEWLINE { build_production }
    96: RHS = RHS SYM { add_symbol_to_list }
    97: RHS = SYM { new_symbol_list }
    98: SYM = NAME { name_as_symbol }
    99: SYM = STRING { string_as_symbol }
   100: 
   101: Accept
   102: RESULT= ['G' -> ['Plist'] {'func': 'just_copy'}, 'Plist' -> ['Plist', 'P'] {'func': 'add_production_to_list'}, 'Plist' -> ['P'] {'func': 'new_production_list'}, 'P' -> ['NAME', '=', 'RHS', '{', 'NAME', '}', 'NEWLINE'] {'func': 'build_production'}, 'RHS' -> ['RHS', 'SYM'] {'func': 'add_symbol_to_list'}, 'RHS' -> ['SYM'] {'func': 'new_symbol_list'}, 'SYM' -> ['NAME'] {'func': 'name_as_symbol'}, 'SYM' -> ['STRING'] {'func': 'string_as_symbol'}]
   103: BOUND= ['G' -> ['Plist'] {'func': <function just_copy at 8176c58>}, 'Plist' -> ['Plist', 'P'] {'func': <function add_production_to_list at 8172860>}, 'Plist' -> ['P'] {'func': <function new_production_list at 817ad10>}, 'P' -> ['NAME', '=', 'RHS', '{', 'NAME', '}', 'NEWLINE'] {'func': <function build_production at 8186350>}, 'RHS' -> ['RHS', 'SYM'] {'func': <function add_symbol_to_list at 8172500>}, 'RHS' -> ['SYM'] {'func': <function new_symbol_list at 8172820>}, 'SYM' -> ['NAME'] {'func': <function name_as_symbol at 80ba370>}, 'SYM' -> ['STRING'] {'func': <function string_as_symbol at 80ba848>}]
   104: 0 : 'G' -> ['Plist'] {'func': <function just_copy at 8176c58>}
   105: 1 : 'Plist' -> ['Plist', 'P'] {'func': <function add_production_to_list at 8172860>}
   106: 2 : 'Plist' -> ['P'] {'func': <function new_production_list at 817ad10>}
   107: 3 : 'P' -> ['NAME', '=', 'RHS', '{', 'NAME', '}', 'NEWLINE'] {'func': <function build_production at 8186350>}
   108: 4 : 'RHS' -> ['RHS', 'SYM'] {'func': <function add_symbol_to_list at 8172500>}
   109: 5 : 'RHS' -> ['SYM'] {'func': <function new_symbol_list at 8172820>}
   110: 6 : 'SYM' -> ['NAME'] {'func': <function name_as_symbol at 80ba370>}
   111: 7 : 'SYM' -> ['STRING'] {'func': <function string_as_symbol at 80ba848>}
   112: Symbols set('SYM', 'Plist', '=', 'NEWLINE', 'RHS', '}', 'STRING', 'NAME', 'P', '{')
   113: Terminals set('STRING', '}', 'NEWLINE', 'NAME', '=', '{')
   114: NonTerminals set('G', 'Plist', 'SYM', 'RHS', 'P')
   115: Directly Derive epsilon set()
   116: Derive epsilon set()
   117: First Sets:
   118: -1 -> set(-1)
   119: Plist -> set('NAME')
   120: } -> set('}')
   121: { -> set('{')
   122: P -> set('NAME')
   123: <EPS> -> set('<EPS>')
   124: NAME -> set('NAME')
   125: = -> set('=')
   126: SYM -> set('STRING', 'NAME')
   127: <EOF> -> set('<EOF>')
   128: NEWLINE -> set('NEWLINE')
   129: RHS -> set('STRING', 'NAME')
   130: G -> set('NAME')
   131: STRING -> set('STRING')
   132: Follow Sets:
   133: G -> set('<EOF>')
   134: Plist -> set('<EOF>', 'NAME')
   135: SYM -> set('{', 'STRING', 'NAME')
   136: RHS -> set('{', 'STRING', 'NAME')
   137: P -> set('<EOF>', 'NAME')
   138: found 4 more kernels
   139: found 2 more kernels
   140: found 4 more kernels
   141: found 2 more kernels
   142: found 1 more kernels
   143: found 1 more kernels
   144: found 1 more kernels
   145: initLALR1items, kernels done, calculating propagations and spontaneous lookaheads
   146: . . . . . . . . . . . . . . . . done init LALR1items
   147: done with lalr1items, reorganizing the data
   148: actions
   149: 0 : {'NAME': ('s', 5)}
   150: 1 : {'<EOF>': ('a', None)}
   151: 2 : {'<EOF>': ('r', 1), 'NAME': ('s', 5)}
   152: 3 : {'<EOF>': ('r', 2), 'NAME': ('r', 2)}
   153: 4 : {'<EOF>': ('r', 3), 'NAME': ('r', 3)}
   154: 5 : {'=': ('s', 6)}
   155: 6 : {'NAME': ('s', 14), 'STRING': ('s', 15)}
   156: 7 : {'{': ('s', 8), 'NAME': ('s', 14), 'STRING': ('s', 15)}
   157: 8 : {'NAME': ('s', 9)}
   158: 9 : {'}': ('s', 10)}
   159: 10 : {'NEWLINE': ('s', 11)}
   160: 11 : {'<EOF>': ('r', 4), 'NAME': ('r', 4)}
   161: 12 : {'{': ('r', 5), 'NAME': ('r', 5), 'STRING': ('r', 5)}
   162: 13 : {'{': ('r', 6), 'NAME': ('r', 6), 'STRING': ('r', 6)}
   163: 14 : {'{': ('r', 7), 'NAME': ('r', 7), 'STRING': ('r', 7)}
   164: 15 : {'{': ('r', 8), 'NAME': ('r', 8), 'STRING': ('r', 8)}
   165: gotos
   166: 0 : {'G': 1, 'Plist': 2, 'P': 4}
   167: 1 : {}
   168: 2 : {'P': 3}
   169: 3 : {}
   170: 4 : {}
   171: 5 : {}
   172: 6 : {'RHS': 7, 'SYM': 13}
   173: 7 : {'SYM': 12}
   174: 8 : {}
   175: 9 : {}
   176: 10 : {}
   177: 11 : {}
   178: 12 : {}
   179: 13 : {}
   180: 14 : {}
   181: 15 : {}
   182: 
   183: --------------------------------------------------------
   184:   TABLES FOR AUTOMATICALLY CONSTRUCTED GRAMMAR GENERATED
   185: --------------------------------------------------------
   186: 
   187: Accept
   188: RESULT= ['G' -> ['Plist'] {'func': 'just_copy'}, 'Plist' -> ['Plist', 'P'] {'func': 'add_production_to_list'}, 'Plist' -> ['P'] {'func': 'new_production_list'}, 'P' -> ['NAME', '=', 'RHS', '{', 'NAME', '}', 'NEWLINE'] {'func': 'build_production'}, 'RHS' -> ['RHS', 'SYM'] {'func': 'add_symbol_to_list'}, 'RHS' -> ['SYM'] {'func': 'new_symbol_list'}, 'SYM' -> ['NAME'] {'func': 'name_as_symbol'}, 'SYM' -> ['STRING'] {'func': 'string_as_symbol'}]
   189: --------------------------------------------------------
   190:  IF THAT WORKED, WE HAVE A BOOTSTRAP
   191: --------------------------------------------------------
   192: Accept
   193: RESULT= ['G' -> ['S'] {'func': 'dummy'}, 'S' -> ['if', 'E', 'then', 'S', 'else', 'S'] {'func': 'dummy'}, 'S' -> ['if', 'E', 'then', 'S'] {'func': 'dummy'}, 'S' -> ['X'] {'func': 'dummy'}, 'E' -> ['X'] {'func': 'dummy'}]
   194: BOUND= ['G' -> ['S'] {'func': <function dummy at 80f3d60>}, 'S' -> ['if', 'E', 'then', 'S', 'else', 'S'] {'func': <function dummy at 80f3d60>}, 'S' -> ['if', 'E', 'then', 'S'] {'func': <function dummy at 80f3d60>}, 'S' -> ['X'] {'func': <function dummy at 80f3d60>}, 'E' -> ['X'] {'func': <function dummy at 80f3d60>}]
   195: 0 : 'G' -> ['S'] {'func': <function dummy at 80f3d60>}
   196: 1 : 'S' -> ['if', 'E', 'then', 'S', 'else', 'S'] {'func': <function dummy at 80f3d60>}
   197: 2 : 'S' -> ['if', 'E', 'then', 'S'] {'func': <function dummy at 80f3d60>}
   198: 3 : 'S' -> ['X'] {'func': <function dummy at 80f3d60>}
   199: 4 : 'E' -> ['X'] {'func': <function dummy at 80f3d60>}
   200: Symbols set('if', 'X', 'E', 'else', 'S', 'then')
   201: Terminals set('if', 'then', 'X', 'else')
   202: NonTerminals set('S', 'G', 'E')
   203: Directly Derive epsilon set()
   204: Derive epsilon set()
   205: First Sets:
   206: if -> set('if')
   207: -1 -> set(-1)
   208: <EOF> -> set('<EOF>')
   209: X -> set('X')
   210: G -> set('if', 'X')
   211: <EPS> -> set('<EPS>')
   212: E -> set('X')
   213: else -> set('else')
   214: S -> set('if', 'X')
   215: then -> set('then')
   216: Follow Sets:
   217: G -> set('<EOF>')
   218: E -> set('then')
   219: S -> set('else', '<EOF>')
   220: found 4 more kernels
   221: found 2 more kernels
   222: found 1 more kernels
   223: found 1 more kernels
   224: found 1 more kernels
   225: found 1 more kernels
   226: initLALR1items, kernels done, calculating propagations and spontaneous lookaheads
   227: . . . . . . . . . . . done init LALR1items
   228: done with lalr1items, reorganizing the data
   229: Shift/Reduce Conflict, Use Shift [6,'else']: ('r', 3) -> ('s', 7)
   230: actions
   231: 0 : {'if': ('s', 3), 'X': ('s', 9)}
   232: 1 : {'<EOF>': ('a', None)}
   233: 2 : {'<EOF>': ('r', 1)}
   234: 3 : {'X': ('s', 10)}
   235: 4 : {'then': ('s', 5)}
   236: 5 : {'if': ('s', 3), 'X': ('s', 9)}
   237: 6 : {'else': ('s', 7), '<EOF>': ('r', 3)}
   238: 7 : {'if': ('s', 3), 'X': ('s', 9)}
   239: 8 : {'else': ('r', 2), '<EOF>': ('r', 2)}
   240: 9 : {'else': ('r', 4), '<EOF>': ('r', 4)}
   241: 10 : {'then': ('r', 5)}
   242: gotos
   243: 0 : {'S': 2, 'G': 1}
   244: 1 : {}
   245: 2 : {}
   246: 3 : {'E': 4}
   247: 4 : {}
   248: 5 : {'S': 6}
   249: 6 : {}
   250: 7 : {'S': 8}
   251: 8 : {}
   252: 9 : {}
   253: 10 : {}
   254: [('if', 'if'), ('X', 'X'), ('then', 'then'), ('X', 'X'), ('else', 'else'), ('X', 'X')]
   255: dummy:reduce 'E' -> ['X'] {'func': <function dummy at 80f3d60>} args= (('X', 'X'),)
   256: dummy:reduce 'S' -> ['X'] {'func': <function dummy at 80f3d60>} args= (('X', 'X'),)
   257: dummy:reduce 'S' -> ['X'] {'func': <function dummy at 80f3d60>} args= (('X', 'X'),)
   258: dummy:reduce 'S' -> ['if', 'E', 'then', 'S', 'else', 'S'] {'func': <function dummy at 80f3d60>} args= (('if', 'if'), ('E', None), ('then', 'then'), ('S', None), ('else', 'else'), ('S', None))
   259: dummy:reduce 'G' -> ['S'] {'func': <function dummy at 80f3d60>} args= (('S', None),)
   260: Accept
   261: RESULT= None
End output section to "/usr/local/bin/python" interscript/tests/tgram.py
     3: #line 17 "parsers.ipk"
     4: 

6.10. Introduction to categories

A category is a collection of arrows together with a associative partial binary operator called composition, and which has unit (identity) arrows called objects.

6.10.1. Category of functions

An important example is a collection of functions which (1) is closed under function composition, and (2) includes the identity mapping for each set which is a domain or codomain of some function.

6.10.2. Category of strings

The set of all strings over some character set is a category, with the single object the empty string (and the composition operation being string concatenation).

More generally, given the empty string and any finite set of strings, the set of all combinations of these strings is said to be the category generated by that set, which is called the generator set.

6.10.3. Paths on graphs

The set of all paths on a graph is a category, with the vericies being considered as identity paths, and composition being path composition. The category is said to be generated by the graph.

6.10.4. Groups

All groups are categories, for example integers, rationals, and reals under addition (or multiplication if zero is removed), invertible matrices and linear operators including stretching and rotation in n-dimensional space.

6.11. Felix Object protocol

Felix is a language for programming with categories. It is characterized by the exclusive use of function composition, having no concept of function application: functions do not have arguments, they're arrows of categories which are composed with other functions.

6.11.1. Category Protocol

A category "c" shall support the following methods:
c.is_arrow(x)
Shall return 1 if the argument is an arrow of the category, and 0 otherwise.
c.is_object(x)
Shall return 1 if the argument is an object of the category, and 0 otherwise.
c.domain(x)
Shall return the domain object of arrow x.
c.codomain(x)
Shall return the codomain object of arrow x.
c.can_compose(x,y)
If x and y are arrows, shall return 1 if x can be composed with y, or 0 if they cannot be composed, else undefined.
c.compose(x,y)
Shall return the composition of x and y if x and y are composable.
c(x1, x2, ...)
Shall return the composition of the arguments if well defined.
The following methods are optional:
c.inverse(x)
Shall return the inverse of an arrow x if it has one.
c.get_arrows()
Shall return a sequence of all the arrows of a category. If defined, the representation of the category is said to be enumerable.
c.get_objects()
Shall return a sequence of all the objects of a category. Shall be defined if "get_arrows()" is defined.
c.get_nonobjects()
Shall return a sequence of all the non-object arrows of a category. Shall be defined if "get_arrows()" is defined.
Composition is a partial binary operator, and shall be associative. The objects shall be precisely theidentity arrows. In particular:
  if c.is_object(p):
    assert c.is_arrow(p)
  if c.is_arrow(x) and c.is_arrow(y) and c.is_arrow(z):
    if c.can_compose(x,y) and c.can_compose(y,z):
      assert c(c(x,y),z) == c(x,c(y,z) # associative
  if c.is_arrow(x):
    assert c.is_object(c.domain(x))    # domain and codomain are objects
    assert c.is_object(c.codomain(x))
    assert c.compose(c.domain(x), x) == x
    assert c.compose(x, c.codomain(x)) == x

6.12. Felix Package

Herein, the python prototype.
Start python section to interscript/felix/__init__.py[1] 1
     1: #line 5 "felix_package.ipk"
     2: # felix package
End python section to interscript/felix/__init__.py[1]
Start python section to interscript/felix/model/__init__.py[1] 1
     1: #line 7 "felix_package.ipk"
     2: # felix object model
     3: 
End python section to interscript/felix/model/__init__.py[1]

6.12.1. Category Base

Start python section to interscript/felix/model/basecat.py[1] 1
     1: #line 12 "felix_package.ipk"
     2: import types
     3: import interscript.core.protocols
     4: class category:
     5:   __class_protocols__ = 'category'
     6: 
     7:   def __call__(self, *args):
     8:     return reduce(self.compose, args)
     9: 

6.12.2. Finite Category model

We build a finite category in two stages. First we construct an empty pre-category, and add arrows and composition rules to it. Then, we check it is indeed a category. Unlike most of the classes in core felix, "fincat" does some argument checking.

6.12.2.1. Implementation

Start python section to interscript/felix/model/fincat.py[1] 1 2 3 4 5
     1: #line 11 "felix_fincat.ipk"
     2: # finite category
     3: from interscript.felix.model.basecat import category
     4: class fincat(category):
End python section to interscript/felix/model/fincat.py[1]
6.12.2.1.1. Data structure
Start python section to interscript/felix/model/fincat.py[2] 1 2 3 4 5
     5: #line 16 "felix_fincat.ipk"
     6:   def __init__(self):
     7:     self.objects = {}
     8:       # keyed by object, value is pair of lists
     9:       # 0: arrows which go out of this object (except self)
    10:       # 1: arrows which go into this object (except self)
    11:     self.arrows = {}
    12:       # keyed by arrow, value is pair (head, tail) of arrow
    13:       # excludes objects
    14:     self.rules = {}
    15:       # keyed by pair, value is result
    16:       # excludes keys for which one or both arguments are identities
    17: 
End python section to interscript/felix/model/fincat.py[2]
6.12.2.1.2. Accessors
Start python section to interscript/felix/model/fincat.py[3] 1 2 3 4 5
    18: #line 30 "felix_fincat.ipk"
    19:   def get_nonobjects(self):
    20:     """return a list of all non-identity arrows
    21:     """
    22:     return self.arrows.keys()
    23: 
    24:   def get_objects(self):
    25:     'return a list of all identity arrows'
    26:     return self.objects.keys()
    27: 
    28:   def get_arrows(self):
    29:     """return a list of all arrows
    30:     """
    31:     return self.objects.keys() + self.arrows.keys()
    32: 
    33:   def domain(self, arrow):
    34:     """get the domain/tail/source object of an arrow
    35:     """
    36:     if arrow in self.objects.keys(): return arrow
    37:     else: return self.arrows[arrow][0]
    38: 
    39:   def codomain(self, arrow):
    40:     """return the codomain/head/destination object of an arrow
    41:     """
    42:     if arrow in self.objects.keys(): return arrow
    43:     else: return self.arrows[arrow][1]
    44: 
    45:   def get_arrows_outof(self, arrow):
    46:     """return a list of all the arrows which can be appended to this arrow
    47:     """
    48:     return self.objects[self.codomain(arrow)][0]
    49: 
    50:   def get_arrows_into(self, object):
    51:     """return a list of all the arrows which can be prepended to this arrow
    52:     """
    53:     return self.objects[self.domain(arrow)][1]
    54: 
    55:   def can_compose(self,a,b):
    56:     """return 1 if arrows can be composed (left to right),
    57:        else return 0
    58:     """
    59:     return self.codomain(a) == self.domain(b)
    60: 
    61:   def compose(self, a, b):
    62:     """return the composition of two arrows,
    63:        raise exception if not composable
    64:     """
    65:     if not self.can_compose(a,b):
    66:       raise 'cannot compose arrows in "compose"'
    67:     if a in self.get_objects(): return b
    68:     elif b in self.get_objects(): return a
    69:     else: return self.rules[(a,b)]
    70: 
End python section to interscript/felix/model/fincat.py[3]
6.12.2.1.3. Predicates
Start python section to interscript/felix/model/fincat.py[4] 1 2 3 4 5
    71: #line 84 "felix_fincat.ipk"
    72:   def is_arrow(self, arrow):
    73:     return arrow in self.get_arrows()
    74: 
    75:   def is_object(self, arrow):
    76:     return arrow in self.get_objects()
    77: 
End python section to interscript/felix/model/fincat.py[4]
6.12.2.1.4. Mutators
Start python section to interscript/felix/model/fincat.py[5] 1 2 3 4 5
    78: #line 92 "felix_fincat.ipk"
    79:   def add_arrow(self, arrow, src, dst):
    80:     """add new arrow to pre-category,
    81:        raise exception if duplicate or
    82:        domain or codomain not extant objects
    83:     """
    84:     if arrow in self.get_arrows():
    85:       raise 'duplicate arrow in "add arrow"'
    86:     if src not in self.get_objects():
    87:       raise 'src not defined in "add arrow"'
    88:     if dst not in self.get_objects():
    89:       raise 'dst not defined in "add arrow"'
    90: 
    91:     self.arrows[arrow] = (src, dst)
    92:     self.objects[src][0].append(arrow)
    93:     self.objects[dst][1].append(arrow)
    94: 
    95:   def add_object(self, object):
    96:     """add new object to pre-category,
    97:        raise exception iof duplicate
    98:     """
    99:     if object in self.get_arrows():
   100:       raise 'duplicate arrow in "add object"'
   101:     self.objects[object]=([],[])
   102: 
   103:   def add_rule(self, left, right, result):
   104:     """add new rule to composition rules,
   105:        raise exception if arrows not defined or
   106:        cannot be composed or
   107:        the rule is already known
   108: 
   109:     """
   110:     msg = ' in add_rule('+str(left)+', '+str(right)+', '+str(result)+')'
   111:     if left not in self.get_arrows():
   112:       raise 'first argument not an arrow'+msg
   113:     if right not in self.get_arrows():
   114:       raise 'second argument not an arrow'+msg
   115:     if result not in self.get_arrows():
   116:       raise 'result not an arrow'+msg
   117: 
   118:     if self.codomain(left) != self.domain(right):
   119:       raise 'arguments cannot be composed'+msg
   120:     if self.domain(left) != self.domain(result):
   121:       raise 'first argument and result require same domain'+msg
   122:     if self.codomain(right) != self.codomain(result):
   123:       raise 'second argument and result require same codomain'+msg
   124: 
   125:     if left in self.get_objects() or right in self.get_objects():
   126:       raise 'attempted to add (duplicate or conflicting) identity rule'
   127:     pair = (left, right)
   128:     if self.rules.has_key(pair):
   129:       raise 'duplicate composition rule'
   130:     self.rules[pair] = result
   131: 
   132:   def copy(self):
   133:     cat = precategory()
   134:     cat.objects = self.objects.copy()
   135:     cat.arrows = self.arrows.copy()
   136:     cat.rules = self.rules.copy()
   137:     return cat
   138: 
   139:   def extend(self, cat):
   140:     # add all the arrows and rules from another category
   141:     # it is OK to add an arrow that already exists, provided
   142:     # it obeys the same rules
   143: 
   144:     for object in cat.objects:
   145:       if object not in self.objects:
   146:         self.add_object(object)
   147:     for arrow in cat.arrows.keys():
   148:       if arrow not in self.arrows:
   149:         self.add_arrow(arrow)
   150:       elif self.arrows[arrow] != cat.arrow[arrow]:
   151:         raise 'incompatible domain or codomain for arrow in "extend category"'
   152:     for rule in cat.rules.keys():
   153:       if not self.rules.has_key(rule):
   154:         self.rules[rule] = cat.rules[rule]
   155:       elif self.rules[rule] != cat.rules[rule]:
   156:         raise 'incompatible composition rules in "extend category"'
   157: 
   158:   def check_complete(self):
   159:     # check that every composible pair has a composition rule
   160:     # skip identities because they're always correct implicitly
   161:     nonobjects = self.get_nonobjects()
   162:     for arrow in nonobjects:
   163:       dom = self.arrows[arrow][0]
   164:       cod = self.arrows[arrow][1]
   165:       for left in self.objects[dom][1]: # arrows into the domain
   166:         if not self.rules.has_key((left, arrow)):
   167:           raise 'incomplete composition set ('+str(left)+', '+str(arrow)+')'
   168:       for right in self.objects[cod][0]: # arrows out of the codomain
   169:         if not self.rules.has_key((arrow, right)):
   170:           raise 'incomplete composition set ('+str(arrow)+', '+str(right)+')'
   171: 
   172: 
   173:   def check_associative(self):
   174:     for a in self.get_nonobjects():
   175:       for b in self.get_nonobjects():
   176:         for c in self.get_nonobjects():
   177:           if self.can_compose(a,b) and self.can_compose(b,c):
   178:             ab = self.compose(a,b)
   179:             bc = self.compose(b,c)
   180:             if self.compose(ab,c) != self.compose(a,bc):
   181:               raise 'Nonassociative precategory'
   182: 
   183:   def print_everything(self, offset=0, compose_sym = '.'):
   184:     p = ' ' * offset
   185:     print p + 'objects:',self.objects.keys()
   186:     print p + 'arrows:'
   187:     for arrow in self.get_nonobjects():
   188:       dom = self.domain(arrow)
   189:       cod = self.codomain(arrow)
   190:       print p + '  '+str(arrow)+':'+str(dom)+'-->'+str(cod)
   191:     print p+'rules:'
   192:     for pair in self.rules.keys():
   193:       result = self.rules[pair]
   194:       print (p + '  '+str(pair[0])+' '+compose_sym+' '+str(pair[1])+
   195:         ' = '+str(result))
   196: 

6.12.3. Standard Categories

6.12.3.1. Implementation

Start python section to interscript/felix/model/stdcat.py[1] 1 2 3 4 5 6 7 8 9 10
     1: #line 6 "felix_stdcat.ipk"
     2: from interscript.felix.model.basecat import category
     3: 
End python section to interscript/felix/model/stdcat.py[1]
6.12.3.1.1. Empty Category
Start python section to interscript/felix/model/stdcat.py[2] 1 2 3 4 5 6 7 8 9 10
     4: #line 10 "felix_stdcat.ipk"
     5: class cat_empty(category):
     6:   def is_arrow(self, arrow): return 0
     7:   is_object = is_arrow
     8: 
End python section to interscript/felix/model/stdcat.py[2]
6.12.3.1.2. Universal Set
Start python section to interscript/felix/model/stdcat.py[3] 1 2 3 4 5 6 7 8 9 10
     9: #line 16 "felix_stdcat.ipk"
    10: class cat_all(category):
    11:   def is_arrow(self, arrow): return 1
    12:   is_object = is_arrow
    13:   def can_compose(self, left, right): return 0
    14: 
End python section to interscript/felix/model/stdcat.py[3]
6.12.3.1.3. Monoids
A monoid is a category with one object.
Start python section to interscript/felix/model/stdcat.py[4] 1 2 3 4 5 6 7 8 9 10
    15: #line 24 "felix_stdcat.ipk"
    16: 
    17: class cat_monoid(category):
    18:   def __init__(self, unit): self.unit = unit
    19: 
    20:   def can_compose(self, left, right): return 1
    21: 
    22:   def domain(self, arrow): return self.unit
    23:   def codomain(self, arrow): return self.unit
    24:   def get_unit(self): return self.unit
    25: 
    26:   def __call__(self, *args):
    27:     return reduce(self.compose, args, self.get_unit())
    28: 
    29:   def is_object(self, object): return object == self.unit
    30: 
End python section to interscript/felix/model/stdcat.py[4]
6.12.3.1.4. Category with one arrow
class cat_one(cat_monoid): def __init__(self, unit): cat_monoid.__init__(self, unit) def is_arrow(self, arrow): return arrow == self.unit
6.12.3.1.5. Integer Addition
The integers under addition are a group; that is, every arrow is invertible. The additive inverse of an integer is its negation.
Start python section to interscript/felix/model/stdcat.py[5] 1 2 3 4 5 6 7 8 9 10
    31: #line 49 "felix_stdcat.ipk"
    32: class int_add(cat_monoid):
    33:   def __init__(self, modulus=0):
    34:     cat_monoid.__init__(self,0)
    35:     self.modulus = abs(modulus)
    36: 
    37:   def compose(self, left, right):
    38:     sum = long(left) + long(right)
    39:     if self.modulus: return sum % self.modulus
    40:     else: return sum
    41: 
    42:   def is_arrow(self, object):
    43:     try:
    44:       as_long = long(object)
    45:       return 1
    46:     except: return 0
    47: 
    48:   def inverse(self, object):
    49:     if self.modulus: return self.modulus - object
    50:     else: return - object
    51: 
End python section to interscript/felix/model/stdcat.py[5]
6.12.3.1.6. Integer Multiplication
Note that this monoid is a group if and only if the modulus is a prime.
Start python section to interscript/felix/model/stdcat.py[6] 1 2 3 4 5 6 7 8 9 10
    52: #line 74 "felix_stdcat.ipk"
    53: class int_mul(cat_monoid):
    54:   def __init__(self, modulus=0):
    55:     cat_monoid.__init__(self,1)
    56:     self.modulus = abs(modulus)
    57: 
    58:   def compose(self, left, right):
    59:     prod = long(left) * long(right)
    60:     if self.modulus: return prod % self.modulus
    61:     else: return prod
    62: 
    63:   def is_arrow(self, object):
    64:     try:
    65:       as_long = long(object)
    66:       return 1
    67:     except: return 0
    68: 
End python section to interscript/felix/model/stdcat.py[6]
6.12.3.1.7. Sequence concatenation
Start python section to interscript/felix/model/stdcat.py[7] 1 2 3 4 5 6 7 8 9 10
    69: #line 92 "felix_stdcat.ipk"
    70: class cat_sequence(cat_monoid):
    71:   def compose(self, left, right): return left + right
    72: 
    73:   def is_arrow(self, object):
    74:     return interscript.core.protocols.has_protocol(object,'sequence')
    75: 
    76:   def is_object(self, object):
    77:     return self.is_arrow(object) and len(object)==0
    78: 
End python section to interscript/felix/model/stdcat.py[7]
6.12.3.1.7.1. Tuples
Start python section to interscript/felix/model/stdcat.py[8] 1 2 3 4 5 6 7 8 9 10
    79: #line 103 "felix_stdcat.ipk"
    80: class cat_tuple(cat_sequence):
    81:   def __init__(self): cat_monoid.__init__(self,())
    82: 
    83:   def is_arrow(self, object):
    84:     return type(object) is types.TupleType
    85: 
End python section to interscript/felix/model/stdcat.py[8]
6.12.3.1.7.2. Lists
Start python section to interscript/felix/model/stdcat.py[9] 1 2 3 4 5 6 7 8 9 10
    86: #line 111 "felix_stdcat.ipk"
    87: class cat_list(cat_sequence):
    88:   def __init__(self): cat_monoid.__init__(self,[])
    89: 
    90:   def is_arrow(self, object):
    91:     return type(object) is types.ListType
    92: 
End python section to interscript/felix/model/stdcat.py[9]
6.12.3.1.7.3. Strings
Start python section to interscript/felix/model/stdcat.py[10] 1 2 3 4 5 6 7 8 9 10
    93: #line 119 "felix_stdcat.ipk"
    94: class cat_string(cat_sequence):
    95:   def __init__(self): cat_monoid.__init__(self,'')
    96: 
    97:   def is_arrow(self, object):
    98:     return type(object) is types.StringType
    99: 
   100: 

6.12.3.2. Test standard categories

Start python section to interscript/felix/tests/stdcat_test.py[1] 1
     1: #line 130 "felix_stdcat.ipk"
     2: import sys
     3: sys.path = [''] + sys.path
     4: import traceback
     5: from interscript.felix.model.stdcat import int_add, int_mul, cat_tuple, cat_list, cat_string
     6: 
     7: add_integers = int_add()
     8: add_integers_mod10 = int_add(10)
     9: mul_integers = int_mul()
    10: mul_integers_mod10 = int_mul(10)
    11: 
    12: tuples = cat_tuple()
    13: lists = cat_list()
    14: strings = cat_string()
    15: 
    16: print strings('Hello',' ','world')
    17: print add_integers(1,2,3,4,5,6,7)
    18: print add_integers_mod10(1,2,3,4,5,6,7)
    19: print mul_integers(1,2,3,4,5,6,7)
    20: print mul_integers_mod10(1,2,3,4,5,6,7)
    21: print tuples((1,2),(3,),(),(4,5,6,7))
    22: print lists([1,2],[3,],[],[4,5,6,7])
    23: 
End python section to interscript/felix/tests/stdcat_test.py[1]
6.12.3.2.1. Test Output
Start output section of "/usr/local/bin/python" interscript/felix/tests/stdcat_test.py
     1: Interscript version 1.0a8 build 1384
     2: Built by root on ruby at Mon Nov 30, 1998 at 08:56 AM (UTC)
     3: Generated by 1.0a8 buildno 1383 host ruby
     4: at Mon Nov 30, 1998 at 08:56 AM (UTC)
     5: Hello world
     6: 28L
     7: 8L
     8: 5040L
     9: 0L
    10: (1, 2, 3, 4, 5, 6, 7)
    11: [1, 2, 3, 4, 5, 6, 7]
End output section to "/usr/local/bin/python" interscript/felix/tests/stdcat_test.py

6.12.4. Categories with simple representation models

Start python section to interscript/felix/model/stdcat2.py[1] 1 2 3
     1: #line 5 "felix_stdcat2.ipk"
     2: from interscript.felix.model.basecat import category
     3: from interscript.core.sets import set
     4: 
End python section to interscript/felix/model/stdcat2.py[1]

6.12.4.1. Sets

All the arrows are objects.
Start python section to interscript/felix/model/stdcat2.py[2] 1 2 3
     5: #line 11 "felix_stdcat2.ipk"
     6: class cat_set(category):
     7:   def __init__(self, *args): self.elements = args
     8: 
     9:   def is_object(self, object): return object in self.elements
    10:   is_arrow = is_object
    11: 
    12:   def can_compose(self,left, right): return left == right
    13: 
    14:   def compose(self, left, right): return left
    15: 
End python section to interscript/felix/model/stdcat2.py[2]

6.12.4.2. Category generated by a directed graph

The category generated by a graph is the set of all paths of the graph plus the set of vertices. Note that a path can't contain an edge more than once.

A graph is represented by a dictionary: the key is a vertex, the value is a list of vertices which there is an edge to. [This model is attributed to Guido van Rossum]

An arrow is a non-empty sequence of vertices such that for each adjacent pair a, b, there is an edge from a to b. (Note that a sequence of one vertex meets this condition).

Start python section to interscript/felix/model/stdcat2.py[3] 1 2 3
    16: #line 36 "felix_stdcat2.ipk"
    17: class cat_dgraph(category):
    18:   def __init__(self):
    19:     self.verticies = {}
    20: 
    21:   def add_vertex(self, vertex)
    22:     self.vertices[vertex]=[]
    23: 
    24:   def add_edge(self, v1, v2):
    25:     self.vertices[v1].append(v2)
    26: 
    27:   def is_object(self, object):
    28:     return self.verticies.has_key(object)
    29: 
    30:   def is_arrow(self,seq):
    31:      if len(seq) == 0: return 0
    32:      first = seq[0]
    33:      for second in seq[1:]:
    34:        if second not in self.vertices[first]: return 0
    35:        first = second
    36:      return 1
    37: 
    38:   def compose(self, a, b): return a + b
    39: 
    40:   de get_objects(self): return self.vertices
    41: 
    42: class cat_graph(cat_dgraph):
    43:   def add_edge(self, v1, v2):
    44:     self.vertices[v1].append(v2)
    45:     self.vertices[v2].append(v1)
    46: 
    47:   def inverse(self, arrow):
    48:     return arrow[:].reverse()
    49: 
    50: class cat_dagraph(cat_dgraph):
    51: 

6.12.5. Function category

There are many possibly representations. We will use a monoidal category whose arrows are class instances of class 'function'. These instances can be called with a single argument, and composed with the infix addition operator.

6.12.5.1. Implementation

6.12.5.1.1. Composable Function
First, we need to be able to compose functions. The function class accepts a list of functions as arguments, saves the list, and calls the functions from left to right when required, passing the single allowed argument to the first function, and the result of that along the chain. The result returned is a traditional value, as is the argument.
Start python section to interscript/felix/model/funcat.py[1] 1 2 3 4 5 6 7 8
     1: #line 21 "felix_func.ipk"
     2: from interscript.felix.model.basecat import category
     3: 
     4: class function:
     5:   def __init__(self, *args):
     6:     self.funcs = args
     7:     self.normalise()
     8: 
     9:   def __call__(self, arg):
    10:     for f in self.funcs:
    11:       #print 'calling',f,'arg',arg
    12:       arg = f(arg)
    13:     return arg
    14: 
    15:   def __and__(self,func):
    16:     return apply(function,self.funcs+func.funcs).normalise()
    17: 
    18:   def __mul__(self, func):
    19:     return function(function_product(self,func))
    20: 
    21:   def __add__(self, func):
    22:     return function(function_sum(self,func))
    23: 
    24:   def normalise(self):
    25:     if self.funcs:
    26:       first = self.funcs[0]
    27:       if isinstance(first, constant):
    28:         self.funcs = (constant(self(None)),)
    29:     return self
    30: 
End python section to interscript/felix/model/funcat.py[1]
6.12.5.1.2. Identity
Start python section to interscript/felix/model/funcat.py[2] 1 2 3 4 5 6 7 8
    31: #line 52 "felix_func.ipk"
    32: class identity(function):
    33:   def __call__(self, arg): return arg
    34:   def __and__(self,func): return func
    35: 
    36: 
    37: 
End python section to interscript/felix/model/funcat.py[2]
6.12.5.1.3. Input Adapter
Wrap any function into a function that accepts a single object which is a pair. The first element of the pair is the tuple of positional arguments and the second the dictionary of keyword arguments. The pair is called the normalised form of a value.
Start python section to interscript/felix/model/funcat.py[3] 1 2 3 4 5 6 7 8
    38: #line 66 "felix_func.ipk"
    39: class input_adapter:
    40:   def __init__(self, func):
    41:     self.func = func
    42: 
    43:   def __call__(self, arg):
    44:     return apply(self.func, arg[0], arg[1])
    45: 
End python section to interscript/felix/model/funcat.py[3]
6.12.5.1.4. Output Adapter
Wrap any function into one that returns a normalised value.
Start python section to interscript/felix/model/funcat.py[4] 1 2 3 4 5 6 7 8
    46: #line 76 "felix_func.ipk"
    47: class output_adapter:
    48:   def __init__(self, func):
    49:     self.func = func
    50: 
    51:   def __call__(self, arg):
    52:     return ((self.func(arg),), {})
    53: 
End python section to interscript/felix/model/funcat.py[4]
6.12.5.1.5. Constant Function
A constant is a function which is a wrapper for a value. It ignores its argument when called, and returns the fixed value it was initialised with.
Start python section to interscript/felix/model/funcat.py[5] 1 2 3 4 5 6 7 8
    54: #line 89 "felix_func.ipk"
    55: class constant(function):
    56:   def __init__(self, value): self.value = value
    57:   def __call__(self, arg): return self.value
    58:   def is_equivalent(self, other): return self.value == other.value
    59: 
End python section to interscript/felix/model/funcat.py[5]
6.12.5.1.6. Function category
The category of all functions.
Start python section to interscript/felix/model/funcat.py[6] 1 2 3 4 5 6 7 8
    60: #line 97 "felix_func.ipk"
    61: class cat_function(category):
    62:   def is_arrow(self, f): return isinstance(f, function)
    63:   def is_object(self, f): return isinstance(f, identity)
    64:   def compose(self, left, right): return left&right
    65:   def domain(self, arrow): return identity()
    66:   def codomain(self, arrow): return identity()
    67: 
    68: 
End python section to interscript/felix/model/funcat.py[6]
6.12.5.1.7. Function Product
A callable object that applies each function in a list to each argument in a list, returning a tuple of results.
Start python section to interscript/felix/model/funcat.py[7] 1 2 3 4 5 6 7 8
    69: #line 109 "felix_func.ipk"
    70: class function_product:
    71:   def __init__(self, *funcs):
    72:     self.funcs = funcs
    73:   def __call__(self, arg):
    74:     #print 'calling product, arg=',arg
    75:     result = []
    76:     for i in range(len(self.funcs)):
    77:       result.append(self.funcs[i](arg[i]))
    78:     return tuple(result)
    79: 
End python section to interscript/felix/model/funcat.py[7]
6.12.5.1.8. Function Sum
A callable object that calls one function in a list to the argument, depending on the discriminant integer.
Start python section to interscript/felix/model/funcat.py[8] 1 2 3 4 5 6 7 8
    80: #line 123 "felix_func.ipk"
    81: class function_sum:
    82:   def __init__(self, *args):
    83:     self.funcs = args
    84:   def __call__(self, arg):
    85:     #print 'function sum, arg=',arg
    86:     return self.funcs[arg[0]](arg[1])
    87: 

6.12.5.2. Test

Start python section to interscript/felix/tests/func_test.py[1] 1
     1: #line 135 "felix_func.ipk"
     2: import sys
     3: sys.path = ['']+sys.path
     4: from interscript.felix.model.funcat import function, constant, identity
     5: from interscript.felix.model.funcat import cat_function
     6: from interscript.felix.model.funcat import function_product, function_sum
     7: from interscript.felix.model.funcat import input_adapter, output_adapter
     8: import math
     9: 
    10: sin = function(math.sin)
    11: print sin(0.5)
    12: 
    13: cos = function(math.cos)
    14: print cos(0.5)
    15: 
    16: square = function(lambda x: x * x)
    17: print square(0.5)
    18: print (sin & square)(0.5)
    19: print (cos & square)(0.5)
    20: 
    21: add = function(lambda x: x[0] + x[1])
    22: print add((1,2))
    23: 
    24: delta = function(lambda x: (x,x))
    25: print delta(7)
    26: print (delta & add)(7)
    27: print (square * square)((2,3))
    28: 
    29: sin2pcos2 = delta & ((sin & square) * (cos & square)) & add
    30: print sin2pcos2(0.5)
    31: 
    32: sign = function(lambda x: (x<0,x)) # sign 1 if negative else 0
    33: print sign(1), sign(-1)
    34: 
    35: negate= function(lambda x: -x)
    36: print negate(1), negate(-1)
    37: 
    38: absolute = sign & (identity() + negate)
    39: 
    40: print absolute(-4), absolute(4)
    41: 
    42: c = constant(1)
    43: print c(99)
    44: 
6.12.5.2.1. Test output
Start output section of "/usr/local/bin/python" interscript/felix/tests/func_test.py
     1: Interscript version 1.0a8 build 1384
     2: Built by root on ruby at Mon Nov 30, 1998 at 08:56 AM (UTC)
     3: Generated by 1.0a8 buildno 1383 host ruby
     4: at Mon Nov 30, 1998 at 08:56 AM (UTC)
     5: 0.479425538604
     6: 0.87758256189
     7: 0.25
     8: 0.229848847066
     9: 0.770151152934
    10: 3
    11: (7, 7)
    12: 14
    13: (4, 9)
    14: 1.0
    15: (0, 1) (1, -1)
    16: -1 1
    17: 4 4
    18: 1
End output section to "/usr/local/bin/python" interscript/felix/tests/func_test.py

6.12.6. Constructions

Herein some ways to make new categories from old ones.
Start python section to interscript/felix/model/cons.py[1] 1 2 3 4 5 6
     1: #line 6 "felix_cons.ipk"
     2: from interscript.felix.model.basecat import category
     3: 
End python section to interscript/felix/model/cons.py[1]

6.12.6.1. Product

The term product is the categorical word for tuple, for sets it is the cartesian product. We form the product by delegation. The element arrows are tuples of arrows. Objects are tuples of objects. Composition is componentwise.
Start python section to interscript/felix/model/cons.py[2] 1 2 3 4 5 6
     4: #line 16 "felix_cons.ipk"
     5: class cat_product(category):
     6:   def __init__(self, *args):
     7:     self.args = args
     8:     self.len = len(args)
     9: 
    10:   def is_arrow(self,arrow):
    11:     for i in range(self.len)):
    12:        if not self.args[i].is_arrow(arrow[i]): return 0
    13:     return 1
    14: 
    15:   def is_object(self,object):
    16:     for i in range(self.len)):
    17:        if not self.args[i].is_object(object[i]): return 0
    18:     return 1
    19: 
    20:   def can_compose(self, left, right):
    21:     for i in range(self.len):
    22:       if not self.args[i].can_compose(left[i],right[i]): return 0
    23:     return 1
    24: 
    25:   def compose(self, left, right):
    26:     l = []
    27:     for i in range(self.len):
    28:       l.append(self.args[i](left[i],right[i]))
    29:     return tuple(l)
    30: 
    31:   def domain(self, x):
    32:     l = []
    33:     for i in range(self.len):
    34:       l.append(self.args[i].domain(x[i]))
    35:     return tuple(l)
    36: 
    37:   def codomain(self, x):
    38:     l = []
    39:     for i in range(self.len):
    40:       l.append(self.args[i].codomain(x[i]))
    41:     return tuple(l)
    42: 
End python section to interscript/felix/model/cons.py[2]

6.12.6.2. Dual

The dual of a category is just the same category with all the arrows reversed.
Start python section to interscript/felix/model/cons.py[3] 1 2 3 4 5 6
    43: #line 58 "felix_cons.ipk"
    44: class cat_dual(category):
    45:   def __init__(self, arg):
    46:     self.arg = arg
    47: 
    48:   def is_arrow(self,arrow):
    49:     return self.arg.is_arrow(arrow)
    50: 
    51:   def is_object(self,object):
    52:     return self.arg.is_object(arrow)
    53: 
    54:   def can_compose(self, left, right):
    55:     return self.arg.can_compose(right, left)
    56: 
    57:   def compose(self, left, right):
    58:     return self.arg.compose(right, left)
    59: 
    60:   def domain(self, x):
    61:     return self.arg.codomain(x)
    62: 
    63:   def codomain(self, x):
    64:     return self.arg.domain(x)
    65: 
End python section to interscript/felix/model/cons.py[3]

6.12.6.3. Undiscriminated Union

The argument categories must have disjoint arrows sets for this construction to work. Use the discriminated union if there is an arrow in common.

The categorical sum, or union, of two categories is just the complete set of all the arrows.

Start python section to interscript/felix/model/cons.py[4] 1 2 3 4 5 6
    66: #line 88 "felix_cons.ipk"
    67: class cat_union(category):
    68:   def __init__(self, *args):
    69:     self.args = args
    70:     self.len = len(args)
    71: 
    72:   def is_arrow(self,arrow):
    73:      for i in range(self.len)):
    74:        if self.args[i].is_arrow(arrow): return 1
    75:     return 0
    76: 
    77:   def is_object(self,object):
    78:      for i in range(self.len)):
    79:        if self.args[i].is_object(object): return 1
    80:     return 0
    81: 
    82:   def can_compose(self, left, right):
    83:     for i in range(self.len):
    84:       if (
    85:         self.args[i].is_arrow(left) and
    86:         self.args[i].is_arrow(right) and
    87:         self.args[i].can_compose.(left,right)): return 1
    88:     return 0
    89: 
    90:   def compose(self, left, right):
    91:     for i in range(self.len):
    92:       if (
    93:         self.args[i].is_arrow(left) and
    94:         self.args[i].is_arrow(right)):
    95:         return self.args[i](left,right)
    96: 
    97:   def domain(self, x):
    98:     for i in range(self.len):
    99:       if self.args[i].is_arrow(x):
   100:         return self.args[i].domain(x)
   101: 
   102:   def codomain(self, x):
   103:     for i in range(self.len):
   104:       if self.args[i].is_arrow(x):
   105:         return self.args[i].codomain(x)
   106: 
End python section to interscript/felix/model/cons.py[4]

6.12.6.4. Tagged category

The same category, with an arrow a converted to a pair (tag, a).
Start python section to interscript/felix/model/cons.py[5] 1 2 3 4 5 6
   107: #line 131 "felix_cons.ipk"
   108: class cat_tagged(category):
   109:   def __init__(self, tag, arg):
   110:     self.arg = arg
   111:     self.tag = tag
   112: 
   113:   def is_arrow(self,arrow):
   114:     return arrow[0] == self.tag and self.arg.is_arrow(arrow[1])
   115: 
   116:   def is_object(self,object):
   117:     return arrow[0] == self.tag and self.arg.is_object(arrow[1])
   118: 
   119:   def compose(self, left, right):
   120:     return (self.tag, self.arg.compose(right[1], left[1]))
   121: 
   122:   def domain(self, x):
   123:     return (self.tag, self.arg.codomain(x))
   124: 
   125:   def codomain(self, x):
   126:     return (self.tag, self.arg.domain(x))
   127: 
   128: class unique_tag: pass
   129: 
End python section to interscript/felix/model/cons.py[5]

6.12.6.5. Discriminated union

We implement a discriminated union by tagging the argument categories with unique tags, and forming the undiscriminated union. It would be better to use the actual categories as their own tags but that would not work if the same category was presented twice in the argument list, which is likely to be the most common case.
Start python section to interscript/felix/model/cons.py[6] 1 2 3 4 5 6
   130: #line 160 "felix_cons.ipk"
   131: def cat_dunion(*args):
   132:   cats = []
   133:   for cat in args:
   134:     cats.append(cat_tagged(unique_tag(),cat))
   135:   return apply(cat_union, tuple(cats))
   136: 
    10: #line 26 "felix_package.ipk"
    11: 

6.13. Architecture

This part discusses the architectural design of Interscript. Here is a simplified picture of which objects refer to which others. Interscript maintains several objects that act as _frames_ (or namespaces) for symbol lookup.
  FRAMES
    process_frame  --> global_frame
    master_frame   --> process_frame
    pass_frame     --> master_frame
    input_frame    --> pass_frame
                   --> weaver_filter
                   --> stack of tangler

    tangler        --> multiplexor
                   --> sink

    weaver_filter  --> multiplexor
    multiplexor    --> weaver
    weaver         --> sink

6.13.1. The universal frame

The most global frame is the _universal frame_, and contains fixed information such as interscript code, constant limits of the implementation, and options which are hardwired into the software. There's no actual universal frame object, but the Python and Interscript 'standards' may be considered universals.

6.13.2. Install Frame

The _install frame_ is used to control how generated files are installed.

An _installation point_ is a directory which will contain a certain class of files. An _installation mode_ is an indication of the permissions an installed file should have.

The install frame contains the default places where development occurs, and where code and documentation should be installed depending on the designation ascribed to the file in interscript sources.

Installation is controlled in several ways. The _kind_ of file is identified in the interscript source, this tells the language used for script, the kind of script, or whether the final target is an executable of dynamically loadable binary. (This information is generally gleaned from the tangler used, plus options if required).

The _stability_ of the version is also identifed as experimental, test, alpha, beta, or production in the interscript source. This information must be supplied by the vendor.

The _domain of applicability_ is identified in the interscript source, this tells if the code is univerally useful, platform specific, should be tailored per site, or tailored per user-group or user. This information must be supplied by the vendor.

Start python section to interscript/frames/install.py[1] 1
     1: #line 62 "frames.ipk"
     2: class install_frame:
     3:   def __init__(self):
     4:     py = 'python'+self.python_version
     5:     self.platform_independent_install_point = sys.prefix
     6:     self.python_header_install_point = sys.prefix + '/include/'+py
     7:     self.python_module_install_point = sys.prefix + '/lib/'+py
     8:     self.python_platform_install_point = sys.prefix + '/lib/'+py+'/plat-'+platform.python_plat
     9: 
    10:     self.platform_dependent_install_point = sys.exec_prefix
    11:     self.python_config_install_point = sys.exec_prefix + '/lib/'+self.python_version+'/config'
    12:     self.python_dynload_install_point = sys.exec_prefix + '/lib/'+self.python_version+'/lib-dynload'
    13: 
    14:     # this is where stuff goes during development
    15:     d = self.development_point = {}
    16:     d['documentation']=self.platform.get_working_directory()
    17:     d['python module']=self.platform.get_working_directory()
    18:     d['python package']=self.platform.get_working_directory()
    19:     d['python cmodule']=self.platform.get_working_directory()
    20:     d['python script']=self.platform.get_working_directory()
    21:     d['executable']=self.platform.get_working_directory()
    22: 
    23:     # this is where standard stuff gets installed for general use
    24:     d = self.standard_install_point = {}
    25:     d['documentation']=sys.prefix+'/doc'
    26:     d['python module']=self.python_module_install_point
    27:     d['python package']=self.python_module_install_point
    28:     d['python cmodule']=self.python_dynload_install_point
    29:     d['python script']=sys.exec_prefix+'/bin'
    30:     d['executable']=sys.exec_prefix+'/bin'
    31: 
    32:     # this is where platform dependent stuff gets installed for general use
    33:     d = self.platform_install_point = {}
    34:     d['documentation']=sys.prefix+'/doc'
    35:     d['python module']=self.python_module_install_point
    36:     d['python package']=self.python_module_install_point
    37:     d['python cmodule']=self.python_dynload_install_point
    38:     d['python script']=sys.exec_prefix+'/bin'
    39:     d['executable']=sys.exec_prefix+'/bin'
    40: 
    41:     # this is where site dependent stuff gets installed for general use
    42:     d = self.site_install_point = {}
    43:     d['documentation']=sys.prefix+'/doc'
    44:     d['python module']=self.python_module_install_point+'/site-packages'
    45:     d['python package']=self.python_module_install_point+'/site-packages'
    46:     d['python cmodule']=self.python_dynload_install_point+'/site-packages'
    47:     d['python script']=sys.exec_prefix+'/bin'
    48:     d['executable']=sys.exec_prefix+'/bin'
    49: 
    50:     # this is where user-group dependent stuff gets installed for use
    51:     d = self.usergrp_install_point = {}
    52:     d['documentation']=sys.prefix+'/doc'
    53:     d['python module']=self.python_module_install_point+'/site-packages'
    54:     d['python package']=self.python_module_install_point+'/site-packages'
    55:     d['python cmodule']=self.python_dynload_install_point+'/site-packages'
    56:     d['python script']=sys.exec_prefix+'/bin'
    57:     d['executable']=sys.exec_prefix+'/bin'
    58: 
    59:     # this is where user dependent stuff gets installed for use
    60:     d = self.user_install_point = {}
    61:     d['documentation']=sys.prefix+'/doc'
    62:     d['python module']=self.python_module_install_point+'/site-packages'
    63:     d['python package']=self.python_module_install_point+'/site-packages'
    64:     d['python cmodule']=self.python_dynload_install_point+'/site-packages'
    65:     d['python script']=sys.exec_prefix+'/bin'
    66:     d['executable']=sys.exec_prefix+'/bin'
    67: 
    68:     self.install_point = {
    69:       'dev': self.development_point,
    70:       'std': self.standard_install_point,
    71:       'plat': self.platform_install_point,
    72:       'site': self.site_install_point,
    73:       'grp': self.usergrp_install_point,
    74:       'user': self.user_install_point
    75:       }
    76: 
    77:     self.trust_map = {
    78:       'experimental':'dev',
    79:       'test':'dev',
    80:       'alpha':'dev',
    81:       'beta':'user',
    82:       'production':'user'
    83:       }
    84: 
    85:   def print_install(self):
    86:     print 'INSTALL POINTS'
    87:     print '----------------------------'
    88:     for k in self.install_point.keys():
    89:       print 'Install Point',k
    90:       d = self.install_point[k]
    91:       for t in d.keys():
    92:         print ' ',t,'-->',d[t]
    93:       print '----------------------------'
    94:       print
    95:     print 'TRUST MAP'
    96:     print '----------------------------'
    97:     for k in self.trust_map.keys():
    98:       print ' ',k,'-->',self.trust_map[k]
    99:     print '----------------------------'
   100:     print
   101: 
   102: 
End python section to interscript/frames/install.py[1]

6.13.3. The user frame

The _user frame_ contains data and functions related to a particular user, such as the users email address. In addition, Interscript imports the module 'user', which executes the file 'pythonrc.py' in the user's home directory under Unix.
Start python section to interscript/frames/user.py[1] 1
     1: #line 169 "frames.ipk"
     2: class user_frame:
     3:   pass
     4: 
End python section to interscript/frames/user.py[1]

6.13.4. The project frame

The _project frame_ contains data and functions related to a specific project. A project may consist of a number of users, and it may contain configuration information such as the style of page headings used,

that relate to all the software of a given project. There is currently no project frame, because the architecture of projects has not yet been designed, however comments from users are solicited.

Start python section to interscript/frames/project.py[1] 1
     1: #line 182 "frames.ipk"
     2: class project_frame:
     3:   pass
     4: 
     5: 
End python section to interscript/frames/project.py[1]
Start python section to interscript/frames/__init__.py[1] 1
     1: #line 188 "frames.ipk"
     2: # frames subpackage

6.13.5. The platform frame

The _platform frame_ contains platform specific data and functions, such as the name of the operating system. These include build options of Python itself, and the platform dependent modules such as 'posix' representing platform specific operating system services and access paths.

Note the tmp.tmp file which is used as a bit bucket for stderr. This works on NT and Unix. It's ugly.

Start python section to interscript/frames/platform.py[1] 1
     1: #line 13 "platform_frame.ipk"
     2: import sys
     3: import os
     4: 
     5: class platform_frame:
     6:   def __init__(self):
     7:     self.python_plat = sys.platform
     8:     self.uname = ['unknown','unknown','unknown']
     9:     try:
    10:       f = os.popen('uname -s 2>tmp.tmp','r')
    11:       self.uname[0] = f.read()
    12:       f.close()
    13:       del f
    14:       f = os.popen('uname -v 2>tmp.tmp','r')
    15:       self.uname[1] = f.read()
    16:       f.close()
    17:       del f
    18:       f = os.popen('uname -r 2>tmp.tmp','r')
    19:       self.uname[2] = f.read()
    20:       f.close()
    21:       del f
    22:     except:
    23:       pass
    24:     self.python_os = os.name
    25:       # one of 'nt', 'posix','dos','mac'
    26: 
    27:   def map_filename(self,path,base,extension):
    28:     return string.join(path,os.sep)+os.sep+base+'.'+extension
    29: 
    30:   def get_working_directory(self):
    31:     return os.getcwd()
    32: 

6.13.6. The site frame

The _site frame_ contains data and functions which configure Interscript to a specific installation. For example, the availability of various tanglers and weavers is likely to be site specific. The specific location of the Python and Interscript systems is part of the conceptual site frame.
Start python section to interscript/frames/site.py[1] 1
     1: #line 10 "site_frame.ipk"
     2: import sys
     3: class site_frame:
     4:   def __init__(self, platform):
     5:     self.platform = platform
     6:     self.python_version = sys.version[:3]
     7:     self.builtin_module_names = sys.builtin_module_names
     8:     self.python_module_search_path = sys.path
     9: 

6.13.7. The process frame

The _process frame_ contains data configuring a particular processing run. That data is gleaned from command line switches, the environment, defaults from other frames, and statistics gathered during processing, and also some data configured by user commands in input files.

User commands may read symbols from this dictionary, and may modify the objects to which the symbol names refer, but are protected from rebinding the names to other objects or values.

The organisation of the process frame is currently haphazard and may change from version to version.

Make an object to hold global variables that user objects can hang onto, to ensure these variables live during the execution of the object destructors.

Start python section to interscript/frames/processf.py[1] 1 2
     1: #line 22 "process_frame.ipk"
     2: from interscript.frames.site import site_frame
     3: from interscript.frames.platform import platform_frame
     4: from interscript.frames.masterf import master_frame
     5: from interscript.drivers.sources.base import eoi
     6: import sys
     7: import traceback
     8: import time
     9: 
    10: class process_frame:
    11:   def __init__(self, global_frame, process_options, argument_frames):
    12:     self.global_frame = global_frame
    13:     self.process_options = process_options
    14:     self.argument_frames = argument_frames
    15: 
    16:     self.break_on_error = 0
    17:     self.debug_constructors = 0
    18:     self.debug_destructors = 0
    19:     self.verbosity = process_options.verbosity
    20:     self.update_files = 1
    21: 
    22:     plat = platform_frame()
    23:     self.site_frame = site_frame(plat)
    24:     # self.site_frame.print_install()
    25: 
    26:   def run(self):
    27:     oldstdout = sys.stdout
    28:     oldstderr = sys.stderr
    29:     f = self.process_options.logfile
    30:     m = self.process_options.logfile_mode
    31:     if self.process_options.logfile:
    32:       try:
    33:         sys.stderr = sys.stdout = open(f,m)
    34:       except IOError:
    35:         print 'Cannot open specified logfile',f
    36:       except:
    37:         print 'Weird error opening specified logfile',f
    38:         traceback.print_exc()
    39: 
    40:     reference_date = time.time()
    41:     local_time = time.localtime(reference_date)
    42:     local_time_string = time.strftime("%a %d %b, %Y %H:%M:%S (%Z)",local_time)
    43:     start_time = time.clock()
    44:     if m: print '<CDATA>'
    45:     print
    46:     print '---------------------------------'
    47:     print 'Interscript '+self.global_frame.version +\
    48:       '['+str(self.global_frame.buildno)+'] Process',local_time_string
    49: 
    50:     try:
    51:       for argument_frame in self.argument_frames:
    52:         master_frame(self,argument_frame)
    53:     finally:
    54:       end_time = time.clock()
    55:       elapsed_time = end_time - start_time
    56:       print 'Elapsed Process Time',int(elapsed_time),'seconds'
    57:       print '================================'
    58:       print
    59:       sys.stdout = oldstdout
    60:       sys.stderr = oldstderr
    61: 
    62:   def get_process_frame(self): return self
    63: 
End python section to interscript/frames/processf.py[1]

6.13.7.1. Execute Python Script

Start python section to interscript/frames/processf.py[2] 1 2
    64: #line 86 "process_frame.ipk"
    65:   def py_exec(self,py,file,count,glb,user):
    66:     # get a lock here, release it later
    67:     try:
    68:       if self.verbosity>4: print 'Executing',py
    69:       exec py in glb,user
    70:     except KeyboardInterrupt:
    71:       self.update_files = 0
    72:       raise KeyboardInterrupt
    73:     except eoi:
    74:       raise eoi
    75:     except:
    76:       print 'error executing python:',file,count,':',py
    77:       traceback.print_exc()
    78:       if self.break_on_error:
    79:         self.update_files = 0
    80:         sys.exit()
    81: 

6.13.8. Master Frame

There is a _master frame_ for each master document file read by Interscript. It contains data for the document which persists between passes on the source. For example the master table of contents is part of the master frame. Information in the master frame is often collected during pass and set into the frame at the end of the pass so it can be used by the next pass: the table of contents is such an example.

Conceptually, if multiple master documents are processed by interscript, elaboration of each document is performed in a separate thread. The master frame contains thread local data, whereas the process frame is shared by all threads.

At the 'document' level, the failure to generate a document correctly is at most fatal to that thread of control because documents are in some senses independent. However, when multiple documents form a project, inter-document dependencies may dictate abortion of the whole processes if one of the master threads fails.

Start python section to interscript/frames/masterf.py[1] 1 2
     1: #line 23 "master_frame.ipk"
     2: from interscript.frames.passf import pass_frame
     3: from interscript.drivers.sources.disk import parse_source_filename
     4: import pickle
     5: 
     6: class master_frame:
     7:   def __init__(self,process,argument_frame):
     8:     self.process = process
     9:     for k in argument_frame.__dict__.keys():
    10:       if process.verbosity > 4:
    11:         print 'setting MASTER',k,'as',argument_frame.__dict__[k]
    12:       setattr(self,k,argument_frame.__dict__[k])
    13:     self.ids = {}
    14:     self.iflist = []
    15:     self.flist = []
    16:     self.fdict = {}
    17:     self.toc = []
    18:     self.include_files = []
    19:     self.classes = {}
    20:     self.functions = {}
    21:     self.sequence_limit = -1
    22:     self.section_index = {}
    23:     self.tests = {}
    24:     self.persistent_frames = {}
    25:     if self.usecache:
    26:       self.cache_name =parse_source_filename(
    27:         self.filename+'.cache', self.source_prefix) [3]
    28:       try:
    29:         cache = open(self.cache_name,'r')
    30:         self.persistent_frames = pickle.load(cache)
    31:         cache.close()
    32:         del cache
    33:       except KeyboardInterrupt: raise
    34:       except: pass
    35: 
End python section to interscript/frames/masterf.py[1]

6.13.8.1. Run the passes

At present, we just run the number of passes specified as the limit. This will change when convergence testing is implemented.

The pass loop moves the identifier list, input and output file lists, and table of contents from the pass frame to the master frame after each pass. This permits this data to be read by the next pass (while it is also regenerating the data for the pass after that).

Conceptually, the loop is said to converge when this data is the same twice in a row. However we do not test this yet because the state information is not complete.

To be complete, it must determine whether the input and output files have changed between passes. This will be done by comparing the file lists, and comparing the last modification dates on the files between passes.

Finally, output to simple files will be ignored. It is necessary to also add user controlled hooks into the convergence tests, because user script can have arbitrary side effects.

Start python section to interscript/frames/masterf.py[2] 1 2
    36: #line 81 "master_frame.ipk"
    37:     for passno in range(self.passes):
    38:       curpass = pass_frame(self, passno)
    39:       self.ids = curpass.ids        # idlist
    40:       self.flist = curpass.flist    # output file list
    41:       self.iflist = curpass.iflist  # input file list
    42:       self.toc = curpass.toc        # table of contents
    43:       self.include_files = curpass.include_files # include files
    44:       self.classes = curpass.classes # classes
    45:       self.functions = curpass.functions # functions
    46:       self.tests = curpass.tests # functions
    47:       self.section_index = curpass.section_index # functions
    48: 
    49:       if self.sequence_limit == -1:
    50:         self.sequence_limit = curpass.sequence
    51:       elif self.sequence_limit != curpass.sequence:
    52:         print 'WARNING: SEQUENCE COUNTER DISPARITY BETWEEN PASSES'
    53:       ds = curpass.fdict
    54:       dd = self.fdict
    55: 
    56:       file_count = 0
    57:       stable_file_count = 0
    58:       unstable_file_count = 0
    59:       new_file_count = 0
    60:       for k in ds.keys():
    61:         file_count = file_count + 1
    62:         if not dd.has_key(k):
    63:           dd[k]=(ds[k],passno)
    64:           new_file_count = new_file_count + 1
    65:         else:
    66:           if ds[k]=='unchanged':
    67:             stable_file_count = stable_file_count + 1
    68:           else:
    69:             unstable_file_count = unstable_file_count + 1
    70:           if ds[k]!='unchanged' or dd[k][0]!='unchanged':
    71:             dd[k]=(ds[k],passno)
    72:       converged = file_count == stable_file_count
    73:       if converged:
    74:         print 'All',file_count,'output files stable on pass',passno,' -- breaking'
    75:         break
    76:       else:
    77:         print 'Of',file_count,'files, only',stable_file_count,'were stable on pass',passno
    78:         print 'There were',new_file_count,'new files,'
    79:         print 'and',unstable_file_count,'unstable files.'
    80:     if self.usecache:
    81:       try:
    82:         cache = open(self.cache_name,'w')
    83:         pickle.dump(self.persistent_frames, cache)
    84:         cache.close()
    85:         del cache
    86:       except KeyboardInterrupt: raise
    87:       except:
    88:         print 'Pickle FAILURE'
    89: 
    90:   def get_master_frame(self): return self
    91: 
    92:   def get_persistent_frame(self, seq):
    93:     if not self.persistent_frames.has_key(seq):
    94:       self.persistent_frames[seq]={}
    95:     return self.persistent_frames[seq]
    96: 

6.13.9. The pass frame

The _pass frame_ contains data gleaned during a single pass over a master document. The pass frame is reinitialised for each pass, so that defaults are re-established.

For each master document thread, multiple passes on a document are performed sequentially: a pass may depend on previous passes.

The thread generating a document is said to converge if an successive passes reach a fixed point; that is, if all the outputs from one pass are the same as from the previous pass.

Conceptually, interscript repeats passes indefinitely until the passes converge; in practice, a limit is placed on the number of passes for two reasons: the first is to prevent unstable definitions locking up the computer, and the second is to allow for the fact that detection of convergence is, in general, difficult and not fully implemented.

For example, although comparison of output files is a useful tool, minor variations between passes, such as time stamps, may lead to failed comparisons based on representation rather than semantic content.

Start python section to interscript/frames/passf.py[1] 1 2
     1: #line 26 "pass_frame.ipk"
     2: import string
     3: import traceback
     4: import sys
     5: 
     6: from interscript.drivers.sources import source_open_error
     7: from interscript.drivers.sources.disk import named_file_source
     8: from interscript.drivers.sources.base import eoi
     9: from interscript.frames.inputf import input_frame
    10: from interscript.weavers.auto import auto_weaver
    11: from interscript.drivers.sources.base import eoi
    12: from interscript.parsers.html import sgml_wrapper, html_filter
    13: 
    14: class pass_frame:
    15:   def __init__(self,master, passno):
    16:     # the display
    17:     self.master = master
    18:     self.process = master.process
    19: 
    20:     self.passno = passno
    21: 
    22:     self.verbosity = master.verbosity
    23:     self.echo_input = master.echo_input
    24:     self.autoweave = master.autoweave
    25: 
    26:     self.ids = {}
    27:     self.flist = []
    28:     self.fdict = {}
    29:     self.iflist = []
    30:     self.toc = []
    31:     self.include_files = []
    32:     self.classes = {}
    33:     self.functions = {}
    34:     self.testno = 0
    35:     self.sequence = 0
    36:     self.tests = {}
    37:     self.section_index = {}
    38: 
    39:     if self.verbosity>=3:
    40:       print 'Autoweave',self.autoweave
    41: 
    42:     file = self.master.filename
    43:     if self.verbosity>=2:
    44:       print 'Processing',file,'Pass',passno
    45: 
End python section to interscript/frames/passf.py[1]

6.13.9.1. Construct input object

We construct an disk source driver by taking the first command line argument as a disk file name. We construct an input frame, and attach the source driver to it.
Start python section to interscript/frames/passf.py[2] 1 2
    46: #line 76 "pass_frame.ipk"
    47: 
    48:     basename = file
    49:     if string.find(file,'.') != -1:
    50:       basename = string.join(string.split(file,'.')[:-1],'.')
    51: 
    52:     weaver = auto_weaver(self, basename, self.autoweave, master.title)
    53:     userdict = {
    54:       'echo_input':self.echo_input,
    55:       'verbosity':self.verbosity
    56:       }
    57: 
    58:     try:
    59:       input_file =named_file_source(self,file, self.master.source_prefix)
    60: 
    61:     except source_open_error, filename:
    62:       if self.verbosity>1:
    63:         print 'Cannot Open File',filename,'for input (ignored)'
    64:       raise
    65:     except KeyboardError:
    66:       raise
    67:     except:
    68:       print "Program error opening",file
    69:       traceback.print_exc()
    70:       raise
    71: 
    72:     self.include_files.append((1,'interscript',file))
    73:     inpt = input_frame(
    74:       self,
    75:       input_file,
    76:       [],
    77:       weaver,
    78:       userdict,
    79:       1)
    80:     inpt.set_warning_character(python='@')
    81:     if self.verbosity>=3:
    82:       print 'input from',inpt.source.get_source_name()
    83: 
    84:     inpt.file_pass()
    85:     # at this point, inpt, weaver, userdict, input_file
    86:     # should all be released (even if 'pass_frame' is held onto,
    87:     # these symbols are defined in the __init__ function frame)
    88: 
    89:   def get_pass_frame(self):
    90:     return self
    91: 
    92:   def get_new_test_number(self):
    93:     self.testno = self.testno + 1
    94:     return self.testno
    95: 
    96:   def get_new_sequence_number(self):
    97:     self.sequence = self.sequence + 1
    98:     return self.sequence
    99: 

6.13.10. Input Frame

An _input frame_ is created for every document and subdocument. Input frames are stacked, typically by @include_file() commands. Input frames implement lexical scoping and help to isolate lexical information pertaining to a single file from containing files. For example, the main parser table, weaver, and tangler stack are part of an input frame.

When the input frame is stacked, its symbol dictionary is copied to the new input frame so that included files inherit the names from the including file. Any rebindings of those name in the new input file will be lost when the file ends, however.

For example, if the weaver is set to an HTML weaver, and an included file sets the weaver to a plain text weaver, when the included files ends, documentation will be written to the HTML weaver. The plain text weaver will have been closed when the last reference to it disappeared.

You should note, however, that while you cannot change the bindings of name in parent documents, you certainly can change the attributes of the objects named by them, and these changes are persistent. For example, if a child document changes an attribute of weaver inherited from the parent, the attribute will remain changed even after the child is exhausted. It's not that this behaviour is 'deliberate', so much as it's the way Python works :-)

Start python section to interscript/frames/inputf.py[1] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
     1: #line 34 "input_frame.ipk"
     2: import string
     3: import re
     4: import traceback
     5: import sys
     6: import os
     7: import tempfile
     8: 
     9: # these imports _should_ come from the global frame!
    10: from interscript.drivers.sources.base import eof, eoi
    11: from interscript.drivers.sources.disk import named_file_source
    12: from interscript.drivers.sources.disk import parse_source_filename
    13: from interscript.drivers.sources.disk import loadfile
    14: from interscript.drivers.sources.cache import cache_source
    15: from interscript.drivers.sinks.bufdisk import named_file_sink
    16: from interscript.drivers.sinks.disk import simple_named_file_sink
    17: from interscript.drivers.sinks.cache import cache_sink
    18: from interscript.drivers.storage.memory import memory
    19: 
    20: from interscript.tanglers.c import c_tangler
    21: from interscript.tanglers.cpp import cpp_tangler
    22: from interscript.tanglers.python import python_tangler
    23: from interscript.tanglers.perl import perl_tangler
    24: from interscript.tanglers.java import java_tangler
    25: from interscript.tanglers.tcl import tcl_tangler
    26: from interscript.tanglers.doc import doc_tangler
    27: from interscript.tanglers.null import null_tangler
    28: from interscript.tanglers.data import data_tangler
    29: from interscript.core.protocols import has_protocol
    30: 
    31: from interscript.parsers.html import sgml_wrapper, html_filter
    32: try:
    33:   import interscript.utilities.diff
    34: except:
    35:   pass
    36: 
    37: def compile_parse_tab(res):
    38:   return map(lambda x: [re.compile(x[0]), x[1]], res)
    39: 
    40: class deduce: pass
    41: 
    42: extension_table = {
    43:   'py':'python',
    44:   'c':'c',
    45:   'h':'c',
    46:   'cpp':'cpp',
    47:   'hpp':'cpp',
    48:   'java':'java',
    49:   'pl':'perl',
    50:   'pak':'interscript',
    51:   'ipk':'interscript',
    52:   'dat':'data',
    53:   'txt':'data',
    54:   'doc':'doc'
    55: }
    56: 
End python section to interscript/frames/inputf.py[1]

6.13.10.1. The input frame

Note the horrid hack: the reg_list is a list of pairs, the second entry is a method which should be bound to this frame, but the frame isn't built yet. So the caller must pass an empty list, and populate it after the frame is constructed.

This has to be fixed.

Start python section to interscript/frames/inputf.py[2] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
    57: #line 97 "input_frame.ipk"
    58: class input_frame:
    59: 
    60:   def __init__(self, pass_frame, src, reg_list, weaver, userdict, depth):
    61:     # the display
    62:     self.pass_frame = pass_frame
    63:     self.master = pass_frame.master
    64:     self.process = self.master.process
    65:     self.global_frame = self.process.global_frame
    66: 
    67:     self.current_weaver = weaver
    68:     self.current_weaver_stack = []
    69: 
    70:     self.depth = depth
    71:     self.source = src
    72:     self.userdict = userdict
    73:     self.reg_list = reg_list
    74:     self.read_buffer = []
    75: 
    76:     self.current_tangler_stack = []
    77:     self.current_tangler = None
    78:     self.line_offset = 0
    79:     self.original_filename = src.get_source_name()
    80:     self.original_count = self.line_offset
    81:     self.current_weaver.set_original_filename(self.original_filename)
    82:     self.head_offset = 0
    83:     self.verbosity = pass_frame.verbosity
    84:     self.tabwidth = self.master.tabwidth
    85: 
    86:     self.cont_re = re.compile('^$|^ (.*)$')
    87:     self.any_line_re = re.compile('^(.*)$')
    88: 
    89:     if self.verbosity>=6:
    90:       print 'initialising input frame',src.get_source_name()
    91:     self.post_methods()
    92: 
    93:   def __del__(self):
    94:     if self.verbosity>=6:
    95:       print 'frame',self.source.name,'deleting'
    96: 
End python section to interscript/frames/inputf.py[2]
6.13.10.1.1. Post user methods
This bit is very hacky! We grab bound methods from input frame and put them in the user dictionary.
Start python section to interscript/frames/inputf.py[3] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
    97: #line 141 "input_frame.ipk"
    98:   def post_methods(self):
    99:     # input frame methods
   100:     method_names = self.__class__.__dict__.keys()
   101:     is_begin_or_end_method = lambda x: x[:3]=='end' or x[:5]=='begin'
   102:     method_names = filter(is_begin_or_end_method, method_names)
   103:     method_names = method_names + [
   104:       'head','heading','push_head','pop_head','set_head',
   105:       'line_break','page_break',
   106:       'set_warning_character',
   107:       'doc','p','eop','cite_url',
   108:       'data_output','c_output','cpp_output',
   109:       'python_output','perl_output',
   110:       'interscript_output',
   111:       'tangler',
   112:       'push','pop','select','comment','resume_code',
   113:       'tangler_push','tangler_pop','tangler_set', # temporarily!
   114:       'get_tangler',
   115:       'untangle',
   116:       'weave','weave_line','tangle',
   117:       'print_identifier_cross_reference',
   118:       'print_contents',
   119:       'print_file_list',
   120:       'print_source_list',
   121:       'print_include_list',
   122:       'print_class_reference',
   123:       'print_file_status',
   124:       'get_weaver',
   125:       'table_row', 'table_rule',
   126:       'item',
   127:       'include_file','include_source',
   128:       'include_code','insert_code','display_code',
   129:       'sink_verbatim','expand','define',
   130:       'include_html','html',
   131:       'capture_output','print_output',
   132:       'capture_python_output','print_python_output',
   133:       'print_python_test_output',
   134:       'set_weaver','get_weaver', 'push_weaver','pop_weaver',
   135:       'get_attribute',
   136:       'interscript_from_options',
   137:       'test_interscript',
   138:       'python','test_python',
   139:       'register_test','set_test_result',
   140:       'set_anchor','ref_anchor'
   141:       ]
   142:     for m in method_names:
   143:       exec 'self.userdict[m]=self.'+m
   144: 
   145:     # pass frame methods
   146:     method_names = [
   147:       'get_pass_frame'
   148:     ]
   149:     for m in method_names:
   150:       exec 'self.userdict[m]=self.pass_frame.'+m
   151: 
   152:     # processs frame methods
   153:     method_names = ['get_process_frame']
   154:     for m in method_names:
   155:       exec 'self.userdict[m]=self.process.'+m
   156: 
   157:     #master frame methods
   158:     method_names = ['get_master_frame']
   159:     for m in method_names:
   160:       exec 'self.userdict[m]=self.master.'+m
   161: 
   162:     #functions (non methods)
   163:     # NOTE: most functions are made available thru the global frame!
   164:     function_names = []
   165:     for f in function_names:
   166:       exec 'self.userdict[f]='+f
   167: 
End python section to interscript/frames/inputf.py[3]
6.13.10.1.2. close
Remove circular references.
Start python section to interscript/frames/inputf.py[4] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   168: #line 214 "input_frame.ipk"
   169:   def close(self):
   170:     if self.verbosity>=6:
   171:       print 'closing frame',self.source.name
   172:     del self.userdict
   173:     del self.current_tangler
   174:     del self.current_weaver
   175:     del self.reg_list
   176:     while self.current_tangler_stack: del self.current_tangler_stack[-1]
   177:     while self.current_weaver_stack: del self.current_weaver_stack[-1]
   178:     try: raise eoi
   179:     except: pass
   180: 
End python section to interscript/frames/inputf.py[4]
6.13.10.1.3. Process file data
Start python section to interscript/frames/inputf.py[5] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   181: #line 228 "input_frame.ipk"
   182:   def file_pass(self):
   183:     while 1:
   184:       try:
   185:         file,count,line = self.readline()
   186: 
   187:         echo = 0
   188:         if self.userdict.has_key('echo_input'):
   189:           echo = self.userdict['echo_input']
   190:         if self.verbosity>=6 or echo and self.verbosity!=0:
   191:           print '%s %6s: %s' % (file,count,line)
   192:         for r in self.reg_list:
   193:           match = r[0].match(line)
   194:           if match:
   195:             r[1](match,file,count,self.process.global_frame.__dict__,self.userdict)
   196:             break
   197:       except eoi:
   198:         if self.verbosity>=3: print 'EOI detected'
   199:         if self.verbosity>=4: print 'Poping input stack'
   200:         if self.current_tangler:
   201:           self.select(None)
   202:         self.close()
   203:         return
   204:       except KeyboardInterrupt:
   205:         print '!!!!!!!!! KEYBOARD INTERRUPT !!!!!!!!!'
   206:         self.process.update_files = 0
   207:         self.close()
   208:         raise KeyboardInterrupt
   209:       except SystemExit,value:
   210:         print '!!!!!!!!! SYSTEM EXIT !!!!!!!!!'
   211:         self.process.update_files = 0
   212:         self.close()
   213:         raise SystemExit,value
   214:       except:
   215:         if self.verbosity>=1:
   216:           print '!!!!!!!!! PROGRAM ERROR !!!!!!!!!'
   217:           traceback.print_exc()
   218:         self.process.update_files = 0
   219:         self.close()
   220:         sys.exit(1)
   221: 
End python section to interscript/frames/inputf.py[5]

6.13.10.2. Commands

6.13.10.2.1. Invoke interscript
This is a blocking call. Beware of side-effects. [Bug in current implementation].
6.13.10.2.1.1. Implementation
Start python section to interscript/frames/inputf.py[6] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   222: #line 275 "input_frame.ipk"
   223:   def interscript_from_options(self,*args):
   224:     from interscript  import run_from_options
   225:     svdin  = sys.stdin
   226:     try:
   227:       try:
   228:         run_from_options(args)
   229:       except KeyboardInterrupt: raise
   230:       except SystemExit: raise
   231:       except:
   232:         print 'Error running embedded interscript from options'
   233:         print 'options were', args
   234:         traceback.print_exc()
   235:     finally:
   236:       sys.stdin  = svdin
   237: 
   238:   # Note: this routine is ONLY useful for testing interscript itself,
   239:   # because it always puts the test code into the interscript directory!
   240:   # This needs to be fixed!!!
   241: 
   242:   def test_interscript(self, description, source_terminator, *args, **kwds):
   243:     testno = self.register_test(description, 'interscript')
   244:     testlabel = 'test_'+str(testno)
   245:     self.set_anchor(testlabel)
   246:     self.current_weaver.writeline(
   247:       'On-the-fly interscript for test '+str(testno)+' follows.')
   248:     source_origin_line = self.original_count
   249:     source_origin_file = self.original_filename
   250:     test_code = self.collect_lines_upto(source_terminator)
   251:     self.current_weaver.script_head('interscript',source_origin_file)
   252:     for i in range(len(test_code)):
   253:       self.current_weaver.echotangle(source_origin_line+i+1,test_code[i])
   254:     self.current_weaver.script_foot('interscript',source_origin_file)
   255: 
   256:     try:
   257:       os.mkdir('interscript/tests')
   258:     except:
   259:       pass
   260:     our_source_filename = 'interscript/tests/test_'+str(testno)+'.tpk'
   261:     f = open(our_source_filename,'w')
   262:     f.write(string.join(test_code,'\n')+'\n')
   263:     f.close()
   264: 
   265:     logfile='interscript/tests/output/test_'+str(testno)+'.log'
   266: 
   267:     kargs =  []
   268:     for key in kwds.keys():
   269:       if key not in ['description','source_terminator']:
   270:         kargs.append('--' + key + '=' + repr(kwds[key]))
   271: 
   272:     newargs = args + tuple(kargs) + (
   273:       '--weaver=html',
   274:       '--weaver-prefix=interscript/tests/output/',
   275:       '--new-logfile='+logfile,
   276:       '--title=Test '+str(testno)+': '+description,
   277:       our_source_filename)
   278:     apply(self.interscript_from_options, newargs)
   279:     self.set_test_result(testno,'inspect')
   280:     self.current_weaver.doc()
   281:     self.current_weaver.writeline('Test output at')
   282:     self.current_weaver.cite_url('../tests/output/test_'+str(testno)+'.html')
   283:     self.current_weaver.writeline('. Logfile at')
   284:     self.current_weaver.cite_url('../tests/output/test_'+str(testno)+'.log')
   285:     self.current_weaver.writeline('.')
   286:     self.current_weaver.par()
   287: 
End python section to interscript/frames/inputf.py[6]
6.13.10.2.1.2. Test
On-the-fly interscript for test 13 follows.
Start interscript section from input_frame.ipk
   342: @print 'running call test'
   343: @head(1,'Call test')
   344: This is a call test.
End interscript section from input_frame.ipk
Test output at ../tests/output/test_13.html. Logfile at ../tests/output/test_13.log.

6.13.10.2.2. Misc: move these
Start python section to interscript/frames/inputf.py[7] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   288: #line 349 "input_frame.ipk"
   289:   def get_attribute(self,name,default=None):
   290:     if self.userdict.has_key(name):
   291:       return self.userdict[name]
   292:     else:
   293:       return default
   294: 
End python section to interscript/frames/inputf.py[7]
6.13.10.2.3. begin/end blocks
The @begin() command creates a new scope, by pushing a new input_frame onto the input stack. The @end() command is used to end a @begin() block. An unbalanced @end() command can be used to terminate input from a file before the physical end of file.

Use of begin/end blocks is important to limit the lifetime of various objects. In particular, if a tangler is writing code to a named_file_sink, then the file will not be closed properly until it is destroyed.

Start python section to interscript/frames/inputf.py[8] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   295: #line 367 "input_frame.ipk"
   296:   def begin(self):
   297:     ho = self.head_offset
   298:     self.select(None)
   299:     inpt = input_frame(
   300:       self.pass_frame,
   301:       self.source,
   302:       [],
   303:       self.current_weaver,
   304:       self.userdict.copy(),
   305:       self.depth)
   306:     inpt.head_offset = ho
   307:     inpt.set_warning_character(python=self.python_warn)
   308:     inpt.file_pass()
   309: 
   310:   def end(self):
   311:     self.select(None)
   312:     raise eoi
   313: 
End python section to interscript/frames/inputf.py[8]
6.13.10.2.3.1. Begin/end test
Start data section to interscript/tests/test_beginend.pak[1] 1
     1: @head(1,'Begin/End test')
     2: We test the @begin and @end commands with a simple scoping test.
     3: First, a level is set to 1, and we create a class with
     4: a destructor and an object thereof.
     5: @class X:
     6:    def __init__(self, level, weaver):
     7:      self.level = level
     8:      self.current_weaver = weaver
     9:    def __del__(self):
    10:      self.current_weaver.writeline('X object of level '+str(self.level)+' destroyed.')
    11:  level=1
    12:  x = X(level, get_weaver())
    13: @weave('Level is '+str(level)+'. ')
    14: @p()
    15: Now, a new block.
    16: @begin()
    17: Check old value of level.
    18: @weave('Level is '+str(level)+'. ')
    19: Now set level to 2, and create another class object.
    20: @level = 2
    21: @x = X(level,get_weaver())
    22: @weave('Level is '+str(level)+'. ')
    23: @p()
    24: Finally we end the block here. This should kill the inner class object.
    25: @end()
    26: @p()
    27: Back in the old block we test the level.
    28: @weave('Level is '+str(level)+'. ')
    29: That's the simple test. Now, the outer class object should die.
End data section to interscript/tests/test_beginend.pak[1]
We can look at the html results at ../tests/test_beginend.html
6.13.10.2.4. Include file/source
The include file command is a subroutine call. It pushes a new input frame associated with the file, causing input to be read from the file. The new input frame has a copy of the user dictionary from the calling frame. When the file ends, the frame is popped which destroys the dictionary; all newly created symbols are lost.

The new input frame does not inherit the parent frames lexicology. In particular, the warning character is restablished as @. This command reasserts document mode, both in the included file and the current one.

The command include_source is a generalisation of include_file which takes any source driver as the input.

Start python section to interscript/frames/inputf.py[9] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   314: #line 438 "input_frame.ipk"
   315:   def include_file(self,name):
   316:     if self.verbosity>=2:
   317:       print 'input from',name
   318:     self.pass_frame.include_files.append((self.depth+1,'interscript',name))
   319:     self.include_source(named_file_source(
   320:       self.pass_frame,name, self.source.directory))
   321: 
   322:   def include_source(self,source):
   323:     self.select(None)
   324:     ho = self.head_offset
   325:     inpt = input_frame(
   326:       self.pass_frame,
   327:       source,
   328:       [],
   329:       self.current_weaver,
   330:       self.userdict.copy(),
   331:       self.depth+1)
   332:     inpt.head_offset = ho
   333:     inpt.set_warning_character(python='@')
   334:     inpt.file_pass()
   335:     self.current_weaver.set_original_filename (self.original_filename)
   336: 
End python section to interscript/frames/inputf.py[9]
6.13.10.2.5. Include/insert code
The @insert_code command inserts a code file into the input stream of the current tangler. It is used to yank code fragments from external files.

The external file can contain any data, all of which is interpreted as literal program code: lines beginning with @, for example, will not be processed as commands.

Note that the file is not written directly to the tangler's sink driver, it is written to the tangler. Therefore, if the code contains embedded documentation constructions in a form the tangler understands, documentation can still be woven. For example if a Perl module containing POD constructions is imported, a perl_tangler will still recognize these constructions and send appropriate documentation commens to its associated weaver.

The @include_code command is the same as the @insert_code command except that the tangler is passed as an argument, rather than the current tangler being used.

Start python section to interscript/frames/inputf.py[10] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   337: #line 482 "input_frame.ipk"
   338:   def insert_code(self,name):
   339:     ifdata = (self.depth+1,'code: '+self.current_tangler.language,name)
   340:     self.pass_frame.include_files.append(ifdata)
   341:     r = []
   342:     source = named_file_source(self.pass_frame,name, self.source.directory)
   343:     inpt = input_frame(
   344:       self.pass_frame,
   345:       source,
   346:       r,
   347:       self.current_weaver,
   348:       self.userdict.copy(),
   349:       self.depth+1)
   350:     r.append([inpt.any_line_re, inpt.do_web])
   351:     inpt.select(self.current_tangler)
   352:     inpt.file_pass()
   353: 
   354:   def include_code(self,name,current_tangler):
   355:     ifdata = (self.depth+1,'code: '+self.current_tangler.language,name)
   356:     self.pass_frame.include_files.append(ifdata)
   357:     r = []
   358:     source = named_file_source(
   359:       self.pass_frame,
   360:       name,
   361:       self.source.directory)
   362:     inpt = input_frame(
   363:       self.pass_frame,
   364:       source,
   365:       r,
   366:       self.current_weaver,
   367:       self.userdict.copy(),
   368:       self.depth+1)
   369:     r.append([inpt.any_line_re, inpt.do_web])
   370:     inpt.select(tangler)
   371:     inpt.file_pass()
   372: 
   373:   def sink_verbatim(self,filename):
   374:     self.current_weaver.label_chunk(filename)
   375:     source = named_file_source(
   376:         self.pass_frame,
   377:         filename,
   378:         self.source.directory)
   379:     data = source.readlines()
   380:     self.current_tangler.sink.writelines(data)
   381: 
   382:   def define(self, macroname, language='data'):
   383:     self.select(self.output(cache_sink(macroname, self.master), language))
   384: 
   385:   def expand(self,macroname):
   386:     self.current_weaver.label_chunk(macroname)
   387:     source = cache_source(macroname, self.master)
   388:     data = source.readlines()
   389:     self.current_tangler.sink.writelines(data)
   390: 
On-the-fly interscript for test 14 follows.
Start interscript section from input_frame.ipk
   536: @head(1,'The main program')
   537: This code includes and external file, chunk.tmp, defining
   538: the body of function f.
   539: You should see the #line directive for it on line 3.
   540: @select(tangler('chunked.tmp','python'))
   541: def f():
   542: @insert_code('chunk.tmp')
   543: def g(): pass
   544: def h():
   545: @sink_verbatim('chunk.tmp')
   546: def k(): pass
   547: @head(1,'The included chunk')
   548: Here's the included chunk, defined after use.
   549: @select(tangler('chunk.tmp','python'))
   550:   pass
   551: @doc()
   552: End example.
   553: @print_source_list(1)
   554: @print_include_list(1)
End interscript section from input_frame.ipk
Test output at ../tests/output/test_14.html. Logfile at ../tests/output/test_14.log.

   391: #line 556 "input_frame.ipk"
   392: 
End python section to interscript/frames/inputf.py[10]
6.13.10.2.6. Include html
The @html and @include_html commands switch the input parser from raw interscript to a small subset of HTML. The parser maps tags to calls to interscript commands. For example, <B> is translated to call the bold() command.

Python script can be included in the html using the tags <SCRIPT LANGUAGE="python"> .. </SCRIPT> At present, the translator has even less features than interscript: it's only a stub for a more full scale translator.

The @html() command is similar, except it takes html data from the current input source.

In both cases, </HTML> terminates HTML parsing.

Start python section to interscript/frames/inputf.py[11] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   393: #line 573 "input_frame.ipk"
   394:   def include_html(source):
   395:     self.select(None)
   396:     r = []
   397:     self.pass_frame.include_files.append((self.depth+1,'html: '+self.current_tangler.language,name))
   398:     inpt = input_frame(
   399:       self.pass_frame,
   400:       source,
   401:       r,
   402:       self.current_weaver,
   403:       self.userdict.copy(),
   404:       self.depth+1)
   405:     inpt.html_parser = sgml_wrapper(html_filter(inpt))
   406:     r.append((inpt.any_line_re,inpt.do_html))
   407:     inpt.file_pass()
   408: 
   409:   def html(self):
   410:     self.select(None)
   411:     r = []
   412:     inpt = input_frame(
   413:       self.pass_frame,
   414:       self.source,
   415:       r,
   416:       self.current_weaver,
   417:       self.userdict.copy(),
   418:       self.depth)
   419:     inpt.html_parser = sgml_wrapper(html_filter(inpt))
   420:     r.append((inpt.any_line_re,inpt.do_html))
   421:     inpt.file_pass()
   422: 
   423: 
   424: 
End python section to interscript/frames/inputf.py[11]
6.13.10.2.7. Verbosity
Start python section to interscript/frames/inputf.py[12] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   425: #line 606 "input_frame.ipk"
   426:   def get_verbosity(self):
   427:     if self.userdict.has_key('verbosity'):
   428:       return self.userdict['verbosity']
   429:     return self.verbosity
   430: 
End python section to interscript/frames/inputf.py[12]
6.13.10.2.8. Weaver Control
Start python section to interscript/frames/inputf.py[13] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   431: #line 613 "input_frame.ipk"
   432:   def get_weaver(self):
   433:     return self.current_weaver
   434: 
   435:   def set_weaver(self,w):
   436:     tmp = self.current_weaver
   437:     self.current_weaver = w
   438:     return tmp
   439: 
   440:   def push_weaver(self,w):
   441:     self.current_weaver_stack.append(self.current_weaver)
   442:     self.current_weaver = w
   443: 
   444:   def pop_weaver(self):
   445:     self.current_weaver = self.current_weaver_stack[-1]
   446:     del self.current_weaver_stack[-1]
   447: 
End python section to interscript/frames/inputf.py[13]
6.13.10.2.9. Anchors
Start python section to interscript/frames/inputf.py[14] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   448: #line 631 "input_frame.ipk"
   449:   def set_anchor(self,label):
   450:     if self.current_tangler:
   451:       self.current_tangler.weaver.set_anchor(label)
   452:     else:
   453:       self.current_weaver.set_anchor(label)
   454: 
   455:   def ref_anchor(self,label):
   456:     self.current_weaver.ref_anchor(label)
   457: 
End python section to interscript/frames/inputf.py[14]
6.13.10.2.10. Parsing
Start python section to interscript/frames/inputf.py[15] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   458: #line 642 "input_frame.ipk"
   459:   def set_warning_character(self,python=None):
   460:     res = self.make_parse_tab(pywarn=python)
   461:     res = compile_parse_tab(res)
   462:     self.reg_list = res
   463:     self.python_warn = python
   464: 
   465:   def normal_line(self,data,file,count):
   466:     weaver = self.get_weaver()
   467:     if self.current_tangler:
   468:       self.current_tangler.writeline(data,file,count)
   469:     else:
   470:       weaver.writeline(data)
   471: 
End python section to interscript/frames/inputf.py[15]
6.13.10.2.11. Input functions
These are private functions used to actually perform input from the input_frame source driver.
Start python section to interscript/frames/inputf.py[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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   472: #line 659 "input_frame.ipk"
   473:   def enqueue_input(self,file, count, line):
   474:     self.read_buffer.append((file,count,line))
   475: 
   476:   def dequeue_input(self):
   477:     data = self.read_buffer[0]
   478:     del self.read_buffer[0]
   479:     return data
   480: 
   481:   # This is the interscript version of a #line directive
   482:   def line(self, number, filename):
   483:     self.inpt.original_file = filename
   484:     self.inpt.line_offset = number - inpt.src.get_lines_read()
   485: 
   486:   def readline(self):
   487:     while 1:
   488:       if self.read_buffer:
   489:         return self.dequeue_input()
   490:       try:
   491:         line = self.source.readline()
   492:         self.real_filename = self.source.get_source_name()
   493:         self.real_count = self.source.get_lines_read()
   494:         self.original_count = self.real_count + self.line_offset
   495:         line = string.rstrip(line)
   496:         self.line = string.expandtabs(line,self.tabwidth)
   497:         return (self.original_filename,self.original_count,self.line)
   498:       except KeyboardInterrupt:
   499:         # should inhibit output for process, not globally
   500:         self.process.update_files = 0
   501:         raise KeyboardInterrupt
   502:       except eof:
   503:         if self.verbosity>=4:
   504:           print 'readline: EOF'
   505:         self.line = None
   506:         raise eoi
   507:       else:
   508:         if self.process.verbosity>=1:
   509:           print 'program error in readline:',sys.exc_info()
   510:         self.process.update_files = 0
   511: 
End python section to interscript/frames/inputf.py[16]
6.13.10.2.12. Untangle
This command is used inside an interscript tangler to put an external file into a .pak archive. It writes out a 'select' (see select) command, and then the file, with leading @ characters converted to two @ characters. Use it like this:
  @select(archive)
  @untangle('fred.pak')
  @untangle('joe.pak')
This mechanism is required to support include files, since a top level document is incomplete otherwise.

Note that the inserted code is not woven! In fact, the tangler never sees it, it simply supplies the sink object.

Start python section to interscript/frames/inputf.py[17] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   512: #line 718 "input_frame.ipk"
   513:   def untangle(self,name):
   514:     if not self.current_tangler:
   515:       raise 'untangle without active tangler'
   516:     f = open(name)
   517:     data = f.readlines()
   518:     f.close()
   519:     self.current_tangler.sink.writeline('@select(output("'+name+'"))')
   520:     for line in data:
   521:       l = string.rstrip(line)
   522:       if len(l):
   523:         if l[0]=='@': l = '@'+l
   524:       self.inpt.tangler.sink.writeline(l)
   525:     self.current_tangler.sink.writeline('@select(None)')
   526:     self.current_tangler.weaver.begin_small()
   527:     self.current_tangler.weaver.writeline('Included '+name+', '+str(len(data))+' lines.')
   528:     self.current_tangler.weaver.end_small()
   529:     self.current_tangler.weaver.line_break()
   530: 
End python section to interscript/frames/inputf.py[17]
6.13.10.2.13. Parser functions
These function actually execute script.

For example, these methods control the disposition of the log. This requires switching the sys.stdout and/or sys.stdlog object.

Similarly, these routines determine the disposition of keyboard interrupts, which normally terminate the whole process. It may be necessary to terminate master documents threads.

Finally, these routines will permits synchronisation of delayed file updates: in a 'commit/rollback' scenario, only the process frame has enough information to permit or deny updates which may depend on all threads elaborating their client documents correctly.

Note that the verbosity level used here is not the same as the master or pass frame verbosity: even if these values are changed by the user document, debugging script execution is determined by the process level verbosity setting. This is necessary so user level document debugging does not interfere with interscript developer debugging.

Other features controlled at the process level include the use of threads, the availability of a GUI, etc.

6.13.10.2.13.1. Utilities
Python is announced by a single @. If the line ends in a : (or some others) the script continues to the first line with a non-space in column 1. The first space is remove from each continuation line.

Tcl is announced by a single !. If the line ends in {, or with a \, then the script is continued as for Python.

In both cases, the head line can have spaces or a # initiated comment afterwards and still be detected: for Tcl, neither is permitted after a slosh and will generate a Tcl error.

Start python section to interscript/frames/inputf.py[18] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   531: #line 778 "input_frame.ipk"
   532: # regexp's for the main functions
   533: 
   534:   def make_parse_tab(self, pywarn = None):
   535:     res = []
   536:     if pywarn:
   537:       res = res + [
   538:         ['^'+pywarn+'('+pywarn+')(.*)$',self.do_quote_at],
   539:         ['^'+pywarn+'(.*[-+*/%:,\([{]) *(#.*)?$', self.do_exec_suite],
   540:         ['^'+pywarn+'(.*)$',self.do_exec_line]
   541:         ]
   542: 
   543: 
   544:     res = res + [
   545:       ['^(.*)$',self.do_web]
   546:       ]
   547:     return res
   548: 
End python section to interscript/frames/inputf.py[18]
6.13.10.2.14. Collect stuff
This command reads ahead in the input until a line is found that does not match the supplied continuation pattern. It then returns all the input lines as a single string. It can be used to drive user defined parser objects, which process the returned string.

For example, the built-in python suite processes uses this function to collect a multiline python suite before executing it.

Start python section to interscript/frames/inputf.py[19] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   549: #line 805 "input_frame.ipk"
   550:   def collect_stuff(self,prefix, cont_re, echo):
   551:     saved = prefix
   552:     try:
   553:       file2,count2,line = self.readline()
   554:       match = cont_re.match(line)
   555:       while match:
   556:         if echo:
   557:           print '%s %6s: %s' % (file2,count2,line)
   558:         body = match.group(1)
   559:         if not body: body = ''
   560:         saved = saved+'\n'+body
   561:         file2,count2,line = self.readline()
   562:         match = cont_re.match(line)
   563:       self.enqueue_input(file2,count2,line)
   564:     except eoi:
   565:       pass
   566:     saved = saved + '\n'
   567:     return saved
   568: 
   569:   def collect_lines_upto(self,terminal):
   570:     term_re = re.compile('^'+terminal+'$')
   571:     saved = []
   572:     file,count,line = self.readline()
   573:     match = term_re.match(line)
   574:     while not match:
   575:       saved.append(line)
   576:       file,count,line = self.readline()
   577:       match = term_re.match(line)
   578:     return saved
   579: 
   580:   def collect_upto(self,terminal):
   581:     return string.join(self.collect_lines_upto(terminal), '\n')+'\n'
   582: 
End python section to interscript/frames/inputf.py[19]
6.13.10.2.15. Execute collected python
Start python section to interscript/frames/inputf.py[20] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   583: #line 840 "input_frame.ipk"
   584:   def python(self, terminal='@end_python'):
   585:     file = self.original_filename
   586:     count = self.original_count
   587:     glb = self.global_frame.__dict__
   588:     user = self.userdict
   589:     data = self.collect_upto(terminal)
   590:     self.process.py_exec(data,file,count,glb,user)
   591: 
End python section to interscript/frames/inputf.py[20]
6.13.10.2.15.1. Test python function
Woven from embedded python script.
6.13.10.2.15.2. Print diff table
Print out a diff table with side by side comparison of files. Requires the diff module. No table is generated if the files compare equal.
Start python section to interscript/frames/inputf.py[21] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   592: #line 860 "input_frame.ipk"
   593:   def print_diff_table(self, comparison,
   594:     actual_heading='Actual', expected_heading='Expected',
   595:     ok_message='Data compared equal.',
   596:     diff_message='Differential follows.'):
   597: 
   598:     equal = len(comparison) == 0
   599:     our_weaver = self.get_weaver()
   600:     if not equal:
   601:       if diff_message:
   602:         our_weaver.writeline(diff_message)
   603:       our_weaver.begin_table('Actual','Expected', CLASS='DIFF')
   604:       for section in comparison:
   605:         left = section[0][1:]
   606:         right = section[1][1:]
   607:         left = string.join(left,'\n')
   608:         right = string.join(right,'\n')
   609:         our_weaver.table_row([left, right])
   610:       our_weaver.end_table()
   611:     else:
   612:       if ok_message:
   613:         our_weaver.writeline(ok_message)
   614: 
End python section to interscript/frames/inputf.py[21]
6.13.10.2.16. Register Test
Start python section to interscript/frames/inputf.py[22] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   615: #line 884 "input_frame.ipk"
   616:   def register_test(self, description, kind):
   617:     testno = self.pass_frame.get_new_test_number()
   618:     testlabel = 'test_'+str(testno)
   619:     self.pass_frame.tests[testno]=\
   620:       [description,testlabel,kind,'Aborted']
   621:     return testno
   622: 
   623:   def set_test_result(self, testno, result):
   624:     self.pass_frame.tests[testno][3]=result
   625: 
End python section to interscript/frames/inputf.py[22]
6.13.10.2.17. Python Test
Start python section to interscript/frames/inputf.py[23] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   626: #line 896 "input_frame.ipk"
   627:   def test_python(self,
   628:     hlevel=None,
   629:     descr=None,
   630:     source_filename=None,
   631:     source_terminator=None,
   632:     expect_filename=None,
   633:     expect_terminator=None,
   634:     diff_context=0):
   635: 
   636:     testno = self.pass_frame.get_new_test_number()
   637:     testlabel = 'test_'+str(testno)
   638:     test_record = self.pass_frame.tests[testno]=\
   639:       [descr,testlabel,'python','Aborted']
   640:     expect = expect_filename or expect_terminator
   641: 
   642:     # print heading
   643:     if hlevel: our_hlevel = hlevel
   644:     else: our_hlevel = self.last_head+1
   645:     if descr == None: descr = 'Test'
   646:     self.head(our_hlevel,'Test '+str(testno)+': '+descr)
   647:     self.set_anchor(testlabel)
   648: 
   649:     our_weaver = self.get_weaver()
   650: 
   651:     if source_terminator:
   652:       our_weaver.writeline('On-the-fly python test script follows.')
   653:       source_origin_line = self.original_count
   654:       source_origin_file = self.original_filename
   655:       test_code = self.collect_lines_upto(source_terminator)
   656:       our_weaver.script_head('python',source_origin_file)
   657:       for i in range(len(test_code)):
   658:         our_weaver.echotangle(source_origin_line+i+1,test_code[i])
   659:       our_weaver.script_foot('python',source_origin_file)
   660:     elif source_filename:
   661:       our_weaver.writeline('Python test script from file '+source_filename+'.')
   662: 
   663:     if expect_terminator:
   664:       expected_origin_line = self.original_count
   665:       expected_origin_file = self.original_filename
   666:       expected_output = self.collect_lines_upto(expect_terminator)
   667:     elif expect_filename:
   668:       # FIX to make document relative
   669:       our_weaver.writeline('Expected output from file '+expected_filename+'.')
   670:       expected_lines = loadfile(expect_filename)
   671: 
   672:     # execute the test code
   673: 
   674:     if source_filename:
   675:       our_source_filename = source_filename
   676:       description = None
   677:     else:
   678:       our_source_filebase = tempfile.mktemp()
   679:       our_source_filename = our_source_filebase + '_test.py'
   680:       f = open(our_source_filename,'w')
   681:       f.write(string.join(test_code,'\n')+'\n')
   682:       f.close()
   683:       description = 'python <<temporary>>'
   684:     our_weaver.writeline('Actual output follows.')
   685: 
   686:     status, actual_output = self.print_python_output(
   687:       our_source_filename,
   688:       description)
   689:     cmd_ok = status == 0
   690: 
   691:     # delete the file if it was created anonymously
   692:     if not source_filename:
   693:       os.remove(our_source_filename)
   694: 
   695:     if expect:
   696:       try:
   697:         diff_lines = interscript.utilities.diff.diff_lines
   698:         comparison = diff_lines(actual_output, expected_output, context=diff_context)
   699:         equal = len(comparison)==0
   700:         self.pass_frame.tests[testno][2]= 'diff'
   701:         self.pass_frame.tests[testno][3]= ('Fail','Ok')[equal]
   702:         if not equal:
   703:           our_weaver.writeline('On-the-fly expected output follows.')
   704:           our_weaver.expected_head(expected_origin_file)
   705:           for i in range(len(expected_output)):
   706:             our_weaver.echotangle(expected_origin_line+i+1,expected_output[i])
   707:           our_weaver.expected_foot(expected_origin_file)
   708:           self.print_diff_table(comparison)
   709:       except ImportError:
   710:         our_weaver.writeline('Unable to import diff to perform comparison.')
   711:       except KeyboardInterrupt: raise
   712:       except SystemExit: raise
   713:       except:
   714:         traceback.print_exc()
   715:     else:
   716:       self.pass_frame.tests[testno][3]='Inspect'
   717: 
End python section to interscript/frames/inputf.py[23]
6.13.10.2.17.1. Test 15: Python test test
On-the-fly python test script follows.
Start python section from input_frame.ipk
   988: print 'Hello from python test function test.'
   989: print 'Hello again from python test function test.'
End python section from input_frame.ipk
Actual output follows.
Start output section of python <>
     1: Hello from python test function test.
     2: Hello again from python test function test.
End output section to python <>
6.13.10.2.17.2. Test 16: Python diff test
On-the-fly python test script follows.
Start python section from input_frame.ipk
   993: print 'Hello from python diff function test.'
   994: print 'Hello again from python diff function test.'
End python section from input_frame.ipk
Actual output follows.
Start output section of python <>
     1: Hello from python diff function test.
     2: Hello again from python diff function test.
End output section to python <>
On-the-fly expected output follows.
Start expected section of input_frame.ipk
   996: Hello from python diff function test.
   997: Hello error from python diff function test.
End expected section to input_frame.ipk
Differential follows.
ActualExpected
2:! Hello again from python diff function test.
2:! Hello error from python diff function test.
6.13.10.2.18. Match Processing functions
These commands process match objects which the parser has construted while scanning the parser table trying to match the input string.
6.13.10.2.18.1. Single Line Python Script
Start python section to interscript/frames/inputf.py[24] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   718: #line 1006 "input_frame.ipk"
   719:   def do_exec_line(self,match, file,count,glb,user):
   720:     self.process.py_exec(match.group(1),file,count,glb,user)
   721: 
End python section to interscript/frames/inputf.py[24]
6.13.10.2.18.2. Multi-Line Python Script
Start python section to interscript/frames/inputf.py[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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   722: #line 1011 "input_frame.ipk"
   723:   def do_exec_suite(self,match,file,count,glb,user):
   724:     saved = self.collect_stuff(match.group(1), self.cont_re, user['echo_input'])
   725:     self.process.py_exec(saved,file,count,glb,user)
   726: 
End python section to interscript/frames/inputf.py[25]
6.13.10.2.18.3. Ordinary Text
Start python section to interscript/frames/inputf.py[26] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   727: #line 1017 "input_frame.ipk"
   728:   def do_web(self,match,file,count,glb,user):
   729:     self.normal_line(match.group(1),file,count)
   730: 
End python section to interscript/frames/inputf.py[26]
6.13.10.2.18.4. Doubled Warning character
Start python section to interscript/frames/inputf.py[27] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   731: #line 1022 "input_frame.ipk"
   732:   def do_quote_at(self,match,file,count,glb,user):
   733:     self.normal_line(match.group(1)+match.group(2),file,count)
   734: 
End python section to interscript/frames/inputf.py[27]
6.13.10.2.18.5. Html input
Start python section to interscript/frames/inputf.py[28] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   735: #line 1027 "input_frame.ipk"
   736:   def do_html(self,match,file,count,glb,user):
   737:     self.html_parser.writeline(match.group(1),file,count)
   738: 
End python section to interscript/frames/inputf.py[28]
6.13.10.2.19. The Tangler Stack
Interscript supports stacking of tanglers. The internal commands tangler_push, and tangler_pop push and pop the stack, while tangler_set changes the top of the stack.

These operations call the start and end section methods of the tangler objects as they become, or cease to become, the current tangler, this ensures correct source file references are inserted into the code files.

Start python section to interscript/frames/inputf.py[29] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   739: #line 1040 "input_frame.ipk"
   740:   def tangler_push(self,f):
   741:     self.current_tangler_stack.append(self.current_tangler)
   742:     self.current_tangler = f
   743: 
   744:   def tangler_pop(self):
   745:     self.current_tangler = self.current_tangler_stack[-1]
   746:     del self.current_tangler_stack[-1]
   747: 
   748:   def tangler_set(self,f):
   749:     self.current_tangler = f
   750: 
   751:   def get_tangler(self):
   752:     return self.current_tangler
   753: 
End python section to interscript/frames/inputf.py[29]
6.13.10.2.20. Tangler Constructors
These are convenience functions that construct tanglers and associated sinks. The argument is a filename which is used to construct a sink to which the tangler is linked. The tanglers are linked to the current weaver.
Start python section to interscript/frames/inputf.py[30] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   754: #line 1060 "input_frame.ipk"
   755:   def data_output(self,f): return self.tangler(f,'data')
   756:   def c_output(self,f): return self.tangler(f,'c')
   757:   def cpp_output(self,f): return self.tangler(f,'cpp')
   758:   def python_output(self,f): return self.tangler(f,'python')
   759:   def perl_output(self,f): return self.tangler(f,'perl')
   760: 
   761:   # temporarily, we'll use a data tangler
   762:   def interscript_output(self,f):
   763:     filename = self.master.tangler_directory+f
   764:     sink = named_file_sink(self.pass_frame,filename,self.master.tangler_prefix)
   765:     return data_tangler(sink,self.get_weaver())
   766: 
   767:   def tangler(self,device, language=deduce):
   768:     if has_protocol(device, 'string'):
   769:       filename = self.master.tangler_directory+device
   770:       sink = named_file_sink(
   771:         self.pass_frame,
   772:         filename,
   773:         self.master.tangler_prefix)
   774:     elif has_protocol(device, 'sink'):
   775:       sink = device
   776:     else: raise TypeError,'tangler device argument must be string or sink'
   777: 
   778:     if language is None: language = 'data'
   779:     if language is deduce:
   780:       try:
   781:         splitup = string.split(sink.name,'.')
   782:         if len(splitup)>1:
   783:           extension = splitup[-1]
   784:           language = extension_table [extension]
   785:         else: language = 'data'
   786:       except KeyError: language = 'data'
   787:       except IndexError: language = 'data'
   788:     language = string.lower(language)
   789:     language = string.replace(language,'++','pp') # C++ hack
   790:     language = string.replace(language,'-','_') # obj-C etc
   791:     cmd = 't='+language+'_tangler(sink,self.current_weaver)'
   792:     exec cmd
   793:     return t
   794: 
End python section to interscript/frames/inputf.py[30]
6.13.10.2.21. Managing the tangler stack
These commands also push, pop, and set the tangler stack, but they also generate start and end section messages in the documentation file. They are intended for use by the end user.

Pushing and popping the stack is useful, for example, to temporarily write a C function declaration to the header file just before it is defined. (In fact, Interscript has some special case functionality to support this while avoiding writing the function signature twice.)

The begin and end comments functions push and pop the tangler stack, the push comments function pushes the comment tangler associated withe the current tangler (if there is a current tangler, otherwise it pushes None. The comment tangler associated with the current tangler could also be, and is by default, None.)

Note that the begin and end comments functions invoke the internal push and pop functions; that is, they do not write begin and end section messages to the documentation file. That's because the comments are actually written to the code file, they're just formatted by the weaver like documentation rather than code.

Design note: There is always a current tangler object, possibly None. Interscript knows it is writing code, except when the current tangler is None, in which case it is writing documentation. I'm not so sure this is a wonderful scheme :-(

The begin and end string functions write the enclosed lines to the code file formatted as a (single) string. The resultant output is echoed to the documentation file.

The begin and end string functions reformat the enclosed lines as a single string in the target programming language. In C, for example, special character such as slosh are replaced by two sloshes. (Note that a leading @ can be included only by writing @@).

The begin string function supports two optional arguments. The eol argument determines what to insert at the end of a line, it will usually be either an empty string, a newline character sequence, or a single space.

Trailing whitespace is removed from each line. It is not possible to disable this feature, and that is deliberate. However, a second argument, width, if positive, will then pad the line to the specified width with spaces. This feature is designed to support two dimensional character arrays.

Design note: there is as yet not support for international character sets.

Start python section to interscript/frames/inputf.py[31] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   795: #line 1151 "input_frame.ipk"
   796:   def push(self,f):
   797:     if self.current_tangler: self.code_foot()
   798:     self.current_tangler_push(f)
   799:     if self.current_tangler: self.code_head()
   800: 
   801:   def pop(self):
   802:     if self.current_tangler: self.code_foot()
   803:     self.current_tangler_pop()
   804:     if self.current_tangler: self.code_head()
   805: 
   806: #line 1162 "input_frame.ipk"
   807:   def select(self, *args, **kwds):
   808:     for arg in args:
   809:       self.select1(arg)
   810:     if kwds.has_key('tangler'):
   811:       self.select_tangler(kwds['tangler'])
   812:     if kwds.has_key('weaver'):
   813:       self.set_weaver(kwds['weaver'])
   814: 
   815:   def select1(self, arg):
   816:     if has_protocol(arg,'tangler'):
   817:       self.select_tangler(arg)
   818:     elif has_protocol(arg, 'weaver'):
   819:       self.set_weaver(arg)
   820:     else:
   821:       pass #permissive
   822: 
   823:   def select_tangler(self,f):
   824:     if self.current_tangler: self.code_foot()
   825:     self.tangler_set(f)
   826:     if self.current_tangler: self.code_head()
   827: 
   828:   def code_head(self):
   829:     dst_filename = self.current_tangler.sink.name
   830:     dst_lineno = self.current_tangler.sink.lines_written
   831:     src_filename = self.original_filename
   832:     src_lineno = self.original_count
   833: 
   834:     index = self.pass_frame.section_index
   835:     list = index.get(dst_filename, [])
   836:     list.append((dst_lineno, src_filename, src_lineno))
   837:     index[dst_filename]=list
   838:     secno = len(list)
   839:     self.current_weaver.code_head(self.current_tangler, secno)
   840: 
   841:   def code_foot(self):
   842:     dst_filename = self.current_tangler.sink.name
   843:     index = self.pass_frame.section_index
   844:     list = index.get(dst_filename, [])
   845:     secno = len(list)
   846:     self.current_weaver.code_foot(self.current_tangler, secno)
   847: 
   848:   def begin_comments(self):
   849:     if self.current_tangler:
   850:       self.current_tangler_push(self.current_tangler.get_comment_tangler())
   851:     else:
   852:       self.current_tangler_push(None)
   853: 
   854:   def end_comments(self):
   855:     self.current_tangler_pop()
   856: 
   857:   def resume_code(self):
   858:     self.current_tangler_pop()
   859: 
   860:   def comment(self,v):
   861:     self.get_weaver().write_comment(v)
   862: 
   863:   def begin_string(self,eol = ' ', width = 0):
   864:     if self.current_tangler:
   865:       self.current_tangler_push(self.current_tangler.get_string_tangler(eol,width))
   866:     else:
   867:       self.current_tangler_push(None)
   868: 
   869:   def end_string(self):
   870:     tangler_pop()
   871: 
   872:   def weave(self,s):
   873:     weaver = self.get_weaver()
   874:     weaver.write(s)
   875: 
   876:   def weave_line(self,s):
   877:     weaver = self.get_weaver()
   878:     weaver.writeline(s)
   879: 
   880:   def tangle(self,s, inhibit_sref=0):
   881:     if self.current_tangler:
   882:       line = self.original_count
   883:       file = self.original_filename
   884:       self.current_tangler.writeline(s,file,line,inhibit_sref)
   885:     else:
   886:       print "tangle: No tangler for",s
   887: 
End python section to interscript/frames/inputf.py[31]
6.13.10.2.22. Miscellaneous
The usual stuff that is hard to classify.
Start python section to interscript/frames/inputf.py[32] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   888: #line 1246 "input_frame.ipk"
   889:   def print_contents(self,*args, **kwds):
   890:     self.select(None)
   891:     weaver = self.get_weaver()
   892:     apply(weaver.print_contents, args, kwds)
   893: 
   894:   def print_file_list(self,*args,**kwds):
   895:     self.select(None)
   896:     weaver = self.get_weaver()
   897:     apply(weaver.print_file_list, args, kwds)
   898: 
   899:   def print_file_status(self,*args,**kwds):
   900:     self.select(None)
   901:     weaver = self.get_weaver()
   902:     apply(weaver.print_file_status, args, kwds)
   903: 
   904:   def print_source_list(self, *args, **kwds):
   905:     self.select(None)
   906:     weaver = self.get_weaver()
   907:     apply(weaver.print_source_list, args, kwds)
   908: 
   909:   def print_include_list(self, *args, **kwds):
   910:     self.select(None)
   911:     weaver = self.get_weaver()
   912:     apply(weaver.print_include_list, args, kwds)
   913: 
   914:   def macro(self,name):
   915:     self.select(None)
   916:     weaver = self.get_weaver()
   917:     return data_tangler(memory(name),weaver)
   918: 
   919:   def print_identifier_cross_reference(self, *args, **kwds):
   920:     self.select(None)
   921:     weaver = self.get_weaver()
   922:     apply(weaver.identifier_reference, args, kwds)
   923: 
   924:   def print_class_reference(self, *args, **kwds):
   925:     self.select(None)
   926:     weaver = self.get_weaver()
   927:     apply(weaver.class_reference, args, kwds)
   928: 
End python section to interscript/frames/inputf.py[32]
6.13.10.2.23. Capture command output
This is unix dependent at present.
Start python section to interscript/frames/inputf.py[33] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   929: #line 1289 "input_frame.ipk"
   930:   def capture_output(self,command):
   931:     commands = self.global_frame.commands
   932:     status, output = commands.getstatusoutput(command)
   933:     data = string.split(output,'\n')
   934:     return (status,data)
   935: 
   936:   def print_output(self,command,description=None):
   937:     status, data = self.capture_output(command)
   938:     weaver = self.get_weaver()
   939:     if description: cmd = description
   940:     else: cmd = command
   941:     weaver.test_output_head(cmd, status)
   942:     for i in range(len(data)):
   943:       line = data[i]
   944:       l = string.rstrip(line)
   945:       weaver.echotangle(i+1,l)
   946:     weaver.test_output_foot(cmd, status)
   947:     return (status, data)
   948: 
   949:   def capture_python_output(self,script):
   950:     return self.capture_output('"'+sys.executable+'" '+script)
   951: 
   952:   def print_python_output(self,script, description=None):
   953:     return self.print_output(
   954:       '"'+sys.executable+'" '+script,
   955:       description)
   956: 
   957:   def print_python_test_output(self,script, descr):
   958:     testno = self.pass_frame.get_new_test_number()
   959:     testlabel = 'test_'+str(testno)
   960:     self.pass_frame.tests[testno]=[descr,testlabel,'python','Unknown']
   961:     self.set_anchor(testlabel)
   962:     return self.print_python_output(script,descr)
   963: 
End python section to interscript/frames/inputf.py[33]
6.13.10.2.24. Documentation Constructions
The following constructions affect the documentation file only. They are used to designate headings, separate paragraphs, print tables, etc.

These functions are members of class input_frame.

6.13.10.2.24.1. Headings
Start python section to interscript/frames/inputf.py[34] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
   964: #line 1331 "input_frame.ipk"
   965:   def head(self, level, text, atext='', anchor=''):
   966:     level = int(level)
   967:     level = level + self.head_offset
   968:     self.last_head = level
   969:     if self.get_verbosity()>=3: print ('  '*(level-1))+'"'+text+'"'
   970:     self.pass_frame.toc.append((level,text))
   971:     weaver = self.get_weaver()
   972:     if self.current_tangler: self.code_foot()
   973:     self.tangler_set(None)
   974:     weaver.head(level,text,atext,anchor)
   975: 
   976:   # like heading, but to be used in code as well:
   977:   # doesn't switch to document mode, doesn't do
   978:   # code headings and footings
   979: 
   980:   def heading(self, level, text, atext='', anchor=''):
   981:     level = int(level)
   982:     level = level + self.head_offset
   983:     self.last_head = level
   984:     if self.get_verbosity()>=3: print ('  '*(level-1))+'"'+text+'"'
   985:     self.pass_frame.toc.append((level,text))
   986:     weaver = self.get_weaver()
   987:     weaver.head(level,text,atext,anchor)
   988: 
   989:   def push_head(self, amt=1):
   990:     self.head_offset = self.head_offset + amt
   991: 
   992:   def pop_head(self, amt=1):
   993:     self.push_head(-amt)
   994: 
   995:   def set_head(self, amt=None):
   996:     if amt != None:
   997:       self.head_offset = amt - 1
   998:     else:
   999:       self.head_offset = self.last_head - 1
  1000: 
End python section to interscript/frames/inputf.py[34]
6.13.10.2.24.2. Paragraphs
Start python section to interscript/frames/inputf.py[35] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
  1001: #line 1369 "input_frame.ipk"
  1002:   def doc(self):
  1003:     if self.current_tangler: self.code_foot()
  1004:     self.tangler_set(None)
  1005: 
  1006:   def p(self): # end a paragraph and start a new one
  1007:     self.current_weaver.par()
  1008: 
  1009:   def eop(self): # end a paragraph without starting a new one
  1010:     self.current_weaver.eop()
  1011: 
  1012:   def line_break(self): self.current_weaver.line_break()
  1013:   def page_break(self): self.current_weaver.page_break()
  1014: 
End python section to interscript/frames/inputf.py[35]
6.13.10.2.24.3. Citations
Start python section to interscript/frames/inputf.py[36] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
  1015: #line 1384 "input_frame.ipk"
  1016:   def cite_url(self, url):
  1017:     self.current_weaver.cite_url(url)
  1018: 
End python section to interscript/frames/inputf.py[36]
6.13.10.2.24.4. Tables
Start python section to interscript/frames/inputf.py[37] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
  1019: #line 1389 "input_frame.ipk"
  1020:   def begin_table(self, *headings, **kwds):
  1021:     apply(self.get_weaver().begin_table, headings, kwds)
  1022: 
  1023:   def table_row(self, *data):
  1024:     self.current_weaver.table_row(data)
  1025: 
  1026:   def end_table(self):
  1027:     self.current_weaver.end_table()
  1028: 
  1029:   def table_rule(self):
  1030:     self.current_weaver.table_rule()
  1031: 
End python section to interscript/frames/inputf.py[37]
6.13.10.2.24.5. Lists
Start python section to interscript/frames/inputf.py[38] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
  1032: #line 1403 "input_frame.ipk"
  1033:   def begin_list(self, style):
  1034:     self.current_weaver.begin_list(style)
  1035: 
  1036:   def end_list(self):
  1037:     self.current_weaver.end_list()
  1038: 
  1039:   def item(self,*args, **kwds):
  1040:     apply(self.current_weaver.item, args, kwds)
  1041: 
  1042:   def begin_numbered_list(self, start=1):
  1043:     self.current_weaver.begin_numbered_list(start)
  1044: 
  1045:   def end_numbered_list(self):
  1046:     self.current_weaver.end_numbered_list()
  1047: 
  1048:   def begin_numbered_list_item(self):
  1049:     self.current_weaver.begin_numbered_list_item()
  1050: 
  1051:   def end_numbered_list_item(self):
  1052:     self.current_weaver.end_numbered_list_item()
  1053: 
  1054:   def begin_bullet_list(self):
  1055:     self.current_weaver.begin_bullet_list()
  1056: 
  1057:   def end_bullet_list(self):
  1058:     self.current_weaver.end_bullet_list()
  1059: 
  1060:   def begin_bullet_list_item(self):
  1061:     self.current_weaver.begin_bullet_list_item()
  1062: 
  1063:   def end_bullet_list_item(self):
  1064:     self.current_weaver.end_bullet_list_item()
  1065: 
  1066:   def begin_keyed_list(self):
  1067:     self.current_weaver.begin_keyed_list()
  1068: 
  1069:   def end_keyed_list(self):
  1070:     self.current_weaver.end_keyed_list()
  1071: 
  1072:   def begin_keyed_list_item(self, key):
  1073:     self.current_weaver.begin_keyed_list_item(key)
  1074: 
  1075:   def end_keyed_list_item(self):
  1076:     self.current_weaver.end_keyed_list_item()
  1077: 
End python section to interscript/frames/inputf.py[38]
6.13.10.2.24.6. Fonts
Start python section to interscript/frames/inputf.py[39] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
  1078: #line 1450 "input_frame.ipk"
  1079:   def begin_emphasize(self):
  1080:     self.current_weaver.begin_emphasize()
  1081: 
  1082:   def end_emphasize(self):
  1083:     self.current_weaver.end_emphasize()
  1084: 
  1085:   def begin_strong(self):
  1086:     self.current_weaver.begin_strong()
  1087: 
  1088:   def end_strong(self):
  1089:     self.current_weaver.end_strong()
  1090: 
  1091:   def begin_italic(self):
  1092:     self.current_weaver.begin_italic()
  1093: 
  1094:   def end_italic(self):
  1095:     self.current_weaver.end_italic()
  1096: 
  1097:   def begin_bold(self):
  1098:     self.current_weaver.begin_bold()
  1099: 
  1100:   def end_bold(self):
  1101:     self.current_weaver.end_bold()
  1102: 
  1103:   def begin_big(self):
  1104:     self.current_weaver.begin_big()
  1105: 
  1106:   def end_big(self):
  1107:     self.current_weaver.end_big()
  1108: 
  1109:   def begin_small(self):
  1110:     self.current_weaver.begin_small()
  1111: 
  1112:   def end_small(self):
  1113:     self.current_weaver.end_small()
  1114: 
  1115:   def begin_code(self):
  1116:     self.current_weaver.begin_code()
  1117: 
  1118:   def end_code(self):
  1119:     self.current_weaver.end_code()
  1120: 
End python section to interscript/frames/inputf.py[39]
6.13.10.2.24.7. Displays
Start python section to interscript/frames/inputf.py[40] 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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
  1121: #line 1494 "input_frame.ipk"
  1122:   def begin_displayed_code(self):
  1123:     self.current_weaver.begin_displayed_code()
  1124: 
  1125:   def end_displayed_code(self):
  1126:     self.current_weaver.end_displayed_code()
  1127: 
  1128:   # this command is used to print out a code file 'verbatim'
  1129:   # without line numbers!
  1130:   def display_code(self,name,kind='code'):
  1131:     self.pass_frame.include_files.append((self.depth+1,kind,name))
  1132:     self.begin_displayed_code()
  1133:     filename = parse_source_filename(name, self.source.directory)[3]
  1134:     f = open(filename)
  1135:     data = f.readlines()
  1136:     f.close()
  1137:     weaver = self.get_weaver()
  1138:     for line in data:
  1139:       l = string.rstrip(line)
  1140:       weaver.writeline(l)
  1141:     self.end_displayed_code()
  1142: 
  1143: #line 1516 "input_frame.ipk"
  1144: 
     3: #line 196 "frames.ipk"
     4: 

6.14. Module getoptions

Provides generic command line processing. Input: a list of words, each of which is an option or filename. Output: a list of pairs, each of which is a list of option value pairs, and a filename. The format for options is --longoption, --longoption=value, -abcd, -abcdef=value.
Start python section to interscript/getoptions.py[1] 1
     1: #line 10 "options.ipk"
     2: import re
     3: 
     4: longopts=re.compile('^--([A-Za-z][-A-Za-z_0-9]*)(?:=(.*))?$')
     5: shortopts=re.compile('^-([A-Za-z]+)(?:=(.*))?$')
     6: 
     7: 
     8: def getopt(args):
     9:   wordno = 0
    10:   result = []
    11:   opts=[]
    12:   while wordno<len(args):
    13:     filename = ''
    14:     word = args[wordno]
    15:     #print 'word',word,
    16:     match = longopts.match(word)
    17:     if match:
    18:       opts.append((match.group(1),match.group(2)))
    19:       #print ':longopt'
    20:     else:
    21:       match = shortopts.match(word)
    22:       if match:
    23:         #print ':shortopt'
    24:         for letter in match.group(1)[:-1]:
    25:           opts.append((letter,None))
    26:         opts.append((match.group(1)[-1],match.group(2)))
    27:       else:
    28:         #print ':filename'
    29:         filename = args[wordno]
    30:         result.append((opts,filename))
    31:         opts=[]
    32:     wordno = wordno + 1
    33: 
    34:   if opts:
    35:     result.append((opts,filename))
    36:   return result

6.14.1. Test 17: generic getoptions module

On-the-fly python test script follows.
Start python section from options.ipk
    47: from interscript import getoptions
    48: args = ['--longopt', '--longopt-value=value', '-short', '-shortval=val2','filename']
    49: result = getoptions.getopt(args)
    50: print result
End python section from options.ipk
Actual output follows.
Start output section of python <>
     1: Interscript version 1.0a8 build 1378
     2: Built by root on ruby at Sun Nov 29, 1998 at 08:48 PM (UTC)
     3: Generated by 1.0a8 buildno 1376 host ruby
     4: at Sun Nov 29, 1998 at 08:48 PM (UTC)
     5: [([('longopt', None), ('longopt-value', 'value'), ('s', None), ('h', None), ('o', None), ('r', None), ('t', None), ('s', None), ('h', None), ('o', None), ('r', None), ('t', None), ('v', None), ('a', None), ('l', 'val2')], 'filename')]
End output section to python <>

6.15. Get Options

This module gets interscript options from the command line.

The verbosity option provides coarse generic control over the amount of information Interscript writes. The default is 2, which only prints 'error' messages. Level 1 is useful when you're fairly sure there are no errors, for example, you have a trustworthy readonly document, but have deleted the output files during a cleanup. Level 0 is very dangerous, since even trustworthy documents can unexpectedly cause errors: perhaps you installed a new version of Python, or perhaps you forgot that by default downloaded files are reloaded from the network automatically once a month?

This module is getting too fat. It also has side effects, making it impossible to use safely within an interscript source.

Start python section to interscript/getframes.py[1] 1 2 3
     1: #line 20 "interscript_options.ipk"
     2: import sys
     3: import traceback
     4: import string
     5: import glob
     6: import os
     7: 
     8: from interscript.getoptions import getopt
     9: 
End python section to interscript/getframes.py[1]

6.15.1. Help Dictionary

Start python section to interscript/getframes.py[2] 1 2 3
    10: #line 30 "interscript_options.ipk"
    11: #option help dictionary
    12: shortoptdict = { 'v':'verbose (verbosity=6)' }
    13: 
    14: longoptdict = {
    15:   'echo_input=':{0:"Don't echo input (default)",1:'Echo input'},
    16:   'verbosity=': {
    17:     0:'no messages', # none _at all_, not even serious errors
    18:     1:'fatal messages', # _only_ serious errors
    19:     2:'warnings',       # all errors
    20:     3:'brief progress', # open and close weavers, tanglers, files
    21:     4:'progress and information', # headings, 'watch it run'
    22:     5:'full progress and information', # full user information
    23:     6:'user source debugging', # full debugging of _user_ script
    24:     7:'interscript debugging', # basic control flow debugging
    25:     8:'full interscript debugging', # enough to debug interscript itself
    26:     9:'eveything' # for unintelligible output :-)
    27:   },
    28:   'weaver=': {
    29:     'html': 'flat html',
    30:     'latex': 'latex2e',
    31:     'text':'plain text',
    32:     'web':'html tree',
    33:   },
    34:   'tangler-prefix=':'absolute native os prefix prepended to tangled code filenames',
    35:   'weaver-prefix=':'absolute native os prefix prepended to woven documentation filenames',
    36:   'tangler-directory=':'interscript filename prefix prepended to tangled code filenames',
    37:   'weaver-directory=':'interscript filename prefix prepended to woven documentation filenames',
    38:   'source-prefix=':'absolute native prefix prepended to input filename',
    39:   'python=':'execute python script',
    40:   'update=':{
    41:     0:'Allow buffered file write (default)',
    42:     1:'Inhibit buffered file write'},
    43:   'download=':{
    44:     0:'only download by ftp or http when necessary',
    45:     1:'force download by ftp or http'},
    46:   'refresh_interval=':
    47:     'download when local file is older than this number of days (default 28)',
    48:   'tabwidth=':'column width for tab expansion (default 8)',
    49:   'passes=':'passs on each file (default 1)',
    50:   'logfile=':'<filename> for messages (append to old file)',
    51:   'new-logfile=':'<filename> for messages (cleared first)',
    52:   'nocache':'disable persistent cache usage',
    53:   'copyright': '(prints) Maxtal P/L Australia',
    54:   'licence': '(prints) Free for any use',
    55:   'author': '(prints) mailto:skaller@maxtal.com.au <John Skaller>',
    56:   'homepage': '(prints) http://www.triode.net.au/~skaller/interscript',
    57:   'executable': 'print python executable name',
    58:   'python-version': 'print python version string',
    59:   'title=':'set document title',
    60:   'html-eol=': {
    61:     'CRLF': 'Kludge Unix host (only) to end html lines (only) with CR/LF'
    62:   },
    63:   'help':'this help',
    64:   'usage':'this help' }
    65: 
    66: 
    67: def print_help():
    68:   print 'Usage: python iscr.py [options] <filename>'
    69:   print 'Short options:'
    70:   keys = shortoptdict.keys()
    71:   keys.sort()
    72:   for k in keys: print_help1(k)
    73:   print 'Long options:'
    74:   keys = longoptdict.keys()
    75:   keys.sort()
    76:   for k in keys: print_help1(k)
    77: 
    78: def print_help1(k):
    79:   if longoptdict.has_key(k):
    80:     usek = '--'+ k
    81:     values = longoptdict[k]
    82:   elif longoptdict.has_key(k+'='):
    83:     usek = '--'+ k + '='
    84:     values = longoptdict[k+'=']
    85:   elif shortoptdict.has_key(k):
    86:     usek = '-' + k
    87:     values = shortoptdict[k]
    88:   elif shortoptdict.has_key(k+'='):
    89:     usek = '-' + k + '='
    90:     values = shortoptdict[k+'=']
    91:   else:
    92:     usek = k
    93:     values = 'Unknown option'
    94: 
    95:   print '  '+usek,
    96:   if values is None:
    97:     print
    98:   elif type(values) is type({}):
    99:     print
   100:     for value in values.keys():
   101:       print '   '+str(value)+':',values[value]
   102:   else:
   103:     print values
   104: 
End python section to interscript/getframes.py[2]

6.15.2. Argument Frame

Just an empty class to hook attributes to.
Start python section to interscript/getframes.py[3] 1 2 3
   105: #line 127 "interscript_options.ipk"
   106: class argument_frame:
   107:   def copy(self):
   108:      other = argument_frame()
   109:      other.__dict__ = self.__dict__.copy()
   110:      return other
   111: 
   112: def getoption_frames(args): # note: has side effects!
   113:   parsed =  getopt(args)
   114:   process_options = argument_frame()
   115:   process_options.verbosity = 2
   116:   process_options.logfile = None
   117:   process_options.logfile_mode = None
   118:   process_options.args = args
   119:   master_frames = []
   120: 
   121:   frame = argument_frame()
   122:   frame.echo_input = 0
   123:   frame.update_files = 1
   124:   frame.tabwidth = 8
   125:   frame.verbosity = 2
   126:   frame.download = 'regularly'
   127:   frame.refresh_interval = 28
   128:   frame.usecache = 1
   129:   frame.passes = 1
   130:   frame.weaver_prefix = ''
   131:   frame.tangler_prefix = ''
   132:   frame.weaver_directory= ''
   133:   frame.tangler_directory = ''
   134:   frame.autoweave = []
   135:   frame.useropt = {}
   136:   frame.html_eol = '\n'
   137:   frame.title = 'Anonymous Interscript Document'
   138:   for opts,filename in parsed:
   139:     for opt,value in opts:
   140:       try:
   141:         if opt == 'verbosity': process_options.verbosity = frame.verbosity = int(value)
   142:         elif opt == 'echo_input': frame.echo_input = int(value)
   143:         elif opt == 'v': process_options.verbosity = frame.verbosity = 6
   144:         elif opt == 'noupdate': frame.update_files = 0
   145:         elif opt == 'nocache': frame.usecache = 0
   146:         elif opt == 'nodownload': frame.download = 'never'
   147:         elif opt == 'download': frame.download = 'always'
   148:         elif opt == 'tabwidth': frame.tabwidth = int(value)
   149:         elif opt == 'passes': frame.passes = int(value)
   150:         elif opt == 'weaver': frame.autoweave.append(value)
   151:         elif opt == 'weaver-prefix': frame.weaver_prefix = value
   152:         elif opt == 'title': frame.title = value
   153:         elif opt == 'tangler-prefix': frame.tangler_prefix = value
   154:         elif opt == 'weaver-directory': frame.weaver_directory = value
   155:         elif opt == 'html-eol':
   156:           if sys.platform == 'Win32':
   157:             print 'CRLF kludge ignored for Win32'
   158:             print 'Use on Unix only, to make html files in DOS format'
   159:           else:
   160:             frame.html_eol = '\r\n'
   161:         elif opt == 'tangler-directory': frame.tangler_directory = value
   162:         elif opt == 'homepage':
   163:           print 'http://www.triode.net.au/~skaller/interscript'
   164:         elif opt == 'author':
   165:           print 'mailto:skaller@maxtal.com.au <John Skaller>'
   166:         elif opt == 'copyright':
   167:           print 'Copyright (C)1998 Maxtal P/L Australia'
   168:         elif opt == 'licence':
   169:           print 'Free for any use'
   170:         elif opt == 'executable':
   171:           print sys.executable
   172:         elif opt == 'python-version':
   173:           print sys.version
   174:         elif opt == 'python':
   175:           try:
   176:             if process_options.verbosity>=3:
   177:               print 'Executing python:'
   178:               print value
   179:             exec value
   180:           except:
   181:             print 'Error in python option'
   182:             traceback.print_exc()
   183:         elif opt == 'logfile':
   184:           process_options.logfile = value
   185:           process_options.logfile_mode = 'a'
   186:         elif opt == 'new-logfile':
   187:           process_options.logfile = value
   188:           process_options.logfile_mode = 'w'
   189:         elif opt in ['help', 'usage']:
   190:           print_help()
   191:           print
   192:         else:
   193:           # FIX: all options should be OK (user options?)
   194:           print 'Nonstandard option',opt,'value',value,'accepted as user option'
   195:           frame.useropt[opt]=value
   196:         if process_options.verbosity>=4: print 'Option:',opt,value
   197:       except:
   198:         print 'Warning: Option',opt,'has bad value',value
   199:         prefix = ''
   200:         while opt[0]=='-': prefix = prefix + '-'; opt=opt[1:]
   201:         print_help1(opt)
   202: 
   203:     files = glob.glob( filename)
   204:     for file in files:
   205:       frame.source_prefix, frame.filename = os.path.split(file)
   206:       master_frames.append(frame.copy())
   207:   return process_options, master_frames
   208: 
   209: 
     6: #line 448 "iscr.pak"
     7: 
     8: 
End python section to interscript/core/__init__.py[1]

6.16. Utility Modules

Start python section to interscript/utilities/__init__.py[1] 1
     1: #line 452 "iscr.pak"
     2: # interscript utilities
     3: 

6.16.1. compiler package

This package
Start python section to interscript/compilers/c.py[1] 1
     1: #line 13 "compilers.ipk"
     2: import os
     3: import sys
     4: import string
     5: import interscript.compilers.cconfig
     6: 
     7: 
     8: class python_module:
     9:   def __init__(self,**kwds):
    10:     self.config = interscript.compilers.cconfig.config()
    11:     self.config.append_dict(kwds)
    12: 
    13:   def configure(self,**kwds):
    14:     self.config.append_dict(kwds)
    15: 
    16:   def compile(self,filename, **kwds):
    17:     config = self.config.copy()
    18:     config.append_dict(kwds)
    19: 
    20:     base = string.join(string.split(filename,'.')[:-1],'.')
    21:     obj = base+'.o'
    22:     cc ='gcc -g -O2 -fpic -fPIC -pedantic '
    23:     inc = '-I' + sys.prefix + '/include/python1.5 '
    24:     if sys.prefix != sys.exec_prefix:
    25:       inc = inc + '-I' + sys.exec_prefix + '/include/python1.5 '
    26:     cstr = str(config)+' '
    27:     arg = cc + cstr +  inc + '-c '+filename + ' -o '+ obj
    28:     print 'system',repr(arg)
    29:     os.system(arg)
    30:     return obj
    31: 
    32:   def link(self,modname, filenames, **kwds):
    33:     config = self.config.copy()
    34:     config.append_dict(kwds)
    35: 
    36:     dll = modname +'.so'
    37:     cc ='gcc -shared -Xlinker -export-dynamic '
    38:     cstr = str(config) + ' '
    39:     lib = '-L' + sys.exec_prefix + '/lib/python1.5 '
    40:     files = string.join(filenames) + ' '
    41:     arg = cc + cstr + lib + files + '-o ' + dll
    42: 
    43:     print 'system',repr(arg)
    44:     os.system(arg)
    45:     return dll
    46: 
    47: class application:
    48:   def __init__(self,**kwds):
    49:     self.config = interscript.compilers.cconfig.config()
    50:     self.config.append_dict(kwds)
    51: 
    52:   def configure(self,**kwds):
    53:     self.config.append_dict(kwds)
    54: 
    55:   def compile(self,filename, **kwds):
    56:     config = self.config.copy()
    57:     config.append_dict(kwds)
    58: 
    59:     base = string.join(string.split(filename,'.')[:-1],'.')
    60:     obj = base+'.o'
    61:     cc ='gcc -g -O2 -fpic -fPIC -pedantic '
    62:     inc = '-I' + sys.prefix + '/include/python1.5 '
    63:     if sys.prefix != sys.exec_prefix:
    64:       inc = inc + '-I' + sys.exec_prefix + '/include/python1.5 '
    65:     cstr = str(config)+' '
    66:     arg = cc + cstr +  inc + '-c '+filename + ' -o '+ obj
    67:     print 'system',repr(arg)
    68:     os.system(arg)
    69:     return obj
    70: 
    71:   def link(self,appname, filenames, **kwds):
    72:     config = self.config.copy()
    73:     config.append_dict(kwds)
    74: 
    75:     cc ='gcc '
    76:     cstr = str(config) + ' '
    77:     lib = '-L' + sys.exec_prefix + '/lib/python1.5 '
    78:     files = string.join(filenames) + ' '
    79:     arg = cc + cstr + lib + files + '-o ' + appname
    80: 
    81:     print 'system',repr(arg)
    82:     os.system(arg)
    83:     return appname
    84: 
End python section to interscript/compilers/c.py[1]
Start python section to interscript/compilers/cpp.py[1] 1
     1: #line 97 "compilers.ipk"
     2: import os
     3: import sys
     4: import string
     5: import interscript.compilers.cconfig
     6: 
     7: class python_module:
     8:   def __init__(self,**kwds):
     9:     self.config = compilers.cconfig.config()
    10:     self.config.append_dict(kwds)
    11: 
    12:   def configure(self,**kwds):
    13:     self.config.append_dict(kwds)
    14: 
    15:   def compile(self,filename, **kwds):
    16:     config = self.config.copy()
    17:     config.append_dict(kwds)
    18: 
    19:     base = string.join(string.split(filename,'.')[:-1],'.')
    20:     obj = base+'.o'
    21:     cc ='g++ -g -O2 -fhandle-exceptions -fpic -fPIC -pedantic '
    22:     inc = '-I' + sys.prefix + '/include/python1.5 '
    23:     if sys.prefix != sys.exec_prefix:
    24:       inc = inc + '-I' + sys.exec_prefix + '/include/python1.5 '
    25:     cstr = str(config)+' '
    26:     arg = cc + cstr +  inc + '-c '+filename + ' -o '+ obj
    27:     print 'system',repr(arg)
    28:     result = os.system(arg)
    29:     if result != 0:
    30:       raise 'Compiler Error'
    31:     return obj
    32: 
    33:   def link(self,modname, filenames, **kwds):
    34:     config = self.config.copy()
    35:     config.append_dict(kwds)
    36: 
    37:     cc ='g++ -shared -Xlinker -export-dynamic '
    38:     cstr = str(config) + ' '
    39:     lib = '-L' + sys.exec_prefix + '/lib/python1.5 '
    40:     dll = modname +'.so'
    41:     files = string.join(filenames) + ' '
    42:     arg = cc + cstr + lib + files + '-o '+dll
    43: 
    44:     print 'system',repr(arg)
    45:     result = os.system(arg)
    46:     if result != 0:
    47:       raise 'Linker Error'
    48:     return dll
    49: 
    50: class application:
    51:   def __init__(self,**kwds):
    52:     self.config = interscript.compilers.cconfig.config()
    53:     self.config.append_dict(kwds)
    54: 
    55:   def configure(self,**kwds):
    56:     self.config.append_dict(kwds)
    57: 
    58:   def compile(self,filename, **kwds):
    59:     config = self.config.copy()
    60:     config.append_dict(kwds)
    61: 
    62:     base = string.join(string.split(filename,'.')[:-1],'.')
    63:     obj = base+'.o'
    64:     cc ='g++ -g -O2 -fhandle-exceptions -fpic -fPIC -pedantic '
    65:     inc = '-I' + sys.prefix + '/include/python1.5 '
    66:     if sys.prefix != sys.exec_prefix:
    67:       inc = inc + '-I' + sys.exec_prefix + '/include/python1.5 '
    68:     cstr = str(config)+' '
    69:     arg = cc + cstr +  inc + '-c '+filename + ' -o '+ obj
    70:     print 'system',repr(arg)
    71:     result = os.system(arg)
    72:     if result != 0:
    73:       raise 'Compiler Error'
    74:     return obj
    75: 
    76:   def link(self,appname, filenames, **kwds):
    77:     config = self.config.copy()
    78:     config.append_dict(kwds)
    79: 
    80:     cc ='g++ '
    81:     cstr = str(config) + ' '
    82:     lib = '-L' + sys.exec_prefix + '/lib/python1.5 '
    83:     files = string.join(filenames) + ' '
    84:     arg = cc + cstr + lib + files + '-o '+appname
    85: 
    86:     print 'system',repr(arg)
    87:     result = os.system(arg)
    88:     if result != 0:
    89:       raise 'Linker Error'
    90:     return appname
    91: 
End python section to interscript/compilers/cpp.py[1]
Start python section to interscript/compilers/cconfig.py[1] 1
     1: #line 188 "compilers.ipk"
     2: import os
     3: import sys
     4: import string
     5: 
     6: class config:
     7:   def __init__(self,**kwds):
     8:     self.libdirs = []
     9:     self.incdirs = []
    10:     self.libs = []
    11:     self.macros = {}
    12:     self.switches = {}
    13:     self.extra = ''
    14:     self.append_dict(kwds)
    15: 
    16:   def copy(self):
    17:     c = config()
    18:     c.libdirs = self.libdirs[:]
    19:     c.incdirs = self.incdirs[:]
    20:     c.libs = self.libs[:]
    21:     c.macros = self.macros.copy()
    22:     c.switches = self.switches.copy()
    23:     c.extra = self.extra
    24:     return c
    25: 
    26:   def append_kwds(self,**kwds):
    27:     self.append_dict(kwds)
    28: 
    29:   def append_dict(self,kwds):
    30:     if kwds.has_key('libdirs'):
    31:       self.libdirs[-1:-1]=kwds['libdirs']
    32:     if kwds.has_key('incdirs'):
    33:       self.incdirs[-1:-1]=kwds['incdirs']
    34:     if kwds.has_key('libs'):
    35:       self.libs[-1:-1]=kwds['libs']
    36:     if kwds.has_key('extra'):
    37:       self.extra = self.extra + ' ' + kwds['extra']
    38:     if kwds.has_key('macros'):
    39:       macros = kwds['macros']
    40:       for macro in macros:
    41:         self.macros[macro] = macros[macro]
    42:     if kwds.has_key('switches'):
    43:       switches = kwds['switches']
    44:       for switch in switches:
    45:         self.switches[switch] = switches[switch]
    46: 
    47:   def __str__(self):
    48:     s = self.extra
    49:     for x in self.libdirs: s = s + ' -L' + x
    50:     for x in self.incdirs : s = s + ' -I' + x
    51:     for x in self.libs: s = s + ' -l' + x
    52:     for x in self.macros.keys():
    53:       s = s + ' -D' + x
    54:       if self.macros[x]: s = s + '=' + self.macros[x]
    55:     for x in self.switches.keys():
    56:       s = s + ' -' + x + self.switches[x]
    57:     return s
    58: 
End python section to interscript/compilers/cconfig.py[1]
Start python section to interscript/compilers/__init__.py[1] 1
     1: #line 246 "compilers.ipk"
     2: # compiler package
End python section to interscript/compilers/__init__.py[1]
Start python section to interscript/tests/test_compilers.py[1] 1
     1: #line 248 "compilers.ipk"
     2: import os
     3: import sys
     4: sys.path = ['']+sys.path
     5: import interscript.compilers.c
     6: cc = interscript.compilers.c.application()
     7: obj = cc.compile('interscript/tests/example.c')
     8: print 'Object file',obj,'generated'
     9: exe = cc.link('interscript/tests/example.exe',[obj])
    10: print 'Executable',exe,'generated'
    11: # sorry... this is unix dependent :-(
    12: os.system('interscript/tests/example.exe')
    13: print 'Executable executed'
    14: 
End python section to interscript/tests/test_compilers.py[1]
Start C section to interscript/tests/example.c[1] 1
     1: #line 262 "compilers.ipk"
     2: #include <stdio.h>
     3: void main() {
     4:   printf("Hello World from compiler test\n");
     5: }
     6: 
End C section to interscript/tests/example.c[1]

6.16.1.1. Test

Test it.
Start output section of C compiler
     1: Hello World from compiler test
     2: Interscript version 1.0a8 build 1384
     3: Built by root on ruby at Mon Nov 30, 1998 at 08:56 AM (UTC)
     4: Generated by 1.0a8 buildno 1383 host ruby
     5: at Mon Nov 30, 1998 at 08:56 AM (UTC)
     6: system 'gcc -g -O2 -fpic -fPIC -pedantic  -I/usr/local/include/python1.5 -c interscript/tests/example.c -o interscript/tests/example.o'
     7: Object file interscript/tests/example.o generated
     8: system 'gcc  -L/usr/local/lib/python1.5 interscript/tests/example.o -o interscript/tests/example.exe'
     9: Executable interscript/tests/example.exe generated
    10: Executable executed
End output section to C compiler

6.16.2. Interscript Standard module diff for Python

This site depedent module implements diff and patch for Python.

6.16.2.1. Description

The diff module is an optional Interscript component. however it is required by the version control subsystem, and may be used by other functions if present. The module provides several functions.

6.16.2.2. Requirements

The function 'compare_files' shall return 1 if two text files have the same contents, and 0 otherwise. The comparison may ignore whitespace at the end of lines but is not required to. The compare files function shall return 1 if the files are exactly equal, in particular if the same file is given as both arguments.

The function 'compare_code_files' is the same as 'compare_files' except it may accept keyword arguments specifying the language of the source code. If such arguments are supplied the function may perform a semantic comparison of the code, and return 1 if the codes are equivalent. The purpose of the function is primarily to avoid rebuilding files differing only in comments, blank lines, etc.

The function 'diff_files' compares two text files, the original file and an upgraded file, and returns a string describing the differences. The string may be in any format, but it must be possible for the patch_file function to modify the original file using this string, and produce an upgraded file which compares equal using the compare files function.

The function 'diff_strings' compares two strings, returning a context diff as a string.

The function 'diff_lines' compares two sequences of strings, returning a diff descriptor as follows (code, left, right). Code may be 'c' for change or 's' for common, left and right are line counts.

The function 'patch_file' takes a string and an original file, and the name of an upgraded file, and produces an upgraded file which has been modified by the patch string in such a way that the compare_files function will report the files are equal. In addition, the function shall accept an empty patch string signifying no differences between the original and upgraded files.

This function is not required to operate correctly if the orginal file has been modified since the patch string was produced by diff_files.

The names of the argument files shall not denote the same file.

The function shall return a result

The function 'posix_patch' is optional. If this function is present, it will take a patch string produced by the standard posix context diff and patch the file. The purpose of this function is to facilitate use of posix context diff as an Internet standard method of transporting source code patches.

The specification of this function is defined as the result of calling diff with the -C option on a system compliant with the ISO Posix standard.

6.16.2.3. Posix Implementation

The following implementation utilises the os.popen and os.system function to dispatch requests to the operating system diff and patch commands, and is intended to work on posix compliant systems. Well, it works on my Linux box :-)
Start python section to interscript/utilities/diff.py[1] 1
     1: #line 75 "diff.ipk"
     2: import os
     3: import tempfile
     4: import string
     5: import re
     6: 
     7: def compare_files(o,m):
     8:   cmd = 'diff -q '+o+' '+m
     9:   f = os.popen(cmd,'r')
    10:   output = f.read()
    11:   result = f.close()
    12:   return len(output)==0
    13: 
    14: def compare_code_files(o,m,**kwds):
    15:   # slack implementation
    16:   return compare_files(o,m)
    17: 
    18: def diff_files(o,m,patch=None, context=10):
    19:   cmd = 'diff -C'+str(context)+' '+o+' '+m
    20:   f = os.popen(cmd,'r')
    21:   output = f.read()
    22:   result = f.close()
    23:   if patch:
    24:     f = open(patch,'w')
    25:     f.write(output)
    26:     f.close()
    27:   return output
    28: 
    29: def diff_strings(o,m,context=0):
    30:   foname = tempfile.mktemp()
    31:   fmname = tempfile.mktemp()
    32:   fo = open(foname,'w')
    33:   fm = open(fmname,'w')
    34:   fo.write(o)
    35:   fm.write(m)
    36:   fo.close()
    37:   fm.close()
    38:   result = diff_files(foname, fmname,context=context)
    39:   os.unlink(foname)
    40:   os.unlink(fmname)
    41:   return result
    42: 
    43: def diff_lines(o,m,context=0):
    44:   os = string.join(o,'\n')+'\n'
    45:   om = string.join(m,'\n')+'\n'
    46:   result = diff_strings(os,om,context=context)
    47:   del os
    48:   del om
    49:   data = string.split(result,'\n')[:-1]
    50:   cs = data[0][0]
    51:   cm = data[1][0]
    52:   sep = data[2]
    53:   lth = len(data)
    54:   sections = []
    55:   for i in range(2,lth):
    56:     if data[i] == sep:
    57:       sections.append([])
    58:     else:
    59:       sections[-1].append(data[i])
    60:   del data
    61:   del lth
    62:   del sep
    63: 
    64:   for i in range(len(sections)):
    65:     section = sections[i]
    66:     sections[i] = []
    67:     for j in range(len(section)):
    68:       line = section[j]
    69:       code = line[0]+line[1]
    70:       if code == cs*2 or code == cm*2:
    71:         k = 0
    72:         first = 0
    73:         count = 0
    74:         while line[k] not in '0123456789': k = k + 1
    75:         while line[k] in '0123456789':
    76:           first = first * 10 +ord(line[k])-ord('0')
    77:           k = k + 1
    78:         first = first - 1
    79:         sections[i].append([[first,0]])
    80:       else:
    81:         lineno = first + count
    82:         count = count + 1
    83:         sections[i][-1][0][1] = count
    84:         sections[i][-1].append(('%3d'%(lineno+1))+':'+line)
    85:   return sections
    86: 
    87: def patch_file(o,diff,m):
    88:   cmd = 'patch -s -c -o ' + m + ' ' + o + ' -'
    89:   print cmd
    90:   f = os.popen(cmd,'w')
    91:   f.write(diff)
    92:   result = f.close()
    93: 
    94: def posix_patch(o,diff,m):
    95:   patch_file(o,diff,m)
    96: 
End python section to interscript/utilities/diff.py[1]

6.16.2.4. Test routine 1

First, create some files to compare!
Start data section to interscript/tests/diff1.dat[1] 1
     1: A file with several lines of text.
     2: A line to be deleted.
     3: To be used by the diff module test.
     4: This line will be changed.
     5: The diff module is used to compare and patch test files.
     6: 
End data section to interscript/tests/diff1.dat[1]
Start data section to interscript/tests/diff2.dat[1] 1
     1: A file with several lines of text.
     2: To be used by the diff module test.
     3: This line is changed.
     4: A NEW LINE INSERTED.
     5: The diff module is used to compare and patch test files.
     6: 
Start python section to interscript/tests/test_diff.py[1] 1
     1: #line 191 "diff.ipk"
     2: import sys
     3: import string
     4: sys.path = [''] + sys.path
     5: import interscript.utilities.diff
     6: diff = interscript.utilities.diff
     7: cmp = diff.compare_files('diff1.dat', 'diff1.dat')
     8: assert cmp
     9: cmp = diff.compare_files('diff1.dat', 'diff2.dat')
    10: assert not cmp
    11: patch = diff.diff_files('diff1.dat','diff2.dat')
    12: print 'patch below'
    13: print patch
    14: print
    15: diff.patch_file('diff1.dat',patch,'diff3.dat')
    16: cmp = diff.compare_files('diff2.dat','diff3.dat')
    17: assert cmp
    18: f = open('diff1.dat')
    19: d1 = f.readlines()
    20: f.close()
    21: for i in range(len(d1)): d1[i] = string.rstrip(d1[i])
    22: f = open('diff2.dat')
    23: d2 = f.readlines()
    24: for i in range(len(d2)): d2[i] = string.rstrip(d2[i])
    25: f.close()
    26: 
    27: d = diff.diff_lines(d1,d2)
    28: for section in d:
    29:   print '*****'
    30:   for part in section:
    31:     print part
    32: 
End python section to interscript/tests/test_diff.py[1]
     7: Now run it.
Start output section of "/usr/local/bin/python" interscript/tests/test_diff.py
Command returned 256
     1: diff: diff1.dat: No such file or directory
     2: diff: diff1.dat: No such file or directory
     3: diff: diff2.dat: No such file or directory
     4: Interscript version 1.0a8 build 1384
     5: Built by root on ruby at Mon Nov 30, 1998 at 08:56 AM (UTC)
     6: Generated by 1.0a8 buildno 1383 host ruby
     7: at Mon Nov 30, 1998 at 08:56 AM (UTC)
     8: Traceback (innermost last):
     9:   File "interscript/tests/test_diff.py", line 10, in ?
    10:     assert not cmp
    11: AssertionError
End output section to "/usr/local/bin/python" interscript/tests/test_diff.py
     8: 
End data section to interscript/tests/diff2.dat[1]

6.16.2.5. Test Routine 2

Use "test_python" function.
6.16.2.5.1. Test 19: Python diff test
On-the-fly python test script follows.
Start python section from diff.ipk
   230: print 'Hello from python diff function test.'
   231: print 'Hello again from python diff function test.'
   232: print 'Hello third from python diff function test.'
   233: print 'Hello fourth from python diff function test.'
End python section from diff.ipk
Actual output follows.
Start output section of python <>
     1: Hello from python diff function test.
     2: Hello again from python diff function test.
     3: Hello third from python diff function test.
     4: Hello fourth from python diff function test.
End output section to python <>
On-the-fly expected output follows.
Start expected section of diff.ipk
   235: Hello from python diff function test.
   236: Hello error from python diff function test.
   237: Hello fourth from python diff function test.
   238: Hello fifth from python diff function test.
End expected section to diff.ipk
Differential follows.
ActualExpected
2:! Hello again from python diff function test.
3:! Hello third from python diff function test.
2:! Hello error from python diff function test.

4:+ Hello fifth from python diff function test.
Hmmm. There should be a difference table here.

6.16.3. Commands

This module is a replacement for the python commands module, which doesn't work properly on NT.
Start python section to interscript/utilities/commands.py[1] 1
     1: #line 6 "commands.ipk"
     2: """Execute shell commands via os.popen() and return status, output.
     3: 
     4: Interface summary:
     5: 
     6:        import commands
     7: 
     8:        outtext = commands.getoutput(cmd)
     9:        (exitstatus, outtext) = commands.getstatusoutput(cmd)
    10:        outtext = commands.getstatus(file)  # returns output of "ls -ld file"
    11: 
    12: A trailing newline is removed from the output string.
    13: 
    14: Encapsulates the basic operation:
    15: 
    16:       pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
    17:       text = pipe.read()
    18:       sts = pipe.close()
    19: 
    20:  [Note:  it would be nice to add functions to interpret the exit status.]
    21: """
    22: 
    23: # Get the output from a shell command into a string.
    24: # The exit status is ignored; a trailing newline is stripped.
    25: # Assume the command will work with '{ ... ; } 2>&1' around it..
    26: #
    27: def getoutput(cmd):
    28:     """Return output (stdout or stderr) of executing cmd in a shell."""
    29:     return getstatusoutput(cmd)[1]
    30: 
    31: 
    32: # Ditto but preserving the exit status.
    33: # Returns a pair (sts, output)
    34: #
    35: def getstatusoutput(cmd):
    36:     """Return (status, output) of executing cmd in a shell."""
    37:     import os
    38:     import sys
    39:     if sys.platform == 'Win32':
    40:       pipe = os.popen(cmd, 'r')
    41:     else: # assume unix
    42:       pipe = os.popen('{ ' + cmd + '; } 2>&1', 'r')
    43:     text = pipe.read()
    44:     sts = pipe.close()
    45:     if sts == None: sts = 0
    46:     if text[-1:] == '\n': text = text[:-1]
    47:     return sts, text
    48: 
    49: 
    50: # Make command argument from directory and pathname (prefix space, add quotes).
    51: #
    52: def mk2arg(head, x):
    53:     import os
    54:     return mkarg(os.path.join(head, x))
    55: 
    56: 
    57: # Make a shell command argument from a string.
    58: # Return a string beginning with a space followed by a shell-quoted
    59: # version of the argument.
    60: # Two strategies: enclose in single quotes if it contains none;
    61: # otherwise, enclose in double quotes and prefix quotable characters
    62: # with backslash.
    63: #
    64: def mkarg(x):
    65:     if '\'' not in x:
    66:         return ' \'' + x + '\''
    67:     s = ' "'
    68:     for c in x:
    69:         if c in '\\$"`':
    70:             s = s + '\\'
    71:         s = s + c
    72:     s = s + '"'
    73:     return s
     4: #line 459 "iscr.pak"
     5: 
     6: 
End python section to interscript/utilities/__init__.py[1]

6.17. Application and tool directory

This is where the interscript mainline and any other shell commands go.
Start python section to interscript/bin/__init__.py[1] 1
     1: #line 464 "iscr.pak"
     2: # dummy interscript.bin
     3: 
End python section to interscript/bin/__init__.py[1]

6.17.1. Stand alone unix/nt mainline

Command line stub.
Start python section to interscript/bin/iscr.py[1] 1
     1: #!/usr/bin/env python
     2: #line 471 "iscr.pak"
     3: import sys
     4: args = sys.argv[1:]
     5: if len(args)>0 and args[0]=='--test':
     6:   print 'Interscript test mode, loading interscript from current directory'
     7:   if sys.path[0]!='':
     8:     sys.path = ['']+ sys.path
     9:   args = args[1:]
    10: import interscript
    11: interscript.run_from_options(args)
    12: 
End python section to interscript/bin/iscr.py[1]

6.17.2. Windows launcher

A batch file to launch interscript. You will need to edit the file!
Start python section to interscript/bin/iscr.bat[1] 1
     1: #line 485 "iscr.pak"
     2: python iscr.py %1 %2 %3 %4 %5 %6 %7 %8 %9
     3: 

     4: #line 488 "iscr.pak"
     5: There's a better way in Windows NT!
     6: (SOMEONE CHECK THIS!)
     7: Using the 'ASSOC' and 'FTYPE' commands,
     8: you can specify the type of .pak files, and what to do with them:
     9: #line 493 "iscr.pak"
    10:   ASSOC .pak=Interscript.Master.Document
    11:   FTYPE Interscript.Master.Document=D:\interscript\interscript\bin\iscr.py %*
12: #line 496 "iscr.pak" 13: and then you can just type the name of the interscript 14: file with options to process it. This should already 15: have been done for python .py files if you ran a recent 16: version of the Windows installer. If you also do:
    17: #line 501 "iscr.pak"
    18:   set PATHEXT=.pak;%PATHEXT%
19: #line 503 "iscr.pak" 20: you won't need to type the extension. To make this persistent, 21: you can use the Control Panel System/Environment editor. 22:
End python section to interscript/bin/iscr.bat[1]

6.18. Test package

Start python section to interscript/tests/__init__.py[1] 1
     1: #line 508 "iscr.pak"
     2: # dummy interscript/test
     3: 
End python section to interscript/tests/__init__.py[1]

7. Appendices

7.1. Index of Identifiers

AMPER interscript/tanglers/python.py: 28, interscript/tokenisers/python.py: 93
ASSOC interscript/bin/iscr.bat: 10
AttributeError interscript/core/stacks.py: 43, 49
B interscript/tests/test_protocol.py: 10, 14, 17
BACKQUOTE interscript/tanglers/python.py: 31, interscript/tokenisers/python.py: 99
Bracket interscript/tokenisers/python.py: 61, 63
BuiltinFunctionType interscript/core/protocols.py: 21
C interscript/parsers/lalr1.py: 399, 400
CHECK interscript/bin/iscr.bat: 6
CIRCUMFLEX interscript/tanglers/python.py: 33, interscript/tokenisers/python.py: 108
CLASS interscript/frames/inputf.py: 603
COLON interscript/tanglers/python.py: 23, interscript/tokenisers/python.py: 85
COMMA interscript/tanglers/python.py: 23, interscript/tokenisers/python.py: 86
COMMENT interscript/tanglers/python.py: 10, 317, interscript/tokenisers/python.py: 7, 8, 231, 265
ClassType interscript/core/protocols.py: 18, 40
CodeType interscript/core/protocols.py: 17
Comment interscript/tokenisers/python.py: 36, 37, 70
ComplexType interscript/core/protocols.py: 31
ContStr interscript/tokenisers/python.py: 68, 71
Control interscript/bin/iscr.bat: 21
D interscript/tests/test_protocol.py: 14, 15, 18, interscript/bin/iscr.bat: 11
DEDENT interscript/tanglers/python.py: 339, interscript/tokenisers/python.py: 240, 316
DOT interscript/tanglers/python.py: 30, interscript/tokenisers/python.py: 97
DOUBLESTAR interscript/tanglers/python.py: 34, interscript/tokenisers/python.py: 111
Decnumber interscript/tokenisers/python.py: 42, 43
DictType interscript/core/protocols.py: 14
Document interscript/bin/iscr.bat: 10, 11
Documents interscript/tests/test_stacking_weaver.pak: 19
Double interscript/tokenisers/python.py: 52, 75
Double3 interscript/tokenisers/python.py: 54, 74
DummyLA interscript/parsers/lalr1.py: 30, 111, 399, 409
EEXIST interscript/drivers/sinks/util.py: 17
ENDMARKER interscript/tokenisers/python.py: 317
ENOENT interscript/drivers/sinks/util.py: 20, 69
EOF interscript/parsers/lalr1.py: 9, 111, 169, 235, 236, 237, 426, 450, 576, 650
EPS interscript/parsers/lalr1.py: 8, 53, 57, 111, 119, 121, 149, 149, 153, 179, 202, 230, 235, 311, 313
EQEQUAL interscript/tanglers/python.py: 31, interscript/tokenisers/python.py: 102
EQUAL interscript/tanglers/python.py: 29, interscript/tokenisers/python.py: 96
ERRORTOKEN interscript/tokenisers/python.py: 204, 309
EllipsisType interscript/core/protocols.py: 28
Environment interscript/bin/iscr.bat: 21
Exception interscript/drivers/sources/__init__.py: 3, interscript/drivers/sources/base.py: 2, 3, interscript/drivers/sinks/__init__.py: 3
Expfloat interscript/tokenisers/python.py: 46, 47
Exponent interscript/tokenisers/python.py: 44, 45, 46
FTP interscript/drivers/sources/ftp.py: 59
FTYPE interscript/bin/iscr.bat: 11
FileType interscript/core/protocols.py: 23
FloatType interscript/core/protocols.py: 10
Floatnumber interscript/tokenisers/python.py: 47, 48, 49
FrameType interscript/core/protocols.py: 26
FunctionType interscript/core/protocols.py: 15
Funny interscript/tokenisers/python.py: 63, 65, 71
GREATER interscript/tanglers/python.py: 29, interscript/tokenisers/python.py: 95
GREATEREQUAL interscript/tanglers/python.py: 32, interscript/tokenisers/python.py: 106
Grammar interscript/parsers/lalr1.py: 29, 111, 257, 260, 399, 409
HTTP interscript/drivers/sources/http.py: 56
Hexnumber interscript/tokenisers/python.py: 40, 43
INDENT interscript/tanglers/python.py: 337, interscript/tokenisers/python.py: 237
IOError interscript/drivers/sinks/util.py: 68, 71, interscript/frames/processf.py: 34
If interscript/bin/iscr.bat: 16
Ignore interscript/tokenisers/python.py: 37, 66
Imagnumber interscript/tokenisers/python.py: 48, 49
ImportError interscript/frames/inputf.py: 709
IndexError interscript/parsers/lalr1.py: 229, interscript/frames/inputf.py: 787
InstanceType interscript/core/protocols.py: 19, 43, 102, interscript/tests/test_protocol.py: 20
IntType interscript/core/protocols.py: 8, interscript/tests/test_protocol.py: 6, 7
Interscript interscript/bin/iscr.bat: 10, 11
Intnumber interscript/tokenisers/python.py: 43, 49
KeyError interscript/parsers/lalr1.py: 484, interscript/frames/inputf.py: 786
KeyboardError interscript/frames/passf.py: 65
KeyboardInterrupt interscript/weavers/multiplexor.py: 23, 24, interscript/weavers/filter.py: 62, interscript/frames/processf.py: 70, 72, interscript/frames/masterf.py: 33, 86, interscript/frames/inputf.py: 204, 208, 229, 498, 501, 711
LALRGrammar interscript/parsers/lalr1.py: 257, 728, 872, 902, 933
LALRitems interscript/parsers/lalr1.py: 514, 572
LBRACE interscript/tanglers/python.py: 20, interscript/tokenisers/python.py: 100
LEFTSHIFT interscript/tanglers/python.py: 34, interscript/tokenisers/python.py: 109
LESS interscript/tanglers/python.py: 29, interscript/tokenisers/python.py: 94
LESSEQUAL interscript/tanglers/python.py: 32, interscript/tokenisers/python.py: 105
LHS interscript/parsers/lalr1.py: 13, 14, 14, 26, 49, 49, 50, 51, 53, 54, 159, 171, 191, 192, 203, 204, 276, 277, 278, 279, 281, 282, 310, 311, 311, 313, 313, 322, 323, 324, 325, 346, 347, 347, 349, 349, 356, 357, 359, 662
LPAR interscript/tanglers/python.py: 18, interscript/tokenisers/python.py: 81
LSQB interscript/tanglers/python.py: 19, interscript/tokenisers/python.py: 83
LambdaType interscript/core/protocols.py: 16
ListType interscript/core/protocols.py: 13, interscript/felix/model/stdcat.py: 91
LongType interscript/core/protocols.py: 9
MINUS interscript/tanglers/python.py: 27, interscript/tokenisers/python.py: 89
MSIE_treehandler interscript/weavers/web.py: 409, 464
MULTILINE_STRING_FIRST interscript/tanglers/python.py: 11, 319, interscript/tokenisers/python.py: 16, 17, 277, 291
MULTILINE_STRING_LAST interscript/tanglers/python.py: 13, 321, interscript/tokenisers/python.py: 22, 23, 196
MULTILINE_STRING_MIDDLE interscript/tanglers/python.py: 12, 320, interscript/tokenisers/python.py: 19, 20, 213
Master interscript/bin/iscr.bat: 10, 11
MethodType interscript/core/protocols.py: 20
ModuleType interscript/core/protocols.py: 22
NAME interscript/tanglers/python.py: 315, 341, interscript/tokenisers/python.py: 297
NEWLINE interscript/tokenisers/python.py: 259
NL interscript/tokenisers/python.py: 10, 11, 231, 261
NOTEQUAL interscript/tanglers/python.py: 32, interscript/tokenisers/python.py: 103, 104
NT interscript/bin/iscr.bat: 5
NUMBER interscript/tanglers/python.py: 322, interscript/tokenisers/python.py: 256
N_TOKENS interscript/tokenisers/python.py: 7, 10, 13, 16, 19, 22
Name interscript/tokenisers/python.py: 38, 65, 71
NameError interscript/core/protocols.py: 32
None interscript/core/sets.py: 6, 54, 66, 133, 141, interscript/core/stacks.py: 54, 55, interscript/core/protocols.py: 49, interscript/drivers/sources/base.py: 33, 36, 39, interscript/weavers/text.py: 57, interscript/weavers/html.py: 40, 68, 320, 329, interscript/weavers/web.py: 124, 204, 218, 339, 348, 350, 352, interscript/tanglers/null.py: 12, interscript/tanglers/python.py: 40, 41, 42, 99, 100, 101, 102, 103, 104, 105, 106, 205, 206, 207, 208, 209, 210, 211, 212, 314, 379, 380, 381, 382, 383, 384, 385, 386, interscript/tanglers/perl.py: 145, interscript/tokenisers/python.py: 78, 78, 150, 202, 207, interscript/parsers/lalr1.py: 551, 552, 583, 650, 675, 833, interscript/felix/model/funcat.py: 28, interscript/frames/inputf.py: 77, 201, 289, 298, 311, 323, 395, 410, 459, 505, 534, 628, 629, 630, 631, 632, 633, 645, 676, 778, 852, 867, 890, 895, 900, 905, 910, 915, 920, 925, 936, 952, 973, 995, 996, 1004, interscript/getoptions.py: 25, interscript/getframes.py: 96, 116, 117, interscript/utilities/diff.py: 18, interscript/utilities/commands.py: 45
NoneType interscript/core/protocols.py: 6
Number interscript/tokenisers/python.py: 49, 65, 71
OP interscript/tanglers/python.py: 26, interscript/tokenisers/python.py: 304
Octnumber interscript/tokenisers/python.py: 41, 43
Operator interscript/tokenisers/python.py: 59, 63
PATHEXT interscript/bin/iscr.bat: 18, 18
PERCENT interscript/tanglers/python.py: 30, interscript/tokenisers/python.py: 98
PLUS interscript/tanglers/python.py: 27, interscript/tokenisers/python.py: 88
Panel interscript/bin/iscr.bat: 21
PlainToken interscript/tokenisers/python.py: 65, 66
Pointfloat interscript/tokenisers/python.py: 45, 47
Production interscript/parsers/lalr1.py: 12, 162, 722, 842, 870
PseudoExtras interscript/tokenisers/python.py: 70, 71
PseudoToken interscript/tokenisers/python.py: 71, 74
RBRACE interscript/tanglers/python.py: 20, interscript/tokenisers/python.py: 101
RHS interscript/parsers/lalr1.py: 13, 15, 15, 20, 26, 52, 53, 54, 56, 95, 118, 124, 125, 130, 175, 178, 180, 181, 182, 182, 184, 185, 187, 188, 190, 196, 197, 197, 199, 201, 207, 208, 208, 210, 224, 226, 228, 273, 273, 274, 278, 279, 281, 282, 321, 321, 324, 325, 358, 358, 359, 378, 380, 386, 386, 401, 403, 581, 587, 588, 614, 666, 755
RIGHTSHIFT interscript/tanglers/python.py: 34, interscript/tokenisers/python.py: 110
RPAR interscript/tanglers/python.py: 18, interscript/tokenisers/python.py: 82
RSQB interscript/tanglers/python.py: 19, interscript/tokenisers/python.py: 84
SEMI interscript/tanglers/python.py: 23, interscript/tokenisers/python.py: 87
SGMLParser interscript/parsers/html.py: 22, 24
SLASH interscript/tanglers/python.py: 27, interscript/tokenisers/python.py: 91
SOMEONE interscript/bin/iscr.bat: 6
STAR interscript/tanglers/python.py: 27, interscript/tokenisers/python.py: 90
STRING interscript/tanglers/python.py: 318, interscript/tokenisers/python.py: 199, 273, 295
ST_MTIME interscript/drivers/sources/ftp.py: 44, interscript/drivers/sources/http.py: 41
Simple interscript/tests/test_stacking_weaver.pak: 5
Single interscript/tokenisers/python.py: 51, 75
Single3 interscript/tokenisers/python.py: 53, 74
SliceType interscript/core/protocols.py: 27
Special interscript/tokenisers/python.py: 62, 63
String interscript/tokenisers/python.py: 56, 65
StringType interscript/core/protocols.py: 11, interscript/felix/model/stdcat.py: 98
System interscript/bin/iscr.bat: 21
SystemExit interscript/frames/inputf.py: 209, 213, 230, 712
THIS interscript/bin/iscr.bat: 6
TILDE interscript/tanglers/python.py: 33, interscript/tokenisers/python.py: 107
There interscript/bin/iscr.bat: 5
This interscript/tests/test_stacking_weaver.pak: 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, interscript/bin/iscr.bat: 14, interscript/tests/example.pak: 4
To interscript/bin/iscr.bat: 20
Token interscript/tokenisers/python.py: 66, 74
TokenError interscript/tanglers/python.py: 300, interscript/tokenisers/python.py: 115, 191, 244
TracebackType interscript/core/protocols.py: 25
Triple interscript/tokenisers/python.py: 55, 70
TupleType interscript/core/protocols.py: 12, interscript/felix/model/stdcat.py: 84
TypeError interscript/frames/inputf.py: 776
TypeType interscript/core/protocols.py: 7, interscript/tests/test_protocol.py: 6
Using interscript/bin/iscr.bat: 7
VBAR interscript/tanglers/python.py: 28, interscript/tokenisers/python.py: 92
ValueError interscript/parsers/lalr1.py: 606
WHITESPACE interscript/tokenisers/python.py: 13, 14
Whitespace interscript/tokenisers/python.py: 35, 37, 37, 71
Windows interscript/bin/iscr.bat: 5, 16
XRangeType interscript/core/protocols.py: 24
__add__ interscript/core/sets.py: 144, interscript/core/stacks.py: 25, interscript/felix/model/funcat.py: 21
__and__ interscript/core/sets.py: 124, interscript/felix/model/funcat.py: 15, 34
__bases__ interscript/core/protocols.py: 99
__builtin__ interscript/__init__.py: 53, 54, 55
__builtins__ interscript/__init__.py: 54
__call__ interscript/felix/model/basecat.py: 7, interscript/felix/model/stdcat.py: 26, interscript/felix/model/funcat.py: 9, 33, 43, 51, 57, 73, 84
__class__ interscript/core/protocols.py: 47, 103, interscript/frames/inputf.py: 100
__class_protocols interscript/weavers/base.py: 3
__class_protocols__ interscript/core/sets.py: 3, interscript/core/stacks.py: 3, interscript/drivers/sources/base.py: 10, interscript/drivers/sinks/base.py: 4, interscript/weavers/multiplexor.py: 4, interscript/tanglers/base.py: 6, interscript/felix/model/basecat.py: 5
__cmp__ interscript/core/sets.py: 102, interscript/core/stacks.py: 26
__del__ interscript/core/stacks.py: 5, interscript/drivers/sources/base.py: 55, interscript/drivers/sinks/disk.py: 24, interscript/drivers/sinks/bufdisk.py: 46, interscript/drivers/sinks/cache.py: 19, interscript/weavers/text.py: 387, interscript/weavers/html.py: 56, interscript/weavers/web.py: 289, interscript/weavers/latex.py: 40, interscript/tanglers/c.py: 42, interscript/tanglers/python.py: 278, interscript/tanglers/perl.py: 29, interscript/frames/inputf.py: 93
__delattr__ interscript/core/stacks.py: 45
__delitem__ interscript/core/sets.py: 117, interscript/core/stacks.py: 19
__delslice__ interscript/core/stacks.py: 22
__dict__ interscript/core/stacks.py: 37, interscript/drivers/sources/base.py: 15, interscript/drivers/sources/ftp.py: 19, interscript/drivers/sources/http.py: 19, interscript/drivers/sinks/base.py: 12, interscript/parsers/lalr1.py: 23, interscript/frames/masterf.py: 9, 11, 12, interscript/frames/inputf.py: 100, 195, 587, interscript/getframes.py: 109, 109
__getattr__ interscript/core/stacks.py: 39, interscript/weavers/multiplexor.py: 47
__getitem__ interscript/core/sets.py: 114, interscript/core/stacks.py: 17
__getslice__ interscript/core/sets.py: 121, interscript/core/stacks.py: 20
__htabrule interscript/weavers/text.py: 171, 214, 216, 219, 222
__init__ interscript/tests/output/mymodule2.py: 4, interscript/tests/output/mymodule3.py: 4, interscript/core/sets.py: 4, interscript/core/stacks.py: 4, interscript/core/protocols.py: 36, interscript/tests/test_protocol.py: 11, interscript/drivers/sources/base.py: 11, 58, 59, interscript/drivers/sources/disk.py: 39, 40, interscript/drivers/sources/url.py: 7, 8, interscript/drivers/sources/ftp.py: 12, 13, interscript/drivers/sources/http.py: 12, 13, interscript/drivers/sources/stdin.py: 12, 13, interscript/drivers/sources/cache.py: 7, 8, interscript/drivers/sinks/base.py: 5, interscript/drivers/sinks/null.py: 4, 5, interscript/drivers/sinks/tee.py: 4, 5, interscript/drivers/sinks/disk.py: 8, 21, interscript/drivers/sinks/bufdisk.py: 10, 32, 43, interscript/drivers/sinks/stdout.py: 5, 6, interscript/drivers/sinks/cache.py: 5, 6, interscript/drivers/storage/memory.py: 7, 8, 9, interscript/weavers/base.py: 4, interscript/weavers/raw.py: 4, 5, interscript/weavers/multiplexor.py: 5, interscript/weavers/text.py: 8, 9, interscript/weavers/html.py: 32, 33, interscript/weavers/web.py: 124, interscript/weavers/latex.py: 22, 23, interscript/weavers/filter.py: 5, 6, interscript/tanglers/base.py: 7, interscript/tanglers/null.py: 12, 13, interscript/tanglers/doc.py: 8, 9, interscript/tanglers/c.py: 9, 10, 32, 33, 48, 50, interscript/tanglers/cpp.py: 9, 10, 32, 33, 43, 44, interscript/tanglers/java.py: 7, 8, interscript/tanglers/tcl.py: 7, 8, interscript/tanglers/python.py: 38, 269, 270, interscript/tanglers/perl.py: 8, 9, interscript/tokenisers/python.py: 141, interscript/parsers/html.py: 6, 23, 24, interscript/parsers/lalr1.py: 13, 33, 259, 260, interscript/felix/model/fincat.py: 6, interscript/felix/model/stdcat.py: 18, 33, 34, 54, 55, 81, 81, 88, 88, 95, 95, interscript/felix/model/stdcat2.py: 7, 18, interscript/felix/model/funcat.py: 5, 40, 48, 56, 71, 82, interscript/felix/model/cons.py: 6, 45, 68, 109, interscript/frames/install.py: 3, interscript/frames/platform.py: 6, interscript/frames/site.py: 4, interscript/frames/processf.py: 11, interscript/frames/masterf.py: 7, interscript/frames/passf.py: 15, interscript/frames/inputf.py: 60, interscript/compilers/c.py: 9, 48, interscript/compilers/cpp.py: 8, 51, interscript/compilers/cconfig.py: 7
__len__ interscript/core/sets.py: 111, interscript/core/stacks.py: 15, interscript/parsers/lalr1.py: 19
__mul__ interscript/core/stacks.py: 23, interscript/felix/model/funcat.py: 18
__name__ interscript/tokenisers/python.py: 319
__nonzero__ interscript/core/sets.py: 96, interscript/core/stacks.py: 16, interscript/weavers/multiplexor.py: 12
__or__ interscript/core/sets.py: 130, 145
__repr__ interscript/core/sets.py: 87, interscript/core/stacks.py: 27, interscript/parsers/lalr1.py: 22
__rmul__ interscript/core/stacks.py: 24
__setattr__ interscript/core/stacks.py: 33
__setitem__ interscript/core/stacks.py: 18
__setslice__ interscript/core/stacks.py: 21
__str__ interscript/compilers/cconfig.py: 47
__sub__ interscript/core/sets.py: 147
__tabrow interscript/weavers/text.py: 177, 215, 221
__version__ interscript/tokenisers/python.py: 2
__xor__ interscript/core/sets.py: 136
_callit interscript/weavers/multiplexor.py: 16, 18, 55, 61, 62, 67, 70
_close interscript/drivers/sources/base.py: 50, 53, 61, interscript/tokenisers/python.py: 218, 227, 314
_current_level interscript/weavers/web.py: 257, 263, 266, 269, 273, 279, 283
_endmode interscript/weavers/html.py: 65, 71, 135, 153, 161, 168, 174, 186, 191, 197, 202, 208, 243, 270, 284, 294, 299, 345, 349, 603, interscript/weavers/web.py: 229
_ensuremode interscript/weavers/html.py: 74, 95, 99, 124, 321, 342, 346, 354, interscript/weavers/web.py: 334
_flush interscript/weavers/text.py: 212, 228, 243, 263, 274, 388
_foot interscript/weavers/web.py: 268, 278
_goto interscript/weavers/text.py: 41, 419, 421, 427, 433, 434
_handle_sref interscript/tanglers/base.py: 28, 41, interscript/tanglers/python.py: 295
_head interscript/weavers/web.py: 264, 271, 282
_ins_head interscript/weavers/web.py: 287, 395
_new_child interscript/weavers/web.py: 316, 323
_next_hnum interscript/weavers/web.py: 260, 270
_pop_level interscript/weavers/web.py: 258, 267
_popw interscript/weavers/web.py: 280, 310
_push_level interscript/weavers/web.py: 259, 265, 272
_pushw interscript/weavers/web.py: 285, 322
_save interscript/parsers/html.py: 35, 129, 137, 140, 143, 146, 149, 152
_saved interscript/parsers/html.py: 38, 131, 138, 141, 144, 147, 150, 153
_setmode interscript/weavers/html.py: 61, 72
_startmode interscript/weavers/html.py: 70, 75
_test1 interscript/parsers/lalr1.py: 704, interscript/tests/tgram.py: 3
_test2 interscript/parsers/lalr1.py: 830, interscript/tests/tgram.py: 4
_trig interscript/weavers/web.py: 279, 284, 391, 396
_write interscript/weavers/text.py: 29, 38, 45, 66, 68, 172, 174, 178, 184, 236, 238, 241, 254, 420, 428, 435, interscript/weavers/html.py: 62, 67, 80, 90, 92, 107, 110, 119, 121, 125, 156, 169, 214, 222, 224, 271, 274, 277, 280, 285, 288, 291, 295, 300, 303, 306, 309, 323, 325, 331, 332, 334, 338, 358, 361, 364, 367, 370, 373, 376, 379, 382, 385, 388, 391, 394, 397, 411, 414, 416, 419, 420, 435, 438, 440, 443, 444, 449, 456, 551, 553, 557, 559, 563, 564, 592, 605, interscript/weavers/web.py: 195, 213, 215, 236, interscript/weavers/latex.py: 53, 56, 61, 62, 75, 78, 84, 89, 201, 208, 210, 220, 223, 241, 242, 243, 248, 254, 286, 293, 324, 337, 339, 354, 357, 360, 367, 370, 373, 376, 379, 382, 385, 388, 391, 394, 397, 400, 403, 406, 410, 412
_write_and_echo interscript/tanglers/base.py: 24, 42
_write_section_ref interscript/weavers/html.py: 128, 146, interscript/weavers/web.py: 218, 246, 248, 250, 252
_write_word interscript/weavers/text.py: 234, 246
_writeline interscript/weavers/text.py: 36, 44, 80, 89, 91, 108, 112, 118, 122, 128, 132, 138, 142, 145, 154, 156, 165, 167, 175, 185, 213, 229, 240, 260, 265, 270, 275, 279, 280, 281, 332, 333, 334, 341, 343, 350, 351, 357, 359, 364, 369, 374, 379, 384, 390, interscript/weavers/html.py: 77, 96, 113, 116, 120, 126, 131, 138, 162, 165, 175, 179, 183, 187, 188, 192, 194, 198, 199, 203, 205, 209, 210, 261, 315, 318, 327, 408, 421, 432, 445, 459, 460, 468, 470, 486, 490, 496, 500, 506, 510, 516, 520, 523, 531, 533, 541, 543, 549, 554, 565, 568, 573, 597, 606, 607, interscript/weavers/web.py: 187, 224, 237, 335, interscript/weavers/latex.py: 50, 58, 63, 72, 80, 83, 85, 93, 99, 105, 142, 151, 156, 166, 177, 179, 180, 182, 187, 190, 192, 195, 198, 214, 217, 227, 231, 235, 238, 277, 279, 283, 288, 295, 298, 301, 305, 308, 311, 318, 321, 331, 334, 348, interscript/tanglers/base.py: 21, 25, interscript/tanglers/c.py: 19, 37, 39, 43, 63, interscript/tanglers/cpp.py: 15, 19, 39, interscript/tanglers/java.py: 13, 17, interscript/tanglers/tcl.py: 12, 16, interscript/tanglers/python.py: 296, 364, 421, interscript/tanglers/perl.py: 159, 279, 283
a interscript/tests/test_stacking_weaver.pak: 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, interscript/parsers/lalr1.py: 651, 652, 682, interscript/felix/model/fincat.py: 55, 59, 61, 65, 67, 68, 69, 174, 177, 178, 180, interscript/felix/model/stdcat2.py: 38, 38, interscript/bin/iscr.bat: 5, 15, interscript/tests/example.pak: 4
ab interscript/felix/model/fincat.py: 178, 180
abs interscript/felix/model/stdcat.py: 35, 56
absolute interscript/felix/tests/func_test.py: 38, 40, 40
acc interscript/parsers/lalr1.py: 517, 518, 519, 520, 521, 522, 523, 524, 525, 527
account interscript/drivers/sources/ftp.py: 72
acount interscript/weavers/html.py: 38, 247, 248, 248, interscript/weavers/web.py: 166, 398, 399, 399, interscript/weavers/latex.py: 29, 273, 274, 274
act interscript/parsers/lalr1.py: 639, 652, 682
action interscript/parsers/lalr1.py: 652, 654, 655, 659, 660
action_table interscript/parsers/lalr1.py: 621, 639, 695
actual_heading interscript/frames/inputf.py: 594
actual_output interscript/frames/inputf.py: 686, 698
add interscript/parsers/lalr1.py: 192, 194, 197, 199, 204, 206, 208, 209, 210, interscript/felix/tests/func_test.py: 21, 22, 26, 29
add_arrow interscript/felix/model/fincat.py: 79, 149
add_class_proto interscript/core/protocols.py: 60, interscript/tests/test_protocol.py: 17, 18
add_class_protos interscript/core/protocols.py: 66, 67
add_edge interscript/felix/model/stdcat2.py: 24, 43
add_integers interscript/felix/tests/stdcat_test.py: 7, 17
add_integers_mod10 interscript/felix/tests/stdcat_test.py: 8, 18
add_obj_proto interscript/core/protocols.py: 51, interscript/tests/test_protocol.py: 19
add_obj_protos interscript/core/protocols.py: 57, 58
add_object interscript/felix/model/fincat.py: 95, 146
add_production_to_list interscript/parsers/lalr1.py: 838, 861
add_rule interscript/felix/model/fincat.py: 103
add_symbol_to_list interscript/parsers/lalr1.py: 847, 864
add_tag interscript/weavers/base.py: 18
add_type_proto interscript/core/protocols.py: 72, interscript/tests/test_protocol.py: 20
add_type_protos interscript/core/protocols.py: 69, 70
add_vertex interscript/felix/model/stdcat2.py: 21
added interscript/parsers/lalr1.py: 114, 120, 128, 134
added_la interscript/parsers/lalr1.py: 472, 490, 493
adjusted_level interscript/weavers/web.py: 396, 406
age interscript/drivers/sources/ftp.py: 46, 47, interscript/drivers/sources/http.py: 43, 44
ahref interscript/weavers/html.py: 255, 266
allhaveeps interscript/parsers/lalr1.py: 145, 151, 153
already interscript/bin/iscr.bat: 14
also interscript/bin/iscr.bat: 16
amt interscript/frames/inputf.py: 989, 990, 992, 993, 995, 996, 997
anchor interscript/weavers/text.py: 326, interscript/weavers/html.py: 130, 131, 242, 244, 255, 259, 259, 259, interscript/weavers/web.py: 113, 117, 120, 198, 201, 221, 222, 223, 223, 224, 262, 264, 271, 282, 285, 287, 325, 326, 387, 395, 397, 398, 404, 406, 545, 547, interscript/weavers/latex.py: 259, 271, 271, 272, 273, 277, 279, interscript/frames/inputf.py: 965, 974, 980, 987
anchor_file interscript/weavers/web.py: 109, 110, 167, 648
any interscript/tokenisers/python.py: 32, 37, 51, 52, 53, 54, 56, 57, 68, 69
any_line_re interscript/frames/inputf.py: 87, 350, 369, 406, 420
append interscript/core/stacks.py: 13, 14, 14, interscript/core/protocols.py: 53, 62, 74, interscript/drivers/sources/base.py: 28, 42, interscript/drivers/sources/disk.py: 41, interscript/drivers/sinks/disk.py: 22, interscript/drivers/sinks/bufdisk.py: 34, 44, interscript/drivers/sinks/cache.py: 13, interscript/drivers/storage/memory.py: 26, interscript/weavers/base.py: 18, interscript/weavers/multiplexor.py: 54, interscript/weavers/text.py: 192, 195, 313, 331, 399, interscript/weavers/html.py: 228, 266, interscript/weavers/web.py: 157, 159, 259, 333, 389, 404, interscript/weavers/auto.py: 43, interscript/weavers/filter.py: 77, interscript/tanglers/python.py: 344, 348, 352, interscript/tanglers/perl.py: 139, interscript/tokenisers/python.py: 165, 236, interscript/parsers/lalr1.py: 234, 237, 359, 369, 382, 388, 410, 413, 429, 447, 449, 460, 491, 509, 512, 576, 579, 633, 791, 798, 807, 812, 816, 822, 825, 939, interscript/felix/model/fincat.py: 92, 93, interscript/felix/model/stdcat2.py: 25, 44, 45, interscript/felix/model/funcat.py: 77, interscript/felix/model/cons.py: 28, 34, 40, 134, interscript/frames/passf.py: 72, interscript/frames/inputf.py: 270, 318, 340, 350, 356, 369, 397, 406, 420, 441, 474, 575, 741, 836, 970, 985, 1131, interscript/getoptions.py: 18, 25, 26, 30, 35, interscript/getframes.py: 150, 206, interscript/utilities/diff.py: 57, 59, 79, 84
append_dict interscript/compilers/c.py: 11, 14, 18, 34, 50, 53, 57, 73, interscript/compilers/cpp.py: 10, 13, 17, 35, 53, 56, 60, 78, interscript/compilers/cconfig.py: 14, 27, 29
append_kwds interscript/compilers/cconfig.py: 26
append_sequence interscript/core/sets.py: 65
application interscript/compilers/c.py: 47, interscript/compilers/cpp.py: 50, interscript/tests/test_compilers.py: 6
apply interscript/core/sets.py: 122, interscript/core/stacks.py: 23, 24, 25, 51, interscript/drivers/sources/base.py: 59, interscript/drivers/sources/disk.py: 40, interscript/drivers/sources/url.py: 8, interscript/drivers/sources/ftp.py: 13, interscript/drivers/sources/stdin.py: 13, interscript/weavers/multiplexor.py: 22, interscript/tokenisers/python.py: 32, 33, 129, 134, interscript/parsers/lalr1.py: 678, interscript/felix/model/funcat.py: 16, 44, interscript/felix/model/cons.py: 135, interscript/frames/inputf.py: 278, 892, 897, 902, 907, 912, 922, 927, 1021, 1040
appname interscript/compilers/c.py: 71, 79, 83, interscript/compilers/cpp.py: 76, 84, 90
appy interscript/drivers/sources/http.py: 13
are interscript/tests/test_stacking_weaver.pak: 5
arg interscript/felix/model/funcat.py: 9, 12, 12, 13, 33, 33, 43, 44, 44, 51, 52, 57, 73, 77, 84, 86, 86, interscript/felix/model/cons.py: 45, 46, 46, 49, 52, 55, 58, 61, 64, 109, 110, 110, 114, 117, 120, 123, 126, interscript/frames/inputf.py: 808, 809, 815, 816, 817, 818, 819, interscript/compilers/c.py: 27, 28, 29, 41, 43, 44, 66, 67, 68, 79, 81, 82, interscript/compilers/cpp.py: 26, 27, 28, 42, 44, 45, 69, 70, 71, 84, 86, 87
args interscript/core/sets.py: 4, 6, interscript/core/stacks.py: 4, 4, interscript/drivers/sources/base.py: 58, 59, interscript/drivers/sinks/tee.py: 4, interscript/weavers/multiplexor.py: 15, 16, 18, 22, 32, 64, 70, interscript/weavers/text.py: 71, 84, 95, 149, 160, interscript/weavers/html.py: 400, 424, 452, 463, 473, 526, 536, interscript/weavers/web.py: 652, 653, 654, 655, 656, interscript/weavers/latex.py: 44, 66, 92, 96, 102, interscript/tokenisers/python.py: 164, 165, interscript/parsers/lalr1.py: 673, 678, 734, 735, 735, 736, 736, 738, 739, 740, 742, 743, 743, 744, 744, 746, 748, 831, 832, 835, 836, 838, 839, 839, 841, 842, 842, 842, 844, 845, 847, 848, 848, 850, 851, 853, 854, 856, 857, interscript/felix/model/basecat.py: 7, 8, interscript/felix/model/stdcat.py: 26, 27, interscript/felix/model/stdcat2.py: 7, 7, interscript/felix/model/funcat.py: 5, 6, 82, 83, interscript/felix/model/cons.py: 6, 7, 7, 8, 12, 17, 22, 28, 34, 40, 68, 69, 69, 70, 74, 79, 85, 86, 87, 93, 94, 95, 99, 100, 104, 105, 131, 133, interscript/frames/inputf.py: 223, 228, 233, 242, 272, 807, 808, 889, 892, 894, 897, 899, 902, 904, 907, 909, 912, 919, 922, 924, 927, 1039, 1040, interscript/getoptions.py: 8, 12, 14, 29, interscript/getframes.py: 112, 113, 118, 118, interscript/bin/iscr.py: 4, 5, 5, 9, 9, 11
argument interscript/tanglers/python.py: 37, 55, 57, 59, 59, 64, 65, 68, 69, 70, 70, 75, 76, 178, 180, 181, 184, 185, 187, 188, 190, 193, 195
argument_frame interscript/frames/processf.py: 51, 52, interscript/frames/masterf.py: 7, 9, 11, 12, interscript/getframes.py: 106, 108, 114, 121
argument_frames interscript/frames/processf.py: 11, 14, 14, 51
arguments interscript/__init__.py: 113, 116, interscript/tanglers/python.py: 62, 64, 73, 75, 78, 100, 110, 112, 117, 119, 192, 193, 199, 206, 224, 230, 380, 395, 395, 408, 408
argv interscript/tokenisers/python.py: 321, 321, interscript/bin/iscr.py: 4
arrow interscript/felix/model/fincat.py: 33, 36, 36, 37, 39, 42, 42, 43, 45, 48, 53, 72, 73, 75, 76, 79, 84, 91, 92, 93, 147, 148, 149, 150, 150, 150, 162, 163, 164, 166, 167, 169, 170, 187, 188, 189, 190, interscript/felix/model/stdcat.py: 6, 11, 22, 23, interscript/felix/model/stdcat2.py: 47, 48, interscript/felix/model/funcat.py: 65, 66, interscript/felix/model/cons.py: 10, 12, 48, 49, 52, 72, 74, 113, 114, 114, 117, 117
arrows interscript/parsers/lalr1.py: 364, 365, interscript/felix/model/fincat.py: 11, 22, 31, 37, 43, 91, 135, 135, 147, 148, 150, 163, 164
as_long interscript/felix/model/stdcat.py: 44, 65
at interscript/weavers/multiplexor.py: 18, 20, 22, 31, 45, interscript/tests/test_stacking_weaver.pak: 19, interscript/parsers/lalr1.py: 529, 530, 533, 545, 557, 562, 569, 578, 579, 584, 597, 609, 619, 695, 698, 699, interscript/tests/example.pak: 4
atag interscript/weavers/html.py: 259, 260, 261, 595, 596, 597
atext interscript/weavers/text.py: 326, interscript/weavers/html.py: 242, 245, interscript/weavers/web.py: 262, 264, 271, 282, 285, 287, 322, 395, 406, interscript/weavers/latex.py: 259, 271, 276, 277, interscript/frames/inputf.py: 965, 974, 980, 987
attr interscript/core/stacks.py: 33, 34, 37, 39, 40, 43, 45, 46, 49
attributes interscript/parsers/html.py: 57, 58, 60, 68, 71, 74, 77, 80, 83, 86, 90, 94, 98, 104, 110, 117, 129, 133, 137, 140, 143, 146, 149, 152, 155, 156, 172, 174
augment interscript/parsers/lalr1.py: 158, 263
author interscript/weavers/html.py: 582, 583, interscript/weavers/web.py: 23, 24, interscript/weavers/latex.py: 189, 190
auto interscript/__init__.py: 25, interscript/frames/passf.py: 10
auto_weaver interscript/__init__.py: 25, interscript/weavers/auto.py: 36, interscript/frames/passf.py: 10, 52
auto_weavers interscript/weavers/auto.py: 29, 42, 43
autoweave interscript/weavers/auto.py: 36, 41, interscript/frames/passf.py: 24, 24, 40, 52, interscript/getframes.py: 134, 150
b interscript/weavers/multiplexor.py: 19, 20, 22, 28, 28, 29, 29, 34, 34, 39, 39, 40, 42, interscript/weavers/web.py: 157, 157, interscript/felix/model/fincat.py: 55, 59, 61, 65, 67, 68, 69, 175, 177, 177, 178, 179, interscript/felix/model/stdcat2.py: 38, 38
base interscript/__init__.py: 11, interscript/core/protocols.py: 99, 100, interscript/drivers/sources/disk.py: 5, 6, interscript/drivers/sources/url.py: 3, 4, interscript/drivers/sources/ftp.py: 7, 8, interscript/drivers/sources/http.py: 4, 5, interscript/drivers/sources/stdin.py: 7, 8, interscript/drivers/sources/cache.py: 2, 3, interscript/drivers/sinks/null.py: 2, interscript/drivers/sinks/tee.py: 2, interscript/drivers/sinks/disk.py: 3, interscript/drivers/sinks/bufdisk.py: 3, interscript/drivers/sinks/stdout.py: 3, interscript/drivers/sinks/cache.py: 3, interscript/drivers/storage/memory.py: 2, 3, 4, interscript/drivers/storage/disk.py: 2, 3, interscript/weavers/raw.py: 2, interscript/weavers/multiplexor.py: 5, 7, 7, 19, interscript/weavers/text.py: 2, interscript/weavers/html.py: 2, interscript/weavers/web.py: 139, 314, 329, 341, 388, 405, 647, 649, interscript/weavers/latex.py: 2, interscript/weavers/filter.py: 5, 6, 16, 20, 24, 29, 40, 42, 49, 55, 60, 67, 72, interscript/tanglers/null.py: 10, interscript/tanglers/doc.py: 5, interscript/tanglers/data.py: 5, interscript/tanglers/c.py: 5, interscript/tanglers/cpp.py: 5, interscript/tanglers/java.py: 2, interscript/tanglers/tcl.py: 2, interscript/tanglers/python.py: 6, interscript/tanglers/perl.py: 2, interscript/parsers/html.py: 2, interscript/frames/platform.py: 27, 28, interscript/frames/processf.py: 5, interscript/frames/passf.py: 8, 11, interscript/frames/inputf.py: 10, interscript/compilers/c.py: 20, 21, 59, 60, interscript/compilers/cpp.py: 19, 20, 62, 63
basecat interscript/felix/model/fincat.py: 3, interscript/felix/model/stdcat.py: 2, interscript/felix/model/stdcat2.py: 2, interscript/felix/model/funcat.py: 2, interscript/felix/model/cons.py: 2
basedir interscript/weavers/web.py: 34, 87, 141, 142, 142, 379, 454, 508, 527, 556, 574, 593, 614, 640
baselinestretch interscript/weavers/latex.py: 174, 176, 177
basename interscript/drivers/sources/disk.py: 34, 35, 36, 44, interscript/drivers/sinks/disk.py: 15, interscript/drivers/sinks/bufdisk.py: 20, interscript/weavers/web.py: 647, interscript/weavers/auto.py: 9, 10, 11, 14, 15, 17, 19, 20, 21, 24, 25, 26, 36, 43, interscript/frames/passf.py: 48, 50, 52
bc interscript/felix/model/fincat.py: 179, 180
be interscript/tests/test_stacking_weaver.pak: 19
been interscript/bin/iscr.bat: 15
begin interscript/frames/inputf.py: 296
begin_big interscript/weavers/html.py: 387, interscript/weavers/latex.py: 396, interscript/parsers/html.py: 83, interscript/frames/inputf.py: 1103, 1104
begin_bold interscript/weavers/html.py: 381, interscript/weavers/latex.py: 390, interscript/tanglers/perl.py: 64, interscript/parsers/html.py: 68, interscript/frames/inputf.py: 1097, 1098
begin_bullet_list interscript/weavers/text.py: 401, interscript/weavers/html.py: 283, interscript/weavers/latex.py: 317, interscript/tanglers/perl.py: 142, interscript/parsers/html.py: 111, interscript/frames/inputf.py: 1054, 1055
begin_bullet_list_item interscript/weavers/text.py: 430, interscript/weavers/html.py: 290, interscript/weavers/latex.py: 323, interscript/tanglers/perl.py: 149, interscript/parsers/html.py: 121, interscript/frames/inputf.py: 1060, 1061
begin_code interscript/weavers/html.py: 357, interscript/weavers/latex.py: 366, interscript/tanglers/perl.py: 72, 82, 88, interscript/parsers/html.py: 86, interscript/frames/inputf.py: 1115, 1116
begin_comments interscript/frames/inputf.py: 848
begin_displayed_code interscript/weavers/text.py: 296, interscript/weavers/html.py: 106, interscript/tests/test_stacking_weaver.pak: 6, interscript/weavers/latex.py: 226, interscript/weavers/filter.py: 58, 61, interscript/parsers/html.py: 94, interscript/frames/inputf.py: 1122, 1123, 1132
begin_displayed_text interscript/weavers/text.py: 304, interscript/weavers/html.py: 98, interscript/weavers/latex.py: 219
begin_emphasize interscript/weavers/text.py: 284, interscript/weavers/html.py: 363, interscript/weavers/latex.py: 372, interscript/parsers/html.py: 74, interscript/frames/inputf.py: 1079, 1080
begin_italic interscript/weavers/html.py: 375, interscript/weavers/latex.py: 384, interscript/tanglers/perl.py: 60, interscript/parsers/html.py: 71, interscript/frames/inputf.py: 1091, 1092
begin_keyed_list interscript/weavers/text.py: 394, interscript/weavers/html.py: 298, interscript/weavers/latex.py: 330, interscript/tanglers/perl.py: 141, interscript/parsers/html.py: 105, interscript/frames/inputf.py: 1066, 1067
begin_keyed_list_item interscript/weavers/text.py: 417, interscript/weavers/html.py: 305, interscript/weavers/latex.py: 336, interscript/tanglers/perl.py: 148, interscript/parsers/html.py: 131, interscript/frames/inputf.py: 1072, 1073
begin_list interscript/weavers/multiplexor.py: 51, interscript/tanglers/perl.py: 137, 249, interscript/frames/inputf.py: 1033, 1034
begin_list_item interscript/tanglers/perl.py: 145, 265
begin_numbered_list interscript/weavers/text.py: 397, interscript/weavers/html.py: 269, interscript/weavers/latex.py: 304, interscript/tanglers/perl.py: 143, interscript/parsers/html.py: 99, interscript/frames/inputf.py: 1042, 1043
begin_numbered_list_item interscript/weavers/text.py: 423, interscript/weavers/html.py: 276, interscript/weavers/latex.py: 310, interscript/tanglers/perl.py: 150, interscript/parsers/html.py: 119, interscript/frames/inputf.py: 1048, 1049
begin_small interscript/weavers/html.py: 393, interscript/weavers/latex.py: 402, interscript/parsers/html.py: 80, interscript/frames/inputf.py: 526, 1109, 1110
begin_string interscript/frames/inputf.py: 863
begin_strong interscript/weavers/text.py: 290, interscript/weavers/html.py: 369, interscript/weavers/latex.py: 378, interscript/parsers/html.py: 77, interscript/frames/inputf.py: 1085, 1086
begin_table interscript/weavers/text.py: 187, interscript/weavers/html.py: 546, interscript/weavers/latex.py: 282, interscript/frames/inputf.py: 603, 1020, 1021
better interscript/bin/iscr.bat: 5
bin interscript/bin/iscr.bat: 11
body interscript/tanglers/python.py: 106, 139, 141, 212, 259, 260, 386, 401, 401, 414, 414, interscript/frames/inputf.py: 558, 559, 559, 560
bootgram interscript/parsers/lalr1.py: 859, 869, 870
border interscript/weavers/html.py: 547, 549
break_list interscript/weavers/web.py: 124, 155, 156, 157, 157, 159, 393
break_on_error interscript/frames/processf.py: 16, 78
bufdisk interscript/__init__.py: 6, interscript/weavers/web.py: 5, interscript/weavers/auto.py: 7, interscript/frames/inputf.py: 15
buffer interscript/weavers/text.py: 16, 244, 247, 252, 252, 260, 261, interscript/tokenisers/python.py: 153, 168, 169, 170, 177, 178, 181
build_production interscript/parsers/lalr1.py: 841, 863
buildno interscript/__init__.py: 70, 82, 97, interscript/frames/processf.py: 48
buildtime interscript/__init__.py: 74, 86, 100, 104
builtin_module_names interscript/frames/site.py: 7, 7
c interscript/__init__.py: 31, interscript/weavers/text.py: 15, 32, 32, 39, 44, 45, 45, 235, 237, 275, 389, interscript/tanglers/java.py: 4, interscript/tanglers/perl.py: 3, interscript/parsers/lalr1.py: 177, 178, 180, 181, 182, 182, 184, 185, 200, 201, 207, 208, 208, 210, interscript/felix/model/fincat.py: 176, 177, 179, 180, interscript/felix/tests/func_test.py: 42, 43, interscript/frames/inputf.py: 20, interscript/compilers/cconfig.py: 17, 18, 19, 20, 21, 22, 23, 24, interscript/tests/test_compilers.py: 5, 6, interscript/utilities/commands.py: 68, 69, 71
c_comment_tangler interscript/tanglers/c.py: 24, 31
c_output interscript/frames/inputf.py: 756
c_string_tangler interscript/tanglers/c.py: 27, 47, interscript/tanglers/cpp.py: 27, interscript/tanglers/java.py: 4, 25, interscript/tanglers/tcl.py: 25, interscript/tanglers/python.py: 372, interscript/tanglers/perl.py: 3, 291
c_tangler interscript/__init__.py: 31, interscript/tanglers/c.py: 8, interscript/frames/inputf.py: 20
cache interscript/__init__.py: 9, 16, interscript/frames/masterf.py: 29, 30, 31, 32, 82, 83, 84, 85, interscript/frames/inputf.py: 14, 17
cache_name interscript/frames/masterf.py: 26, 29, 82
cache_sink interscript/__init__.py: 9, interscript/drivers/sinks/cache.py: 4, interscript/frames/inputf.py: 17, 383
cache_source interscript/__init__.py: 16, interscript/drivers/sources/cache.py: 6, interscript/frames/inputf.py: 14, 387
calc_LALR1items interscript/parsers/lalr1.py: 264, 466
calc_action_table interscript/parsers/lalr1.py: 265, 571
calc_firstmap interscript/parsers/lalr1.py: 71, 109
calc_followmap interscript/parsers/lalr1.py: 77, 168
calc_goto_table interscript/parsers/lalr1.py: 266, 624
calc_lhsdereps interscript/parsers/lalr1.py: 67, 85
calc_ntfirstmap interscript/parsers/lalr1.py: 261, 270
calc_tfirstmap interscript/parsers/lalr1.py: 262, 353
callable interscript/parsers/lalr1.py: 677
callit interscript/weavers/multiplexor.py: 15, 49
can interscript/bin/iscr.bat: 8, 13, 21
can_compose interscript/felix/model/fincat.py: 55, 65, 177, 177, interscript/felix/model/stdcat.py: 13, 20, interscript/felix/model/stdcat2.py: 12, interscript/felix/model/cons.py: 20, 22, 54, 55, 82, 87
capture_output interscript/frames/inputf.py: 930, 937, 950
capture_python_output interscript/frames/inputf.py: 949
cat interscript/felix/model/fincat.py: 133, 134, 135, 136, 137, 139, 144, 147, 150, 152, 154, 155, interscript/felix/model/cons.py: 133, 134
cat_all interscript/felix/model/stdcat.py: 10
cat_dagraph interscript/felix/model/stdcat2.py: 50
cat_dgraph interscript/felix/model/stdcat2.py: 17, 42, 50
cat_dual interscript/felix/model/cons.py: 44
cat_dunion interscript/felix/model/cons.py: 131
cat_empty interscript/felix/model/stdcat.py: 5
cat_function interscript/felix/model/funcat.py: 61, interscript/felix/tests/func_test.py: 5
cat_graph interscript/felix/model/stdcat2.py: 42
cat_list interscript/felix/model/stdcat.py: 87, interscript/felix/tests/stdcat_test.py: 5, 13
cat_monoid interscript/felix/model/stdcat.py: 17, 32, 34, 53, 55, 70, 81, 88, 95
cat_product interscript/felix/model/cons.py: 5
cat_sequence interscript/felix/model/stdcat.py: 70, 80, 87, 94
cat_set interscript/felix/model/stdcat2.py: 6
cat_string interscript/felix/model/stdcat.py: 94, interscript/felix/tests/stdcat_test.py: 5, 14
cat_tagged interscript/felix/model/cons.py: 108, 134
cat_tuple interscript/felix/model/stdcat.py: 80, interscript/felix/tests/stdcat_test.py: 5, 12
cat_union interscript/felix/model/cons.py: 67, 135
category interscript/felix/model/basecat.py: 4, interscript/felix/model/fincat.py: 3, 4, interscript/felix/model/stdcat.py: 2, 5, 10, 17, interscript/felix/model/stdcat2.py: 2, 6, 17, interscript/felix/model/funcat.py: 2, 61, interscript/felix/model/cons.py: 2, 5, 44, 67, 108
cats interscript/felix/model/cons.py: 132, 134, 135
cc interscript/compilers/c.py: 22, 27, 37, 41, 61, 66, 75, 79, interscript/compilers/cpp.py: 21, 26, 37, 42, 64, 69, 80, 84, interscript/tests/test_compilers.py: 6, 7, 9
cconfig interscript/compilers/c.py: 5, 10, 49, interscript/compilers/cpp.py: 5, 9, 52
ch interscript/weavers/html.py: 13, 14, 15, 17, 22, 23, 24, 26, interscript/weavers/latex.py: 7, 8, 8, 15, 16, 17, interscript/tanglers/c.py: 59, 60, 60, 61, interscript/parsers/html.py: 44, 45, 45, 46
chain_filters interscript/weavers/filter.py: 70, 81
change_passno interscript/weavers/text.py: 110, 111, 120, 121, 130, 131, 132, 140, interscript/weavers/html.py: 488, 489, 498, 499, 508, 509, 510, 518
chars_written interscript/tanglers/python.py: 307, 313, 327, 328
check_associative interscript/felix/model/fincat.py: 173
check_complete interscript/felix/model/fincat.py: 158
child interscript/weavers/web.py: 110, 112, 113, 380, 388, 389
childcount interscript/weavers/web.py: 162, 180, 194, 317, 317, 319, 320, 325, 345, 346, 351, 354, 357, 403
choices interscript/tokenisers/python.py: 31, 31, 32, 32, 33, 33
chr interscript/tanglers/perl.py: 98
cite_url interscript/weavers/text.py: 438, interscript/weavers/html.py: 337, interscript/weavers/latex.py: 409, interscript/frames/inputf.py: 282, 284, 1016, 1017
class_name interscript/tanglers/python.py: 333, 345, 349, 355
class_reference interscript/weavers/html.py: 424, interscript/weavers/web.py: 654, interscript/weavers/latex.py: 66, interscript/frames/inputf.py: 927
classes interscript/weavers/html.py: 425, 427, interscript/weavers/web.py: 563, 565, interscript/weavers/latex.py: 67, interscript/tanglers/python.py: 347, 347, 348, interscript/frames/masterf.py: 19, 44, 44, interscript/frames/passf.py: 32
classof interscript/core/protocols.py: 45, 95
classref interscript/weavers/web.py: 54, 72
clock interscript/frames/processf.py: 43, 54
close interscript/drivers/sources/base.py: 48, 55, 62, interscript/drivers/sources/disk.py: 20, interscript/drivers/sources/ftp.py: 37, 89, 95, 100, 113, 121, interscript/drivers/sources/http.py: 34, 80, 86, 99, interscript/drivers/sinks/util.py: 66, interscript/drivers/sinks/base.py: 42, interscript/drivers/sinks/disk.py: 25, interscript/drivers/sinks/bufdisk.py: 48, 53, 57, 64, interscript/tanglers/python.py: 280, interscript/tokenisers/python.py: 167, interscript/parsers/html.py: 12, 13, interscript/frames/platform.py: 12, 16, 20, interscript/frames/masterf.py: 31, 84, interscript/frames/inputf.py: 169, 202, 207, 212, 219, 263, 518, 682, 1136, interscript/utilities/diff.py: 11, 22, 26, 36, 37, 92, interscript/tests/test_diff.py: 20, 25, interscript/utilities/commands.py: 44
closed interscript/drivers/sources/base.py: 16, 25, 49, 51, 65, interscript/drivers/sources/disk.py: 49, interscript/drivers/sources/url.py: 11, interscript/drivers/sources/ftp.py: 25, interscript/drivers/sources/http.py: 25, interscript/drivers/sources/stdin.py: 15, 18, interscript/drivers/sources/cache.py: 13, interscript/drivers/sinks/base.py: 10, 43, interscript/drivers/sinks/cache.py: 9, interscript/drivers/storage/memory.py: 15
closure interscript/parsers/lalr1.py: 218, 399
cls interscript/core/protocols.py: 60, 61, 62, 64, 78, 79, 80, 81, 95, 96, 97, 99
cm interscript/utilities/diff.py: 51, 70
cmd interscript/weavers/latex.py: 270, 277, 279, interscript/tanglers/perl.py: 53, 55, 57, 57, 58, 58, 59, 63, 67, 71, 75, 80, 85, 91, 94, 202, 207, 219, 223, 227, 231, 235, 259, 267, 270, 273, interscript/frames/inputf.py: 791, 792, 939, 940, 941, 946, interscript/utilities/diff.py: 8, 9, 19, 20, 88, 89, 90, interscript/utilities/commands.py: 27, 29, 35, 40, 42
cmd_ok interscript/frames/inputf.py: 689
cmds interscript/weavers/latex.py: 260, 270
cmp interscript/core/sets.py: 109, interscript/core/stacks.py: 26, interscript/tests/test_diff.py: 7, 8, 9, 10, 16, 17
cod interscript/felix/model/fincat.py: 164, 168, 189, 190
code interscript/weavers/text.py: 19, 259, 298, 302, interscript/tanglers/python.py: 56, 58, 58, 60, 63, 65, 65, 66, 69, 70, 70, 71, 74, 76, 76, 77, 77, 78, 78, 79, 82, 85, 85, 87, 87, 89, 89, 90, 90, 91, 109, 111, 111, 112, 112, 113, 113, 114, 114, 118, 118, 119, 119, 123, 123, 124, 124, 127, 127, 131, 131, 133, 133, 136, 136, 140, 140, 142, 142, 146, 146, 147, 147, 148, 148, 153, 153, 154, 154, 159, 159, 160, 160, 161, 161, 164, 164, 165, 165, 168, 168, 170, 170, 172, 174, interscript/utilities/diff.py: 69, 70, 70
code_foot interscript/weavers/text.py: 345, interscript/weavers/html.py: 151, interscript/weavers/latex.py: 252, interscript/frames/inputf.py: 797, 802, 824, 841, 846, 972, 1003
code_head interscript/weavers/text.py: 336, interscript/weavers/html.py: 133, interscript/weavers/web.py: 226, interscript/weavers/latex.py: 246, interscript/frames/inputf.py: 799, 804, 826, 828, 839
codomain interscript/felix/model/fincat.py: 39, 48, 59, 118, 122, 122, 189, interscript/felix/model/stdcat.py: 23, interscript/felix/model/funcat.py: 66, interscript/felix/model/cons.py: 37, 40, 61, 63, 102, 105, 123, 125
collect_lines_upto interscript/frames/inputf.py: 250, 569, 581, 655, 666
collect_stuff interscript/frames/inputf.py: 550, 724
collect_upto interscript/frames/inputf.py: 580, 589
column interscript/weavers/text.py: 41, 43, 43, 43, 44, 45, 45, interscript/tokenisers/python.py: 220, 222, 222, 223, 223, 224, 235, 236, 238
colw interscript/weavers/text.py: 171, 173, 177, 179, 180, 203, 206, 206, 211, 211, 214, 215, 216, 219, 221, 222
command interscript/weavers/text.py: 355, 357, 362, 364, 367, 369, 372, 374, 377, 379, 382, 384, interscript/weavers/html.py: 173, 177, 185, 188, 190, 192, 196, 199, 201, 203, 207, 210, interscript/tanglers/python.py: 288, 289, interscript/frames/inputf.py: 930, 932, 936, 937, 940
commands interscript/__init__.py: 46, interscript/frames/inputf.py: 931, 931, 932, interscript/bin/iscr.bat: 7
comment interscript/frames/inputf.py: 860
comments interscript/weavers/html.py: 41, 314, interscript/weavers/latex.py: 31, 347
compare_code_files interscript/utilities/diff.py: 14
compare_files interscript/utilities/diff.py: 7, 16, interscript/tests/test_diff.py: 7, 9, 16
comparison interscript/frames/inputf.py: 593, 598, 604, 698, 699, 708
compile interscript/weavers/filter.py: 7, interscript/tanglers/c.py: 11, interscript/tanglers/cpp.py: 11, interscript/tanglers/java.py: 9, interscript/tanglers/python.py: 271, 272, interscript/tanglers/perl.py: 14, 16, 17, 18, interscript/tokenisers/python.py: 74, 75, 75, interscript/frames/inputf.py: 38, 86, 87, 570, interscript/getoptions.py: 4, 5, interscript/compilers/c.py: 16, 55, interscript/compilers/cpp.py: 15, 58, interscript/tests/test_compilers.py: 7
compile_parse_tab interscript/frames/inputf.py: 37, 461
compilers interscript/compilers/c.py: 5, 10, 49, interscript/compilers/cpp.py: 5, 9, 52, interscript/tests/test_compilers.py: 5, 6
component interscript/drivers/sinks/util.py: 33, 34
compose interscript/felix/model/basecat.py: 8, interscript/felix/model/fincat.py: 61, 178, 179, 180, 180, interscript/felix/model/stdcat.py: 27, 37, 58, 71, interscript/felix/model/stdcat2.py: 14, 38, interscript/felix/model/funcat.py: 64, interscript/felix/model/cons.py: 25, 57, 58, 90, 119, 120
compose_sym interscript/felix/model/fincat.py: 183, 194
config interscript/compilers/c.py: 10, 10, 11, 14, 17, 17, 18, 26, 33, 33, 34, 38, 49, 49, 50, 53, 56, 56, 57, 65, 72, 72, 73, 76, interscript/compilers/cpp.py: 9, 9, 10, 13, 16, 16, 17, 25, 34, 34, 35, 38, 52, 52, 53, 56, 59, 59, 60, 68, 77, 77, 78, 81, interscript/compilers/cconfig.py: 6, 17
configure interscript/compilers/c.py: 13, 52, interscript/compilers/cpp.py: 12, 55
connect interscript/drivers/sources/ftp.py: 63, 65, interscript/drivers/sources/http.py: 60, 62
constant interscript/felix/model/funcat.py: 27, 28, 55, interscript/felix/tests/func_test.py: 4, 42
cont_re interscript/frames/inputf.py: 86, 550, 554, 562, 724
contains interscript/core/sets.py: 9, interscript/parsers/lalr1.py: 96, 119, 127, 130, 592
contents interscript/weavers/web.py: 53, 64, 71
context interscript/frames/inputf.py: 698, interscript/utilities/diff.py: 18, 19, 29, 38, 38, 43, 46, 46
continued interscript/tokenisers/python.py: 148, 217, 245, 299
contline interscript/tokenisers/python.py: 150, 200, 202, 205, 207, 211, 211, 281, 289
contstr interscript/tokenisers/python.py: 149, 189, 199, 201, 204, 206, 210, 210, 280, 288
converged interscript/parsers/lalr1.py: 89, 90, 91, 102, 104, interscript/frames/masterf.py: 72, 73
copy interscript/core/sets.py: 78, 81, 83, 132, interscript/tests/test_sets.py: 14, interscript/core/stacks.py: 51, interscript/parsers/lalr1.py: 23, 86, 178, 201, interscript/felix/model/fincat.py: 132, 134, 135, 136, interscript/frames/inputf.py: 304, 330, 348, 367, 403, 417, interscript/getframes.py: 107, 109, 206, interscript/compilers/c.py: 17, 33, 56, 72, interscript/compilers/cpp.py: 16, 34, 59, 77, interscript/compilers/cconfig.py: 16, 21, 22
core interscript/__init__.py: 47, 48, 49, 50, interscript/tests/test_sets.py: 2, 3, interscript/tests/test_protocol.py: 4, 5, interscript/weavers/html.py: 5, 6, 7, interscript/weavers/web.py: 7, interscript/felix/model/basecat.py: 3, interscript/felix/model/stdcat.py: 74, interscript/felix/model/stdcat2.py: 3, interscript/frames/inputf.py: 29
cos interscript/felix/tests/func_test.py: 13, 13, 14, 19, 29
count interscript/core/sets.py: 49, interscript/core/stacks.py: 52, 52, interscript/weavers/text.py: 231, 232, interscript/weavers/html.py: 313, 317, 320, 322, 323, 448, 449, interscript/weavers/web.py: 646, 648, 650, interscript/weavers/latex.py: 88, 89, 346, 350, interscript/tanglers/base.py: 28, 31, 33, 38, 40, 41, 44, interscript/tanglers/null.py: 19, interscript/tanglers/doc.py: 15, 16, interscript/tanglers/c.py: 14, 17, 18, 35, 36, 55, interscript/tanglers/cpp.py: 17, 18, 37, interscript/tanglers/java.py: 15, 16, interscript/tanglers/tcl.py: 14, 15, interscript/tanglers/python.py: 285, 289, 291, 295, 344, 348, 352, 359, 360, 362, 363, 418, interscript/tanglers/perl.py: 152, 155, 156, 158, 281, 282, interscript/parsers/html.py: 9, interscript/frames/processf.py: 65, 76, interscript/frames/inputf.py: 185, 191, 195, 465, 468, 473, 474, 572, 576, 586, 590, 719, 720, 723, 725, 728, 729, 732, 733, 736, 737, interscript/utilities/diff.py: 73, 81, 82, 82, 83
count2 interscript/frames/inputf.py: 553, 557, 561, 563
counter interscript/weavers/text.py: 315, 316, 317, interscript/weavers/html.py: 230, 231, 232, 265
cpi interscript/parsers/lalr1.py: 400, 401, 403, 410, 413, 415
cpp interscript/__init__.py: 32, interscript/tanglers/java.py: 3, interscript/tanglers/tcl.py: 3, interscript/frames/inputf.py: 21
cpp_comment_tangler interscript/tanglers/cpp.py: 24, 42, interscript/tanglers/java.py: 3, 22
cpp_output interscript/frames/inputf.py: 757
cpp_tangler interscript/__init__.py: 32, interscript/tanglers/cpp.py: 8, interscript/frames/inputf.py: 21
create_directory interscript/drivers/sinks/util.py: 13, 32, 35
create_filter_chain interscript/weavers/filter.py: 80
create_filters interscript/weavers/filter.py: 74, 81
cri interscript/parsers/lalr1.py: 400, 401, 403, 410, 413, 415
cs interscript/utilities/diff.py: 50, 70
cstr interscript/compilers/c.py: 26, 27, 38, 41, 65, 66, 76, 79, interscript/compilers/cpp.py: 25, 26, 38, 42, 68, 69, 81, 84
curdir interscript/drivers/sinks/util.py: 45, 50, 50, 50, 55
curpass interscript/frames/masterf.py: 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 50, 51, 53
current_tangler interscript/frames/inputf.py: 77, 173, 200, 339, 351, 354, 355, 380, 389, 397, 450, 451, 467, 468, 514, 519, 525, 526, 527, 528, 529, 741, 742, 745, 749, 752, 797, 799, 802, 804, 824, 826, 829, 830, 839, 842, 846, 849, 850, 864, 865, 881, 884, 972, 1003
current_tangler_pop interscript/frames/inputf.py: 803, 855, 858
current_tangler_push interscript/frames/inputf.py: 798, 850, 852, 865, 867
current_tangler_stack interscript/frames/inputf.py: 76, 176, 176, 741, 745, 746
current_weaver interscript/frames/inputf.py: 67, 81, 174, 246, 251, 253, 254, 280, 281, 282, 283, 284, 285, 286, 303, 329, 335, 347, 366, 374, 386, 402, 416, 433, 436, 437, 441, 442, 445, 453, 456, 839, 846, 1007, 1010, 1012, 1013, 1017, 1024, 1027, 1030, 1034, 1037, 1040, 1043, 1046, 1049, 1052, 1055, 1058, 1061, 1064, 1067, 1070, 1073, 1076, 1080, 1083, 1086, 1089, 1092, 1095, 1098, 1101, 1104, 1107, 1110, 1113, 1116, 1119, 1123, 1126
current_weaver_stack interscript/frames/inputf.py: 68, 177, 177, 441, 445, 446
cutoff interscript/parsers/lalr1.py: 175, 176, 177, 188, 189, 200
cvt_code interscript/weavers/html.py: 6, 6, 11, 96, 126, 318, 332, interscript/weavers/web.py: 4, interscript/weavers/latex.py: 5, 53, 58, 80, 99, 105, 217, 249, 255
cvt_text interscript/weavers/html.py: 7, 7, 20, 90, interscript/weavers/web.py: 4, interscript/weavers/latex.py: 13, 187, 190, 208
cwd interscript/drivers/sources/ftp.py: 80
d interscript/tests/test_protocol.py: 15, 19, 22, 23, 24, 25, 26, 27, interscript/weavers/html.py: 558, 560, interscript/weavers/latex.py: 292, 294, interscript/parsers/lalr1.py: 23, 24, 25, 26, 212, 213, 214, 291, 292, 294, 299, 334, 335, 383, 384, interscript/frames/install.py: 15, 16, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 30, 33, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 51, 52, 53, 54, 55, 56, 57, 60, 61, 62, 63, 64, 65, 66, 90, 91, 92, interscript/tests/test_diff.py: 27, 28
d1 interscript/tests/test_diff.py: 19, 21, 21, 21, 27
d2 interscript/tests/test_diff.py: 23, 24, 24, 24, 27
data interscript/__init__.py: 35, interscript/drivers/sources/disk.py: 19, 21, 22, 22, 23, interscript/drivers/sources/ftp.py: 27, 28, interscript/drivers/sinks/util.py: 16, 17, 18, 18, 68, 69, 71, interscript/drivers/sinks/cache.py: 16, 17, interscript/drivers/storage/memory.py: 32, 33, interscript/weavers/text.py: 177, 182, 183, 191, 192, 217, 218, 221, 231, 232, interscript/weavers/html.py: 118, 120, 313, 315, 318, 556, 558, interscript/weavers/web.py: 601, 602, 603, 605, interscript/weavers/latex.py: 240, 242, 290, 291, 292, 346, 348, 350, interscript/weavers/filter.py: 26, 30, 32, 41, 47, 48, 50, 52, 54, 54, interscript/tanglers/base.py: 21, 22, 24, 25, 26, 40, 42, interscript/tanglers/null.py: 19, interscript/tanglers/doc.py: 15, 16, interscript/tanglers/c.py: 18, 19, 21, 35, 37, 39, 40, 55, 56, 56, 57, 57, 59, 64, interscript/tanglers/cpp.py: 18, 19, 21, 37, 38, interscript/tanglers/java.py: 16, 17, 19, interscript/tanglers/tcl.py: 15, 16, 18, interscript/tanglers/python.py: 285, 286, 293, 294, 296, 299, 303, 313, 326, 328, 363, 364, 366, 418, 420, interscript/tanglers/perl.py: 104, 105, 152, 159, 162, 171, 183, 282, 283, 284, interscript/tokenisers/python.py: 160, 161, 174, 175, interscript/parsers/html.py: 9, 10, 42, 44, 52, 53, 55, interscript/parsers/lalr1.py: 638, 644, 649, 649, interscript/frames/inputf.py: 28, 379, 380, 388, 389, 465, 468, 470, 477, 479, 517, 520, 527, 589, 590, 933, 934, 937, 942, 943, 947, 1023, 1024, 1135, 1138, interscript/utilities/diff.py: 49, 50, 51, 52, 53, 56, 59, 60
data_output interscript/frames/inputf.py: 755
data_tangler interscript/__init__.py: 35, interscript/tanglers/data.py: 7, interscript/frames/inputf.py: 28, 765, 917
dc interscript/weavers/html.py: 413, 416, 419, 437, 440, 443, interscript/weavers/web.py: 107, 113, interscript/weavers/latex.py: 55, 58, 61, 77, 80, 83
dd interscript/frames/masterf.py: 54, 62, 63, 70, 71
de interscript/felix/model/stdcat2.py: 40
debug interscript/weavers/web.py: 163, 311
debug_constructors interscript/frames/processf.py: 17
debug_destructors interscript/frames/processf.py: 18
debug_missing_methods interscript/weavers/multiplexor.py: 9, 36, interscript/weavers/web.py: 133
deduce interscript/frames/inputf.py: 40, 767, 779
default interscript/tanglers/python.py: 42, 46, 46, 70, 70, 185, 187, interscript/frames/inputf.py: 289, 293
define interscript/frames/inputf.py: 382
delta interscript/felix/tests/func_test.py: 24, 25, 26, 29
depth interscript/frames/inputf.py: 60, 70, 70, 305, 318, 331, 339, 349, 355, 368, 397, 404, 418, 1131
dequeue_input interscript/frames/inputf.py: 476, 489
descr interscript/weavers/web.py: 630, 632, interscript/frames/inputf.py: 629, 639, 645, 645, 646, 957, 960, 962
description interscript/weavers/web.py: 70, 80, interscript/tanglers/python.py: 41, 45, 45, 99, 188, 190, 205, 221, 379, 394, 394, 407, 407, interscript/frames/inputf.py: 242, 243, 276, 616, 620, 676, 683, 688, 936, 939, 939, 952, 955
development_point interscript/frames/install.py: 15, 69
device interscript/frames/inputf.py: 767, 768, 769, 774, 775
df interscript/weavers/html.py: 413, 415, 416, 417, 437, 439, 440, 441, interscript/weavers/web.py: 107, 116, 117, 118, interscript/weavers/latex.py: 55, 57, 58, 59, 77, 79, 80, 81
dict interscript/core/sets.py: 77, interscript/weavers/html.py: 142, 143, 144, interscript/weavers/web.py: 98, 99, 104, 232, 233, 234, 534, 536, 542
diff interscript/frames/inputf.py: 33, 697, interscript/utilities/diff.py: 87, 91, 94, 95, interscript/tests/test_diff.py: 5, 6, 6, 7, 9, 11, 15, 16, 27
diff_context interscript/frames/inputf.py: 634, 698
diff_files interscript/utilities/diff.py: 18, 38, interscript/tests/test_diff.py: 11
diff_foot interscript/weavers/text.py: 382, interscript/weavers/html.py: 207
diff_head interscript/weavers/text.py: 377, interscript/weavers/html.py: 201
diff_lines interscript/frames/inputf.py: 697, 697, 698, interscript/utilities/diff.py: 43, interscript/tests/test_diff.py: 27
diff_message interscript/frames/inputf.py: 596, 601, 602
diff_strings interscript/utilities/diff.py: 29, 46
digits interscript/tanglers/perl.py: 97, 98, interscript/tokenisers/python.py: 138, interscript/parsers/lalr1.py: 788
digits_re interscript/tanglers/perl.py: 17, 95
dir interscript/drivers/sinks/util.py: 13, 14, 15, 18, 19, 20
directory interscript/drivers/sources/disk.py: 31, 32, 33, 33, 35, 36, 44, interscript/weavers/auto.py: 9, 10, 14, 15, 19, 20, 24, 25, 39, 43, interscript/frames/inputf.py: 320, 342, 361, 378, 1133
disable interscript/weavers/base.py: 15, 21
disk interscript/__init__.py: 7, 12, interscript/drivers/storage/disk.py: 7, interscript/weavers/web.py: 6, interscript/frames/masterf.py: 3, interscript/frames/passf.py: 7, interscript/frames/inputf.py: 11, 12, 13, 16
display_code interscript/frames/inputf.py: 1130
div_class interscript/weavers/html.py: 181, 182, 183, 193, 194, 204, 205
divid interscript/weavers/web.py: 472, 473, 483, 484
dll interscript/compilers/c.py: 36, 41, 45, interscript/compilers/cpp.py: 40, 42, 48
do interscript/bin/iscr.bat: 8, 16
do_exec_line interscript/frames/inputf.py: 540, 719
do_exec_suite interscript/frames/inputf.py: 539, 723
do_html interscript/frames/inputf.py: 406, 420, 736
do_quote_at interscript/frames/inputf.py: 538, 732
do_web interscript/frames/inputf.py: 350, 369, 545, 728
doc interscript/__init__.py: 38, interscript/weavers/web.py: 49, 67, interscript/frames/inputf.py: 26, 280, 1002
doc_level interscript/weavers/web.py: 392, 393
doc_tangler interscript/__init__.py: 38, interscript/tanglers/doc.py: 7, interscript/frames/inputf.py: 26
docopts interscript/weavers/latex.py: 135, 137, 139, 139, 140
docoptstr interscript/weavers/latex.py: 138, 139, 141, 142
documentclass interscript/weavers/latex.py: 115, 117, 142
dom interscript/felix/model/fincat.py: 163, 165, 188, 190
domain interscript/felix/model/fincat.py: 33, 53, 59, 118, 120, 120, 188, interscript/felix/model/stdcat.py: 22, interscript/felix/model/funcat.py: 65, interscript/felix/model/cons.py: 31, 34, 60, 64, 97, 100, 122, 126
done interscript/bin/iscr.bat: 15
dosoptstr interscript/weavers/latex.py: 141
double3prog interscript/tokenisers/python.py: 73, 76, 77, 78
download interscript/drivers/sources/ftp.py: 47, 49, 52, 52, 53, 53, 55, interscript/drivers/sources/http.py: 44, 46, 49, 49, 50, 50, 52, interscript/getframes.py: 126, 146, 147
drivers interscript/__init__.py: 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 18, interscript/drivers/sources/disk.py: 4, 5, 6, interscript/drivers/sources/url.py: 3, 4, interscript/drivers/sources/ftp.py: 7, 8, interscript/drivers/sources/http.py: 4, 5, interscript/drivers/sources/stdin.py: 7, 8, interscript/drivers/sources/cache.py: 2, 3, interscript/drivers/sinks/null.py: 2, interscript/drivers/sinks/tee.py: 2, interscript/drivers/sinks/disk.py: 3, 4, 5, interscript/drivers/sinks/bufdisk.py: 3, 4, 5, interscript/drivers/sinks/stdout.py: 3, interscript/drivers/sinks/cache.py: 3, interscript/drivers/storage/memory.py: 2, 3, 4, interscript/drivers/storage/disk.py: 2, 3, interscript/weavers/web.py: 5, 6, interscript/weavers/auto.py: 7, interscript/parsers/html.py: 2, interscript/frames/processf.py: 5, interscript/frames/masterf.py: 3, interscript/frames/passf.py: 6, 7, 8, 11, interscript/frames/inputf.py: 10, 11, 12, 13, 14, 15, 16, 17, 18
ds interscript/frames/masterf.py: 53, 60, 63, 66, 70, 71
dst interscript/felix/model/fincat.py: 79, 88, 91, 93
dst_count interscript/tanglers/python.py: 331, 344, 348, 352
dst_file interscript/tanglers/python.py: 332, 344, 348, 352
dst_filename interscript/weavers/web.py: 227, 228, interscript/frames/inputf.py: 829, 835, 837, 842, 844
dst_lineno interscript/frames/inputf.py: 830, 836
dummy interscript/tanglers/python.py: 310, 336, interscript/parsers/lalr1.py: 831
dump interscript/frames/masterf.py: 83
e interscript/core/sets.py: 6, 6, 9, 10, 14, 15, 20, 21, 28, 29, 30, 31, 46, 47, 49, 50, 53, 54, 57, 58, 61, 62, 62, 66, 66, 104, 104, 126, 127, 127, 133, 133, 138, 138, 139, 140, 140, 141, 149, 150, 150, interscript/tanglers/python.py: 300, 301
echo interscript/frames/inputf.py: 187, 189, 190, 550, 556
echo_input interscript/frames/passf.py: 23, 23, 54, interscript/getframes.py: 122, 142
echotangle interscript/weavers/text.py: 231, interscript/weavers/html.py: 313, interscript/weavers/latex.py: 346, interscript/tanglers/base.py: 26, interscript/tanglers/c.py: 21, interscript/tanglers/cpp.py: 21, interscript/tanglers/java.py: 19, interscript/tanglers/tcl.py: 18, interscript/tanglers/python.py: 366, interscript/tanglers/perl.py: 171, 284, interscript/frames/inputf.py: 253, 658, 706, 945
ecol interscript/tokenisers/python.py: 116, 118
editor interscript/bin/iscr.bat: 21
elapsed_time interscript/frames/processf.py: 55, 56
elements interscript/felix/model/stdcat2.py: 7, 9
emit_contents_line interscript/weavers/web.py: 471, 482, 493
enable interscript/weavers/base.py: 14, interscript/tanglers/perl.py: 211, 274
enabled interscript/weavers/base.py: 5, 14, 15, interscript/weavers/text.py: 30, 37, 42, interscript/weavers/html.py: 78, 81, interscript/weavers/web.py: 493, 497, interscript/weavers/latex.py: 199, 202, interscript/weavers/filter.py: 27, 53
end interscript/weavers/filter.py: 36, interscript/tokenisers/python.py: 194, 194, 197, 197, 199, 200, 250, 251, 251, 252, 271, interscript/frames/inputf.py: 310
end_b interscript/parsers/html.py: 69
end_big interscript/weavers/html.py: 390, interscript/weavers/latex.py: 399, interscript/parsers/html.py: 84, 84, interscript/frames/inputf.py: 1106, 1107
end_body interscript/parsers/html.py: 61
end_bold interscript/weavers/html.py: 384, interscript/weavers/latex.py: 393, interscript/tanglers/perl.py: 66, interscript/parsers/html.py: 69, interscript/frames/inputf.py: 1100, 1101
end_bullet_list interscript/weavers/text.py: 413, interscript/weavers/html.py: 287, interscript/weavers/latex.py: 320, interscript/tanglers/perl.py: 130, interscript/parsers/html.py: 114, interscript/frames/inputf.py: 1057, 1058
end_bullet_list_item interscript/weavers/html.py: 293, interscript/weavers/latex.py: 326, interscript/tanglers/perl.py: 123, interscript/parsers/html.py: 127, interscript/frames/inputf.py: 1063, 1064
end_code interscript/weavers/html.py: 360, interscript/weavers/latex.py: 369, interscript/tanglers/perl.py: 74, 84, 90, interscript/parsers/html.py: 87, 87, interscript/frames/inputf.py: 1118, 1119
end_code_line interscript/weavers/html.py: 327, interscript/tanglers/python.py: 197, 222, 229, 231, 240, 246, 248, 257, 264, 329
end_comments interscript/frames/inputf.py: 854
end_dd interscript/parsers/html.py: 134
end_displayed_code interscript/weavers/text.py: 300, interscript/weavers/html.py: 109, interscript/tests/test_stacking_weaver.pak: 18, interscript/weavers/latex.py: 230, interscript/weavers/filter.py: 65, 67, interscript/parsers/html.py: 95, interscript/frames/inputf.py: 1125, 1126, 1141
end_displayed_text interscript/weavers/text.py: 308, interscript/weavers/html.py: 103, interscript/weavers/latex.py: 222
end_dl interscript/parsers/html.py: 107
end_dt interscript/parsers/html.py: 130
end_em interscript/parsers/html.py: 75
end_emphasize interscript/weavers/text.py: 287, interscript/weavers/html.py: 366, interscript/weavers/latex.py: 375, interscript/parsers/html.py: 75, interscript/frames/inputf.py: 1082, 1083
end_h1 interscript/parsers/html.py: 138
end_h2 interscript/parsers/html.py: 141
end_h3 interscript/parsers/html.py: 144
end_h4 interscript/parsers/html.py: 147
end_h5 interscript/parsers/html.py: 150
end_h6 interscript/parsers/html.py: 153
end_head interscript/parsers/html.py: 59
end_html interscript/parsers/html.py: 62
end_i interscript/parsers/html.py: 72
end_italic interscript/weavers/html.py: 378, interscript/weavers/latex.py: 387, interscript/tanglers/perl.py: 62, interscript/parsers/html.py: 72, interscript/frames/inputf.py: 1094, 1095
end_keyed_list interscript/weavers/text.py: 404, interscript/weavers/html.py: 302, interscript/weavers/latex.py: 333, interscript/tanglers/perl.py: 129, interscript/parsers/html.py: 108, interscript/frames/inputf.py: 1069, 1070
end_keyed_list_item interscript/weavers/html.py: 308, interscript/weavers/latex.py: 341, interscript/tanglers/perl.py: 122, interscript/parsers/html.py: 134, interscript/frames/inputf.py: 1075, 1076
end_li interscript/parsers/html.py: 123
end_list interscript/weavers/multiplexor.py: 57, interscript/tanglers/perl.py: 126, 135, 233, interscript/frames/inputf.py: 1036, 1037
end_list_item interscript/tanglers/perl.py: 119, 232, 242
end_lists interscript/tanglers/perl.py: 31, 134, 208, 220, 224
end_numbered_list interscript/weavers/text.py: 408, interscript/weavers/html.py: 273, interscript/weavers/latex.py: 307, interscript/tanglers/perl.py: 131, interscript/parsers/html.py: 102, interscript/frames/inputf.py: 1045, 1046
end_numbered_list_item interscript/weavers/html.py: 279, interscript/weavers/latex.py: 313, interscript/tanglers/perl.py: 124, interscript/parsers/html.py: 125, interscript/frames/inputf.py: 1051, 1052
end_ol interscript/parsers/html.py: 101
end_p interscript/parsers/html.py: 91
end_pre interscript/parsers/html.py: 95
end_script interscript/parsers/html.py: 179
end_small interscript/weavers/html.py: 396, interscript/weavers/latex.py: 405, interscript/parsers/html.py: 81, 81, interscript/frames/inputf.py: 528, 1112, 1113
end_string interscript/frames/inputf.py: 869
end_strong interscript/weavers/text.py: 293, interscript/weavers/html.py: 372, interscript/weavers/latex.py: 381, interscript/parsers/html.py: 78, 78, interscript/frames/inputf.py: 1088, 1089
end_table interscript/weavers/text.py: 197, interscript/weavers/html.py: 567, interscript/weavers/latex.py: 300, interscript/frames/inputf.py: 610, 1026, 1027
end_time interscript/frames/processf.py: 54, 55
end_ul interscript/parsers/html.py: 113
endheaders interscript/drivers/sources/http.py: 75
endmatch interscript/tokenisers/python.py: 192, 193, 194, 269, 270, 271
endmethod interscript/weavers/filter.py: 5, 9, 9, 45, 76, 77
endpos interscript/weavers/filter.py: 36, 37, 46
endprog interscript/tokenisers/python.py: 192, 268, 269, 287
endprogs interscript/tokenisers/python.py: 75, 268, 287, 287
enqueue_input interscript/frames/inputf.py: 473, 563
entity interscript/tanglers/perl.py: 103, 104, 104
entity_re interscript/tanglers/perl.py: 18, 101
entry interscript/weavers/text.py: 181, 183, 183, 184
eof interscript/__init__.py: 11, interscript/drivers/sources/base.py: 2, 25, 29, 65, 67, interscript/drivers/sources/disk.py: 6, interscript/drivers/sources/url.py: 4, interscript/drivers/sources/ftp.py: 8, interscript/drivers/sources/http.py: 5, interscript/drivers/sources/stdin.py: 8, 19, 21, interscript/drivers/sources/cache.py: 3, 19, interscript/drivers/storage/memory.py: 3, 21, interscript/parsers/lalr1.py: 169, 172, 717, interscript/frames/inputf.py: 10, 502
eoi interscript/__init__.py: 11, interscript/drivers/sources/base.py: 3, interscript/parsers/html.py: 2, 65, interscript/frames/processf.py: 5, 73, 74, interscript/frames/passf.py: 8, 11, interscript/frames/inputf.py: 10, 178, 197, 312, 506, 564
eol interscript/drivers/sinks/disk.py: 8, 9, 9, 28, interscript/drivers/sinks/bufdisk.py: 10, 14, 14, 74, interscript/weavers/web.py: 36, 36, 89, 89, 169, 169, 379, 456, 456, 510, 510, 529, 529, 558, 558, 576, 576, 595, 595, 616, 616, 640, interscript/tests/test_stacking_weaver.pak: 2, interscript/weavers/auto.py: 9, 10, 10, 14, 15, 15, 19, 24, 38, 43, interscript/tanglers/c.py: 26, 27, 48, 49, 51, 51, 62, interscript/tanglers/cpp.py: 26, 27, interscript/tanglers/java.py: 24, 25, interscript/tanglers/tcl.py: 23, 25, interscript/tanglers/python.py: 371, 372, interscript/tanglers/perl.py: 289, 291, interscript/frames/inputf.py: 863, 865
eop interscript/weavers/html.py: 348, interscript/weavers/latex.py: 359, interscript/parsers/html.py: 91, interscript/frames/inputf.py: 1009, 1010
epilog interscript/weavers/html.py: 57, 601, interscript/weavers/latex.py: 41, 194
epos interscript/tokenisers/python.py: 251, 256, 259, 261, 265, 295, 297, 304, 307
epslhs interscript/parsers/lalr1.py: 46, 53, 54, 65, 86, 592, 596
eq interscript/core/sets.py: 24
equal interscript/frames/inputf.py: 598, 600, 699, 701, 702
erow interscript/tokenisers/python.py: 116, 118
errcode interscript/drivers/sources/http.py: 76, 77, 77, 107
errmsg interscript/drivers/sources/http.py: 76, 77, 107
errno interscript/drivers/sinks/util.py: 4, 17, 20, 69
error interscript/drivers/sinks/util.py: 16, 18, 20
esc_re interscript/tanglers/perl.py: 16, 51, 112, 257, 261
eval interscript/parsers/lalr1.py: 899, 930
example interscript/tests/example.pak: 4
exc_info interscript/frames/inputf.py: 509
excise interscript/core/sets.py: 61, interscript/parsers/lalr1.py: 179
excludeid interscript/tanglers/python.py: 273, 342
exe interscript/tests/test_compilers.py: 9, 10
exec_prefix interscript/frames/install.py: 10, 11, 12, 29, 30, 38, 39, 47, 48, 56, 57, 65, 66, interscript/compilers/c.py: 24, 25, 39, 63, 64, 77, interscript/compilers/cpp.py: 23, 24, 39, 66, 67, 82
executable interscript/frames/inputf.py: 950, 954, interscript/getframes.py: 171
exit interscript/frames/processf.py: 80, interscript/frames/inputf.py: 220
expand interscript/frames/inputf.py: 385
expandtabs interscript/frames/inputf.py: 496
expect interscript/frames/inputf.py: 640, 695
expect_filename interscript/frames/inputf.py: 632, 640, 667, 670
expect_terminator interscript/frames/inputf.py: 633, 640, 663, 666
expected_filename interscript/frames/inputf.py: 669
expected_foot interscript/weavers/text.py: 372, interscript/weavers/html.py: 196, interscript/frames/inputf.py: 707
expected_head interscript/weavers/text.py: 367, interscript/weavers/html.py: 190, interscript/frames/inputf.py: 704
expected_heading interscript/frames/inputf.py: 594
expected_lines interscript/frames/inputf.py: 670
expected_origin_file interscript/frames/inputf.py: 665, 704, 707
expected_origin_line interscript/frames/inputf.py: 664, 706
expected_output interscript/frames/inputf.py: 666, 698, 705, 706
extend interscript/felix/model/fincat.py: 139
extension interscript/frames/platform.py: 27, 28, interscript/frames/inputf.py: 783, 784, interscript/bin/iscr.bat: 20
extension_table interscript/frames/inputf.py: 42, 784
extra interscript/weavers/html.py: 585, 587, interscript/weavers/web.py: 370, 371, 372, 373, 374, 374, 375, 375, 376, 376, 377, 377, 386, interscript/compilers/cconfig.py: 13, 23, 23, 37, 37, 48
f interscript/drivers/sources/disk.py: 16, 19, 20, interscript/drivers/sources/ftp.py: 36, 37, interscript/drivers/sources/http.py: 33, 34, interscript/parsers/lalr1.py: 125, 126, 178, 179, 182, 185, 201, 202, interscript/felix/model/funcat.py: 10, 12, 62, 62, 63, 63, interscript/frames/platform.py: 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, interscript/frames/processf.py: 29, 33, 35, 37, interscript/frames/inputf.py: 165, 166, 261, 262, 263, 516, 517, 518, 680, 681, 682, 740, 742, 748, 749, 755, 755, 756, 756, 757, 757, 758, 758, 759, 759, 762, 763, 796, 798, 823, 825, 1134, 1135, 1136, interscript/utilities/diff.py: 9, 10, 11, 20, 21, 22, 24, 25, 26, 90, 91, 92, interscript/tests/test_diff.py: 18, 19, 20, 22, 23, 25
fadd interscript/parsers/lalr1.py: 734, 757
fdict interscript/drivers/sinks/bufdisk.py: 29, 40, 61, 67, 70, interscript/weavers/text.py: 100, 101, 110, 120, 130, 140, interscript/weavers/html.py: 478, 479, 488, 498, 508, 518, interscript/frames/masterf.py: 16, 53, 54, interscript/frames/passf.py: 28
fdummy interscript/parsers/lalr1.py: 738, 756
feed interscript/parsers/html.py: 10, 33
felix interscript/felix/model/fincat.py: 3, interscript/felix/model/stdcat.py: 2, interscript/felix/tests/stdcat_test.py: 5, interscript/felix/model/stdcat2.py: 2, interscript/felix/model/funcat.py: 2, interscript/felix/tests/func_test.py: 4, 5, 6, 7, interscript/felix/model/cons.py: 2
fetch interscript/drivers/sources/ftp.py: 23, 30, interscript/drivers/sources/http.py: 23, 27
file interscript/drivers/sources/base.py: 62, 66, interscript/drivers/sources/disk.py: 48, interscript/drivers/sources/url.py: 10, interscript/drivers/sources/ftp.py: 24, 28, 86, 89, 93, 94, 95, 98, 99, 100, 111, 112, 113, 121, interscript/drivers/sources/http.py: 24, 78, 79, 80, 84, 85, 86, 97, 98, 99, 115, interscript/drivers/sinks/disk.py: 18, 21, 21, 25, 27, interscript/drivers/sinks/bufdisk.py: 28, 32, 32, 39, 43, 43, 48, 62, 63, 64, 73, interscript/weavers/html.py: 448, 449, interscript/weavers/web.py: 646, 648, 650, interscript/weavers/latex.py: 88, 89, interscript/tanglers/base.py: 28, 30, 33, 37, 40, 41, 44, interscript/tanglers/null.py: 19, interscript/tanglers/doc.py: 15, 16, interscript/tanglers/c.py: 14, 17, 18, 35, 55, interscript/tanglers/cpp.py: 17, 18, 37, interscript/tanglers/java.py: 15, 16, interscript/tanglers/tcl.py: 14, 15, interscript/tanglers/python.py: 285, 289, 291, 295, 302, 344, 348, 352, 359, 360, 362, 363, 418, interscript/tanglers/perl.py: 152, 154, 156, 157, 281, 282, interscript/parsers/html.py: 9, interscript/frames/processf.py: 65, 76, interscript/frames/passf.py: 42, 44, 48, 49, 50, 59, 68, 72, interscript/frames/inputf.py: 185, 191, 195, 465, 468, 473, 474, 572, 576, 585, 590, 719, 720, 723, 725, 728, 729, 732, 733, 736, 737, 883, 884, interscript/getframes.py: 204, 205, interscript/bin/iscr.bat: 14
file2 interscript/frames/inputf.py: 553, 557, 561, 563
file_count interscript/frames/masterf.py: 56, 61, 61, 72, 74, 77
file_exists interscript/drivers/sinks/util.py: 63, interscript/drivers/sinks/bufdisk.py: 5, 23
file_pass interscript/frames/passf.py: 84, interscript/frames/inputf.py: 182, 308, 334, 352, 371, 407, 421
file_source interscript/drivers/sources/base.py: 57, interscript/drivers/sources/disk.py: 5, 38, 40, interscript/drivers/sources/url.py: 3, 6, 8, interscript/drivers/sources/ftp.py: 7, 11, 13, interscript/drivers/sources/http.py: 4, 11, 13
filename interscript/drivers/sources/disk.py: 13, 16, 18, 25, 26, 39, 41, 42, 44, 45, 48, 51, interscript/drivers/sources/url.py: 7, 9, 10, interscript/drivers/sinks/bufdisk.py: 32, 43, 51, 60, 62, 66, 69, interscript/weavers/text.py: 48, 49, 340, 342, 349, 351, interscript/weavers/html.py: 123, 126, 128, 129, 136, 141, 143, 144, 146, 154, 158, 160, 164, 167, 171, interscript/weavers/web.py: 31, 34, 70, 80, 84, 87, 190, 191, 218, 220, 230, 233, 234, 240, 246, 248, 250, 252, 323, 333, 335, 379, 403, 404, 505, 508, 524, 527, 553, 556, 571, 574, 590, 593, 611, 614, 637, 638, 640, 647, 648, interscript/weavers/latex.py: 186, interscript/frames/masterf.py: 27, interscript/frames/passf.py: 42, 61, 63, interscript/frames/inputf.py: 373, 374, 377, 482, 483, 763, 764, 769, 772, 1133, 1134, interscript/getoptions.py: 13, 29, 30, 35, interscript/getframes.py: 138, 203, 205, interscript/compilers/c.py: 16, 20, 27, 55, 59, 66, interscript/compilers/cpp.py: 15, 19, 26, 58, 62, 69
filenames interscript/compilers/c.py: 32, 40, 71, 78, interscript/compilers/cpp.py: 33, 41, 76, 83
files interscript/getframes.py: 203, 204, interscript/compilers/c.py: 40, 41, 78, 79, interscript/compilers/cpp.py: 41, 42, 83, 84, interscript/bin/iscr.bat: 8, 15
filestatus interscript/weavers/web.py: 58, 76
filestatus_output interscript/weavers/web.py: 639, 643
filestatus_weaver interscript/weavers/web.py: 641, 644
filter interscript/__init__.py: 26, interscript/frames/inputf.py: 102
filters interscript/weavers/filter.py: 70, 71, 72, 72, 75, 77, 78
final interscript/tanglers/python.py: 105, 166, 167, 211, 385, 400, 400, 413, 413
fincat interscript/felix/model/fincat.py: 4
find interscript/weavers/web.py: 152, interscript/frames/passf.py: 49
first interscript/tanglers/python.py: 311, 313, 326, interscript/felix/model/stdcat2.py: 32, 34, 35, interscript/felix/model/funcat.py: 26, 27, interscript/utilities/diff.py: 72, 76, 76, 78, 78, 79, 81
firstmap interscript/parsers/lalr1.py: 74, 75, 136, 147, 178, 201, 589
firstofstring interscript/parsers/lalr1.py: 143, 232, 274, 294, 299
firsts interscript/parsers/lalr1.py: 116, 119, 121, 127, 129, 133
flag interscript/weavers/web.py: 496, 497, 498
flist interscript/drivers/sinks/disk.py: 22, interscript/drivers/sinks/bufdisk.py: 34, 44, interscript/weavers/text.py: 87, 88, interscript/weavers/html.py: 466, 467, interscript/weavers/latex.py: 98, interscript/frames/masterf.py: 15, 40, 40, interscript/frames/passf.py: 27
flow_escape interscript/tanglers/perl.py: 30, 33, 194
flow_parse interscript/tanglers/perl.py: 40, 44, 47, 61, 65, 70, 73, 78, 83, 89, 93, 109
flow_text interscript/tanglers/perl.py: 34, 36, 187, 192, 192
flush interscript/drivers/sources/base.py: 54, interscript/drivers/sinks/base.py: 46
fm interscript/utilities/diff.py: 33, 35, 37
fmname interscript/utilities/diff.py: 31, 33, 38, 40
fnav interscript/weavers/web.py: 368, 384
fo interscript/utilities/diff.py: 32, 34, 36
follow interscript/parsers/lalr1.py: 170, 172, 180, 182, 182, 185, 191, 192, 196, 197, 197, 199, 203, 204, 207, 208, 208, 210, 211, 213, 214, 215
followmap interscript/parsers/lalr1.py: 80, 81, 215, 593
foname interscript/utilities/diff.py: 30, 32, 38, 39
fos interscript/parsers/lalr1.py: 274, 275, 280, 282, 294, 296, 297, 299, 300, 301, 303
foundmore interscript/parsers/lalr1.py: 285, 295, 302, 304, 328, 337, 339, 361, 368, 370
fparens interscript/parsers/lalr1.py: 746, 759
fragment interscript/weavers/html.py: 329, 332
frame interscript/getframes.py: 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 160, 161, 195, 205, 205, 206
frame_name interscript/weavers/web.py: 39, 44, 45
frame_percent interscript/weavers/web.py: 39, 40, 44
frame_src interscript/weavers/web.py: 39, 44, 45
frames interscript/__init__.py: 115, interscript/frames/processf.py: 2, 3, 4, interscript/frames/masterf.py: 2, interscript/frames/passf.py: 9
frames_anchor interscript/weavers/web.py: 461
frames_sink interscript/weavers/web.py: 24
fred interscript/tests/test_protocol.py: 12
ftimes interscript/parsers/lalr1.py: 742, 758
ftp interscript/__init__.py: 14, interscript/drivers/sources/ftp.py: 59, 63, 65, 72, 73, 74, 75, 80, 88, 90, 123, interscript/drivers/sources/http.py: 62
ftp_file_source interscript/__init__.py: 14, interscript/drivers/sources/ftp.py: 11
ftplib interscript/drivers/sources/ftp.py: 4, 59
full_filename interscript/drivers/sources/disk.py: 35, 36
func interscript/parsers/lalr1.py: 756, 757, 758, 759, 842, 870, 899, 899, 930, 930, interscript/felix/model/funcat.py: 15, 16, 18, 19, 21, 22, 34, 34, 40, 41, 41, 44, 48, 49, 49, 52
funcat interscript/felix/tests/func_test.py: 4, 5, 6, 7
funcref interscript/weavers/web.py: 55, 73
funcs interscript/felix/model/funcat.py: 6, 10, 16, 16, 25, 26, 28, 71, 72, 72, 76, 77, 83, 86
function interscript/tanglers/python.py: 374, interscript/felix/model/funcat.py: 4, 16, 19, 22, 32, 55, 62, interscript/felix/tests/func_test.py: 4, 10, 13, 16, 21, 24, 32, 35
function_name interscript/tanglers/python.py: 334, 350, 353, 357
function_names interscript/frames/inputf.py: 164, 165
function_product interscript/felix/model/funcat.py: 19, 70, interscript/felix/tests/func_test.py: 6
function_reference interscript/weavers/web.py: 655
function_sum interscript/felix/model/funcat.py: 22, 81, interscript/felix/tests/func_test.py: 6
functions interscript/weavers/web.py: 581, 583, interscript/tanglers/python.py: 351, 351, 352, interscript/frames/masterf.py: 20, 45, 45, interscript/frames/passf.py: 33
g interscript/drivers/sources/ftp.py: 17, 17, 51, 52, 53, interscript/drivers/sources/http.py: 17, 17, 48, 49, 50, interscript/parsers/lalr1.py: 427, 428, 428, 429, 603, 605, 728, 754, 755, 756, 757, 758, 759, 763, 773, 872, 873, 895, 902, 903, 911, 926
ge interscript/core/sets.py: 19, 25, 35, interscript/tests/test_sets.py: 25, 34
generator_buildno interscript/__init__.py: 75, 87, 102
generator_buildtime interscript/__init__.py: 79, 91
generator_hostname interscript/__init__.py: 76, 88, 103
generator_username interscript/__init__.py: 77, 89
generator_version interscript/__init__.py: 78, 90, 101
get interscript/drivers/sources/cache.py: 12, interscript/weavers/text.py: 74, interscript/weavers/html.py: 455, 547, 548, 585, interscript/weavers/web.py: 138, 318, 350, interscript/tanglers/perl.py: 104, interscript/parsers/lalr1.py: 116, 125, 226, 281, 383, 530, 590, interscript/frames/inputf.py: 835, 844
get_anchor interscript/weavers/text.py: 56, 64, interscript/weavers/html.py: 130, 216, 220, interscript/weavers/web.py: 203, 211, 221, 545, 631
get_arrows interscript/felix/model/fincat.py: 28, 73, 84, 99, 111, 113, 115
get_arrows_into interscript/felix/model/fincat.py: 50
get_arrows_outof interscript/felix/model/fincat.py: 45
get_attribute interscript/frames/inputf.py: 289
get_comment_tangler interscript/tanglers/null.py: 16, interscript/tanglers/doc.py: 12, interscript/tanglers/c.py: 23, interscript/tanglers/cpp.py: 23, interscript/tanglers/java.py: 21, interscript/tanglers/tcl.py: 20, interscript/tanglers/python.py: 368, interscript/tanglers/perl.py: 286, interscript/frames/inputf.py: 850
get_filename interscript/drivers/sources/base.py: 71
get_formatted_heading_number interscript/weavers/text.py: 319, 330, interscript/weavers/html.py: 234, 251, interscript/weavers/web.py: 303, 330, 331, 400, 401
get_language interscript/weavers/text.py: 339, 348, interscript/weavers/html.py: 137, 155, interscript/weavers/web.py: 231, interscript/tanglers/base.py: 16
get_lines_read interscript/drivers/sources/base.py: 21, interscript/frames/inputf.py: 484, 493
get_master_frame interscript/frames/masterf.py: 90
get_new_sequence_number interscript/weavers/base.py: 11, interscript/weavers/web.py: 129, interscript/frames/passf.py: 96
get_new_test_number interscript/frames/passf.py: 92, interscript/frames/inputf.py: 617, 636, 958
get_nonobjects interscript/felix/model/fincat.py: 19, 161, 174, 175, 176, 187
get_objects interscript/felix/model/fincat.py: 24, 67, 68, 76, 86, 88, 125, 125, interscript/felix/model/stdcat2.py: 40
get_pass_frame interscript/tests/test_stacking_weaver.pak: 2, 3, interscript/frames/passf.py: 89
get_persistent_frame interscript/drivers/sources/cache.py: 11, interscript/drivers/sinks/cache.py: 20, interscript/weavers/base.py: 12, interscript/weavers/web.py: 130, interscript/frames/masterf.py: 92
get_process_frame interscript/frames/processf.py: 62
get_sink_name interscript/drivers/sinks/base.py: 33, interscript/weavers/raw.py: 6, interscript/weavers/text.py: 12, 340, 349, interscript/weavers/html.py: 35, 136, 154, interscript/weavers/web.py: 230, interscript/weavers/latex.py: 27, 249, 255
get_source_name interscript/drivers/sources/base.py: 18, interscript/frames/passf.py: 82, interscript/frames/inputf.py: 79, 90, 492
get_string_tangler interscript/tanglers/c.py: 26, interscript/tanglers/cpp.py: 26, interscript/tanglers/java.py: 24, interscript/tanglers/tcl.py: 23, interscript/tanglers/python.py: 371, interscript/tanglers/perl.py: 289, interscript/frames/inputf.py: 865
get_tangler interscript/frames/inputf.py: 751
get_tokens interscript/tokenisers/python.py: 155, 162, 172
get_unit interscript/felix/model/stdcat.py: 24, 27
get_verbosity interscript/frames/inputf.py: 426, 969, 984
get_weaver interscript/tanglers/python.py: 372, interscript/tanglers/perl.py: 291, interscript/parsers/html.py: 28, interscript/frames/inputf.py: 432, 466, 599, 649, 765, 861, 873, 877, 891, 896, 901, 906, 911, 916, 921, 926, 938, 971, 986, 1021, 1137
get_working_directory interscript/frames/install.py: 16, 17, 18, 19, 20, 21, interscript/frames/platform.py: 30
getattr interscript/core/protocols.py: 53, 62, 81, 93, interscript/weavers/multiplexor.py: 22, interscript/parsers/lalr1.py: 677, 678
getcwd interscript/drivers/sources/disk.py: 28, interscript/drivers/sinks/util.py: 45, interscript/frames/platform.py: 31
getfile interscript/drivers/sources/http.py: 78
getframes interscript/__init__.py: 114
getopt interscript/getoptions.py: 8, interscript/getframes.py: 8, 113
getoption_frames interscript/__init__.py: 114, 116, interscript/getframes.py: 112
getoptions interscript/__init__.py: 51, interscript/getframes.py: 8
getoutput interscript/utilities/commands.py: 27
getreply interscript/drivers/sources/http.py: 76
getstatusoutput interscript/frames/inputf.py: 932, interscript/utilities/commands.py: 29, 35
glb interscript/frames/processf.py: 65, 69, interscript/frames/inputf.py: 587, 590, 719, 720, 723, 725, 728, 732, 736
glob interscript/getframes.py: 5, 203, 203
global_frame interscript/__init__.py: 4, 96, 97, 98, 99, 100, 101, 102, 103, 104, 117, interscript/weavers/web.py: 25, interscript/frames/processf.py: 11, 12, 12, 47, 48, interscript/frames/inputf.py: 65, 65, 195, 587, 931
globals interscript/tanglers/python.py: 289, interscript/parsers/html.py: 183
go interscript/parsers/lalr1.py: 640, 681
goto interscript/parsers/lalr1.py: 375, 407, 427, 603, 615, 631, 631, 632, 632
goto_table interscript/parsers/lalr1.py: 634, 640, 696
gotomap interscript/parsers/lalr1.py: 397, 404, 405, 408
group interscript/weavers/filter.py: 44, interscript/tanglers/python.py: 288, interscript/tanglers/perl.py: 53, 97, 103, 202, 221, 225, 239, 259, 268, 271, interscript/tokenisers/python.py: 31, 32, 33, 43, 45, 47, 48, 49, 55, 56, 59, 62, 63, 65, 68, 68, 69, 70, 71, interscript/frames/inputf.py: 558, 720, 724, 729, 733, 733, 737, interscript/getoptions.py: 18, 18, 24, 26, 26
gs_list interscript/parsers/lalr1.py: 143, 146, 147
gstack interscript/parsers/lalr1.py: 5, 641
gt interscript/core/sets.py: 34, interscript/tests/test_sets.py: 26, 35, interscript/parsers/lalr1.py: 615, 616, 617, 629, 632, 633, 696, 701, 702
h interscript/weavers/text.py: 97, 99, 104, 106, 108, 114, 116, 118, 124, 126, 128, 134, 136, 138, 330, 332, 333, interscript/weavers/html.py: 475, 477, 482, 484, 486, 492, 494, 496, 502, 504, 506, 512, 514, 516, 550, 552, interscript/weavers/web.py: 332, 333, 335, 382, 402, 404, interscript/weavers/latex.py: 285, 287
ha interscript/weavers/web.py: 81, 82
handle_comment interscript/parsers/html.py: 52
handle_data interscript/parsers/html.py: 42
has_class_proto interscript/core/protocols.py: 78, 97, 100
has_key interscript/core/sets.py: 10, 21, 29, 50, 62, 140, interscript/core/protocols.py: 73, 87, interscript/weavers/text.py: 52, 58, 59, interscript/weavers/html.py: 48, 143, 253, 581, 591, 593, 594, 598, 604, interscript/weavers/web.py: 22, 109, 145, 199, 205, 206, 233, interscript/weavers/latex.py: 116, 136, 144, 149, 154, 164, 175, 183, 188, interscript/weavers/auto.py: 42, interscript/tanglers/python.py: 343, 347, 351, interscript/parsers/lalr1.py: 49, 180, 191, 196, 203, 207, 276, 278, 293, 310, 322, 324, 336, 346, 356, 404, 412, interscript/felix/model/fincat.py: 128, 153, 166, 169, interscript/felix/model/stdcat2.py: 28, interscript/frames/masterf.py: 62, 93, interscript/frames/inputf.py: 188, 290, 427, 810, 812, interscript/getframes.py: 79, 82, 85, 88, interscript/compilers/cconfig.py: 30, 32, 34, 36, 38, 42
has_protocol interscript/core/protocols.py: 91, 109, interscript/tests/test_protocol.py: 6, 7, 8, 22, 23, 24, 25, 26, 27, interscript/felix/model/stdcat.py: 74, interscript/frames/inputf.py: 29, 768, 774, 816, 818
has_protocols interscript/core/protocols.py: 107
has_type_proto interscript/core/protocols.py: 84, 101
hasattr interscript/core/protocols.py: 52, 61, 80, 92, 104, interscript/drivers/sources/ftp.py: 20, 31, 51, 62, 69, 70, 71, 79, 118, interscript/drivers/sources/http.py: 20, 28, 48, 59, 67, 103, interscript/drivers/sinks/bufdisk.py: 49, interscript/weavers/multiplexor.py: 20, 28, 29, 39, 40, 43, interscript/weavers/web.py: 147, interscript/tanglers/perl.py: 209, 236, interscript/parsers/lalr1.py: 553, 554, 676
hash_comment_tangler interscript/tanglers/cpp.py: 31, 42, 44, interscript/tanglers/tcl.py: 3, 21, interscript/tanglers/perl.py: 287
have interscript/bin/iscr.bat: 15
hcount interscript/weavers/text.py: 26, 313, 313, 314, 314, 315, 316, 321, 322, 323, interscript/weavers/html.py: 39, 228, 228, 229, 229, 230, 231, 236, 237, 238, 265, interscript/weavers/web.py: 165, 257, 258, 259, 260, 260, 305, 306, 307
head interscript/weavers/text.py: 73, 86, 99, 106, 116, 126, 136, 151, 162, 326, interscript/weavers/html.py: 242, 407, 431, 454, 465, 477, 484, 494, 504, 514, 528, 538, interscript/weavers/web.py: 262, 406, interscript/tests/test_stacking_weaver.pak: 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, interscript/weavers/latex.py: 49, 71, 97, 103, 259, interscript/tanglers/perl.py: 221, 225, interscript/parsers/html.py: 138, 141, 144, 147, 150, 153, interscript/frames/inputf.py: 646, 965, 974, 987, interscript/utilities/commands.py: 52, 54, interscript/tests/example.pak: 3, 5, 8
head_extra interscript/weavers/web.py: 386
head_offset interscript/frames/inputf.py: 82, 297, 306, 324, 332, 967, 982, 990, 990, 997, 999
headers interscript/drivers/sources/http.py: 76
headid interscript/weavers/web.py: 495, 498
heading interscript/frames/inputf.py: 980
heading_level_offset interscript/weavers/html.py: 44, 257, 599, interscript/weavers/latex.py: 34, 145, 268, interscript/tanglers/perl.py: 8, 15, 15, 221, 225
heading_prefix interscript/weavers/web.py: 385
heading_reference interscript/weavers/web.py: 652
headings interscript/weavers/text.py: 187, 188, interscript/weavers/html.py: 546, 549, 550, interscript/tests/test_stacking_weaver.pak: 5, interscript/weavers/latex.py: 282, 283, 284, 285, interscript/frames/inputf.py: 1020, 1021
hello interscript/tests/output/mymodule2.py: 6, interscript/tests/output/mymodule3.py: 7
hlevel interscript/weavers/text.py: 71, 72, 73, 84, 85, 86, 95, 98, 99, 105, 106, 115, 116, 125, 126, 135, 136, 149, 150, 151, 160, 161, 162, interscript/weavers/html.py: 400, 406, 407, 424, 430, 431, 452, 453, 454, 463, 464, 465, 473, 476, 477, 483, 484, 493, 494, 503, 504, 513, 514, 526, 527, 528, 536, 537, 538, interscript/weavers/web.py: 644, interscript/weavers/latex.py: 44, 48, 49, 66, 70, 71, 96, 97, 102, 103, interscript/frames/inputf.py: 628, 643, 643
hn interscript/weavers/web.py: 330, 332, 385, 400, 402
hnav interscript/weavers/web.py: 186, 187, 367, 383
hnum interscript/weavers/web.py: 331, 333, 401, 404, 468, 471, 472, 476, 482, 483, 493, 495
hnumber interscript/weavers/text.py: 320, 322, 322, 323, 323, 324, interscript/weavers/html.py: 235, 237, 237, 238, 238, 239, 251, 255, 262, interscript/weavers/web.py: 304, 306, 306, 307, 307, 308
ho interscript/frames/inputf.py: 297, 306, 324, 332
home interscript/weavers/web.py: 338, 364, 364
home_anchor interscript/weavers/web.py: 174, 175, 338, 461
home_file interscript/weavers/web.py: 81, 144, 150, 174, 177, 374
home_nav interscript/weavers/web.py: 175
host interscript/drivers/sources/ftp.py: 12, 16, 16, 63, 65, 66, 120, interscript/drivers/sources/http.py: 12, 16, 16, 60, 62, 63, 105
hostname interscript/__init__.py: 72, 84, 99
hprefix interscript/weavers/html.py: 252, 254, 255, 262
href interscript/weavers/text.py: 57, 60, 61, 64, 65, 66, interscript/weavers/html.py: 220, 221, 222, interscript/weavers/web.py: 194, 196, 204, 207, 208, 211, 212, 213, 468, 471, 476, 482, 493, 500, 502, 631, 632
html interscript/__init__.py: 22, 29, interscript/weavers/web.py: 3, 4, interscript/weavers/auto.py: 5, interscript/frames/passf.py: 12, interscript/frames/inputf.py: 31, 409
html_entity interscript/tanglers/perl.py: 20, 104
html_eol interscript/weavers/auto.py: 38, interscript/getframes.py: 136, 160
html_filter interscript/__init__.py: 29, interscript/parsers/html.py: 22, interscript/frames/passf.py: 12, interscript/frames/inputf.py: 31, 405, 419
html_level interscript/weavers/html.py: 257, 258, 258, 261, 263
html_parser interscript/frames/inputf.py: 405, 419, 737
html_weaver interscript/__init__.py: 22, interscript/weavers/html.py: 29, interscript/weavers/web.py: 3, 380, 641, interscript/tests/test_stacking_weaver.pak: 3, interscript/weavers/auto.py: 5, 12, 16
http interscript/__init__.py: 15, interscript/drivers/sources/http.py: 56, 60, 72, 73, 74, 75, 76, 78
http_file_source interscript/__init__.py: 15, interscript/drivers/sources/http.py: 11
httplib interscript/drivers/sources/http.py: 8, 56
i interscript/core/sets.py: 121, 122, interscript/core/stacks.py: 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 30, 30, interscript/drivers/sources/disk.py: 21, 22, 22, interscript/weavers/text.py: 179, 180, 182, 183, 204, 205, 206, 206, 209, 210, 211, 211, 321, 322, interscript/weavers/html.py: 145, 146, 236, 237, interscript/weavers/web.py: 159, 159, 218, 219, 220, 305, 306, 467, 468, 470, 470, 475, 476, 478, 478, 543, 544, 546, interscript/weavers/filter.py: 71, 72, 72, interscript/parsers/lalr1.py: 39, 40, 40, 123, 124, 125, 130, 131, 131, 213, 213, 280, 281, 387, 388, 388, 698, 699, 699, 701, 702, 702, 754, 755, 756, 780, 784, 784, 784, 785, 787, 788, 789, 790, 790, 793, 794, 794, 795, 796, 797, 797, 799, 800, 800, 802, 803, 803, 804, 805, 806, 806, 808, 809, 809, 811, 812, 812, 813, 813, 815, 817, 817, 819, 820, 820, 821, 822, 823, 823, 825, 826, 826, interscript/felix/model/funcat.py: 76, 77, 77, interscript/felix/model/cons.py: 11, 12, 12, 16, 17, 17, 21, 22, 22, 22, 27, 28, 28, 28, 33, 34, 34, 39, 40, 40, 73, 74, 78, 79, 83, 85, 86, 87, 91, 93, 94, 95, 98, 99, 100, 103, 104, 105, interscript/frames/inputf.py: 252, 253, 253, 657, 658, 658, 705, 706, 706, 942, 943, 945, interscript/utilities/diff.py: 55, 56, 59, 64, 65, 66, 79, 83, 84, interscript/tests/test_diff.py: 21, 21, 21, 24, 24, 24
id interscript/tanglers/python.py: 310, 316, 336, 342, 342, 343, 343, 344, 347, 347, 348, 351, 351, 352, 354, 356, interscript/parsers/lalr1.py: 717, 727, 768, 769, 769, 771, 771
identifier_reference interscript/weavers/html.py: 400, interscript/weavers/web.py: 653, interscript/weavers/latex.py: 44, interscript/frames/inputf.py: 922
identity interscript/felix/model/funcat.py: 32, 63, 65, 66, interscript/felix/tests/func_test.py: 4, 38
identref interscript/weavers/web.py: 56, 74
ids interscript/weavers/html.py: 401, 401, 402, 403, 403, 404, 410, 425, 426, 427, 428, 434, interscript/weavers/web.py: 515, 515, 516, 517, 517, 519, 563, 564, 565, 567, 581, 582, 583, 585, 621, 622, 623, 627, 630, interscript/weavers/latex.py: 45, 45, 46, 52, 67, 68, 74, interscript/tanglers/python.py: 343, 343, 344, interscript/frames/masterf.py: 13, 39, 39, interscript/frames/passf.py: 26
ifdata interscript/frames/inputf.py: 339, 340, 355, 356
iflist interscript/drivers/sources/disk.py: 41, interscript/weavers/text.py: 152, 153, interscript/weavers/html.py: 529, 530, interscript/weavers/latex.py: 104, interscript/frames/masterf.py: 14, 41, 41, interscript/frames/passf.py: 29
ifthenelse interscript/parsers/lalr1.py: 933, 934, 941
ii interscript/parsers/lalr1.py: 475, 478, 478, 480, 481, 481
inc interscript/compilers/c.py: 23, 25, 25, 27, 62, 64, 64, 66, interscript/compilers/cpp.py: 22, 24, 24, 26, 65, 67, 67, 69
incdirs interscript/compilers/cconfig.py: 9, 19, 19, 33, 50
include_code interscript/frames/inputf.py: 354
include_file interscript/frames/inputf.py: 315
include_files interscript/weavers/text.py: 163, 164, interscript/weavers/html.py: 539, 540, interscript/weavers/web.py: 601, 603, interscript/frames/masterf.py: 18, 43, 43, interscript/frames/passf.py: 31, 72, interscript/frames/inputf.py: 318, 340, 356, 397, 1131
include_html interscript/frames/inputf.py: 394
include_source interscript/frames/inputf.py: 319, 322
indent interscript/tanglers/python.py: 49, 50, 52, 53, 55, 58, 62, 65, 73, 76, 78, 81, 85, 87, 97, 109, 112, 118, 119, 123, 124, 127, 131, 133, 136, 140, 142, 146, 147, 148, 153, 154, 159, 160, 161, 164, 165, 168, 170, 178, 179, 192, 195, 199, 203, 215, 226, 230, 235, 244, 247, 252, 262, 376, 392, 405, interscript/tokenisers/python.py: 315
indents interscript/tokenisers/python.py: 151, 235, 236, 238, 239, 239, 315
index interscript/core/sets.py: 46, 47, 114, 115, 117, 118, interscript/core/stacks.py: 17, 17, 18, 18, 19, 19, 53, 53, 59, 59, interscript/weavers/html.py: 128, 129, 130, interscript/parsers/lalr1.py: 233, 234, 236, 237, 387, 407, 459, 487, 605, 617, 632, interscript/frames/inputf.py: 834, 835, 837, 843, 844
indexnav interscript/weavers/web.py: 52, 63
indexview interscript/weavers/web.py: 51, 66
inhibit_sref interscript/tanglers/base.py: 10, 28, 29, 29, 40, 41, interscript/tanglers/null.py: 19, interscript/tanglers/doc.py: 15, interscript/tanglers/c.py: 35, 55, interscript/tanglers/cpp.py: 37, interscript/tanglers/python.py: 285, 294, 295, 418, interscript/tanglers/perl.py: 152, 153, 153, interscript/frames/inputf.py: 880, 884
initLALR1items interscript/parsers/lalr1.py: 442, 467
initial interscript/tanglers/python.py: 104, 130, 132, 210, 384, 399, 399, 412, 412, interscript/tokenisers/python.py: 252, 254, 255, 257, 263, 283, 287, 296, 298, 301, 302
inner interscript/parsers/lalr1.py: 459, 460, 487, 489, 491, 505, 508, 509, 511, 512
inpt interscript/frames/passf.py: 73, 80, 82, 84, interscript/frames/inputf.py: 299, 306, 307, 308, 325, 332, 333, 334, 343, 350, 350, 351, 352, 362, 369, 369, 370, 371, 398, 405, 405, 406, 406, 407, 412, 419, 419, 420, 420, 421, 483, 484, 484, 524
input interscript/parsers/lalr1.py: 768, 773, 881, 890, 919, 925, 935, 936
input_adapter interscript/felix/model/funcat.py: 39, interscript/felix/tests/func_test.py: 7
input_file interscript/frames/passf.py: 59, 75
input_filename interscript/drivers/sinks/disk.py: 8, 14, 21, interscript/drivers/sinks/bufdisk.py: 10, 19, 26, 29, 32, 34, 37, 40, 43, 44
input_frame interscript/parsers/html.py: 23, 27, 27, 28, 29, 63, 183, interscript/frames/passf.py: 9, 73, interscript/frames/inputf.py: 58, 299, 325, 343, 362, 398, 412
inputf interscript/frames/passf.py: 9
insert interscript/core/sets.py: 53, 104, 127, 138, 150, interscript/core/stacks.py: 59, 59, interscript/parsers/lalr1.py: 50, 51, 53, 54, 57, 100, 121, 129, 162, 213, 670, 672
insert_code interscript/frames/inputf.py: 338
install_frame interscript/frames/install.py: 2
install_point interscript/frames/install.py: 68, 88, 90
installer interscript/bin/iscr.bat: 16
int interscript/tanglers/perl.py: 98, interscript/frames/processf.py: 56, interscript/frames/inputf.py: 966, 981, interscript/getframes.py: 141, 142, 148, 149
int_add interscript/felix/model/stdcat.py: 32, interscript/felix/tests/stdcat_test.py: 5, 7, 8
int_mul interscript/felix/model/stdcat.py: 53, interscript/felix/tests/stdcat_test.py: 5, 9, 10
internal interscript/tests/test_stacking_weaver.pak: 8, 9, 12, 13, 14
interscript interscript/__init__.py: 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 18, 20, 21, 22, 23, 24, 25, 26, 27, 29, 31, 32, 33, 34, 35, 36, 37, 38, 39, 46, 47, 48, 49, 50, 114, 115, interscript/tests/test_sets.py: 2, 3, interscript/tests/test_protocol.py: 4, 5, interscript/drivers/sources/disk.py: 4, 5, 6, interscript/drivers/sources/url.py: 3, 4, interscript/drivers/sources/ftp.py: 7, 8, interscript/drivers/sources/http.py: 4, 5, interscript/drivers/sources/stdin.py: 7, 8, interscript/drivers/sources/cache.py: 2, 3, interscript/drivers/sinks/null.py: 2, interscript/drivers/sinks/tee.py: 2, interscript/drivers/sinks/disk.py: 3, 4, 5, interscript/drivers/sinks/bufdisk.py: 3, 4, 5, interscript/drivers/sinks/stdout.py: 3, interscript/drivers/sinks/cache.py: 3, interscript/drivers/storage/memory.py: 2, 3, 4, interscript/drivers/storage/disk.py: 2, 3, interscript/weavers/raw.py: 2, interscript/weavers/text.py: 2, interscript/weavers/html.py: 2, 5, 6, 7, interscript/weavers/web.py: 2, 3, 4, 5, 6, 7, interscript/weavers/latex.py: 2, interscript/weavers/auto.py: 2, 3, 4, 5, 6, 7, interscript/weavers/filter.py: 2, interscript/tanglers/null.py: 10, interscript/tanglers/doc.py: 5, interscript/tanglers/data.py: 5, interscript/tanglers/c.py: 5, interscript/tanglers/cpp.py: 5, interscript/tanglers/java.py: 2, 3, 4, interscript/tanglers/tcl.py: 2, 3, interscript/tanglers/python.py: 6, 9, 10, interscript/tanglers/perl.py: 2, 3, interscript/parsers/html.py: 2, interscript/tests/tgram.py: 2, 3, 4, interscript/felix/model/basecat.py: 3, interscript/felix/model/fincat.py: 3, interscript/felix/model/stdcat.py: 2, 74, interscript/felix/tests/stdcat_test.py: 5, interscript/felix/model/stdcat2.py: 2, 3, interscript/felix/model/funcat.py: 2, interscript/felix/tests/func_test.py: 4, 5, 6, 7, interscript/felix/model/cons.py: 2, interscript/frames/processf.py: 2, 3, 4, 5, interscript/frames/masterf.py: 2, 3, interscript/frames/passf.py: 6, 7, 8, 9, 10, 11, 12, interscript/frames/inputf.py: 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 33, 224, 697, interscript/getframes.py: 8, interscript/compilers/c.py: 5, 10, 49, interscript/compilers/cpp.py: 5, 52, interscript/tests/test_compilers.py: 5, 6, interscript/tests/test_diff.py: 5, 6, interscript/bin/iscr.py: 10, 11, interscript/bin/iscr.bat: 11, 11, 13, interscript/tests/example.pak: 4
interscript_from_options interscript/frames/inputf.py: 223, 278
interscript_output interscript/frames/inputf.py: 762
inverse interscript/felix/model/stdcat.py: 48, interscript/felix/model/stdcat2.py: 47
ip interscript/parsers/lalr1.py: 645, 649, 649, 656, 656
is_arrow interscript/felix/model/fincat.py: 72, interscript/felix/model/stdcat.py: 6, 7, 11, 12, 42, 63, 73, 77, 83, 90, 97, interscript/felix/model/stdcat2.py: 10, 30, interscript/felix/model/funcat.py: 62, interscript/felix/model/cons.py: 10, 12, 48, 49, 72, 74, 85, 86, 93, 94, 99, 104, 113, 114
is_begin_or_end_method interscript/frames/inputf.py: 101, 102
is_equivalent interscript/felix/model/funcat.py: 58
is_object interscript/felix/model/fincat.py: 75, interscript/felix/model/stdcat.py: 7, 12, 29, 76, interscript/felix/model/stdcat2.py: 9, 10, 27, interscript/felix/model/funcat.py: 63, interscript/felix/model/cons.py: 15, 17, 51, 52, 77, 79, 116, 117
isatty interscript/drivers/sources/base.py: 45, interscript/drivers/sinks/base.py: 17
isclass interscript/core/protocols.py: 39
iscr interscript/bin/iscr.bat: 2, 11
iscrcopt interscript/weavers/html.py: 5, 6, 7
isdir interscript/drivers/sinks/util.py: 14, 19
isinstance interscript/felix/model/funcat.py: 27, 62, 63
isinstancetype interscript/core/protocols.py: 42, 46
iskeyword interscript/tanglers/python.py: 316, 342
it interscript/bin/iscr.bat: 14
item interscript/core/stacks.py: 52, 52, 53, 53, 59, 59, 60, 60, interscript/weavers/multiplexor.py: 64, interscript/parsers/lalr1.py: 480, 483, 506, 508, 509, interscript/frames/inputf.py: 1039, 1040
item_i interscript/parsers/lalr1.py: 504, 507, 510, 510
items interscript/parsers/lalr1.py: 218, 219, 220, 425, 427, 572, 577, 625, 628, 632, 632
itemset interscript/parsers/lalr1.py: 375, 377, 393, 398, 407, 454, 457
j interscript/core/sets.py: 121, 122, interscript/core/stacks.py: 20, 20, 21, 21, 22, 22, interscript/utilities/diff.py: 67, 68
java interscript/__init__.py: 33, interscript/frames/inputf.py: 24
java_tangler interscript/__init__.py: 33, interscript/tanglers/java.py: 6, interscript/frames/inputf.py: 24
join interscript/drivers/sources/base.py: 37, interscript/drivers/sources/disk.py: 31, interscript/drivers/sinks/base.py: 31, interscript/weavers/web.py: 141, interscript/tokenisers/python.py: 31, interscript/frames/platform.py: 28, interscript/frames/passf.py: 50, interscript/frames/inputf.py: 262, 581, 607, 608, 681, interscript/compilers/c.py: 20, 40, 59, 78, interscript/compilers/cpp.py: 19, 41, 62, 83, interscript/utilities/diff.py: 44, 45, interscript/utilities/commands.py: 54
just interscript/bin/iscr.bat: 13
just_copy interscript/parsers/lalr1.py: 856, 860
k interscript/core/sets.py: 118, 119, interscript/drivers/sources/base.py: 14, 15, 15, interscript/drivers/sources/ftp.py: 18, 19, 19, interscript/drivers/sources/http.py: 18, 19, 19, interscript/drivers/sinks/base.py: 11, 12, 12, interscript/drivers/storage/memory.py: 13, 14, 14, interscript/weavers/html.py: 409, 410, 411, 433, 434, 435, interscript/weavers/web.py: 103, 104, 105, 540, 541, 542, 544, interscript/weavers/latex.py: 51, 52, 53, 73, 74, 75, interscript/parsers/lalr1.py: 16, 17, 17, 211, 213, 214, 292, 293, 294, 297, 299, 301, 303, 335, 336, 338, 365, 366, 384, 385, 591, 592, 593, 596, interscript/frames/install.py: 88, 89, 90, 97, 98, 98, interscript/frames/masterf.py: 9, 11, 11, 12, 12, 60, 62, 63, 63, 66, 70, 70, 71, 71, interscript/getframes.py: 72, 72, 76, 76, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 92, interscript/utilities/diff.py: 71, 74, 74, 74, 75, 76, 77, 77
k1 interscript/core/sets.py: 105, 106, 109
k2 interscript/core/sets.py: 107, 108, 109
kargs interscript/frames/inputf.py: 267, 270, 272
kernelitems interscript/parsers/lalr1.py: 394, 443, 470, 603, 605, 615, 616, 617, 625
kernels interscript/parsers/lalr1.py: 394, 443, 446, 448, 454, 459
kernelsoflalr1items interscript/parsers/lalr1.py: 420, 443
key interscript/core/sets.py: 91, 91, interscript/weavers/text.py: 109, 110, 112, 119, 120, 122, 129, 130, 132, 139, 140, 142, 417, 420, 425, 428, 432, 435, interscript/weavers/html.py: 305, 306, 487, 488, 490, 497, 498, 500, 507, 508, 510, 517, 518, 520, interscript/weavers/web.py: 108, 109, 110, 629, 630, 632, interscript/weavers/latex.py: 336, 338, interscript/tanglers/perl.py: 145, 148, 239, 240, 240, 246, 247, 256, 263, 265, interscript/frames/inputf.py: 268, 269, 270, 270, 1072, 1073
keys interscript/core/sets.py: 14, 30, 41, 44, 47, 70, 74, 88, 88, 90, 90, 91, 105, 107, 115, 118, 122, 126, 139, 149, interscript/drivers/sources/base.py: 14, interscript/drivers/sources/ftp.py: 18, interscript/drivers/sources/http.py: 18, interscript/drivers/sinks/base.py: 11, interscript/drivers/storage/memory.py: 13, interscript/weavers/text.py: 101, interscript/weavers/html.py: 404, 404, 405, 409, 428, 428, 429, 433, 479, interscript/weavers/web.py: 99, 99, 100, 103, 536, 536, 537, 540, 627, 627, 628, 629, interscript/weavers/latex.py: 46, 46, 47, 51, 68, 68, 69, 73, interscript/parsers/lalr1.py: 16, 74, 80, 154, 211, 286, 289, 292, 329, 332, 335, 362, 363, 365, 384, 591, interscript/felix/model/fincat.py: 22, 26, 31, 31, 36, 42, 147, 152, 185, 192, interscript/frames/install.py: 88, 91, 97, interscript/frames/masterf.py: 9, 60, interscript/frames/inputf.py: 100, 268, interscript/getframes.py: 70, 70, 71, 72, 74, 74, 75, 76, 100, interscript/compilers/cconfig.py: 52, 55
keyword interscript/tanglers/python.py: 14, 316, 342
keywords interscript/weavers/html.py: 45, 253, 254, 572, 602, interscript/weavers/web.py: 22, 23, 134, 138
kind interscript/weavers/html.py: 329, 330, 331, 333, interscript/weavers/web.py: 630, 632, interscript/tanglers/python.py: 310, 315, 317, 318, 322, 323, 324, 325, 336, 337, 339, 341, interscript/tanglers/perl.py: 120, 122, 123, 124, 127, 129, 130, 131, 137, 139, 141, 142, 143, 146, 148, 149, 150, interscript/frames/inputf.py: 616, 620, 1130, 1131
kpi interscript/parsers/lalr1.py: 398, 399, 412, 413, 415
kri interscript/parsers/lalr1.py: 398, 399, 412, 413, 415
kwds interscript/drivers/sources/base.py: 11, 14, 15, 58, 59, interscript/drivers/sources/disk.py: 39, 40, interscript/drivers/sources/url.py: 7, 8, interscript/drivers/sources/ftp.py: 12, 13, 18, 19, interscript/drivers/sources/http.py: 12, 13, 18, 19, interscript/drivers/sources/stdin.py: 12, 13, interscript/drivers/sinks/base.py: 5, 11, 12, interscript/drivers/sinks/tee.py: 4, interscript/drivers/storage/memory.py: 7, 13, 14, interscript/weavers/raw.py: 4, interscript/weavers/multiplexor.py: 15, 16, 18, 22, 33, 64, 70, interscript/weavers/text.py: 8, 71, 84, 95, 149, 160, 187, interscript/weavers/html.py: 32, 45, 48, 49, 400, 424, 452, 463, 473, 526, 536, 546, 547, 548, 572, 581, 582, 585, 591, 592, 593, 594, 594, 595, 595, 598, 599, 602, 604, 605, interscript/weavers/web.py: 124, 134, 145, 146, 652, 653, 654, 655, 656, interscript/weavers/latex.py: 22, 37, 44, 66, 92, 96, 102, 108, 116, 117, 136, 137, 144, 145, 149, 150, 154, 155, 164, 165, 175, 176, 183, 184, 188, 189, 282, interscript/parsers/lalr1.py: 13, 16, 17, interscript/frames/inputf.py: 242, 268, 270, 807, 810, 811, 812, 813, 889, 892, 894, 897, 899, 902, 904, 907, 909, 912, 919, 922, 924, 927, 1020, 1021, 1039, 1040, interscript/compilers/c.py: 9, 11, 13, 14, 16, 18, 32, 34, 48, 50, 52, 53, 55, 57, 71, 73, interscript/compilers/cpp.py: 8, 10, 12, 13, 15, 17, 33, 35, 51, 53, 55, 56, 58, 60, 76, 78, interscript/compilers/cconfig.py: 7, 14, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 42, 43, interscript/utilities/diff.py: 14
l interscript/weavers/html.py: 12, 15, 15, 17, 17, 18, 21, 24, 24, 26, 26, 27, interscript/weavers/latex.py: 14, 16, 16, 17, 17, 18, interscript/felix/model/cons.py: 26, 28, 29, 32, 34, 35, 38, 40, 41, interscript/frames/inputf.py: 521, 522, 523, 523, 523, 524, 944, 945, 1139, 1140
la_table interscript/parsers/lalr1.py: 445, 447, 449, 450, 460, 463, 467, 474, 489, 491, 507
label interscript/weavers/text.py: 51, 54, 56, 59, 60, 63, 64, 68, interscript/weavers/html.py: 213, 214, 216, 217, 219, 220, 222, 224, interscript/weavers/web.py: 193, 194, 195, 196, 198, 201, 203, 206, 207, 210, 211, 213, 215, 322, 324, 326, 387, 630, 631, interscript/frames/inputf.py: 449, 451, 453, 455, 456
label_chunk interscript/weavers/html.py: 123, interscript/frames/inputf.py: 374, 386
lalr1 interscript/tests/tgram.py: 2, 3, 4
language interscript/weavers/text.py: 339, 341, 348, 351, interscript/weavers/html.py: 137, 140, 155, 157, 160, 163, 167, 170, interscript/weavers/web.py: 231, 239, interscript/tanglers/base.py: 14, 16, interscript/tanglers/null.py: 14, interscript/tanglers/doc.py: 10, interscript/tanglers/c.py: 12, 53, interscript/tanglers/cpp.py: 12, 35, interscript/tanglers/java.py: 10, interscript/tanglers/tcl.py: 9, interscript/tanglers/python.py: 276, interscript/tanglers/perl.py: 10, interscript/frames/inputf.py: 339, 355, 382, 383, 397, 767, 778, 778, 779, 784, 785, 786, 787, 788, 788, 789, 789, 790, 790, 791
last interscript/weavers/web.py: 318, 319, 350, 351, 351, interscript/tanglers/python.py: 312, 326, 327
last_head interscript/frames/inputf.py: 644, 968, 983, 999
last_inhibit_sref interscript/drivers/sinks/base.py: 9, interscript/tanglers/base.py: 32, 34, 36
last_level interscript/weavers/web.py: 465, 474, 479, 481, 481, 485, 486, 488, 488
last_source_count interscript/tanglers/base.py: 31, 38, interscript/tanglers/perl.py: 155, 158
last_source_file interscript/drivers/sinks/base.py: 7, interscript/tanglers/base.py: 30, 37, interscript/tanglers/perl.py: 154, 157
last_source_line interscript/drivers/sinks/base.py: 8
latex interscript/__init__.py: 21, interscript/weavers/auto.py: 4
latex_weaver interscript/__init__.py: 21, interscript/weavers/latex.py: 20, interscript/weavers/auto.py: 4, 22
le interscript/core/sets.py: 13, 25, 38, interscript/tests/test_sets.py: 23, 32
left interscript/felix/model/fincat.py: 103, 110, 111, 118, 120, 125, 127, 165, 166, 167, interscript/felix/model/stdcat.py: 13, 20, 37, 38, 58, 59, 71, 71, interscript/felix/model/stdcat2.py: 12, 12, 14, 14, interscript/felix/model/funcat.py: 64, 64, interscript/felix/model/cons.py: 20, 22, 25, 28, 54, 55, 57, 58, 82, 85, 87, 90, 93, 95, 119, 120, interscript/frames/inputf.py: 605, 607, 607, 609
len interscript/core/sets.py: 97, 112, interscript/core/stacks.py: 7, 15, 16, interscript/drivers/sources/base.py: 67, interscript/drivers/sources/disk.py: 21, interscript/drivers/sources/stdin.py: 21, interscript/drivers/sources/cache.py: 16, interscript/drivers/sinks/util.py: 27, interscript/drivers/storage/memory.py: 18, interscript/weavers/text.py: 32, 79, 79, 179, 182, 198, 201, 204, 205, 209, 210, 237, 313, 314, 321, 333, interscript/weavers/html.py: 144, 228, 229, 236, 549, interscript/weavers/web.py: 234, 257, 305, 392, 470, 475, 478, 516, 542, 564, 582, 622, interscript/weavers/latex.py: 140, 283, interscript/weavers/filter.py: 48, 71, interscript/tanglers/python.py: 293, interscript/tanglers/perl.py: 57, 246, interscript/tokenisers/python.py: 186, 205, 214, 232, 278, 292, 321, interscript/parsers/lalr1.py: 20, 39, 52, 54, 124, 146, 175, 188, 224, 378, 401, 434, 446, 448, 581, 644, 649, 666, 698, 701, 754, 755, interscript/felix/model/stdcat.py: 77, interscript/felix/model/stdcat2.py: 31, interscript/felix/model/funcat.py: 76, interscript/felix/model/cons.py: 8, 8, 11, 16, 21, 27, 33, 39, 70, 70, 73, 78, 83, 91, 98, 103, interscript/frames/inputf.py: 252, 522, 527, 598, 657, 699, 705, 782, 838, 845, 942, interscript/getoptions.py: 12, interscript/utilities/diff.py: 12, 53, 64, 67, interscript/tests/test_diff.py: 21, 24, interscript/bin/iscr.py: 5
lend interscript/tanglers/python.py: 310, 312, 336
letter interscript/getoptions.py: 24, 25
letters interscript/tokenisers/python.py: 138, interscript/parsers/lalr1.py: 787, 788
lev interscript/weavers/latex.py: 268, 269, 269, 270
level interscript/weavers/text.py: 75, 76, 77, 164, 165, 312, 313, 314, 315, 316, 326, 329, 331, interscript/weavers/html.py: 227, 228, 229, 230, 231, 242, 250, 257, 265, 266, 457, 458, 459, 540, 541, interscript/weavers/web.py: 262, 263, 266, 269, 273, 283, 284, 285, 287, 322, 333, 395, 396, 404, 468, 471, 471, 474, 476, 479, 482, 482, 485, 493, 494, 605, 606, interscript/tests/test_stacking_weaver.pak: 19, interscript/weavers/latex.py: 259, 268, interscript/tanglers/python.py: 335, 338, 338, 340, 340, interscript/frames/inputf.py: 965, 966, 966, 967, 967, 968, 969, 970, 974, 980, 981, 981, 982, 982, 983, 984, 985, 987
lexeme interscript/parsers/lalr1.py: 786, 789, 789, 791, 796, 796, 798, 805, 805, 807
lhsdereps interscript/parsers/lalr1.py: 69, 105, 130
lhsprods interscript/parsers/lalr1.py: 47, 49, 49, 50, 93, 117, 226, 385
lhss interscript/parsers/lalr1.py: 159, 161
lib interscript/compilers/c.py: 39, 41, 77, 79, interscript/compilers/cpp.py: 39, 42, 82, 84
libdirs interscript/compilers/cconfig.py: 8, 18, 18, 31, 49
libs interscript/compilers/cconfig.py: 10, 20, 20, 35, 51
line interscript/drivers/sources/base.py: 41, 42, 66, 67, 69, interscript/drivers/sources/stdin.py: 20, 21, 23, interscript/drivers/sources/cache.py: 17, 21, interscript/drivers/sinks/base.py: 19, 20, 24, 25, 28, 28, 38, 39, interscript/drivers/sinks/null.py: 7, interscript/drivers/sinks/tee.py: 7, interscript/drivers/sinks/disk.py: 27, 27, interscript/drivers/sinks/bufdisk.py: 73, 73, interscript/drivers/sinks/stdout.py: 8, 9, interscript/drivers/storage/memory.py: 19, 23, interscript/weavers/base.py: 23, 24, 26, 27, interscript/weavers/text.py: 29, 31, 32, 33, 36, 38, 75, 77, 88, 89, 153, 154, 227, 229, 249, 251, 251, 252, 254, 256, 258, 265, interscript/weavers/html.py: 11, 13, 20, 22, 77, 78, 80, 81, 83, 84, 86, 90, 92, 94, 96, 457, 459, 467, 468, 530, 531, 561, 562, interscript/weavers/latex.py: 5, 7, 13, 15, 98, 99, 104, 105, 198, 199, 201, 202, 204, 206, 206, 207, 208, 210, 212, 213, 216, 217, interscript/tanglers/base.py: 18, interscript/tanglers/c.py: 14, 15, 58, 60, 60, 61, 61, 62, 62, 63, interscript/tanglers/cpp.py: 14, 15, 39, interscript/tanglers/java.py: 12, 13, interscript/tanglers/tcl.py: 11, 12, interscript/tanglers/python.py: 132, 133, 141, 142, 167, 168, 172, 173, 260, 263, 302, 359, 360, 421, interscript/tanglers/perl.py: 34, 35, 40, 183, 184, 186, 189, 192, 278, 279, interscript/tokenisers/python.py: 116, 125, 126, 127, 131, 179, 180, 184, 186, 190, 192, 197, 197, 199, 200, 203, 203, 204, 205, 210, 211, 214, 214, 214, 218, 222, 223, 224, 229, 231, 231, 232, 232, 237, 237, 240, 243, 248, 252, 252, 256, 259, 261, 265, 269, 272, 273, 276, 278, 278, 280, 281, 288, 289, 292, 292, 292, 295, 297, 304, 307, 309, 310, interscript/frames/inputf.py: 185, 191, 193, 473, 474, 482, 491, 495, 495, 496, 496, 497, 505, 520, 521, 553, 554, 557, 561, 562, 563, 572, 573, 575, 576, 577, 882, 884, 943, 944, 1138, 1139, interscript/utilities/diff.py: 68, 69, 69, 74, 75, 76, 84
line_break interscript/weavers/text.py: 268, 273, interscript/weavers/html.py: 112, interscript/weavers/latex.py: 234, interscript/frames/inputf.py: 529, 1012, 1012
line_offset interscript/frames/inputf.py: 78, 80, 484, 494
lineno interscript/weavers/text.py: 75, 78, interscript/utilities/diff.py: 81, 84
lines interscript/drivers/sources/base.py: 26, 28, 31, interscript/drivers/sinks/base.py: 27, 28, 30, 31, 37, 38, 40, interscript/weavers/html.py: 560, 561, interscript/tokenisers/python.py: 175, 176, 177, 177, 179, 181
lines_read interscript/drivers/sources/base.py: 12, 22, 68, 68, interscript/drivers/sources/stdin.py: 22, 22, interscript/drivers/sources/cache.py: 16, 17, 20, 20, 24, interscript/drivers/storage/memory.py: 18, 19, 22, 22, 30
lines_written interscript/drivers/sinks/base.py: 6, 22, 22, interscript/weavers/text.py: 54, 331, interscript/tanglers/base.py: 26, interscript/tanglers/c.py: 21, interscript/tanglers/cpp.py: 21, interscript/tanglers/java.py: 19, interscript/tanglers/tcl.py: 18, interscript/tanglers/python.py: 293, 308, 331, 366, interscript/tanglers/perl.py: 171, 284, interscript/frames/inputf.py: 830
link interscript/tests/test_stacking_weaver.pak: 7, 10, 11, interscript/compilers/c.py: 32, 71, interscript/compilers/cpp.py: 33, 76, interscript/tests/test_compilers.py: 9
list interscript/core/sets.py: 69, interscript/core/stacks.py: 4, interscript/drivers/sources/cache.py: 12, 16, 17, interscript/drivers/sinks/cache.py: 8, 13, 21, interscript/drivers/storage/memory.py: 12, 18, 19, 26, interscript/weavers/html.py: 42, interscript/weavers/latex.py: 33, interscript/parsers/lalr1.py: 575, 627, interscript/frames/inputf.py: 835, 836, 837, 838, 844, 845
list_kind interscript/parsers/html.py: 100, 106, 112, 118, 124
list_stack interscript/weavers/multiplexor.py: 10, 54, 58, 59, 65, 69
list_type interscript/tanglers/perl.py: 13, 120, 127, 132, 135, 139, 146, 245, 248, 249, 250
lists interscript/felix/tests/stdcat_test.py: 13, 22
ljust interscript/tanglers/c.py: 57
lnum interscript/tokenisers/python.py: 148, 185, 185, 185, 197, 197, 200, 205, 214, 214, 232, 232, 237, 237, 240, 240, 244, 251, 251, 273, 278, 279, 286, 292, 292, 310, 310, 316, 316, 317, 317
load interscript/frames/masterf.py: 30
loadfile interscript/drivers/sources/disk.py: 13, interscript/frames/inputf.py: 13, 670
local_file_exists interscript/drivers/sources/ftp.py: 34, 41, 43, 97, interscript/drivers/sources/http.py: 31, 38, 40, 83
local_file_modify_time interscript/drivers/sources/ftp.py: 44, 46, interscript/drivers/sources/http.py: 41, 43
local_filename interscript/drivers/sources/ftp.py: 21, 24, 36, 38, 40, 44, 98, 103, 105, 107, 111, interscript/drivers/sources/http.py: 21, 24, 33, 35, 37, 41, 84, 89, 91, 93, 97, 115
local_time interscript/frames/processf.py: 41, 42
local_time_string interscript/frames/processf.py: 42, 48
localtime interscript/frames/processf.py: 41
logfile interscript/frames/processf.py: 29, 31, interscript/frames/inputf.py: 265, 275, interscript/getframes.py: 116, 184, 187
logfile_mode interscript/frames/processf.py: 30, interscript/getframes.py: 117, 185, 188
login interscript/drivers/sources/ftp.py: 72, 73, 74, 75
long interscript/felix/model/stdcat.py: 38, 38, 44, 59, 59, 65
longoptdict interscript/getframes.py: 14, 74, 79, 81, 82, 84
longopts interscript/getoptions.py: 4, 16
lookaheads interscript/parsers/lalr1.py: 393, 457
lower interscript/parsers/html.py: 175, 176, interscript/frames/inputf.py: 788
lparen interscript/parsers/lalr1.py: 717, 726, 768, 769
lstart interscript/tanglers/python.py: 310, 311, 336
lt interscript/core/sets.py: 37, interscript/tests/test_sets.py: 24, 33
lth interscript/utilities/diff.py: 53, 55, 61
m interscript/frames/processf.py: 30, 33, 44, interscript/frames/inputf.py: 142, 143, 149, 150, 154, 155, 159, 160, interscript/utilities/diff.py: 7, 8, 14, 16, 18, 19, 29, 35, 43, 45, 87, 88, 94, 95
macro interscript/frames/inputf.py: 914, interscript/compilers/cconfig.py: 40, 41, 41
macroname interscript/frames/inputf.py: 382, 383, 385, 386, 387
macros interscript/drivers/sources/cache.py: 11, 12, interscript/drivers/sinks/cache.py: 20, 21, interscript/compilers/cconfig.py: 11, 21, 21, 39, 40, 41, 41, 52, 54, 54
make interscript/bin/iscr.bat: 20
make_parse_tab interscript/frames/inputf.py: 460, 534
map interscript/tokenisers/python.py: 73, interscript/parsers/lalr1.py: 159, 722, 870, interscript/frames/inputf.py: 38
map_filename interscript/frames/platform.py: 27
margin interscript/weavers/text.py: 23, 236, 241, 306, 306, 310, 310, 395, 395, 398, 398, 402, 402, 406, 406, 410, 410, 415, 415, 419, 421, 427, 434
markup interscript/tanglers/python.py: 314, 316, 317, 321, 322, 323, 324, 325, 326
markup_filter interscript/__init__.py: 26, interscript/weavers/filter.py: 4, 77
master interscript/weavers/base.py: 9, 9, 12, interscript/weavers/text.py: 87, 88, 100, 101, 110, 120, 130, 140, 152, 153, 163, 164, interscript/weavers/html.py: 142, 401, 425, 466, 467, 478, 479, 488, 498, 508, 518, 529, 530, 539, 540, interscript/weavers/web.py: 35, 88, 126, 126, 130, 232, 379, 455, 509, 515, 528, 557, 563, 575, 581, 594, 601, 615, 621, 640, interscript/weavers/latex.py: 32, 32, 45, 67, 98, 104, 186, interscript/weavers/auto.py: 37, 38, 39, interscript/tanglers/base.py: 12, 12, 13, interscript/frames/passf.py: 15, 17, 17, 18, 22, 23, 24, 42, 52, 59, interscript/frames/inputf.py: 63, 63, 64, 84, 383, 387, 763, 764, 769, 773
master_frame interscript/drivers/sources/cache.py: 7, 11, interscript/drivers/sinks/cache.py: 5, 10, 10, 20, interscript/frames/processf.py: 4, 52, interscript/frames/masterf.py: 6
master_frames interscript/getframes.py: 119, 206, 207
master_options interscript/__init__.py: 116, 117
masterf interscript/frames/processf.py: 4
match interscript/weavers/filter.py: 32, 34, 35, 36, 44, 47, interscript/tanglers/python.py: 286, 286, 287, 288, interscript/tanglers/perl.py: 51, 51, 52, 53, 95, 95, 96, 97, 101, 101, 102, 103, 112, 112, 162, 257, 257, 258, 259, 261, 261, interscript/tokenisers/python.py: 192, 248, 269, interscript/frames/inputf.py: 193, 193, 194, 195, 554, 554, 555, 558, 562, 562, 573, 573, 574, 577, 577, 719, 720, 723, 724, 728, 729, 732, 733, 733, 736, 737, interscript/getoptions.py: 16, 16, 17, 18, 18, 21, 21, 22, 24, 26, 26
matchPOD interscript/tanglers/python.py: 271, 286
matchcomment interscript/tanglers/python.py: 272
matchid interscript/tanglers/c.py: 11, interscript/tanglers/cpp.py: 11, interscript/tanglers/java.py: 9
math interscript/felix/tests/func_test.py: 8, 10, 13
max interscript/core/sets.py: 43, 44, interscript/weavers/web.py: 319, interscript/tokenisers/python.py: 186, 221, 227, 247
maxlev interscript/weavers/text.py: 71, 76, interscript/weavers/html.py: 452, 458
maybe interscript/tokenisers/python.py: 33, 37, 45
memory interscript/__init__.py: 18, 18, interscript/drivers/storage/memory.py: 6, interscript/frames/inputf.py: 18, 18, 917
method_names interscript/frames/inputf.py: 100, 102, 102, 103, 103, 142, 146, 149, 153, 154, 158, 159
mid interscript/weavers/text.py: 79, 80
midpos interscript/weavers/filter.py: 35, 37, 39, 41
min interscript/core/sets.py: 40, 41
minimal interscript/tests/example.pak: 4
mk2arg interscript/utilities/commands.py: 52
mk_classref interscript/weavers/web.py: 292, 553
mk_contents interscript/weavers/web.py: 294, 451
mk_dir interscript/drivers/sinks/util.py: 26, interscript/drivers/sinks/disk.py: 5, 16, interscript/drivers/sinks/bufdisk.py: 5, 21
mk_filestatus interscript/weavers/web.py: 298, 637
mk_frame interscript/weavers/web.py: 30, 62, 65
mk_frames interscript/weavers/web.py: 49, 177
mk_funcref interscript/weavers/web.py: 291, 571
mk_head interscript/weavers/web.py: 13, 37, 90, 457, 511, 530, 560, 578, 597, 618
mk_html interscript/weavers/auto.py: 9, 30
mk_identref interscript/weavers/web.py: 293, 505
mk_latex interscript/weavers/auto.py: 19, 32
mk_sectionref interscript/weavers/web.py: 296, 524
mk_sourceref interscript/weavers/web.py: 297, 590
mk_testref interscript/weavers/web.py: 295, 611
mk_text interscript/weavers/auto.py: 24, 33
mk_web interscript/weavers/auto.py: 14, 31
mkarg interscript/utilities/commands.py: 54, 64
mkdir interscript/drivers/sinks/util.py: 15, interscript/frames/inputf.py: 257
mktemp interscript/drivers/sources/ftp.py: 85, interscript/drivers/sinks/bufdisk.py: 24, interscript/frames/inputf.py: 678, interscript/utilities/diff.py: 30, 31
mode interscript/drivers/sources/base.py: 13, interscript/weavers/html.py: 40, 61, 62, 63, 63, 66, 67, 68, 70, 72, 74, 75, 75, 75, 352, interscript/tanglers/perl.py: 12, 168, 169, 181, 214
model interscript/felix/model/fincat.py: 3, interscript/felix/model/stdcat.py: 2, interscript/felix/tests/stdcat_test.py: 5, interscript/felix/model/stdcat2.py: 2, interscript/felix/model/funcat.py: 2, interscript/felix/tests/func_test.py: 4, 5, 6, 7, interscript/felix/model/cons.py: 2
modname interscript/compilers/c.py: 32, 36, interscript/compilers/cpp.py: 33, 40
modulus interscript/felix/model/stdcat.py: 33, 35, 35, 39, 39, 49, 49, 54, 56, 56, 60, 60
more interscript/parsers/lalr1.py: 222, 234, 237, 238, 239, 240
msg interscript/felix/model/fincat.py: 110, 112, 114, 116, 119, 121, 123
mul_integers interscript/felix/tests/stdcat_test.py: 9, 19
mul_integers_mod10 interscript/felix/tests/stdcat_test.py: 10, 20
multiplexor interscript/__init__.py: 27, 27, interscript/weavers/multiplexor.py: 3, interscript/weavers/web.py: 2, 2, 12, interscript/weavers/auto.py: 2, 2, 44, interscript/weavers/filter.py: 2, 2, 4, 6
myanchor interscript/weavers/html.py: 244, 245, 245, 246, 247, 260
myclass interscript/tests/output/mymodule2.py: 3, interscript/tests/output/mymodule3.py: 3
mysink interscript/tests/test_stacking_weaver.pak: 2, 3
n interscript/tanglers/perl.py: 98, 99, interscript/parsers/lalr1.py: 644, 666, 668, 671, 671
name interscript/tests/output/mymodule2.py: 4, 5, 5, 7, interscript/tests/output/mymodule3.py: 4, 5, 5, 8, interscript/core/protocols.py: 36, 37, 37, 104, interscript/drivers/sources/base.py: 19, 72, interscript/drivers/sources/disk.py: 42, interscript/drivers/sources/url.py: 9, interscript/drivers/sources/ftp.py: 14, interscript/drivers/sources/http.py: 14, interscript/drivers/sources/stdin.py: 14, interscript/drivers/sources/cache.py: 7, 9, 9, 12, interscript/drivers/sinks/base.py: 34, interscript/drivers/sinks/null.py: 5, interscript/drivers/sinks/disk.py: 21, interscript/drivers/sinks/bufdisk.py: 32, 43, 47, 61, 67, 70, interscript/drivers/sinks/stdout.py: 6, interscript/drivers/sinks/cache.py: 5, 6, 6, 21, interscript/drivers/storage/memory.py: 7, 10, 10, interscript/weavers/raw.py: 10, 10, interscript/weavers/multiplexor.py: 8, 27, 29, 29, 34, 44, interscript/weavers/text.py: 21, 21, 164, 165, interscript/weavers/html.py: 43, 43, 51, 129, 130, 540, 541, interscript/weavers/web.py: 30, 31, 140, 168, 220, 221, 227, 312, 341, 544, 545, 605, 606, interscript/weavers/latex.py: 35, 35, interscript/weavers/filter.py: 11, interscript/tanglers/python.py: 39, 43, 43, 59, 69, 86, 89, 90, 98, 109, 180, 204, 218, 283, 332, 375, 393, 406, interscript/frames/platform.py: 24, interscript/frames/inputf.py: 95, 171, 289, 290, 291, 315, 317, 318, 320, 338, 339, 342, 354, 355, 360, 397, 513, 516, 519, 527, 781, 829, 842, 914, 917, 1130, 1131, 1133, interscript/bin/iscr.bat: 13
name_as_symbol interscript/parsers/lalr1.py: 850, 866
namechars interscript/tokenisers/python.py: 138, 296
named_file_sink interscript/__init__.py: 6, interscript/drivers/sinks/bufdisk.py: 9, interscript/weavers/web.py: 5, 32, 85, 379, 452, 506, 525, 554, 572, 591, 612, interscript/tests/test_stacking_weaver.pak: 2, interscript/weavers/auto.py: 7, 10, 15, 20, 25, interscript/frames/inputf.py: 15, 764, 770
named_file_source interscript/__init__.py: 12, interscript/drivers/sources/disk.py: 38, interscript/frames/passf.py: 7, 59, interscript/frames/inputf.py: 11, 319, 342, 358, 375
nav interscript/weavers/web.py: 69, 80, 80, 82, 82, 93, 183, 184, 184, 186, 360, 361, 361, 362, 362, 363, 363, 364, 364, 365, 365, 367, 368, 461, 462
ne interscript/core/sets.py: 27, 35, 38
need interscript/bin/iscr.bat: 20
needcont interscript/tokenisers/python.py: 149, 201, 203, 288
negate interscript/felix/tests/func_test.py: 35, 36, 36, 38
new interscript/parsers/lalr1.py: 529, 533, 537, 540, 541, 543, 544, 545, 548, 550, 557, 561, 562, 563, 565, 568, 569, 582, 583, 584, 596, 597, 608, 609, 618, 619
new_data interscript/parsers/html.py: 43, 46, 46, 48, 50
new_file interscript/drivers/sinks/bufdisk.py: 55, 56, 57
new_file_count interscript/frames/masterf.py: 59, 64, 64, 78
new_heading interscript/weavers/text.py: 312, 329, interscript/weavers/html.py: 227, 250
new_lines interscript/drivers/sinks/bufdisk.py: 56, 59, 63
new_production_list interscript/parsers/lalr1.py: 835, 862
new_symbol_list interscript/parsers/lalr1.py: 844, 865
newargs interscript/frames/inputf.py: 272, 278
newlines interscript/drivers/sources/ftp.py: 94, 102, 112, interscript/drivers/sources/http.py: 79, 88, 98
newmkntfirstmap interscript/parsers/lalr1.py: 317
newp interscript/parsers/lalr1.py: 550, 554, 554
newpart interscript/parsers/lalr1.py: 228, 230, 231, 235
newpri interscript/parsers/lalr1.py: 552, 554, 555, 556
news interscript/parsers/lalr1.py: 605, 608, 617, 618
newstate interscript/parsers/lalr1.py: 405, 407, 408, 410, 413, 415
newsym interscript/parsers/lalr1.py: 160, 161, 161, 161, 162
newtodo interscript/parsers/lalr1.py: 424, 429, 430, 434, 435, 436
next interscript/weavers/web.py: 180, 181, 181, 184, 184, 352, 354, 355, 361, 375, 375
next_anchor interscript/weavers/web.py: 355, 361
next_level interscript/weavers/web.py: 469, 470, 471, 477, 478, 482
nonobjects interscript/felix/model/fincat.py: 161, 162
nonterms interscript/parsers/lalr1.py: 45, 51, 59, 64, 87, 115, 173, 273, 321, 426, 587, 627, 627, 630
normal_line interscript/frames/inputf.py: 465, 729, 733
normalise interscript/felix/model/funcat.py: 7, 16, 24
now interscript/drivers/sources/ftp.py: 45, 46, interscript/drivers/sources/http.py: 42, 43
ns interscript/parsers/lalr1.py: 458, 459, 460
nsections interscript/weavers/html.py: 144, 145, interscript/weavers/web.py: 234, 235, 241, 241, 244, 245, 251, 252, 542, 543
nt interscript/parsers/lalr1.py: 74, 75, 75, 80, 81, 81, 92, 93, 100, 101, 115, 116, 117, 133, 287, 288, 293, 294, 297, 299, 301, 303, 330, 331, 336, 338, 363, 364, 367, 369, 588, 589, 590, 601, 630, 631, 632, 662, 680, 681
ntfirst interscript/parsers/lalr1.py: 589
ntfirstmap interscript/parsers/lalr1.py: 314, 350, 363, 364, 383, 590
ntfirsts interscript/parsers/lalr1.py: 590, 591
nts interscript/parsers/lalr1.py: 173, 181, 184, 190
null interscript/__init__.py: 8, 37, interscript/frames/inputf.py: 27
null_sink interscript/__init__.py: 8, interscript/drivers/sinks/null.py: 3, interscript/tanglers/null.py: 13, interscript/tanglers/doc.py: 9
null_tangler interscript/__init__.py: 37, interscript/tanglers/null.py: 11, interscript/frames/inputf.py: 27
number interscript/frames/inputf.py: 482, 484
numbered_list_stack interscript/weavers/text.py: 24, 399, 411, 425, 426, 426
numchars interscript/tokenisers/python.py: 138, 254
o interscript/utilities/diff.py: 7, 8, 14, 16, 18, 19, 29, 34, 43, 44, 87, 88, 94, 95
obj interscript/core/protocols.py: 39, 40, 42, 43, 45, 46, 47, interscript/compilers/c.py: 21, 27, 30, 60, 66, 69, interscript/compilers/cpp.py: 20, 26, 31, 63, 69, 74, interscript/tests/test_compilers.py: 7, 8, 9
object interscript/core/protocols.py: 51, 52, 53, 55, 57, 58, 66, 67, 69, 70, 84, 85, 91, 92, 93, 95, 101, 104, 107, 109, interscript/felix/model/fincat.py: 50, 95, 99, 101, 144, 145, 146, interscript/felix/model/stdcat.py: 29, 29, 42, 44, 48, 49, 50, 63, 65, 73, 74, 76, 77, 77, 83, 84, 90, 91, 97, 98, interscript/felix/model/stdcat2.py: 9, 9, 27, 28, interscript/felix/model/cons.py: 15, 17, 51, 77, 79, 116
objects interscript/felix/model/fincat.py: 7, 26, 31, 36, 42, 48, 53, 92, 93, 101, 134, 134, 144, 145, 165, 168, 185
of interscript/bin/iscr.bat: 8, 13, 16, interscript/tests/example.pak: 4
offset interscript/weavers/web.py: 391, 393, interscript/felix/model/fincat.py: 183, 184
ok_message interscript/frames/inputf.py: 595, 612, 613
old interscript/parsers/lalr1.py: 530, 532, 537, 540, 541, 543, 544, 548, 549, 561, 563, 565, 568
old_df interscript/weavers/html.py: 412, 414, 415, 417, 436, 438, 439, 441, interscript/weavers/web.py: 106, 115, 116, 118, interscript/weavers/latex.py: 54, 56, 57, 59, 76, 78, 79, 81
oldlines interscript/drivers/sources/ftp.py: 99, 102, interscript/drivers/sources/http.py: 85, 88
oldp interscript/parsers/lalr1.py: 549, 553, 553
oldpri interscript/parsers/lalr1.py: 551, 553, 555, 556
oldstderr interscript/frames/processf.py: 28, 60
oldstdout interscript/frames/processf.py: 27, 59
om interscript/utilities/diff.py: 45, 46, 48
op interscript/tokenisers/python.py: 306, 307
opdict interscript/tokenisers/python.py: 80, 306
open interscript/drivers/sources/disk.py: 16, 48, interscript/drivers/sources/ftp.py: 24, 36, 86, 93, 98, 111, interscript/drivers/sources/http.py: 24, 33, 84, 97, 115, interscript/drivers/sinks/util.py: 66, interscript/drivers/sinks/disk.py: 18, interscript/drivers/sinks/bufdisk.py: 28, 39, 51, 55, 62, interscript/tokenisers/python.py: 321, interscript/frames/processf.py: 33, interscript/frames/masterf.py: 29, 82, interscript/frames/inputf.py: 261, 516, 680, 1134, interscript/utilities/diff.py: 24, 32, 33, interscript/tests/test_diff.py: 18, 22
open_item interscript/weavers/multiplexor.py: 58, 60, 65, 66
opt interscript/weavers/latex.py: 140, 141, interscript/getframes.py: 139, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 161, 162, 164, 166, 168, 170, 172, 174, 183, 186, 189, 194, 195, 196, 198, 200, 200, 200, 201
options interscript/bin/iscr.bat: 14
opts interscript/getoptions.py: 11, 18, 25, 26, 30, 31, 34, 35, interscript/getframes.py: 138, 139
ord interscript/utilities/diff.py: 76, 76
order interscript/core/stacks.py: 54, 55, 58
orientation interscript/weavers/web.py: 30, 43
original_count interscript/frames/inputf.py: 80, 248, 494, 497, 586, 653, 664, 832, 882
original_file interscript/drivers/sinks/bufdisk.py: 51, 52, 53, interscript/frames/inputf.py: 483
original_filename interscript/weavers/text.py: 49, interscript/weavers/web.py: 136, 191, 365, interscript/frames/inputf.py: 79, 81, 249, 335, 497, 585, 654, 665, 831, 883
original_lines interscript/drivers/sinks/bufdisk.py: 52, 59
os interscript/__init__.py: 42, interscript/drivers/sources/disk.py: 8, 28, 29, 30, 31, 32, 33, interscript/drivers/sources/ftp.py: 6, 22, 22, 44, 114, 122, interscript/drivers/sources/http.py: 6, 22, 22, 41, interscript/drivers/sinks/util.py: 2, 3, 15, 16, 18, 20, 34, 36, 42, 45, 50, 55, interscript/drivers/sinks/bufdisk.py: 7, 33, 33, 71, interscript/frames/platform.py: 3, 10, 14, 18, 24, 28, 28, 31, interscript/frames/inputf.py: 6, 257, 693, interscript/getframes.py: 6, 205, interscript/compilers/c.py: 2, 29, 44, 68, 82, interscript/compilers/cpp.py: 2, 28, 45, 71, 87, interscript/compilers/cconfig.py: 2, interscript/tests/test_compilers.py: 2, 12, interscript/utilities/diff.py: 2, 9, 20, 39, 40, 44, 46, 47, 90, interscript/utilities/commands.py: 37, 40, 42, 53, 54
other interscript/core/sets.py: 102, 104, interscript/core/stacks.py: 26, 26, interscript/felix/model/funcat.py: 58, 58, interscript/getframes.py: 108, 109, 110
our_hlevel interscript/frames/inputf.py: 643, 644, 646
our_source_filebase interscript/frames/inputf.py: 678, 679
our_source_filename interscript/frames/inputf.py: 260, 261, 277, 675, 679, 680, 687, 693
our_weaver interscript/frames/inputf.py: 599, 602, 603, 609, 610, 613, 649, 652, 656, 658, 659, 661, 669, 684, 703, 704, 706, 707, 710
output interscript/frames/inputf.py: 383, 932, 933, interscript/utilities/diff.py: 10, 12, 21, 25, 27
output_adapter interscript/felix/model/funcat.py: 47, interscript/felix/tests/func_test.py: 7
p interscript/core/sets.py: 89, 90, 90, 91, 91, 92, 92, 93, interscript/core/protocols.py: 58, 58, 67, 67, 70, 70, 108, 109, interscript/weavers/latex.py: 163, 164, 165, 166, interscript/parsers/lalr1.py: 48, 49, 49, 50, 50, 51, 52, 53, 53, 54, 54, 56, 93, 95, 117, 118, 124, 125, 130, 174, 175, 178, 180, 181, 182, 182, 184, 185, 186, 187, 188, 190, 191, 192, 196, 197, 197, 199, 201, 203, 204, 207, 208, 208, 210, 226, 233, 234, 236, 237, 272, 273, 273, 274, 276, 277, 278, 278, 279, 279, 281, 281, 282, 282, 309, 310, 311, 311, 313, 313, 320, 321, 321, 322, 323, 324, 324, 325, 325, 345, 346, 347, 347, 349, 349, 355, 356, 357, 358, 358, 359, 359, 385, 386, 386, 387, 694, 695, 696, 899, 899, 899, 930, 930, 930, interscript/felix/model/fincat.py: 184, 185, 186, 190, 191, 194, interscript/frames/inputf.py: 1006
p_nullable interscript/parsers/lalr1.py: 94, 97, 99
page_break interscript/weavers/text.py: 277, interscript/weavers/html.py: 115, interscript/weavers/latex.py: 237, interscript/frames/inputf.py: 1013, 1013
page_format_params interscript/weavers/latex.py: 159, 163
pagefoot interscript/weavers/web.py: 384
pagehead interscript/weavers/web.py: 383
pagenumbering interscript/weavers/latex.py: 153, 155, 156
pagestyle interscript/weavers/latex.py: 148, 150, 151
pair interscript/felix/model/fincat.py: 127, 128, 130, 192, 193, 194, 194
pak interscript/bin/iscr.bat: 8, 10, 18
par interscript/weavers/text.py: 81, 92, 146, 157, 168, 267, 278, 297, 301, 305, 309, 327, 338, 347, 353, 356, 360, 363, 365, 368, 370, 373, 375, 378, 380, 383, 385, 405, 409, 414, 418, 424, 431, interscript/weavers/html.py: 344, interscript/weavers/latex.py: 356, interscript/tanglers/perl.py: 195, interscript/frames/inputf.py: 286, 1007
param interscript/weavers/latex.py: 165, 166, interscript/parsers/html.py: 174, 175
parenlev interscript/tokenisers/python.py: 148, 217, 258, 301, 301, 302, 302
parent_sink interscript/weavers/web.py: 140, 141, 144
parent_weaver interscript/weavers/web.py: 124, 125, 139, 140, 147, 148, 161, 169, 187
parse interscript/parsers/lalr1.py: 638, 773, 895, 911, 926, 941
parse_source_filename interscript/drivers/sources/disk.py: 25, 45, interscript/frames/masterf.py: 3, 26, interscript/frames/inputf.py: 12, 1133
parsed interscript/getframes.py: 113, 138
parsers interscript/__init__.py: 29, interscript/tests/tgram.py: 2, 3, 4, interscript/frames/passf.py: 12, interscript/frames/inputf.py: 31
part interscript/tests/test_diff.py: 30, 31
pass_frame interscript/drivers/sources/disk.py: 39, 41, interscript/drivers/sinks/disk.py: 8, 22, interscript/drivers/sinks/bufdisk.py: 10, 11, 11, 12, 13, 29, 34, 40, 44, 61, 67, 70, interscript/weavers/base.py: 4, 8, 8, 9, 11, interscript/weavers/raw.py: 4, 5, interscript/weavers/multiplexor.py: 5, 6, 6, interscript/weavers/text.py: 8, 9, 10, 91, 96, 156, 167, interscript/weavers/html.py: 32, 33, 34, 403, 427, 470, 474, 533, 543, interscript/weavers/web.py: 33, 86, 125, 125, 126, 127, 129, 132, 379, 381, 453, 507, 517, 526, 534, 555, 565, 573, 583, 592, 603, 613, 623, 640, 642, interscript/weavers/latex.py: 22, 23, 24, 32, 186, interscript/weavers/auto.py: 9, 10, 12, 14, 15, 16, 19, 20, 22, 24, 25, 27, 36, 37, 38, 39, 43, 44, interscript/weavers/filter.py: 5, 6, interscript/tanglers/base.py: 11, 11, 12, interscript/tanglers/python.py: 343, 343, 344, 347, 347, 348, 351, 351, 352, interscript/frames/masterf.py: 2, 38, interscript/frames/passf.py: 14, interscript/frames/inputf.py: 60, 62, 62, 63, 83, 300, 318, 320, 326, 340, 342, 344, 356, 359, 363, 376, 397, 399, 413, 617, 619, 624, 636, 638, 700, 701, 716, 764, 771, 834, 843, 958, 960, 970, 985, 1131
passes interscript/frames/masterf.py: 37, interscript/getframes.py: 129, 149
passf interscript/frames/masterf.py: 2
passno interscript/weavers/text.py: 91, 96, 96, 97, 145, 156, 167, interscript/weavers/html.py: 470, 474, 474, 475, 523, 533, 543, interscript/frames/masterf.py: 37, 38, 63, 71, 74, 77, interscript/frames/passf.py: 15, 20, 20, 44
password interscript/drivers/sources/ftp.py: 72, 73
patch interscript/utilities/diff.py: 18, 23, 24, interscript/tests/test_diff.py: 11, 13, 15
patch_file interscript/utilities/diff.py: 87, 95, interscript/tests/test_diff.py: 15
path interscript/drivers/sinks/util.py: 3, interscript/felix/tests/stdcat_test.py: 3, 3, interscript/felix/tests/func_test.py: 3, 3, interscript/frames/platform.py: 27, 28, interscript/frames/site.py: 8, interscript/getframes.py: 205, interscript/tests/test_compilers.py: 4, 4, interscript/tests/test_diff.py: 4, 4, interscript/utilities/commands.py: 54, interscript/bin/iscr.py: 7, 8, 8
pathlist interscript/drivers/sources/disk.py: 26, 31, 34, 36, 44, interscript/drivers/sinks/util.py: 26, 27, 31, 33, 36, 40, interscript/drivers/sinks/disk.py: 14, 15, 16, interscript/drivers/sinks/bufdisk.py: 19, 20, 21
pathname interscript/drivers/sinks/util.py: 31, 32, 34, 34, 35, 36, 36, 40, 42, 55, 55, 56, 63, 66, interscript/drivers/sinks/disk.py: 16, 18, 20, 22, interscript/drivers/sinks/bufdisk.py: 21, 23, 32, 39, 42, 43
pattern interscript/weavers/web.py: 31, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 84, 124, 151, 151, 152, 153, 153, 180, 194, 291, 292, 293, 294, 295, 296, 297, 298, 320, 325, 346, 354, 357, 370, 371, 372, 373, 403, interscript/weavers/filter.py: 38
pc interscript/weavers/web.py: 38, 40, 40, 41, 41, 43
perl interscript/__init__.py: 34, interscript/frames/inputf.py: 23
perl_output interscript/frames/inputf.py: 759
perl_tangler interscript/__init__.py: 34, interscript/tanglers/perl.py: 7, interscript/frames/inputf.py: 23
persistent interscript/bin/iscr.bat: 20
persistent_frame interscript/weavers/base.py: 12, interscript/weavers/text.py: 52, 53, 54, 58, 59, 60, 74, 391, interscript/weavers/html.py: 58, 455, interscript/weavers/web.py: 130, 199, 200, 201, 205, 206, 207, 318, 319, 350
persistent_frames interscript/frames/masterf.py: 24, 30, 83, 93, 94, 95
pi interscript/parsers/lalr1.py: 319, 377, 378, 380, 382, 458, 459
pickle interscript/frames/masterf.py: 4, 30, 83
pipe interscript/utilities/commands.py: 40, 42, 43, 44
pitem interscript/parsers/lalr1.py: 486, 487
plain_text_weaver interscript/__init__.py: 20, interscript/weavers/text.py: 7, interscript/weavers/auto.py: 3, 27
plat interscript/frames/processf.py: 22, 23
platform interscript/frames/install.py: 8, 16, 17, 18, 19, 20, 21, interscript/frames/platform.py: 7, interscript/frames/site.py: 4, 5, 5, interscript/frames/processf.py: 3, interscript/getframes.py: 156, interscript/utilities/commands.py: 39
platform_dependent_install_point interscript/frames/install.py: 10
platform_frame interscript/frames/platform.py: 5, interscript/frames/processf.py: 3, 22
platform_independent_install_point interscript/frames/install.py: 5
platform_install_point interscript/frames/install.py: 33, 71
plus interscript/parsers/lalr1.py: 717, 722, 768
pod interscript/tanglers/perl.py: 162, 169, 182, 200, 202, 221, 225, 239, 268, 271
pod_mode interscript/tanglers/perl.py: 210, 213, 229, 238, 241, 244, 269, 272, 276
pod_par interscript/tanglers/perl.py: 185, 186, 187, 188, 193, 196, 201
pod_re interscript/tanglers/perl.py: 14, 162
pop interscript/core/stacks.py: 9, interscript/parsers/lalr1.py: 669, 670, 683, 684, 685, interscript/frames/inputf.py: 801
pop_head interscript/frames/inputf.py: 992
pop_weaver interscript/frames/inputf.py: 444
popen interscript/frames/platform.py: 10, 14, 18, interscript/utilities/diff.py: 9, 20, 90, interscript/utilities/commands.py: 40, 42
port interscript/drivers/sources/ftp.py: 63, interscript/drivers/sources/http.py: 60
pos interscript/tokenisers/python.py: 186, 194, 221, 222, 223, 224, 226, 226, 227, 229, 231, 231, 232, 237, 237, 240, 240, 247, 248, 251, 269, 271, 272, 273, 309, 310, 310, 311, 311
posix_patch interscript/utilities/diff.py: 94
posixpath interscript/drivers/sinks/util.py: 3, 14, 19
post_methods interscript/frames/inputf.py: 91, 98
postcondition interscript/tanglers/python.py: 52, 53, 103, 152, 154, 209, 250, 256, 383, 398, 398, 411, 411
pr interscript/parsers/lalr1.py: 457, 461
pr_conflict interscript/parsers/lalr1.py: 517, 541, 544, 563, 565, 568
pr_tab interscript/parsers/lalr1.py: 694, 763, 873, 903, 934
pre interscript/tanglers/perl.py: 53, 54, 54, 259, 260
precategory interscript/felix/model/fincat.py: 133
precondition interscript/tanglers/python.py: 49, 50, 101, 122, 124, 207, 233, 239, 381, 396, 396, 409, 409
prefix interscript/drivers/sources/disk.py: 25, 27, 28, 29, 30, 30, 31, 39, 45, interscript/drivers/sinks/util.py: 26, 31, 40, interscript/drivers/sinks/disk.py: 8, 16, interscript/drivers/sinks/bufdisk.py: 10, 21, interscript/weavers/text.py: 77, 79, 80, interscript/weavers/auto.py: 9, 10, 14, 15, 19, 20, 24, 25, 37, 43, interscript/tanglers/cpp.py: 32, 34, 34, 35, 39, interscript/frames/install.py: 5, 6, 7, 8, 25, 34, 43, 52, 61, interscript/frames/inputf.py: 550, 551, interscript/getframes.py: 199, 200, 200, interscript/compilers/c.py: 23, 24, 62, 63, interscript/compilers/cpp.py: 22, 23, 65, 66
prev interscript/weavers/web.py: 346, 347, 348, 363, 376, 376
prev_anchor interscript/weavers/web.py: 347, 363
print_class_reference interscript/frames/inputf.py: 924
print_contents interscript/weavers/text.py: 71, interscript/weavers/html.py: 452, interscript/weavers/latex.py: 92, interscript/frames/inputf.py: 889, 892
print_diff_table interscript/frames/inputf.py: 593, 708
print_everything interscript/felix/model/fincat.py: 183
print_exc interscript/weavers/multiplexor.py: 35, interscript/weavers/web.py: 301, interscript/parsers/html.py: 186, interscript/frames/processf.py: 38, 77, interscript/frames/passf.py: 69, interscript/frames/inputf.py: 217, 234, 714, interscript/getframes.py: 182
print_file_list interscript/weavers/text.py: 84, interscript/weavers/html.py: 463, interscript/weavers/latex.py: 96, interscript/frames/inputf.py: 894, 897
print_file_status interscript/weavers/text.py: 95, interscript/weavers/html.py: 473, interscript/weavers/web.py: 644, interscript/frames/inputf.py: 899, 902
print_help interscript/getframes.py: 67, 190
print_help1 interscript/getframes.py: 72, 76, 78, 201
print_identifier_cross_reference interscript/frames/inputf.py: 919
print_include_list interscript/weavers/text.py: 160, interscript/weavers/html.py: 536, interscript/frames/inputf.py: 909, 912
print_install interscript/frames/install.py: 85
print_output interscript/frames/inputf.py: 936, 953
print_python_output interscript/frames/inputf.py: 686, 952, 962, interscript/tests/example.pak: 9
print_python_test_output interscript/frames/inputf.py: 957
print_source_list interscript/weavers/text.py: 149, interscript/weavers/html.py: 526, interscript/weavers/latex.py: 102, interscript/frames/inputf.py: 904, 907
print_table interscript/weavers/web.py: 98, 519, 567, 585
printtoken interscript/tokenisers/python.py: 116, 122
priority interscript/parsers/lalr1.py: 553, 554
process interscript/__init__.py: 117, 118, 119, interscript/drivers/sinks/bufdisk.py: 12, 12, 50, interscript/weavers/web.py: 25, 127, 127, interscript/tanglers/base.py: 13, 13, interscript/frames/masterf.py: 7, 8, 8, 10, interscript/frames/passf.py: 18, 18, interscript/frames/inputf.py: 64, 64, 65, 195, 206, 211, 218, 500, 508, 510, 590, 720, 725, interscript/bin/iscr.bat: 14
process_frame interscript/__init__.py: 115, 117, interscript/frames/processf.py: 10
process_options interscript/__init__.py: 116, 117, interscript/frames/processf.py: 11, 13, 13, 19, 29, 30, 31, interscript/getframes.py: 114, 115, 116, 117, 118, 141, 143, 176, 184, 185, 187, 188, 196, 207
processf interscript/__init__.py: 115
prod interscript/parsers/lalr1.py: 661, 662, 666, 672, 676, 677, 678, 734, 738, 742, 746, 831, 832, 835, 838, 841, 844, 847, 850, 853, 856, interscript/felix/model/stdcat.py: 59, 60, 61
prodind interscript/parsers/lalr1.py: 223, 224, 226, 228, 580, 581, 582, 582, 587, 588, 594, 614
prodn interscript/parsers/lalr1.py: 660, 661
prods interscript/parsers/lalr1.py: 33, 36, 259, 260, 722, 728, 870, 872, 896, 897, 899, 900, 902, 912, 913, 927, 928, 930, 931, 933, 942, 943
productions interscript/parsers/lalr1.py: 36, 39, 40, 48, 159, 162, 165, 171, 174, 186, 224, 226, 228, 233, 234, 236, 237, 272, 309, 320, 345, 355, 378, 380, 387, 401, 403, 549, 550, 581, 587, 588, 614, 661, 754, 755, 756, 757, 758, 759
project_frame interscript/frames/project.py: 2
prolog interscript/weavers/html.py: 53, 571, interscript/weavers/latex.py: 37, 108
propagates interscript/parsers/lalr1.py: 396, 412, 413, 415, 416
proplist interscript/parsers/lalr1.py: 483, 486
props interscript/parsers/lalr1.py: 444, 461, 463, 467, 483
propterms interscript/parsers/lalr1.py: 476, 477, 488
prose interscript/weavers/html.py: 341, interscript/weavers/latex.py: 353, interscript/parsers/html.py: 90
protocol interscript/__init__.py: 50, interscript/core/protocols.py: 51, 53, 55, 60, 62, 64, 72, 74, 76, 78, 79, 81, 84, 86, 88, 91, 93, 97, 100, 101, 102, 103, 104, interscript/tests/test_protocol.py: 5, 6, 7, 8, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 27, interscript/weavers/raw.py: 7, interscript/weavers/multiplexor.py: 26, 28, 28, 34, 37, 39, 39, 45, interscript/weavers/text.py: 13, interscript/weavers/html.py: 36, interscript/weavers/web.py: 164, interscript/weavers/latex.py: 28, interscript/weavers/filter.py: 10, interscript/tanglers/python.py: 40, 44, 44, 57, 59, 84, 86, 181, 184
protocols interscript/__init__.py: 49, 50, interscript/core/protocols.py: 57, 58, 66, 67, 69, 70, 107, 108, interscript/tests/test_protocol.py: 4, 5, interscript/felix/model/basecat.py: 3, interscript/felix/model/stdcat.py: 74, interscript/frames/inputf.py: 29
provides_attr interscript/core/protocols.py: 35, 103, interscript/tests/test_protocol.py: 27
pseudomatch interscript/tokenisers/python.py: 248, 249, 250
pseudoprog interscript/tokenisers/python.py: 73, 248
pstate interscript/parsers/lalr1.py: 486, 487, 489, 491
pt interscript/parsers/lalr1.py: 488, 489, 491
push interscript/core/stacks.py: 13, interscript/parsers/lalr1.py: 643, 657, 658, 680, 681, interscript/frames/inputf.py: 796
push_head interscript/frames/inputf.py: 989, 993
push_weaver interscript/frames/inputf.py: 440
putheader interscript/drivers/sources/http.py: 73, 74
putrequest interscript/drivers/sources/http.py: 72
py interscript/frames/install.py: 4, 6, 7, 8, interscript/frames/processf.py: 65, 68, 69, 76, interscript/bin/iscr.bat: 2, 11, 15
py_bracket_tokens interscript/tanglers/python.py: 17, 323
py_exec interscript/tanglers/python.py: 289, interscript/frames/processf.py: 65, interscript/frames/inputf.py: 590, 720, 725
py_op_tokens interscript/tanglers/python.py: 25, 325
py_punct_tokens interscript/tanglers/python.py: 22, 324
python interscript/__init__.py: 36, interscript/tanglers/python.py: 9, 10, interscript/frames/passf.py: 80, interscript/frames/inputf.py: 22, 307, 333, 459, 460, 463, 584, interscript/bin/iscr.bat: 2, 15
python_config_install_point interscript/frames/install.py: 11
python_dynload_install_point interscript/frames/install.py: 12, 28, 37, 46, 55, 64
python_header_install_point interscript/frames/install.py: 6
python_module interscript/compilers/c.py: 8, interscript/compilers/cpp.py: 7
python_module_install_point interscript/frames/install.py: 7, 26, 27, 35, 36, 44, 45, 53, 54, 62, 63
python_module_search_path interscript/frames/site.py: 8
python_os interscript/frames/platform.py: 24
python_output interscript/frames/inputf.py: 758, interscript/tests/example.pak: 6
python_plat interscript/frames/install.py: 8, interscript/frames/platform.py: 7
python_platform_install_point interscript/frames/install.py: 8
python_tangler interscript/__init__.py: 36, interscript/tanglers/python.py: 268, interscript/frames/inputf.py: 22
python_tokeniser interscript/tanglers/python.py: 9, 275, interscript/tokenisers/python.py: 124, 140
python_version interscript/frames/install.py: 4, 11, 12, interscript/frames/site.py: 6
python_warn interscript/frames/inputf.py: 307, 463
pywarn interscript/frames/inputf.py: 460, 534, 536, 538, 538, 539, 540
quit interscript/drivers/sources/ftp.py: 90, 123
r interscript/parsers/lalr1.py: 595, 597, interscript/frames/inputf.py: 192, 193, 195, 341, 346, 350, 357, 365, 369, 396, 401, 406, 411, 415, 420
ran interscript/bin/iscr.bat: 15
range interscript/drivers/sources/disk.py: 21, interscript/weavers/text.py: 179, 204, 209, 321, interscript/weavers/html.py: 145, 236, interscript/weavers/web.py: 159, 305, 475, 543, interscript/weavers/latex.py: 140, interscript/weavers/filter.py: 71, interscript/parsers/lalr1.py: 39, 146, 175, 188, 446, 448, 698, 701, 754, interscript/felix/model/funcat.py: 76, interscript/felix/model/cons.py: 11, 16, 21, 27, 33, 39, 73, 78, 83, 91, 98, 103, interscript/frames/masterf.py: 37, interscript/frames/inputf.py: 252, 657, 705, 942, interscript/utilities/diff.py: 55, 64, 67, interscript/tests/test_diff.py: 21, 24
raw interscript/__init__.py: 23, interscript/weavers/base.py: 17, 20, interscript/weavers/filter.py: 18, 20
raw_close interscript/drivers/sinks/base.py: 14, 44
raw_eol interscript/drivers/sinks/base.py: 16, 21, interscript/drivers/sinks/disk.py: 28, interscript/drivers/sinks/bufdisk.py: 74, interscript/drivers/sinks/cache.py: 12, interscript/drivers/storage/memory.py: 25
raw_flush interscript/drivers/sinks/base.py: 15, 47
raw_readline interscript/drivers/sources/base.py: 28, 34, 64, interscript/drivers/sources/stdin.py: 17, interscript/drivers/sources/cache.py: 15, interscript/drivers/storage/memory.py: 17
raw_readlines interscript/drivers/sources/base.py: 24, 37, 41
raw_weaver interscript/__init__.py: 23, interscript/weavers/raw.py: 3
raw_write interscript/drivers/sinks/base.py: 16, 20, 40, interscript/drivers/sinks/null.py: 7, interscript/drivers/sinks/tee.py: 7, interscript/drivers/sinks/disk.py: 27, 28, interscript/drivers/sinks/bufdisk.py: 73, 74, interscript/drivers/sinks/stdout.py: 8, interscript/drivers/sinks/cache.py: 16, interscript/drivers/storage/memory.py: 32
raw_writeline interscript/drivers/sinks/base.py: 19, 28, 39
raw_writelines interscript/drivers/sinks/base.py: 27
rawif interscript/weavers/base.py: 19, interscript/weavers/filter.py: 22, 24, interscript/tanglers/perl.py: 268, 271
re interscript/__init__.py: 44, interscript/weavers/filter.py: 3, 7, interscript/tanglers/c.py: 6, 11, interscript/tanglers/cpp.py: 6, 11, interscript/tanglers/java.py: 5, 9, interscript/tanglers/python.py: 7, 271, 272, interscript/tanglers/perl.py: 4, 14, 16, 17, 18, interscript/tokenisers/python.py: 4, 74, 75, 75, interscript/frames/inputf.py: 3, 38, 86, 87, 570, interscript/getoptions.py: 2, 4, 5, interscript/utilities/diff.py: 5
read interscript/drivers/sources/base.py: 36, interscript/frames/platform.py: 11, 15, 19, interscript/utilities/diff.py: 10, 21, interscript/utilities/commands.py: 43
read_buffer interscript/frames/inputf.py: 74, 474, 477, 478, 488
readline interscript/drivers/sources/base.py: 33, 66, interscript/drivers/sources/stdin.py: 20, interscript/tokenisers/python.py: 121, 125, 131, 321, 322, interscript/frames/inputf.py: 185, 486, 491, 553, 561, 572, 576
readlines interscript/drivers/sources/base.py: 39, interscript/drivers/sources/disk.py: 19, interscript/drivers/sources/ftp.py: 94, 99, interscript/drivers/sources/http.py: 79, 85, interscript/drivers/sinks/bufdisk.py: 52, 56, interscript/frames/inputf.py: 379, 388, 517, 1135, interscript/tests/test_diff.py: 19, 23
real_count interscript/frames/inputf.py: 493, 494
real_filename interscript/frames/inputf.py: 492
recent interscript/bin/iscr.bat: 15
reduce interscript/parsers/lalr1.py: 638, 676, 677, 678, interscript/felix/model/basecat.py: 8, interscript/felix/model/stdcat.py: 27
reduceterms interscript/parsers/lalr1.py: 593, 594, 595
ref interscript/parsers/html.py: 161, 162, 164, 165
ref_anchor interscript/weavers/text.py: 63, interscript/weavers/html.py: 219, interscript/weavers/web.py: 210, interscript/frames/inputf.py: 455, 456
reference_date interscript/frames/processf.py: 40, 41
refresh_interval interscript/drivers/sources/ftp.py: 32, 33, 33, 47, interscript/drivers/sources/http.py: 29, 30, 30, 44, interscript/getframes.py: 127
refs interscript/weavers/html.py: 410, 413, 434, 437, interscript/weavers/web.py: 104, 107, interscript/weavers/latex.py: 52, 55, 74, 77
reg_list interscript/frames/inputf.py: 60, 73, 73, 175, 192, 462
regexp interscript/weavers/filter.py: 5, 7, 7, 10, 32, 38, 47, 76, 77
register_anchor interscript/weavers/web.py: 196, 198, 326
register_test interscript/frames/inputf.py: 243, 616
rej interscript/parsers/lalr1.py: 517, 518, 519, 520, 521, 522, 523, 524, 525, 527
remote_directory interscript/drivers/sources/ftp.py: 80, 81, 119, interscript/drivers/sources/http.py: 68, 104
remote_filename interscript/drivers/sources/ftp.py: 12, 14, 15, 15, 21, 57, 88, 103, 117, interscript/drivers/sources/http.py: 12, 14, 15, 15, 21, 54, 66, 89, 102
remove interscript/core/sets.py: 57, interscript/core/stacks.py: 60, 60, interscript/drivers/sources/ftp.py: 114, 122, interscript/drivers/sinks/bufdisk.py: 71, interscript/parsers/lalr1.py: 101, interscript/frames/inputf.py: 693
replace interscript/frames/inputf.py: 789, 790
report_comments interscript/tanglers/python.py: 275, interscript/tokenisers/python.py: 123, 124, 141, 143, 143, 230, 260, 264
report_unbalanced interscript/parsers/html.py: 169
repr interscript/core/sets.py: 90, 91, interscript/core/stacks.py: 29, 30, interscript/tanglers/python.py: 190, interscript/tokenisers/python.py: 118, interscript/parsers/lalr1.py: 519, 521, 523, 525, 527, interscript/frames/inputf.py: 270, interscript/compilers/c.py: 28, 43, 67, 81, interscript/compilers/cpp.py: 27, 44, 70, 86
res interscript/parsers/lalr1.py: 86, 87, 96, 100, 105, 110, 112, 116, 125, 133, 136, 219, 233, 236, 239, 239, 243, 271, 276, 277, 278, 279, 281, 282, 286, 288, 291, 293, 294, 297, 299, 301, 303, 310, 311, 313, 314, 318, 322, 323, 324, 325, 329, 331, 334, 336, 338, 346, 347, 349, 350, 354, 356, 357, 359, 362, 366, 367, 369, 371, 376, 382, 388, 388, 389, 390, 421, 428, 435, 435, 437, 438, 501, 512, 514, 573, 579, 621, 626, 633, 634, 675, 678, 680, 684, 688, 773, 774, 895, 896, 911, 912, 926, 927, 941, 942, interscript/frames/inputf.py: 37, 38, 460, 461, 461, 462, 535, 537, 537, 544, 544, 547
reset interscript/tokenisers/python.py: 145, 147, interscript/parsers/html.py: 15, 16
reskeys interscript/parsers/lalr1.py: 286, 287, 290, 329, 330, 333, 362
resolve interscript/parsers/lalr1.py: 529, 584, 597, 609, 619
result interscript/weavers/web.py: 630, 632, interscript/tanglers/python.py: 83, 84, 86, 86, 88, 89, 102, 158, 160, 208, 242, 247, 382, 397, 397, 410, 410, interscript/felix/model/fincat.py: 103, 110, 115, 120, 122, 130, 193, 195, interscript/felix/model/funcat.py: 75, 77, 78, interscript/frames/inputf.py: 623, 624, interscript/getoptions.py: 10, 30, 35, 36, interscript/compilers/cpp.py: 28, 29, 45, 46, 71, 72, 87, 88, interscript/utilities/diff.py: 11, 22, 38, 41, 46, 49, 92
results interscript/tanglers/python.py: 81, 83, 88, 90
resume_code interscript/frames/inputf.py: 857
retrlines interscript/drivers/sources/ftp.py: 88
reverse interscript/core/stacks.py: 61, 61, interscript/parsers/lalr1.py: 176, 189, interscript/felix/model/stdcat2.py: 48
rewind_source interscript/drivers/sources/cache.py: 23, interscript/drivers/storage/memory.py: 29
rhs interscript/core/sets.py: 13, 15, 19, 20, 24, 25, 25, 27, 28, 31, 34, 35, 35, 37, 38, 38
rhsdict interscript/parsers/lalr1.py: 288, 289, 331, 332
rhsind interscript/parsers/lalr1.py: 223, 224, 226, 228, 580, 581, 587, 588, 594, 614
ri interscript/parsers/lalr1.py: 377, 378, 380, 382, 458, 459
right interscript/core/sets.py: 103, 104, 107, 124, 127, 130, 133, 136, 138, 144, 145, 147, 150, interscript/felix/model/fincat.py: 103, 110, 113, 118, 122, 125, 127, 168, 169, 170, interscript/felix/model/stdcat.py: 13, 20, 37, 38, 58, 59, 71, 71, interscript/felix/model/stdcat2.py: 12, 12, 14, interscript/felix/model/funcat.py: 64, 64, interscript/felix/model/cons.py: 20, 22, 25, 28, 54, 55, 57, 58, 82, 86, 87, 90, 94, 95, 119, 120, interscript/frames/inputf.py: 606, 608, 608, 609
rnt interscript/parsers/lalr1.py: 289, 290, 291, 294, 299, 332, 333, 334
row interscript/weavers/text.py: 199, 200, 201, 207, 208, 209, 210
rparen interscript/parsers/lalr1.py: 717, 726, 769, 770
rstrip interscript/drivers/sources/base.py: 69, interscript/drivers/sources/disk.py: 22, interscript/drivers/sources/stdin.py: 23, interscript/weavers/latex.py: 206, interscript/tanglers/c.py: 56, interscript/tanglers/perl.py: 183, interscript/frames/inputf.py: 495, 521, 944, 1139, interscript/tests/test_diff.py: 21, 24
rule interscript/felix/model/fincat.py: 152, 153, 154, 154, 155, 155
rules interscript/felix/model/fincat.py: 14, 69, 128, 130, 136, 136, 152, 153, 154, 154, 155, 155, 166, 169, 192, 193
run interscript/__init__.py: 118, interscript/frames/processf.py: 26
run_from_options interscript/__init__.py: 113, interscript/frames/inputf.py: 224, 228, interscript/bin/iscr.py: 11
s interscript/core/sets.py: 5, 6, 10, 14, 21, 29, 30, 41, 44, 47, 50, 54, 58, 62, 62, 66, 70, 74, 78, 82, 83, 83, 83, 84, 88, 97, 105, 107, 112, 115, 118, 119, 122, 125, 126, 127, 128, 131, 132, 132, 132, 133, 133, 134, 137, 138, 139, 140, 140, 140, 140, 141, 141, 142, 148, 149, 150, 151, interscript/core/stacks.py: 4, 7, 7, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 25, 25, 25, 26, 26, 28, 29, 29, 29, 29, 30, 30, 30, 31, 35, 41, 47, 51, 52, 53, 56, 58, 59, 60, 61, interscript/parsers/lalr1.py: 148, 148, 380, 381, 383, 403, 404, 405, 407, 408, 426, 427, 648, 652, 655, 658, 679, 681, 682, 686, 779, 781, 781, 784, 785, 787, 788, 789, 793, 795, 796, 799, 802, 804, 805, 808, 811, 812, 812, 815, 819, 821, 822, 825, interscript/frames/inputf.py: 872, 874, 876, 878, 880, 884, 886, interscript/compilers/cconfig.py: 48, 49, 49, 50, 50, 51, 51, 53, 53, 54, 54, 56, 56, 57, interscript/utilities/commands.py: 67, 70, 70, 71, 71, 72, 72, 73, interscript/bin/iscr.bat: 5
s1 interscript/tests/test_sets.py: 5, 7, 9, 10, 11, 12, 13, 14, 14, 15, 15, 15, 16, 17, 19, 20, 21, 23, 24, 25, 26, 28, 30, 32, 33, 34, 35
s2 interscript/tests/test_sets.py: 6, 8, 9, 10, 11, 12, 13, 15, 15, 15, 19, 20, 21, 23, 24, 25, 26, 29, 31, 32, 33, 34, 35
save_data interscript/parsers/html.py: 25, 36, 39, 47
saved interscript/drivers/sources/cache.py: 10, interscript/drivers/sinks/cache.py: 7, 13, 14, 17, 17, interscript/drivers/storage/memory.py: 11, 26, 27, 33, 33, interscript/frames/inputf.py: 551, 560, 560, 566, 566, 567, 571, 575, 578, 724, 725
saved_comments interscript/parsers/html.py: 55, 55, 177, 183
saved_data interscript/parsers/html.py: 37, 40, 48, 48
saved_mode interscript/weavers/html.py: 352, 354
sc interscript/weavers/html.py: 413, 416, 419, 437, 440, 443, interscript/weavers/web.py: 107, 108, 113, interscript/weavers/latex.py: 55, 58, 61, 77, 80, 83
scol interscript/tokenisers/python.py: 116, 118
script interscript/frames/inputf.py: 949, 950, 952, 954, 957, 962
script_comment_tangler interscript/tanglers/python.py: 369, 417
script_foot interscript/weavers/html.py: 167, interscript/frames/inputf.py: 254, 659
script_head interscript/weavers/html.py: 160, interscript/frames/inputf.py: 251, 656
script_language interscript/parsers/html.py: 26, 54, 176, 181, 188
search interscript/weavers/filter.py: 32, 47
secno interscript/weavers/text.py: 336, 342, 345, 352, interscript/weavers/html.py: 133, 141, 151, 158, interscript/weavers/web.py: 226, 228, 240, 245, 246, 247, 248, 249, 251, interscript/weavers/latex.py: 246, 250, 252, 256, interscript/frames/inputf.py: 838, 839, 845, 846
second interscript/felix/model/stdcat2.py: 33, 34, 35
section interscript/frames/inputf.py: 604, 605, 606, interscript/utilities/diff.py: 65, 67, 68, interscript/tests/test_diff.py: 28, 30
section_index interscript/weavers/html.py: 142, interscript/weavers/web.py: 232, 534, interscript/frames/masterf.py: 22, 47, 47, interscript/frames/passf.py: 37, interscript/frames/inputf.py: 834, 843
sectionref interscript/weavers/web.py: 59, 77
sections interscript/utilities/diff.py: 54, 57, 59, 64, 65, 66, 79, 83, 84, 85
select interscript/frames/inputf.py: 201, 298, 311, 323, 351, 370, 383, 395, 410, 807, 890, 895, 900, 905, 910, 915, 920, 925, interscript/tests/example.pak: 6
select1 interscript/frames/inputf.py: 809, 815
select_tangler interscript/frames/inputf.py: 811, 817, 823
self interscript/tests/output/mymodule2.py: 4, 5, 6, 7, interscript/tests/output/mymodule3.py: 4, 5, 7, 8, interscript/core/sets.py: 4, 5, 6, 9, 10, 13, 14, 19, 21, 24, 25, 25, 27, 29, 30, 34, 35, 35, 37, 38, 38, 40, 41, 43, 44, 46, 47, 49, 50, 53, 54, 57, 58, 61, 62, 62, 65, 66, 69, 70, 73, 74, 77, 78, 81, 83, 87, 88, 96, 102, 105, 111, 112, 114, 115, 117, 118, 119, 121, 122, 124, 126, 130, 132, 136, 139, 144, 145, 147, 149, interscript/core/stacks.py: 4, 4, 5, 7, 7, 9, 10, 11, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 29, 29, 30, 33, 35, 37, 39, 41, 45, 47, 51, 51, 52, 52, 53, 53, 54, 56, 58, 59, 59, 60, 60, 61, 61, interscript/core/protocols.py: 36, 37, interscript/tests/test_protocol.py: 11, 12, interscript/drivers/sources/base.py: 11, 12, 13, 15, 16, 18, 19, 21, 22, 24, 25, 28, 33, 34, 36, 37, 39, 41, 45, 48, 49, 50, 51, 53, 54, 55, 55, 58, 59, 61, 62, 64, 65, 66, 68, 68, 71, 72, interscript/drivers/sources/disk.py: 39, 40, 42, 44, 44, 44, 48, 48, 49, interscript/drivers/sources/url.py: 7, 8, 9, 10, 11, interscript/drivers/sources/ftp.py: 12, 13, 14, 15, 16, 17, 19, 20, 21, 21, 22, 23, 24, 24, 25, 27, 28, 30, 31, 32, 33, 33, 34, 36, 38, 40, 41, 43, 44, 44, 46, 47, 51, 52, 53, 57, 62, 63, 63, 65, 66, 69, 70, 71, 72, 72, 72, 73, 73, 74, 79, 80, 81, 86, 88, 88, 89, 97, 98, 103, 103, 105, 107, 111, 114, 114, 117, 118, 119, 120, 122, interscript/drivers/sources/http.py: 12, 13, 14, 15, 16, 17, 19, 20, 21, 21, 22, 23, 24, 24, 25, 27, 28, 29, 30, 30, 31, 33, 35, 37, 38, 40, 41, 41, 43, 44, 48, 49, 50, 54, 59, 60, 60, 62, 63, 66, 67, 68, 83, 84, 89, 89, 91, 93, 97, 102, 103, 104, 105, 115, 115, interscript/drivers/sources/stdin.py: 12, 13, 14, 15, 17, 18, 22, 22, interscript/drivers/sources/cache.py: 7, 8, 9, 10, 12, 13, 15, 16, 16, 17, 17, 20, 20, 23, 24, interscript/drivers/sinks/base.py: 5, 6, 7, 8, 9, 10, 12, 14, 15, 16, 16, 17, 19, 20, 21, 22, 22, 24, 25, 27, 28, 30, 31, 33, 34, 36, 39, 40, 42, 43, 44, 46, 47, interscript/drivers/sinks/null.py: 4, 5, 7, interscript/drivers/sinks/tee.py: 4, 5, 7, interscript/drivers/sinks/disk.py: 8, 9, 15, 21, 24, 25, 27, 27, 28, 28, 28, interscript/drivers/sinks/bufdisk.py: 10, 11, 12, 13, 13, 14, 20, 24, 25, 26, 28, 29, 31, 32, 33, 34, 36, 40, 43, 44, 46, 47, 47, 48, 49, 50, 51, 55, 60, 60, 61, 61, 62, 66, 66, 67, 67, 69, 69, 70, 70, 71, 71, 73, 73, 74, 74, 74, interscript/drivers/sinks/stdout.py: 5, 6, 8, interscript/drivers/sinks/cache.py: 5, 6, 7, 8, 9, 10, 12, 13, 13, 14, 16, 17, 17, 19, 20, 21, 21, interscript/drivers/storage/memory.py: 7, 8, 9, 10, 11, 12, 14, 15, 17, 18, 18, 19, 19, 22, 22, 25, 26, 26, 27, 29, 30, 32, 33, 33, interscript/weavers/base.py: 4, 5, 6, 7, 8, 9, 11, 11, 12, 12, 12, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 20, 20, 21, 23, 24, 26, 27, interscript/weavers/raw.py: 4, 5, 7, 8, 9, 10, 10, interscript/weavers/multiplexor.py: 5, 6, 7, 8, 9, 10, 12, 15, 16, 16, 18, 19, 36, 47, 48, 49, 51, 54, 55, 57, 58, 59, 61, 62, 64, 65, 67, 69, 70, interscript/weavers/text.py: 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 32, 34, 36, 37, 38, 39, 41, 42, 43, 44, 44, 45, 45, 45, 48, 49, 51, 52, 53, 54, 54, 56, 58, 59, 60, 63, 64, 66, 68, 71, 73, 74, 79, 80, 81, 84, 86, 87, 88, 89, 91, 91, 92, 95, 96, 99, 100, 101, 106, 108, 110, 112, 116, 118, 120, 122, 126, 128, 130, 132, 136, 138, 140, 142, 145, 146, 149, 151, 152, 153, 154, 156, 156, 157, 160, 162, 163, 164, 165, 167, 167, 168, 171, 172, 174, 175, 177, 178, 184, 185, 187, 188, 189, 191, 192, 194, 195, 197, 198, 199, 204, 205, 207, 212, 213, 214, 215, 215, 216, 217, 219, 221, 222, 223, 224, 227, 228, 229, 231, 232, 234, 235, 236, 236, 237, 237, 238, 240, 241, 241, 243, 244, 244, 246, 247, 249, 250, 251, 252, 252, 254, 256, 257, 258, 259, 260, 260, 261, 263, 265, 267, 268, 269, 270, 271, 273, 274, 275, 275, 277, 278, 279, 280, 280, 281, 282, 284, 285, 287, 288, 290, 291, 293, 294, 296, 297, 298, 300, 301, 302, 304, 305, 306, 306, 308, 309, 310, 310, 312, 313, 313, 314, 314, 315, 316, 319, 321, 322, 323, 326, 327, 328, 329, 330, 331, 331, 332, 333, 334, 336, 338, 341, 343, 345, 347, 350, 351, 353, 355, 356, 357, 359, 360, 362, 363, 364, 365, 367, 368, 369, 370, 372, 373, 374, 375, 377, 378, 379, 380, 382, 383, 384, 385, 387, 388, 389, 390, 391, 391, 394, 395, 395, 397, 398, 398, 399, 401, 402, 402, 404, 405, 406, 406, 408, 409, 410, 410, 411, 413, 414, 415, 415, 417, 418, 419, 419, 420, 421, 421, 423, 424, 425, 426, 426, 427, 427, 428, 430, 431, 433, 434, 434, 435, 438, 439, interscript/weavers/html.py: 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 43, 44, 45, 46, 47, 49, 51, 53, 56, 57, 58, 58, 61, 62, 63, 65, 66, 67, 67, 68, 70, 71, 72, 74, 75, 75, 77, 78, 78, 80, 81, 81, 83, 84, 86, 89, 90, 92, 94, 95, 96, 98, 99, 101, 103, 104, 106, 107, 109, 110, 112, 113, 115, 116, 118, 119, 120, 121, 123, 124, 125, 126, 128, 130, 131, 133, 135, 138, 142, 146, 151, 153, 156, 160, 161, 162, 165, 167, 168, 169, 173, 174, 175, 179, 183, 185, 186, 187, 188, 190, 191, 192, 194, 196, 197, 198, 199, 201, 202, 203, 205, 207, 208, 209, 210, 213, 214, 216, 219, 220, 222, 224, 227, 228, 228, 229, 229, 230, 231, 234, 236, 237, 238, 242, 243, 247, 248, 248, 250, 251, 253, 254, 257, 261, 265, 266, 269, 270, 271, 273, 274, 276, 277, 279, 280, 283, 284, 285, 287, 288, 290, 291, 293, 294, 295, 298, 299, 300, 302, 303, 305, 306, 308, 309, 313, 314, 315, 317, 318, 320, 321, 323, 325, 327, 327, 329, 331, 332, 334, 337, 338, 341, 342, 344, 345, 346, 348, 349, 351, 352, 353, 354, 357, 358, 360, 361, 363, 364, 366, 367, 369, 370, 372, 373, 375, 376, 378, 379, 381, 382, 384, 385, 387, 388, 390, 391, 393, 394, 396, 397, 400, 401, 403, 407, 408, 411, 414, 416, 419, 420, 421, 424, 425, 427, 431, 432, 435, 438, 440, 443, 444, 445, 448, 449, 452, 454, 455, 456, 459, 460, 463, 465, 466, 467, 468, 470, 470, 473, 474, 477, 478, 479, 484, 486, 488, 490, 494, 496, 498, 500, 504, 506, 508, 510, 514, 516, 518, 520, 523, 526, 528, 529, 530, 531, 533, 533, 536, 538, 539, 540, 541, 543, 543, 546, 549, 551, 552, 553, 554, 556, 557, 559, 562, 563, 564, 565, 567, 568, 571, 572, 573, 578, 578, 592, 597, 597, 599, 601, 602, 603, 605, 606, 607, interscript/weavers/web.py: 13, 19, 22, 23, 24, 25, 30, 31, 33, 34, 35, 36, 37, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 62, 65, 81, 84, 86, 87, 88, 89, 90, 98, 109, 110, 124, 125, 126, 126, 127, 127, 129, 129, 130, 130, 130, 132, 132, 133, 134, 136, 138, 138, 139, 141, 142, 142, 144, 146, 148, 150, 150, 151, 153, 153, 155, 157, 159, 161, 162, 163, 164, 165, 166, 167, 168, 169, 172, 174, 174, 175, 175, 177, 177, 180, 180, 190, 191, 193, 194, 194, 195, 196, 198, 199, 200, 201, 203, 205, 206, 207, 210, 211, 213, 215, 218, 221, 224, 226, 228, 229, 232, 236, 237, 246, 248, 250, 252, 257, 257, 258, 258, 259, 259, 260, 260, 260, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 278, 279, 279, 280, 282, 283, 284, 285, 287, 289, 291, 291, 292, 292, 293, 293, 294, 294, 295, 295, 296, 296, 297, 297, 298, 298, 303, 305, 306, 307, 310, 311, 311, 312, 313, 314, 314, 316, 317, 317, 318, 319, 319, 320, 320, 322, 323, 325, 325, 326, 329, 329, 330, 331, 333, 334, 335, 338, 341, 345, 346, 346, 350, 351, 354, 354, 357, 357, 365, 370, 371, 372, 373, 374, 379, 379, 379, 379, 381, 388, 389, 391, 392, 393, 395, 396, 398, 399, 399, 400, 401, 403, 403, 404, 405, 451, 452, 453, 454, 455, 456, 457, 457, 458, 461, 461, 462, 466, 468, 470, 470, 471, 475, 476, 478, 478, 480, 482, 491, 493, 494, 498, 500, 502, 505, 507, 508, 509, 510, 511, 515, 517, 519, 524, 526, 527, 528, 529, 530, 534, 545, 553, 555, 556, 557, 558, 560, 563, 565, 567, 571, 573, 574, 575, 576, 578, 581, 583, 585, 590, 592, 593, 594, 595, 597, 601, 603, 611, 613, 614, 615, 616, 618, 621, 623, 631, 637, 640, 640, 640, 642, 646, 647, 648, 649, 652, 653, 654, 655, 656, interscript/weavers/latex.py: 22, 23, 24, 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 37, 40, 41, 44, 45, 49, 50, 53, 56, 58, 61, 62, 63, 66, 67, 71, 72, 75, 78, 80, 83, 84, 85, 88, 89, 92, 93, 96, 97, 98, 99, 102, 103, 104, 105, 108, 142, 145, 151, 156, 166, 177, 179, 180, 182, 186, 187, 190, 192, 194, 195, 198, 199, 199, 201, 202, 202, 204, 205, 205, 208, 210, 212, 213, 214, 216, 217, 219, 220, 222, 223, 226, 227, 228, 230, 231, 232, 234, 235, 237, 238, 240, 241, 242, 243, 246, 248, 252, 254, 259, 268, 273, 274, 274, 277, 279, 282, 283, 284, 286, 287, 288, 290, 291, 293, 294, 295, 297, 298, 300, 301, 304, 305, 307, 308, 310, 311, 313, 317, 318, 320, 321, 323, 324, 326, 330, 331, 333, 334, 336, 337, 338, 339, 341, 346, 347, 348, 350, 353, 354, 356, 357, 359, 360, 362, 363, 366, 367, 369, 370, 372, 373, 375, 376, 378, 379, 381, 382, 384, 385, 387, 388, 390, 391, 393, 394, 396, 397, 399, 400, 402, 403, 405, 406, 409, 410, 411, 412, interscript/weavers/filter.py: 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 18, 19, 20, 22, 23, 26, 27, 28, 29, 32, 38, 40, 42, 43, 45, 47, 49, 52, 53, 54, 55, 58, 59, 60, 65, 66, 67, interscript/tanglers/base.py: 7, 8, 9, 10, 11, 12, 12, 13, 13, 14, 16, 16, 18, 21, 22, 24, 25, 26, 26, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 40, 41, 42, 44, interscript/tanglers/null.py: 12, 13, 14, 16, 17, 19, interscript/tanglers/doc.py: 8, 9, 10, 12, 13, 15, 16, interscript/tanglers/c.py: 9, 10, 11, 12, 14, 15, 17, 19, 20, 21, 21, 23, 24, 26, 27, 27, 32, 33, 35, 36, 37, 39, 40, 42, 43, 48, 50, 51, 52, 53, 55, 57, 57, 62, 63, 64, interscript/tanglers/cpp.py: 9, 10, 11, 12, 14, 15, 17, 19, 20, 21, 21, 23, 24, 26, 27, 27, 32, 33, 34, 35, 37, 38, 39, 39, 43, 44, interscript/tanglers/java.py: 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 19, 21, 22, 24, 25, 25, interscript/tanglers/tcl.py: 7, 8, 9, 11, 12, 14, 16, 17, 18, 18, 20, 21, 23, 25, 25, interscript/tanglers/python.py: 38, 43, 44, 45, 46, 269, 270, 271, 272, 273, 274, 275, 276, 278, 280, 283, 285, 286, 289, 291, 293, 295, 296, 299, 308, 308, 313, 326, 328, 329, 331, 332, 342, 343, 343, 344, 347, 347, 348, 351, 351, 352, 359, 360, 362, 364, 365, 366, 366, 368, 369, 371, 372, 372, 374, 389, 404, 418, 419, 420, 421, interscript/tanglers/perl.py: 8, 9, 10, 12, 13, 14, 15, 16, 17, 18, 20, 29, 30, 31, 33, 34, 36, 40, 43, 44, 47, 49, 51, 61, 65, 70, 73, 78, 83, 89, 93, 95, 101, 104, 109, 112, 115, 119, 120, 121, 126, 127, 128, 132, 134, 135, 135, 137, 139, 140, 145, 146, 147, 152, 153, 154, 155, 156, 157, 158, 159, 162, 168, 169, 171, 171, 181, 185, 186, 187, 187, 188, 189, 192, 192, 193, 194, 195, 196, 201, 208, 209, 210, 211, 212, 213, 214, 220, 221, 221, 224, 225, 225, 229, 232, 233, 236, 238, 241, 242, 244, 249, 250, 257, 261, 265, 268, 269, 271, 272, 274, 275, 276, 278, 279, 281, 283, 284, 284, 286, 287, 289, 291, 291, interscript/tokenisers/python.py: 141, 142, 143, 144, 145, 147, 148, 148, 148, 149, 149, 150, 151, 152, 153, 155, 156, 157, 160, 161, 162, 164, 165, 167, 168, 169, 169, 170, 171, 172, 174, 177, 178, 180, 181, 184, 185, 185, 187, 189, 191, 192, 195, 199, 200, 200, 201, 201, 202, 203, 204, 205, 205, 206, 207, 210, 210, 211, 211, 212, 217, 217, 218, 227, 230, 235, 236, 238, 239, 239, 245, 258, 260, 264, 268, 269, 275, 279, 280, 281, 286, 287, 288, 288, 289, 290, 299, 301, 301, 302, 302, 303, 314, 315, 316, 316, 316, 317, 317, 317, interscript/parsers/html.py: 6, 7, 9, 10, 13, 13, 15, 16, 23, 24, 25, 26, 27, 28, 29, 33, 35, 36, 37, 38, 39, 40, 42, 47, 48, 48, 50, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 64, 68, 68, 69, 69, 71, 71, 72, 72, 74, 74, 75, 75, 77, 77, 78, 78, 80, 80, 81, 81, 83, 83, 84, 84, 86, 86, 87, 87, 90, 90, 91, 91, 94, 94, 95, 95, 98, 99, 100, 101, 102, 104, 105, 106, 107, 108, 110, 111, 112, 113, 114, 117, 118, 119, 121, 123, 124, 125, 127, 129, 129, 130, 131, 131, 133, 134, 134, 137, 137, 138, 138, 138, 140, 140, 141, 141, 141, 143, 143, 144, 144, 144, 146, 146, 147, 147, 147, 149, 149, 150, 150, 150, 152, 152, 153, 153, 153, 155, 158, 161, 164, 169, 172, 173, 176, 177, 179, 180, 181, 183, 183, 188, interscript/parsers/lalr1.py: 13, 14, 15, 17, 19, 20, 22, 23, 26, 26, 33, 34, 35, 36, 39, 40, 44, 45, 46, 47, 48, 49, 49, 50, 51, 53, 54, 57, 59, 59, 59, 62, 63, 64, 65, 67, 69, 71, 74, 75, 77, 80, 81, 85, 86, 87, 93, 105, 109, 111, 115, 117, 130, 136, 143, 147, 158, 159, 160, 162, 162, 164, 165, 168, 171, 173, 174, 178, 186, 201, 215, 218, 224, 226, 226, 228, 232, 233, 234, 236, 237, 259, 260, 261, 262, 263, 264, 265, 266, 267, 270, 272, 273, 274, 294, 299, 309, 314, 317, 320, 321, 345, 350, 353, 355, 358, 363, 364, 371, 375, 378, 380, 383, 385, 387, 393, 394, 399, 401, 403, 407, 420, 426, 426, 427, 433, 442, 443, 443, 451, 455, 457, 466, 467, 468, 470, 499, 514, 517, 529, 541, 544, 549, 550, 563, 565, 568, 571, 572, 575, 581, 584, 587, 587, 588, 589, 590, 592, 593, 596, 597, 601, 603, 603, 605, 609, 614, 615, 615, 616, 617, 619, 621, 624, 625, 627, 631, 634, 638, 639, 640, 661, interscript/felix/model/basecat.py: 7, 8, interscript/felix/model/fincat.py: 6, 7, 11, 14, 19, 22, 24, 26, 28, 31, 31, 33, 36, 37, 39, 42, 43, 45, 48, 48, 50, 53, 53, 55, 59, 59, 61, 65, 67, 68, 69, 72, 73, 75, 76, 79, 84, 86, 88, 91, 92, 93, 95, 99, 101, 103, 111, 113, 115, 118, 118, 120, 120, 122, 122, 125, 125, 128, 130, 132, 134, 135, 136, 139, 145, 146, 148, 149, 150, 153, 154, 155, 158, 161, 163, 164, 165, 166, 168, 169, 173, 174, 175, 176, 177, 177, 178, 179, 180, 180, 183, 185, 187, 188, 189, 192, 193, interscript/felix/model/stdcat.py: 6, 11, 13, 18, 18, 20, 22, 22, 23, 23, 24, 24, 26, 27, 27, 29, 29, 33, 34, 35, 37, 39, 39, 42, 48, 49, 49, 54, 55, 56, 58, 60, 60, 63, 71, 73, 76, 77, 81, 81, 83, 88, 88, 90, 95, 95, 97, interscript/felix/model/stdcat2.py: 7, 7, 9, 9, 12, 14, 18, 19, 21, 22, 24, 25, 27, 28, 30, 34, 38, 40, 40, 43, 44, 45, 47, interscript/felix/model/funcat.py: 5, 6, 7, 9, 10, 15, 16, 18, 19, 21, 22, 24, 25, 26, 28, 28, 29, 33, 34, 40, 41, 43, 44, 48, 49, 51, 52, 56, 56, 57, 57, 58, 58, 62, 63, 64, 65, 66, 71, 72, 73, 76, 77, 82, 83, 84, 86, interscript/felix/model/cons.py: 6, 7, 8, 10, 11, 12, 15, 16, 17, 20, 21, 22, 25, 27, 28, 31, 33, 34, 37, 39, 40, 45, 46, 48, 49, 51, 52, 54, 55, 57, 58, 60, 61, 63, 64, 68, 69, 70, 72, 73, 74, 77, 78, 79, 82, 83, 85, 86, 87, 90, 91, 93, 94, 95, 97, 98, 99, 100, 102, 103, 104, 105, 109, 110, 111, 113, 114, 114, 116, 117, 117, 119, 120, 120, 122, 123, 123, 125, 126, 126, interscript/frames/install.py: 3, 4, 5, 6, 7, 8, 10, 11, 11, 12, 12, 15, 16, 17, 18, 19, 20, 21, 24, 26, 27, 28, 33, 35, 36, 37, 42, 44, 45, 46, 51, 53, 54, 55, 60, 62, 63, 64, 68, 69, 70, 71, 72, 73, 74, 77, 85, 88, 90, 97, 98, interscript/frames/platform.py: 6, 7, 8, 11, 15, 19, 24, 27, 30, interscript/frames/site.py: 4, 5, 6, 7, 8, interscript/frames/processf.py: 11, 12, 13, 14, 16, 17, 18, 19, 20, 23, 26, 29, 30, 31, 47, 48, 51, 52, 62, 62, 65, 68, 71, 78, 79, interscript/frames/masterf.py: 7, 8, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 29, 30, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 50, 51, 54, 80, 82, 83, 90, 90, 92, 93, 94, 95, interscript/frames/passf.py: 15, 17, 18, 20, 22, 23, 24, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 40, 42, 43, 52, 52, 54, 55, 59, 59, 62, 72, 74, 81, 89, 90, 92, 93, 93, 94, 96, 97, 97, 98, interscript/frames/inputf.py: 60, 62, 63, 64, 64, 65, 65, 67, 68, 70, 71, 72, 73, 74, 76, 77, 78, 79, 80, 80, 81, 81, 82, 83, 84, 84, 86, 87, 89, 91, 93, 94, 95, 98, 100, 169, 170, 171, 172, 173, 174, 175, 176, 176, 177, 177, 182, 185, 188, 189, 190, 190, 192, 195, 195, 198, 199, 200, 201, 202, 206, 207, 211, 212, 215, 218, 219, 223, 242, 243, 245, 246, 248, 249, 250, 251, 253, 254, 278, 279, 280, 281, 282, 283, 284, 285, 286, 289, 290, 291, 296, 297, 298, 300, 301, 303, 304, 305, 307, 310, 311, 315, 316, 318, 318, 319, 320, 320, 322, 323, 324, 326, 329, 330, 331, 335, 335, 338, 339, 339, 340, 342, 342, 344, 347, 348, 349, 351, 354, 355, 355, 356, 359, 361, 363, 366, 367, 368, 373, 374, 376, 378, 380, 382, 383, 383, 383, 385, 386, 387, 389, 395, 397, 397, 397, 399, 402, 403, 404, 409, 410, 413, 414, 416, 417, 418, 426, 427, 428, 429, 432, 433, 435, 436, 437, 440, 441, 441, 442, 444, 445, 445, 446, 449, 450, 451, 453, 455, 456, 459, 460, 462, 463, 465, 466, 467, 468, 473, 474, 476, 477, 478, 482, 483, 484, 486, 488, 489, 491, 492, 492, 493, 493, 494, 494, 494, 496, 496, 497, 497, 497, 500, 503, 505, 508, 510, 513, 514, 519, 524, 525, 526, 527, 528, 529, 534, 538, 539, 540, 545, 550, 553, 561, 563, 569, 572, 576, 580, 581, 584, 585, 586, 587, 588, 589, 590, 593, 599, 616, 617, 619, 623, 624, 627, 636, 638, 644, 646, 647, 649, 653, 654, 655, 664, 665, 666, 686, 700, 701, 708, 716, 719, 720, 723, 724, 724, 725, 728, 729, 732, 733, 736, 737, 740, 741, 741, 742, 744, 745, 745, 746, 748, 749, 751, 752, 755, 755, 756, 756, 757, 757, 758, 758, 759, 759, 762, 763, 764, 764, 765, 767, 769, 771, 773, 796, 797, 797, 798, 799, 799, 801, 802, 802, 803, 804, 804, 807, 809, 811, 813, 815, 817, 819, 823, 824, 824, 825, 826, 826, 828, 829, 830, 831, 832, 834, 839, 839, 841, 842, 843, 846, 846, 848, 849, 850, 850, 852, 854, 855, 857, 858, 860, 861, 863, 864, 865, 865, 867, 869, 872, 873, 876, 877, 880, 881, 882, 883, 884, 889, 890, 891, 894, 895, 896, 899, 900, 901, 904, 905, 906, 909, 910, 911, 914, 915, 916, 919, 920, 921, 924, 925, 926, 930, 931, 936, 937, 938, 949, 950, 952, 953, 957, 958, 960, 961, 962, 965, 967, 968, 969, 970, 971, 972, 972, 973, 980, 982, 983, 984, 985, 986, 989, 990, 990, 992, 993, 995, 997, 999, 999, 1002, 1003, 1003, 1004, 1006, 1007, 1009, 1010, 1012, 1012, 1013, 1013, 1016, 1017, 1020, 1021, 1023, 1024, 1026, 1027, 1029, 1030, 1033, 1034, 1036, 1037, 1039, 1040, 1042, 1043, 1045, 1046, 1048, 1049, 1051, 1052, 1054, 1055, 1057, 1058, 1060, 1061, 1063, 1064, 1066, 1067, 1069, 1070, 1072, 1073, 1075, 1076, 1079, 1080, 1082, 1083, 1085, 1086, 1088, 1089, 1091, 1092, 1094, 1095, 1097, 1098, 1100, 1101, 1103, 1104, 1106, 1107, 1109, 1110, 1112, 1113, 1115, 1116, 1118, 1119, 1122, 1123, 1125, 1126, 1130, 1131, 1131, 1132, 1133, 1137, 1141, interscript/getframes.py: 107, 109, interscript/compilers/c.py: 9, 10, 11, 13, 14, 16, 17, 32, 33, 48, 49, 50, 52, 53, 55, 56, 71, 72, interscript/compilers/cpp.py: 8, 9, 10, 12, 13, 15, 16, 33, 34, 51, 52, 53, 55, 56, 58, 59, 76, 77, interscript/compilers/cconfig.py: 7, 8, 9, 10, 11, 12, 13, 14, 16, 18, 19, 20, 21, 22, 23, 26, 27, 29, 31, 33, 35, 37, 37, 41, 45, 47, 48, 49, 50, 51, 52, 54, 54, 55, 56
sep interscript/drivers/sources/disk.py: 29, 30, 31, 32, 33, interscript/drivers/sinks/util.py: 34, 36, 42, 50, 55, interscript/weavers/text.py: 319, 322, interscript/weavers/html.py: 234, 237, interscript/weavers/web.py: 303, interscript/frames/platform.py: 28, 28, interscript/utilities/diff.py: 52, 56, 62
seq interscript/core/sets.py: 65, 66, interscript/core/stacks.py: 21, 21, interscript/felix/model/stdcat2.py: 30, 31, 32, 33, interscript/frames/masterf.py: 92, 93, 94, 95
sequence interscript/weavers/base.py: 11, 12, interscript/weavers/web.py: 129, 130, interscript/frames/masterf.py: 50, 51, interscript/frames/passf.py: 35, 97, 97, 98
sequence_limit interscript/frames/masterf.py: 21, 49, 50, 51
set interscript/__init__.py: 47, interscript/core/sets.py: 2, 82, 103, 122, 125, 131, 137, 148, interscript/tests/test_sets.py: 3, 3, 5, 6, 28, 29, interscript/weavers/web.py: 7, interscript/parsers/lalr1.py: 4, 4, 44, 45, 46, 49, 112, 116, 125, 172, 206, 212, interscript/felix/model/stdcat2.py: 3, interscript/bin/iscr.bat: 18
set_anchor interscript/weavers/text.py: 51, interscript/weavers/html.py: 213, interscript/weavers/web.py: 193, 228, interscript/frames/inputf.py: 245, 449, 451, 453, 647, 961
set_fc_anchor interscript/weavers/html.py: 448, interscript/weavers/web.py: 646, 650, interscript/weavers/latex.py: 88, interscript/tanglers/python.py: 291
set_head interscript/frames/inputf.py: 995
set_original_filename interscript/weavers/text.py: 48, interscript/weavers/web.py: 190, interscript/frames/inputf.py: 81, 335
set_test_result interscript/frames/inputf.py: 279, 623
set_warning_character interscript/frames/passf.py: 80, interscript/frames/inputf.py: 307, 333, 459
set_weaver interscript/frames/inputf.py: 435, 813, 819
setattr interscript/core/protocols.py: 55, 64, interscript/parsers/lalr1.py: 17, interscript/frames/masterf.py: 12
sets interscript/__init__.py: 47, interscript/tests/test_sets.py: 2, 3, interscript/weavers/web.py: 7, interscript/parsers/lalr1.py: 2, 4, interscript/felix/model/stdcat2.py: 3
setsofitems interscript/parsers/lalr1.py: 394, 407
sf interscript/weavers/html.py: 413, 416, 419, 437, 440, 443, interscript/weavers/web.py: 107, 108, 113, interscript/weavers/latex.py: 55, 58, 61, 77, 80, 83
sgml interscript/parsers/html.py: 6, 7, 7, 10, 13, 16
sgml_wrapper interscript/__init__.py: 29, interscript/parsers/html.py: 5, interscript/frames/passf.py: 12, interscript/frames/inputf.py: 31, 405, 419
sgmllib interscript/parsers/html.py: 20, 22, 24
shortoptdict interscript/getframes.py: 12, 70, 85, 87, 88, 90
shortopts interscript/getoptions.py: 5, 21
should interscript/tests/test_stacking_weaver.pak: 19, interscript/bin/iscr.bat: 14
sign interscript/felix/tests/func_test.py: 32, 33, 33, 38
simple_named_file_sink interscript/__init__.py: 7, interscript/drivers/sinks/disk.py: 7, interscript/weavers/web.py: 6, 639, interscript/frames/inputf.py: 16
sin interscript/felix/tests/func_test.py: 10, 10, 11, 18, 29
sin2pcos2 interscript/felix/tests/func_test.py: 29, 30
single3prog interscript/tokenisers/python.py: 73, 76, 77, 78
sink interscript/weavers/base.py: 27, interscript/weavers/raw.py: 9, 10, interscript/weavers/multiplexor.py: 42, 42, 43, 44, interscript/weavers/text.py: 20, 21, 31, 54, 331, 340, 349, interscript/weavers/html.py: 37, 43, 51, 78, 81, 136, 154, interscript/weavers/web.py: 13, 14, 32, 37, 42, 85, 90, 91, 98, 101, 140, 169, 227, 230, 341, 379, 381, 506, 511, 512, 519, 525, 530, 531, 538, 554, 559, 560, 567, 572, 577, 578, 585, 591, 596, 597, 612, 617, 618, 647, interscript/weavers/latex.py: 25, 35, 186, 199, 202, 249, 255, interscript/tanglers/base.py: 7, 8, 8, 22, 26, 30, 31, 32, 34, 36, 37, 38, interscript/tanglers/c.py: 9, 10, 21, 24, 27, 32, 33, 48, 50, interscript/tanglers/cpp.py: 9, 10, 21, 24, 27, interscript/tanglers/java.py: 7, 8, 19, 22, 25, interscript/tanglers/tcl.py: 7, 8, 18, 21, 25, interscript/tanglers/python.py: 94, 173, 269, 270, 283, 293, 308, 331, 332, 366, 369, 372, 389, interscript/tanglers/perl.py: 8, 9, 154, 155, 157, 158, 171, 284, 287, 291, interscript/frames/inputf.py: 380, 389, 519, 524, 525, 764, 765, 770, 775, 781, 829, 830, 842
sink_base interscript/drivers/sinks/base.py: 3, interscript/drivers/sinks/null.py: 2, 3, 5, interscript/drivers/sinks/tee.py: 2, 3, 5, interscript/drivers/sinks/disk.py: 3, 7, 21, interscript/drivers/sinks/bufdisk.py: 3, 9, 32, 43, interscript/drivers/sinks/stdout.py: 3, 4, 6, interscript/drivers/sinks/cache.py: 3, 4, 6, interscript/drivers/storage/memory.py: 4, 6, 9, interscript/drivers/storage/disk.py: 3, 7
sink_open_error interscript/drivers/sinks/__init__.py: 3, interscript/drivers/sinks/disk.py: 4, 20, interscript/drivers/sinks/bufdisk.py: 4, 31, 42
sink_verbatim interscript/frames/inputf.py: 373
sinkname interscript/weavers/multiplexor.py: 38, 41, 44, 45
sinks interscript/__init__.py: 6, 7, 8, 9, interscript/drivers/sinks/null.py: 2, interscript/drivers/sinks/tee.py: 2, interscript/drivers/sinks/disk.py: 3, 4, 5, interscript/drivers/sinks/bufdisk.py: 3, 4, 5, interscript/drivers/sinks/stdout.py: 3, interscript/drivers/sinks/cache.py: 3, interscript/drivers/storage/memory.py: 4, interscript/drivers/storage/disk.py: 3, interscript/weavers/web.py: 5, 6, interscript/weavers/auto.py: 7, interscript/frames/inputf.py: 15, 16, 17
site interscript/frames/processf.py: 2
site_frame interscript/frames/site.py: 3, interscript/frames/processf.py: 2, 23, 23
site_install_point interscript/frames/install.py: 42, 72
sizehint interscript/drivers/sources/base.py: 33, 36, 39
skeys interscript/weavers/text.py: 101, 102, 109, 119, 129, 139, interscript/weavers/html.py: 479, 480, 487, 497, 507, 517
soi interscript/parsers/lalr1.py: 470, 480, 487, 503
sop interscript/weavers/text.py: 25, 34, 269, 271, 282
sort interscript/core/sets.py: 106, 108, interscript/core/stacks.py: 54, 56, 58, interscript/weavers/text.py: 102, interscript/weavers/html.py: 405, 429, 480, interscript/weavers/web.py: 100, 537, 628, interscript/weavers/latex.py: 47, 69, interscript/parsers/lalr1.py: 275, 296, 300, 389, 437, 511, interscript/getframes.py: 71, 75
source interscript/drivers/sources/base.py: 9, 57, 59, interscript/drivers/sources/stdin.py: 7, 11, 13, interscript/drivers/sources/cache.py: 2, 6, 8, interscript/drivers/storage/memory.py: 2, 6, 8, interscript/drivers/storage/disk.py: 2, 7, interscript/frames/passf.py: 82, interscript/frames/inputf.py: 71, 95, 171, 301, 320, 322, 327, 342, 342, 345, 358, 361, 364, 375, 378, 379, 387, 388, 394, 400, 414, 491, 492, 493, 1133
source_file interscript/tanglers/python.py: 95, 377, 390
source_filename interscript/frames/inputf.py: 630, 660, 661, 674, 675, 692
source_line interscript/tanglers/python.py: 96, 378, 391
source_open_error interscript/drivers/sources/__init__.py: 3, interscript/drivers/sources/disk.py: 4, 18, 51, interscript/frames/passf.py: 6, 61
source_origin_file interscript/frames/inputf.py: 249, 251, 254, 654, 656, 659
source_origin_line interscript/frames/inputf.py: 248, 253, 653, 658
source_prefix interscript/frames/masterf.py: 27, interscript/frames/passf.py: 59, interscript/getframes.py: 205
source_terminator interscript/frames/inputf.py: 242, 250, 631, 651, 655
sourceref interscript/weavers/web.py: 60, 78
sources interscript/__init__.py: 11, 12, 13, 14, 15, 16, interscript/drivers/sources/disk.py: 4, 5, 6, interscript/drivers/sources/url.py: 3, 4, interscript/drivers/sources/ftp.py: 7, 8, interscript/drivers/sources/http.py: 4, 5, interscript/drivers/sources/stdin.py: 7, 8, interscript/drivers/sources/cache.py: 2, 3, interscript/drivers/storage/memory.py: 2, 3, interscript/drivers/storage/disk.py: 2, interscript/parsers/html.py: 2, interscript/frames/processf.py: 5, interscript/frames/masterf.py: 3, interscript/frames/passf.py: 6, 7, 8, 11, interscript/frames/inputf.py: 10, 11, 12, 13, 14
sp interscript/parsers/lalr1.py: 457, 458
span interscript/tokenisers/python.py: 250
spawned interscript/tests/test_stacking_weaver.pak: 19
specify interscript/bin/iscr.bat: 8
split interscript/drivers/sources/disk.py: 26, interscript/drivers/sinks/base.py: 37, interscript/drivers/sinks/disk.py: 14, interscript/drivers/sinks/bufdisk.py: 19, interscript/weavers/text.py: 244, interscript/weavers/html.py: 560, interscript/weavers/web.py: 141, 144, 341, interscript/tanglers/python.py: 172, interscript/tokenisers/python.py: 175, interscript/frames/passf.py: 50, interscript/frames/inputf.py: 781, 933, interscript/getframes.py: 205, interscript/compilers/c.py: 20, 59, interscript/compilers/cpp.py: 19, 62, interscript/utilities/diff.py: 49
split_multiline_strings interscript/tanglers/python.py: 275, interscript/tokenisers/python.py: 123, 124, 141, 144, 144, 195, 212, 275, 290
splitup interscript/frames/inputf.py: 781, 782, 783
spontaneous interscript/parsers/lalr1.py: 395, 410, 416
spos interscript/tokenisers/python.py: 251, 256, 259, 261, 265, 273, 278, 295, 297, 304, 307
square interscript/felix/tests/func_test.py: 16, 17, 18, 19, 27, 27, 29, 29
squashop interscript/tokenisers/python.py: 123, 124, 141, 142, 142, 303
src interscript/felix/model/fincat.py: 79, 86, 91, 92, interscript/frames/inputf.py: 60, 71, 79, 90, 484
src_filename interscript/frames/inputf.py: 831, 836
src_lineno interscript/frames/inputf.py: 832, 836
srow interscript/tokenisers/python.py: 116, 118
stable_file_count interscript/frames/masterf.py: 57, 67, 67, 72, 77
stack interscript/__init__.py: 48, interscript/core/stacks.py: 2, 23, 24, 25, 51, interscript/weavers/web.py: 161, 312, 313, 314, 329, 389, 392, interscript/parsers/lalr1.py: 5, 641, 643, 648, 657, 658, 669, 670, 679, 680, 681, 683, 684, 685, 686
stacking interscript/tests/test_stacking_weaver.pak: 5, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41
stacking_weaver interscript/__init__.py: 24, interscript/weavers/web.py: 12, 464, interscript/tests/test_stacking_weaver.pak: 4, interscript/weavers/auto.py: 6, 17
stacks interscript/__init__.py: 48, interscript/parsers/lalr1.py: 3, 5
standard_install_point interscript/frames/install.py: 24, 70
start interscript/weavers/text.py: 397, 399, interscript/weavers/html.py: 269, 271, interscript/weavers/latex.py: 304, interscript/weavers/filter.py: 35, interscript/tokenisers/python.py: 250, 251, 252, 252, 272, 276, 279, 280, 286, 288, 292, 292, interscript/parsers/lalr1.py: 33, 35, 35, 160, 162, 259, 260, interscript/frames/inputf.py: 1042, 1043
start_b interscript/parsers/html.py: 68
start_big interscript/parsers/html.py: 83
start_body interscript/parsers/html.py: 60
start_code interscript/parsers/html.py: 86
start_code_line interscript/weavers/html.py: 317, 320, interscript/tanglers/python.py: 194, 198, 214, 225, 234, 243, 251, 261, 308
start_dd interscript/parsers/html.py: 133
start_dl interscript/parsers/html.py: 104
start_dt interscript/parsers/html.py: 129
start_em interscript/parsers/html.py: 74
start_h1 interscript/parsers/html.py: 137
start_h2 interscript/parsers/html.py: 140
start_h3 interscript/parsers/html.py: 143
start_h4 interscript/parsers/html.py: 146
start_h5 interscript/parsers/html.py: 149
start_h6 interscript/parsers/html.py: 152
start_head interscript/parsers/html.py: 58
start_html interscript/parsers/html.py: 57
start_i interscript/parsers/html.py: 71
start_li interscript/parsers/html.py: 117
start_ol interscript/parsers/html.py: 98
start_p interscript/parsers/html.py: 90
start_pre interscript/parsers/html.py: 94
start_script interscript/parsers/html.py: 172
start_section interscript/tanglers/base.py: 33, 44, interscript/tanglers/c.py: 17, interscript/tanglers/cpp.py: 17, interscript/tanglers/java.py: 15, interscript/tanglers/tcl.py: 14, interscript/tanglers/python.py: 362, interscript/tanglers/perl.py: 156, 281
start_small interscript/parsers/html.py: 80
start_strong interscript/parsers/html.py: 77
start_time interscript/frames/processf.py: 43, 55
start_ul interscript/parsers/html.py: 110
startmethod interscript/weavers/filter.py: 5, 8, 8, 43, 76, 77
startpos interscript/weavers/filter.py: 33, 39, 41, 46, 47, 48, 50
startsym interscript/parsers/lalr1.py: 171, 172
stat interscript/drivers/sources/ftp.py: 44, 44, interscript/drivers/sources/http.py: 41, 41
state interscript/parsers/lalr1.py: 474, 476, 503, 506, 517, 519, 521, 523, 525, 527, 577, 580, 628, 631
state_i interscript/parsers/lalr1.py: 453, 461, 462, 462, 473, 480, 483, 492, 492, 502, 507, 513, 513, 529, 541, 544, 563, 565, 568, 574, 584, 597, 603, 609, 615, 619, 620, 620
status interscript/weavers/text.py: 110, 111, 120, 121, 130, 131, 140, 141, 355, 358, 359, 362, interscript/weavers/html.py: 173, 178, 180, 181, 185, 488, 489, 498, 499, 508, 509, 518, 519, interscript/frames/inputf.py: 686, 689, 932, 934, 937, 941, 946, 947
stdcat interscript/felix/tests/stdcat_test.py: 5
stderr interscript/frames/processf.py: 28, 33, 60
stdin interscript/drivers/sources/stdin.py: 20, interscript/tokenisers/python.py: 322, interscript/frames/inputf.py: 225, 236
stdin_source interscript/drivers/sources/stdin.py: 11
stdout interscript/drivers/sinks/stdout.py: 9, interscript/frames/processf.py: 27, 33, 59
stdout_sink interscript/drivers/sinks/stdout.py: 4
storage interscript/__init__.py: 18, interscript/frames/inputf.py: 18
str interscript/drivers/sources/http.py: 60, 77, interscript/weavers/text.py: 66, 78, 91, 97, 132, 145, 156, 167, 322, 323, 342, 352, 359, interscript/weavers/html.py: 129, 130, 141, 158, 180, 237, 238, 247, 255, 261, 262, 263, 271, 416, 416, 419, 419, 440, 440, 443, 443, 449, 470, 475, 510, 523, 533, 543, 549, 549, interscript/weavers/web.py: 40, 113, 113, 219, 220, 228, 240, 241, 306, 307, 398, 544, 546, 632, interscript/weavers/latex.py: 58, 58, 61, 61, 80, 80, 83, 83, 89, 177, 250, 256, 273, interscript/tanglers/c.py: 18, interscript/tanglers/cpp.py: 18, interscript/tanglers/java.py: 16, interscript/tanglers/tcl.py: 15, interscript/tanglers/python.py: 363, interscript/tanglers/perl.py: 282, interscript/felix/model/fincat.py: 110, 110, 110, 167, 167, 170, 170, 190, 190, 190, 194, 194, 195, interscript/frames/processf.py: 48, interscript/frames/inputf.py: 244, 247, 260, 265, 276, 282, 284, 527, 618, 637, 646, 959, interscript/getframes.py: 101, interscript/compilers/c.py: 26, 38, 65, 76, interscript/compilers/cpp.py: 25, 38, 68, 81, interscript/utilities/diff.py: 19
strftime interscript/frames/processf.py: 42
string interscript/__init__.py: 43, interscript/drivers/sources/base.py: 8, 37, 69, interscript/drivers/sources/disk.py: 7, 22, 26, 31, interscript/drivers/sources/url.py: 5, interscript/drivers/sources/ftp.py: 9, interscript/drivers/sources/http.py: 9, interscript/drivers/sources/stdin.py: 9, 23, interscript/drivers/sources/cache.py: 4, interscript/drivers/sinks/base.py: 2, 31, 37, interscript/drivers/sinks/disk.py: 2, 14, interscript/drivers/sinks/bufdisk.py: 2, 19, interscript/weavers/text.py: 3, 18, 18, 244, 251, interscript/weavers/html.py: 3, 560, interscript/weavers/web.py: 8, 141, 141, 144, 152, 341, interscript/weavers/latex.py: 3, 206, interscript/tanglers/c.py: 7, 56, 57, interscript/tanglers/python.py: 8, 172, interscript/tanglers/perl.py: 5, 183, 240, interscript/tokenisers/python.py: 4, 31, 138, 138, 175, interscript/parsers/html.py: 3, 175, 176, interscript/parsers/lalr1.py: 778, 787, 788, 788, interscript/frames/platform.py: 28, interscript/frames/passf.py: 2, 49, 50, 50, interscript/frames/inputf.py: 2, 262, 495, 496, 521, 581, 607, 608, 681, 781, 788, 789, 790, 933, 944, 1139, interscript/getframes.py: 4, interscript/compilers/c.py: 4, 20, 20, 40, 59, 59, 78, interscript/compilers/cpp.py: 4, 19, 19, 41, 62, 62, 83, interscript/compilers/cconfig.py: 4, interscript/utilities/diff.py: 4, 44, 45, 49, interscript/tests/test_diff.py: 3, 21, 24
string_as_symbol interscript/parsers/lalr1.py: 853, 867
stringofsyms interscript/parsers/lalr1.py: 231, 232
strings interscript/felix/tests/stdcat_test.py: 14, 16
strip interscript/tanglers/perl.py: 240
stripkey interscript/tanglers/perl.py: 255, 260, 260, 262, 262, 263
strong interscript/weavers/text.py: 17, 251, 291, 294, 328
strstart interscript/tokenisers/python.py: 191, 200, 205, 279, 286
sts interscript/utilities/commands.py: 44, 45, 45, 47
style interscript/weavers/multiplexor.py: 51, 52, 53, 54, 55, 58, 61, 62, 65, 67, 70, interscript/frames/inputf.py: 1033, 1034
subframes interscript/weavers/web.py: 30, 39, 44
suffix interscript/weavers/text.py: 78, 79, 80
sum interscript/felix/model/stdcat.py: 38, 39, 40
svdin interscript/frames/inputf.py: 225, 236
switch interscript/compilers/cconfig.py: 44, 45, 45
switches interscript/compilers/cconfig.py: 12, 22, 22, 43, 44, 45, 45, 55, 56
sym interscript/parsers/lalr1.py: 56, 57, 57, 95, 96, 111, 112, 112, 375, 381, 386, 517, 519, 521, 523, 525, 527, 529, 530, 533, 541, 544, 545, 557, 562, 563, 565, 568, 569
symbols interscript/parsers/lalr1.py: 44, 57, 59, 62
sys interscript/tests/output/mymodule2.py: 2, interscript/tests/output/mymodule3.py: 2, interscript/__init__.py: 41, interscript/drivers/sources/stdin.py: 6, 20, interscript/drivers/sinks/stdout.py: 2, 9, interscript/drivers/sinks/cache.py: 2, interscript/tokenisers/python.py: 320, 321, 321, 322, interscript/felix/tests/stdcat_test.py: 2, 3, 3, interscript/felix/tests/func_test.py: 2, 3, 3, interscript/frames/install.py: 5, 6, 7, 8, 10, 11, 12, 25, 29, 30, 34, 38, 39, 43, 47, 48, 52, 56, 57, 61, 65, 66, interscript/frames/platform.py: 2, 7, interscript/frames/site.py: 2, 6, 7, 8, interscript/frames/processf.py: 6, 27, 28, 33, 33, 59, 60, 80, interscript/frames/passf.py: 4, interscript/frames/inputf.py: 5, 220, 225, 236, 509, 950, 954, interscript/getframes.py: 2, 156, 171, 173, interscript/compilers/c.py: 3, 23, 24, 24, 25, 39, 62, 63, 63, 64, 77, interscript/compilers/cpp.py: 3, 22, 23, 23, 24, 39, 65, 66, 66, 67, 82, interscript/compilers/cconfig.py: 3, interscript/tests/test_compilers.py: 3, 4, 4, interscript/tests/test_diff.py: 2, 4, 4, interscript/utilities/commands.py: 38, 39, interscript/bin/iscr.py: 3, 4, 7, 8, 8
system interscript/compilers/c.py: 29, 44, 68, 82, interscript/compilers/cpp.py: 28, 45, 71, 87, interscript/tests/test_compilers.py: 12
t interscript/tokenisers/python.py: 124, 127, 128, 130, 132, 133, 135, interscript/parsers/lalr1.py: 126, 127, 129, 232, 233, 234, 366, 367, 369, 400, 409, 410, 458, 460, 602, 603, 609, 614, 615, 619, 892, 892, interscript/frames/install.py: 91, 92, 92, interscript/frames/inputf.py: 793, interscript/bin/iscr.bat: 20
table_data interscript/weavers/text.py: 189, 192, 195, 199, 207, 217, 224
table_headings interscript/weavers/text.py: 188, 198, 204, 205, 215, 223
table_row interscript/weavers/text.py: 191, interscript/weavers/html.py: 556, interscript/weavers/latex.py: 290, interscript/frames/inputf.py: 609, 1023, 1024
table_rule interscript/weavers/text.py: 194, interscript/weavers/latex.py: 297, interscript/frames/inputf.py: 1029, 1030
table_rule_object interscript/weavers/text.py: 5, 195, 200, 208, 218
tabsize interscript/tokenisers/python.py: 114, 223, 223
tabwidth interscript/frames/inputf.py: 84, 84, 496, interscript/getframes.py: 124, 148
tag interscript/weavers/base.py: 18, 18, 19, 20, interscript/weavers/html.py: 118, 119, 121, interscript/weavers/latex.py: 240, 241, interscript/weavers/filter.py: 22, 24, interscript/parsers/html.py: 155, 156, 158, 159, 169, 170, interscript/felix/model/cons.py: 109, 111, 111, 114, 117, 120, 123, 126
tag_stack interscript/weavers/latex.py: 30
tags interscript/weavers/base.py: 7, 18, 20, interscript/weavers/raw.py: 8, interscript/weavers/text.py: 22, interscript/weavers/html.py: 46
tail interscript/tanglers/perl.py: 40, 41, 44, 44, 47, 48, 51, 53, 55, 61, 61, 65, 65, 70, 70, 73, 73, 78, 78, 83, 83, 89, 89, 93, 93, 95, 97, 101, 103, 109, 109, 112, 115, 256, 257, 259, 261, 262, 262
tangle interscript/frames/inputf.py: 880
tangle_argument interscript/tanglers/python.py: 68, 76, 78
tangle_argument_check interscript/tanglers/python.py: 55, 65
tangle_argument_checks interscript/tanglers/python.py: 62, 119
tangle_arguments interscript/tanglers/python.py: 73, 112
tangle_function interscript/tanglers/python.py: 93, 388
tangle_postcondition interscript/tanglers/python.py: 52, 154
tangle_precondition interscript/tanglers/python.py: 49, 124
tangle_result interscript/tanglers/python.py: 81, 160
tangler interscript/weavers/text.py: 336, 337, 339, 340, 345, 346, 348, 349, interscript/weavers/html.py: 133, 134, 136, 137, 151, 152, 154, 155, interscript/weavers/web.py: 226, 227, 230, 231, interscript/weavers/latex.py: 246, 247, 249, 252, 253, 255, interscript/frames/inputf.py: 370, 524, 755, 756, 757, 758, 759, 767
tangler_base interscript/tanglers/base.py: 5, interscript/tanglers/null.py: 10, 11, 13, interscript/tanglers/doc.py: 5, 7, 9, interscript/tanglers/data.py: 5, 7, interscript/tanglers/c.py: 5, 8, 10, 31, 33, 47, 50, interscript/tanglers/cpp.py: 5, 8, 10, 31, 33, interscript/tanglers/java.py: 2, 6, 8, interscript/tanglers/tcl.py: 2, 6, 8, interscript/tanglers/python.py: 6, 268, 270, 417, interscript/tanglers/perl.py: 2, 7, 9, 159
tangler_directory interscript/frames/inputf.py: 763, 769, interscript/getframes.py: 133, 161
tangler_pop interscript/frames/inputf.py: 744, 870
tangler_prefix interscript/frames/inputf.py: 764, 773, interscript/getframes.py: 131, 153
tangler_push interscript/frames/inputf.py: 740
tangler_set interscript/frames/inputf.py: 748, 825, 973, 1004
tanglers interscript/__init__.py: 31, 32, 33, 34, 35, 36, 37, 38, 39, interscript/tanglers/null.py: 10, interscript/tanglers/doc.py: 5, interscript/tanglers/data.py: 5, interscript/tanglers/c.py: 5, interscript/tanglers/cpp.py: 5, interscript/tanglers/java.py: 2, 3, 4, interscript/tanglers/tcl.py: 2, 3, interscript/tanglers/python.py: 6, interscript/tanglers/perl.py: 2, 3, interscript/frames/inputf.py: 20, 21, 22, 23, 24, 25, 26, 27, 28
target interscript/weavers/web.py: 451, 460, 471, 482, 493, 499, 500, 505, 524, 546, 553, 571, 590, 611, 632
tbclass interscript/weavers/html.py: 548, 549
tcl interscript/__init__.py: 39, interscript/frames/inputf.py: 25
tcl_tangler interscript/__init__.py: 39, interscript/tanglers/tcl.py: 6, interscript/frames/inputf.py: 25
tee_sink interscript/drivers/sinks/tee.py: 3
temp interscript/weavers/multiplexor.py: 16, 48
tempfile interscript/drivers/sources/ftp.py: 85, interscript/drivers/sinks/bufdisk.py: 6, 24, interscript/frames/inputf.py: 7, 678, interscript/utilities/diff.py: 3, 30, 31
term interscript/parsers/lalr1.py: 223, 231, 235, 507, 508, 509, 580, 584, 594
term_re interscript/frames/inputf.py: 570, 573, 577
terminal interscript/frames/inputf.py: 569, 570, 580, 581, 584, 589
terms interscript/parsers/lalr1.py: 59, 63, 111, 358, 426, 575, 575, 576
test interscript/tests/test_stacking_weaver.pak: 5, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41
test_code interscript/frames/inputf.py: 250, 252, 253, 262, 655, 657, 658, 681
test_interscript interscript/frames/inputf.py: 242
test_output_foot interscript/weavers/text.py: 362, interscript/weavers/html.py: 185, interscript/frames/inputf.py: 946
test_output_head interscript/weavers/text.py: 355, interscript/weavers/html.py: 173, interscript/frames/inputf.py: 941
test_python interscript/frames/inputf.py: 627
test_record interscript/frames/inputf.py: 638
test_reference interscript/weavers/web.py: 656
testlabel interscript/frames/inputf.py: 244, 245, 618, 620, 637, 639, 647, 959, 960, 961
testno interscript/frames/passf.py: 34, 93, 93, 94, interscript/frames/inputf.py: 243, 244, 247, 260, 265, 276, 279, 282, 284, 617, 618, 619, 621, 623, 624, 636, 637, 638, 646, 700, 701, 716, 958, 959, 960
testref interscript/weavers/web.py: 57, 75
tests interscript/weavers/web.py: 621, 623, interscript/frames/masterf.py: 23, 46, 46, interscript/frames/passf.py: 36, interscript/frames/inputf.py: 619, 624, 638, 700, 701, 716, 960
text interscript/__init__.py: 20, interscript/drivers/sinks/base.py: 36, 37, interscript/weavers/text.py: 326, 330, 331, interscript/weavers/html.py: 242, 255, 262, interscript/weavers/web.py: 218, 219, 219, 223, 262, 264, 271, 282, 285, 287, 322, 332, 395, 402, 406, 468, 471, 476, 482, 493, 500, 502, interscript/weavers/latex.py: 259, 277, 279, interscript/weavers/auto.py: 3, interscript/frames/inputf.py: 965, 969, 970, 974, 980, 984, 985, 987, interscript/utilities/commands.py: 43, 46, 46, 46, 47
tfirstmap interscript/parsers/lalr1.py: 371, 601
tfirsts interscript/parsers/lalr1.py: 601, 602
the interscript/bin/iscr.bat: 7, 8, 13, 13, 16, 20, 21
them interscript/bin/iscr.bat: 8
then interscript/bin/iscr.bat: 13
this interscript/weavers/web.py: 357, 358, interscript/bin/iscr.bat: 20
this_anchor interscript/weavers/web.py: 358, 365
thread interscript/__init__.py: 58
time interscript/__init__.py: 45, interscript/drivers/sources/ftp.py: 5, 45, 45, interscript/drivers/sources/http.py: 7, 42, 42, interscript/frames/processf.py: 8, 40, 40, 41, 42, 43, 54
times interscript/parsers/lalr1.py: 717, 724, 769, 770, 771
title interscript/weavers/html.py: 49, 51, 578, 597, interscript/weavers/web.py: 19, 146, 148, 148, 150, 382, 643, interscript/tests/test_stacking_weaver.pak: 3, interscript/weavers/latex.py: 184, 186, 187, interscript/weavers/auto.py: 9, 11, 11, 12, 12, 14, 16, 16, 19, 21, 21, 22, 22, 24, 26, 26, 27, 27, 36, 43, interscript/frames/passf.py: 52, interscript/getframes.py: 137, 152
tmp interscript/core/stacks.py: 10, 12, interscript/tokenisers/python.py: 156, 158, interscript/parsers/lalr1.py: 147, 148, 149, interscript/frames/inputf.py: 436, 438
tmp_filename interscript/drivers/sources/ftp.py: 85, 86, 87, 93, 114, 122, interscript/drivers/sinks/bufdisk.py: 24, 26, 28, 31, 55, 71
tmpres interscript/parsers/lalr1.py: 144, 148, 149, 153, 154
to interscript/bin/iscr.bat: 8, 14, 20
to_download interscript/drivers/sources/http.py: 66, 68, 68, 72
toc interscript/weavers/text.py: 27, 74, 75, 331, 391, interscript/weavers/html.py: 47, 58, 266, 455, 457, interscript/weavers/web.py: 172, 333, 404, 466, 468, 470, 470, 475, 476, 478, 478, interscript/frames/masterf.py: 17, 42, 42, interscript/frames/passf.py: 30, interscript/frames/inputf.py: 970, 985
toc_depth interscript/weavers/web.py: 138
toc_filename interscript/weavers/web.py: 451, 454
toc_sink interscript/weavers/web.py: 452, 457, 458, 462, 480, 491, 494, 498, 500, 502
todo interscript/parsers/lalr1.py: 220, 223, 240, 422, 425, 436
tok interscript/parsers/lalr1.py: 938, 939, 939
tok_name interscript/tokenisers/python.py: 8, 11, 14, 17, 20, 23, 118
token interscript/tanglers/python.py: 15, 18, 18, 19, 19, 20, 20, 23, 23, 23, 26, 27, 27, 27, 27, 28, 28, 29, 29, 29, 30, 30, 31, 31, 32, 32, 32, 33, 33, 34, 34, 34, 315, 318, 322, 337, 339, 341, interscript/tokenisers/python.py: 5, 116, 118, 128, 129, 133, 134, 252, 255, 256, 259, 261, 265, 266, 268, 272, 273, 276, 278, 284, 285, 287, 295, 297, 304, 306, 307, interscript/parsers/lalr1.py: 649, 650, 651, 657
tokeneater interscript/tokenisers/python.py: 122, 129, 134, 164, 187, 187, 196, 199, 204, 213, 231, 237, 240, 256, 259, 261, 265, 273, 277, 291, 295, 297, 304, 307, 309, 316, 317
tokenise interscript/tokenisers/python.py: 121, 321, 322, interscript/parsers/lalr1.py: 779, 890, 925, 936
tokeniser interscript/tanglers/python.py: 275, 280, 299
tokenisers interscript/tanglers/python.py: 9, 10
tokenize interscript/tanglers/python.py: 299, interscript/tokenisers/python.py: 160
tokenprog interscript/tokenisers/python.py: 73
tokens interscript/tanglers/python.py: 280, 299, 309, 310, 336, interscript/tokenisers/python.py: 128, 130, 133, 135, 152, 156, 157, 165, interscript/parsers/lalr1.py: 890, 891, 892, 895, 911, 925, 926, 936, 938
toks interscript/parsers/lalr1.py: 716, 717, 782, 785, 791, 798, 799, 807, 808, 812, 816, 821, 822, 825, 937, 939, 940, 941
top interscript/weavers/web.py: 50, interscript/parsers/lalr1.py: 648, 679
traceback interscript/weavers/multiplexor.py: 2, 35, interscript/weavers/web.py: 9, 301, interscript/parsers/html.py: 4, 186, interscript/felix/tests/stdcat_test.py: 4, interscript/frames/processf.py: 7, 38, 77, interscript/frames/passf.py: 3, 69, interscript/frames/inputf.py: 4, 217, 234, 714, interscript/getframes.py: 3, 182
transfer interscript/drivers/sources/ftp.py: 27, 88
translate interscript/weavers/base.py: 16, interscript/weavers/filter.py: 14, 16, interscript/tanglers/perl.py: 212, 275
translating interscript/weavers/base.py: 6, 16, 17, interscript/weavers/text.py: 250, 257, interscript/weavers/html.py: 89, interscript/weavers/latex.py: 205, interscript/weavers/filter.py: 12, 15, 19, 23, 28, 59, 66
triples interscript/weavers/filter.py: 74, 76, 80, 81
trust_map interscript/frames/install.py: 77, 97, 98
tuple interscript/core/sets.py: 73, 74, 122, interscript/core/stacks.py: 23, 24, 25, 51, interscript/parsers/lalr1.py: 673, interscript/felix/model/funcat.py: 78, interscript/felix/model/cons.py: 29, 35, 41, 135, interscript/frames/inputf.py: 272
tuples interscript/felix/tests/stdcat_test.py: 12, 21
typ interscript/core/protocols.py: 72, 73, 74, 76, 85, 86, 87, 88
type interscript/core/protocols.py: 40, 43, 85, 102, interscript/weavers/text.py: 164, 165, interscript/weavers/html.py: 269, 271, 540, 541, interscript/weavers/web.py: 605, 606, interscript/weavers/latex.py: 304, interscript/tokenisers/python.py: 116, 118, interscript/felix/model/stdcat.py: 84, 91, 98, interscript/getframes.py: 98, 98, interscript/bin/iscr.bat: 8, 13, 20
type_protocols interscript/core/protocols.py: 5, 31, 73, 74, 76, 87, 88
types interscript/core/protocols.py: 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 31, 40, 43, 102, interscript/tests/test_protocol.py: 3, 6, 6, 7, 20, interscript/felix/model/basecat.py: 2, interscript/felix/model/stdcat.py: 84, 91, 98
uname interscript/frames/platform.py: 8, 11, 15, 19
unaugment interscript/parsers/lalr1.py: 164, 267
unique_tag interscript/felix/model/cons.py: 128, 134
unit interscript/felix/model/stdcat.py: 18, 18, 18, 22, 23, 24, 29
unknown_charref interscript/parsers/html.py: 161
unknown_endtag interscript/parsers/html.py: 158
unknown_entityref interscript/parsers/html.py: 164
unknown_starttag interscript/parsers/html.py: 155
unlink interscript/utilities/diff.py: 39, 40
unstable_file_count interscript/frames/masterf.py: 58, 69, 69, 79
untangle interscript/frames/inputf.py: 513
up interscript/weavers/web.py: 339, 341, 342, 362, 377, 377
up_anchor interscript/weavers/web.py: 342, 362
update_files interscript/drivers/sinks/bufdisk.py: 50, interscript/frames/processf.py: 20, 71, 79, interscript/frames/inputf.py: 206, 211, 218, 500, 510, interscript/getframes.py: 123, 144
upper interscript/weavers/text.py: 251
url interscript/__init__.py: 13, interscript/weavers/text.py: 438, 439, interscript/weavers/html.py: 337, 338, 338, interscript/weavers/latex.py: 409, 411, interscript/frames/inputf.py: 1016, 1017
url_source interscript/__init__.py: 13, interscript/drivers/sources/url.py: 6
urllib interscript/drivers/sources/url.py: 10
urlopen interscript/drivers/sources/url.py: 10
use interscript/bin/iscr.bat: 21
usecache interscript/frames/masterf.py: 25, 80, interscript/getframes.py: 128, 145
usek interscript/getframes.py: 80, 83, 86, 89, 92, 95
user interscript/drivers/sources/ftp.py: 72, 73, 74, interscript/frames/processf.py: 65, 69, interscript/frames/inputf.py: 588, 590, 719, 720, 723, 724, 725, 728, 732, 736
user_frame interscript/frames/user.py: 2
user_install_point interscript/frames/install.py: 60, 74
userdict interscript/tanglers/python.py: 274, 289, interscript/parsers/html.py: 183, interscript/frames/passf.py: 53, 78, interscript/frames/inputf.py: 60, 72, 72, 172, 188, 189, 195, 290, 291, 304, 330, 348, 367, 403, 417, 427, 428, 588
usergrp_install_point interscript/frames/install.py: 51, 73
username interscript/__init__.py: 73, 85, 98
useropt interscript/getframes.py: 135, 195
util interscript/drivers/sinks/disk.py: 5, interscript/drivers/sinks/bufdisk.py: 5
utilities interscript/__init__.py: 46, interscript/frames/inputf.py: 33, 697, interscript/tests/test_diff.py: 5, 6
v interscript/core/protocols.py: 97, 98, interscript/weavers/html.py: 351, 353, interscript/weavers/latex.py: 6, 8, 8, 9, 9, 10, 10, 11, 362, 363, interscript/frames/inputf.py: 860, 861
v1 interscript/felix/model/stdcat2.py: 24, 25, 43, 44, 45
v2 interscript/felix/model/stdcat2.py: 24, 25, 43, 44, 45
vals interscript/parsers/lalr1.py: 667, 670, 672, 673
value interscript/core/stacks.py: 18, 18, 33, 35, 37, interscript/parsers/html.py: 174, 176, interscript/felix/model/funcat.py: 56, 56, 56, 57, 58, 58, interscript/frames/inputf.py: 209, 213, interscript/getframes.py: 100, 101, 101, 139, 141, 142, 148, 149, 150, 151, 152, 153, 154, 161, 178, 179, 184, 187, 194, 195, 196, 198
values interscript/getframes.py: 81, 84, 87, 90, 93, 96, 98, 100, 101, 103
verbatim interscript/weavers/latex.py: 36, 205, 228, 232
verbosity interscript/drivers/sources/ftp.py: 38, 40, 57, 76, 91, 103, 105, 107, interscript/drivers/sinks/bufdisk.py: 13, 13, 25, 36, 47, 60, 66, 69, interscript/weavers/raw.py: 6, interscript/weavers/text.py: 10, 10, 11, interscript/weavers/html.py: 34, 34, 35, interscript/weavers/web.py: 132, 132, 311, interscript/weavers/latex.py: 24, 24, 26, interscript/tanglers/perl.py: 42, 237, interscript/parsers/html.py: 29, 29, 53, 173, 180, interscript/parsers/lalr1.py: 33, 34, 34, 38, 61, 68, 72, 78, 259, 260, 433, 451, 455, 468, 499, 872, 902, 933, interscript/frames/processf.py: 19, 19, 68, interscript/frames/masterf.py: 10, interscript/frames/passf.py: 22, 22, 39, 43, 55, 62, 81, interscript/frames/inputf.py: 83, 83, 89, 94, 170, 190, 190, 198, 199, 215, 316, 429, 503, 508, interscript/getframes.py: 115, 125, 141, 141, 143, 143, 176, 196
version interscript/__init__.py: 71, 83, 96, interscript/weavers/web.py: 25, 25, 27, interscript/frames/site.py: 6, interscript/frames/processf.py: 47, interscript/getframes.py: 173, interscript/bin/iscr.bat: 16
vertex interscript/felix/model/stdcat2.py: 21, 22
vertices interscript/felix/model/stdcat2.py: 22, 25, 34, 40, 44, 45
verticies interscript/felix/model/stdcat2.py: 19, 28
w interscript/weavers/text.py: 173, 174, 180, 181, 183, 201, 202, 202, 205, 206, 206, 210, 211, 211, 245, 246, interscript/weavers/html.py: 138, 139, 147, 148, 573, 574, 575, 576, 580, 583, 584, 586, 587, 588, 589, 590, interscript/weavers/web.py: 14, 15, 16, 17, 19, 21, 27, 28, 42, 43, 45, 46, 47, 91, 92, 93, 94, 95, 101, 102, 105, 115, 117, 120, 121, 122, 236, 238, 241, 242, 458, 459, 463, 464, 473, 484, 487, 489, 490, 512, 513, 518, 521, 522, 531, 532, 535, 538, 539, 541, 547, 548, 549, 550, 551, 559, 561, 566, 568, 569, 577, 579, 584, 587, 588, 596, 598, 600, 606, 608, 609, 617, 619, 624, 625, 626, 632, 633, 634, 635, interscript/weavers/auto.py: 10, 12, 15, 16, 16, 17, 20, 22, 25, 27, 41, 42, 43, interscript/frames/inputf.py: 435, 437, 440, 442
way interscript/bin/iscr.bat: 5
weave interscript/frames/inputf.py: 872
weave_argument interscript/tanglers/python.py: 178, 195, 199
weave_arguments interscript/tanglers/python.py: 192, 230, 247
weave_function interscript/tanglers/python.py: 201, 403
weave_line interscript/frames/inputf.py: 876
weaver interscript/weavers/web.py: 405, 406, 649, 650, interscript/tests/test_stacking_weaver.pak: 3, 4, 4, 5, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, interscript/weavers/filter.py: 16, 16, 20, 20, 24, 24, 29, 30, 40, 41, 42, 44, 49, 50, 55, 56, 60, 61, 67, 67, interscript/tanglers/base.py: 7, 9, 9, 11, 26, interscript/tanglers/null.py: 12, 13, interscript/tanglers/doc.py: 8, 9, 16, interscript/tanglers/c.py: 9, 10, 20, 21, 27, 32, 33, 40, 48, 50, 64, interscript/tanglers/cpp.py: 9, 10, 20, 21, 24, 27, 32, 33, 38, 43, 44, interscript/tanglers/java.py: 7, 8, 18, 19, 25, interscript/tanglers/tcl.py: 7, 8, 17, 18, 21, 25, interscript/tanglers/python.py: 178, 179, 180, 182, 183, 184, 186, 187, 189, 190, 192, 194, 195, 196, 197, 198, 199, 202, 214, 215, 216, 217, 218, 219, 220, 221, 222, 225, 226, 227, 228, 229, 230, 231, 234, 235, 236, 237, 238, 239, 240, 243, 244, 245, 246, 247, 248, 251, 252, 253, 254, 255, 256, 257, 261, 262, 263, 264, 269, 270, 291, 308, 313, 326, 328, 329, 365, 366, 404, 419, 420, interscript/tanglers/perl.py: 8, 9, 43, 49, 49, 54, 60, 62, 64, 66, 72, 74, 77, 79, 82, 84, 88, 90, 99, 105, 108, 110, 115, 121, 121, 122, 123, 124, 128, 128, 129, 130, 131, 140, 140, 141, 142, 143, 147, 147, 148, 149, 150, 171, 189, 195, 211, 212, 221, 225, 268, 271, 274, 275, 276, 284, 287, interscript/parsers/html.py: 28, 50, 64, 68, 69, 71, 72, 74, 75, 77, 78, 80, 81, 83, 84, 86, 87, 90, 91, 94, 95, 99, 102, 105, 108, 111, 114, 119, 121, 125, 127, 131, 134, 138, 141, 144, 147, 150, 153, interscript/frames/passf.py: 52, 77, interscript/frames/inputf.py: 60, 67, 451, 466, 470, 526, 527, 528, 529, 873, 874, 877, 878, 891, 892, 896, 897, 901, 902, 906, 907, 911, 912, 916, 917, 921, 922, 926, 927, 938, 941, 945, 946, 971, 974, 986, 987, 1137, 1140
weaver_base interscript/weavers/base.py: 2, interscript/weavers/raw.py: 2, 3, 5, interscript/weavers/text.py: 2, 7, 9, interscript/weavers/html.py: 2, 29, 33, interscript/weavers/latex.py: 2, 20, 23
weaver_directory interscript/weavers/auto.py: 39, interscript/getframes.py: 132, 154
weaver_prefix interscript/weavers/web.py: 35, 88, 379, 455, 509, 528, 557, 575, 594, 615, 640, interscript/weavers/auto.py: 37, interscript/getframes.py: 130, 151
weavers interscript/__init__.py: 20, 21, 22, 23, 24, 25, 26, 27, interscript/weavers/raw.py: 2, interscript/weavers/text.py: 2, interscript/weavers/html.py: 2, interscript/weavers/web.py: 2, 3, 4, interscript/weavers/latex.py: 2, interscript/weavers/auto.py: 2, 3, 4, 5, 6, 40, 43, 44, interscript/weavers/filter.py: 2, interscript/frames/passf.py: 10
web interscript/__init__.py: 24, interscript/weavers/auto.py: 6
what interscript/bin/iscr.bat: 8
width interscript/weavers/text.py: 14, 43, 79, 198, 202, 202, 203, 237, 280, interscript/tanglers/c.py: 26, 27, 48, 49, 52, 52, 57, 57, interscript/tanglers/cpp.py: 26, 27, interscript/tanglers/java.py: 24, 25, interscript/tanglers/tcl.py: 23, 25, interscript/tanglers/python.py: 371, 372, interscript/tanglers/perl.py: 289, 291, interscript/frames/inputf.py: 863, 865
with interscript/bin/iscr.bat: 8, 14
wl interscript/weavers/web.py: 237, 253, 254
wnts interscript/parsers/lalr1.py: 87, 92, 101, 101
won interscript/bin/iscr.bat: 20
word interscript/weavers/text.py: 234, 236, 237, 238, 241, interscript/getoptions.py: 14, 16, 21
wordno interscript/getoptions.py: 9, 12, 14, 29, 32, 32
words interscript/weavers/text.py: 244, 245
work interscript/tests/example.pak: 4
write interscript/drivers/sources/ftp.py: 28, interscript/drivers/sinks/base.py: 25, 31, 36, interscript/drivers/sinks/disk.py: 27, interscript/drivers/sinks/bufdisk.py: 73, interscript/drivers/sinks/stdout.py: 9, interscript/weavers/base.py: 24, 26, 27, interscript/weavers/text.py: 31, 249, 258, 285, 288, 439, interscript/weavers/html.py: 81, 84, 86, 101, 104, 552, 562, interscript/weavers/latex.py: 202, 204, 213, 284, 287, 291, 294, 338, 411, interscript/weavers/filter.py: 26, 30, 41, 44, 50, 54, interscript/tanglers/perl.py: 43, 54, 77, 79, 99, 105, 108, 110, interscript/tokenisers/python.py: 161, 174, interscript/parsers/html.py: 50, interscript/frames/inputf.py: 262, 681, 874, interscript/utilities/diff.py: 25, 34, 35, 91
write_code_fragment interscript/weavers/html.py: 329, interscript/tanglers/python.py: 179, 180, 182, 183, 184, 186, 187, 189, 190, 196, 215, 216, 217, 218, 219, 220, 221, 226, 227, 228, 235, 236, 237, 238, 239, 244, 245, 252, 253, 254, 255, 256, 262, 263, 313, 326, 328
write_comment interscript/weavers/html.py: 351, interscript/weavers/latex.py: 362, interscript/tanglers/base.py: 18, interscript/tanglers/c.py: 14, interscript/tanglers/cpp.py: 14, interscript/tanglers/java.py: 12, interscript/tanglers/tcl.py: 11, interscript/tanglers/python.py: 359, interscript/tanglers/perl.py: 278, interscript/frames/inputf.py: 861
write_tagged interscript/weavers/html.py: 118, 353, 578, interscript/weavers/latex.py: 240, 363
writecode interscript/weavers/text.py: 227, 232, interscript/weavers/html.py: 94, interscript/weavers/latex.py: 216, 350, interscript/tanglers/perl.py: 189
writeline interscript/drivers/sinks/base.py: 24, interscript/weavers/base.py: 23, interscript/weavers/text.py: 256, interscript/weavers/html.py: 78, 83, interscript/weavers/web.py: 14, 24, 42, 91, 101, 458, 462, 480, 494, 498, 500, 502, 512, 531, 538, 559, 577, 596, 617, interscript/weavers/latex.py: 199, 212, interscript/weavers/filter.py: 52, 56, interscript/tanglers/base.py: 22, 40, interscript/tanglers/null.py: 19, interscript/tanglers/doc.py: 15, 16, interscript/tanglers/c.py: 15, 35, 40, 55, 64, interscript/tanglers/cpp.py: 37, 38, interscript/tanglers/python.py: 173, 285, 360, 418, 420, interscript/tanglers/perl.py: 115, 152, interscript/tokenisers/python.py: 127, 132, 169, 171, 180, 184, interscript/parsers/html.py: 9, interscript/frames/inputf.py: 246, 281, 283, 285, 468, 470, 519, 524, 525, 527, 602, 613, 652, 661, 669, 684, 703, 710, 737, 878, 884, 1140
writelines interscript/drivers/sources/ftp.py: 112, interscript/drivers/sources/http.py: 98, interscript/drivers/sinks/base.py: 30, interscript/drivers/sinks/bufdisk.py: 63, interscript/frames/inputf.py: 380, 389
writer interscript/weavers/raw.py: 4, 6, 9, interscript/weavers/text.py: 8, 12, 20, interscript/weavers/html.py: 32, 35, 37, interscript/weavers/latex.py: 22, 25, 27, interscript/tanglers/cpp.py: 32, 33, 43, 44
x interscript/core/stacks.py: 13, 13, 14, 14, interscript/drivers/sources/base.py: 40, 42, 43, interscript/weavers/multiplexor.py: 47, 48, interscript/parsers/lalr1.py: 146, 147, 159, 159, 446, 448, 449, 722, 722, 722, 870, 870, 870, 870, interscript/felix/tests/func_test.py: 16, 16, 16, 21, 21, 21, 24, 24, 24, 32, 32, 32, 35, 35, interscript/felix/model/cons.py: 31, 34, 37, 40, 60, 61, 63, 64, 97, 99, 100, 102, 104, 105, 122, 123, 125, 126, interscript/frames/inputf.py: 38, 38, 38, 101, 101, 101, interscript/compilers/cconfig.py: 49, 49, 50, 50, 51, 51, 52, 53, 54, 54, 55, 56, 56, interscript/utilities/commands.py: 52, 54, 64, 65, 66, 68
y interscript/parsers/lalr1.py: 448
you interscript/bin/iscr.bat: 8, 13, 15, 16, 20, 21

7.2. Index of Classes

B interscript/tests/test_protocol.py: 10
D interscript/tests/test_protocol.py: 14
Grammar interscript/parsers/lalr1.py: 29
LALRGrammar interscript/parsers/lalr1.py: 257
Production interscript/parsers/lalr1.py: 12
application interscript/compilers/c.py: 47, interscript/compilers/cpp.py: 50
argument interscript/tanglers/python.py: 37
argument_frame interscript/getframes.py: 106
c_comment_tangler interscript/tanglers/c.py: 31
c_string_tangler interscript/tanglers/c.py: 47
c_tangler interscript/tanglers/c.py: 8
cache_sink interscript/drivers/sinks/cache.py: 4
cache_source interscript/drivers/sources/cache.py: 6
cat_all interscript/felix/model/stdcat.py: 10
cat_dagraph interscript/felix/model/stdcat2.py: 50
cat_dgraph interscript/felix/model/stdcat2.py: 17
cat_dual interscript/felix/model/cons.py: 44
cat_empty interscript/felix/model/stdcat.py: 5
cat_function interscript/felix/model/funcat.py: 61
cat_graph interscript/felix/model/stdcat2.py: 42
cat_list interscript/felix/model/stdcat.py: 87
cat_monoid interscript/felix/model/stdcat.py: 17
cat_product interscript/felix/model/cons.py: 5
cat_sequence interscript/felix/model/stdcat.py: 70
cat_set interscript/felix/model/stdcat2.py: 6
cat_string interscript/felix/model/stdcat.py: 94
cat_tagged interscript/felix/model/cons.py: 108
cat_tuple interscript/felix/model/stdcat.py: 80
cat_union interscript/felix/model/cons.py: 67
category interscript/felix/model/basecat.py: 4
config interscript/compilers/cconfig.py: 6
constant interscript/felix/model/funcat.py: 55
cpp_comment_tangler interscript/tanglers/cpp.py: 42
cpp_tangler interscript/tanglers/cpp.py: 8
data_tangler interscript/tanglers/data.py: 7
deduce interscript/frames/inputf.py: 40
disk interscript/drivers/storage/disk.py: 7
doc_tangler interscript/tanglers/doc.py: 7
eof interscript/drivers/sources/base.py: 2
eoi interscript/drivers/sources/base.py: 3
file_source interscript/drivers/sources/base.py: 57
fincat interscript/felix/model/fincat.py: 4
ftp_file_source interscript/drivers/sources/ftp.py: 11
function interscript/felix/model/funcat.py: 4
function_product interscript/felix/model/funcat.py: 70
function_sum interscript/felix/model/funcat.py: 81
global_frame interscript/__init__.py: 4
hash_comment_tangler interscript/tanglers/cpp.py: 31
html_filter interscript/parsers/html.py: 22
html_weaver interscript/weavers/html.py: 29
http_file_source interscript/drivers/sources/http.py: 11
identity interscript/felix/model/funcat.py: 32
input_adapter interscript/felix/model/funcat.py: 39
input_frame interscript/frames/inputf.py: 58
install_frame interscript/frames/install.py: 2
int_add interscript/felix/model/stdcat.py: 32
int_mul interscript/felix/model/stdcat.py: 53
java_tangler interscript/tanglers/java.py: 6
latex_weaver interscript/weavers/latex.py: 20
markup_filter interscript/weavers/filter.py: 4
master_frame interscript/frames/masterf.py: 6
memory interscript/drivers/storage/memory.py: 6
multiplexor interscript/weavers/multiplexor.py: 3
myclass interscript/tests/output/mymodule2.py: 3, interscript/tests/output/mymodule3.py: 3
named_file_sink interscript/drivers/sinks/bufdisk.py: 9
named_file_source interscript/drivers/sources/disk.py: 38
null_sink interscript/drivers/sinks/null.py: 3
null_tangler interscript/tanglers/null.py: 11
output_adapter interscript/felix/model/funcat.py: 47
pass_frame interscript/frames/passf.py: 14
perl_tangler interscript/tanglers/perl.py: 7
plain_text_weaver interscript/weavers/text.py: 7
platform_frame interscript/frames/platform.py: 5
process_frame interscript/frames/processf.py: 10
project_frame interscript/frames/project.py: 2
provides_attr interscript/core/protocols.py: 35
python_module interscript/compilers/c.py: 8, interscript/compilers/cpp.py: 7
python_tangler interscript/tanglers/python.py: 268
python_tokeniser interscript/tokenisers/python.py: 140
raw_weaver interscript/weavers/raw.py: 3
script_comment_tangler interscript/tanglers/python.py: 417
set interscript/core/sets.py: 2
sgml_wrapper interscript/parsers/html.py: 5
simple_named_file_sink interscript/drivers/sinks/disk.py: 7
sink_base interscript/drivers/sinks/base.py: 3
sink_open_error interscript/drivers/sinks/__init__.py: 3
site_frame interscript/frames/site.py: 3
source interscript/drivers/sources/base.py: 9
source_open_error interscript/drivers/sources/__init__.py: 3
stack interscript/core/stacks.py: 2
stacking_weaver interscript/weavers/web.py: 12
stdin_source interscript/drivers/sources/stdin.py: 11
stdout_sink interscript/drivers/sinks/stdout.py: 4
table_rule_object interscript/weavers/text.py: 5
tangler_base interscript/tanglers/base.py: 5
tcl_tangler interscript/tanglers/tcl.py: 6
tee_sink interscript/drivers/sinks/tee.py: 3
unique_tag interscript/felix/model/cons.py: 128
url_source interscript/drivers/sources/url.py: 6
user_frame interscript/frames/user.py: 2
weaver_base interscript/weavers/base.py: 2

7.3. File List

interscript/doc/iscr.txt
interscript/doc/iscrp.html
interscript/doc/iscrs.html
interscript/doc/iscr_indexview.html
interscript/doc/iscr_top.html
interscript/doc/iscr_indexnav.html
interscript/doc/iscr.tex
interscript/doc/iscr_0001.html
interscript/doc/iscr_0002.html
interscript/doc/iscr_0003.html
interscript/doc/iscr_0004.html
interscript/doc/iscr_0005.html
interscript/doc/iscr_0006.html
interscript/doc/iscr_0007.html
interscript/doc/iscr_0008.html
interscript/doc/iscr_0009.html
interscript/doc/iscr_0010.html
interscript/doc/iscr_0011.html
interscript/doc/iscr_0012.html
interscript/doc/iscr_0013.html
interscript/doc/iscr_0014.html
interscript/doc/iscr_0015.html
interscript/doc/iscr_0016.html
interscript/doc/iscr_0017.html
interscript/doc/iscr_0018.html
interscript/doc/iscr_0019.html
interscript/doc/iscr_0020.html
interscript/doc/iscr_0021.html
interscript/doc/iscr_0022.html
interscript/doc/iscr_0023.html
interscript/doc/iscr_0024.html
interscript/doc/iscr_0025.html
interscript/doc/iscr_0026.html
interscript/doc/iscr_0027.html
interscript/doc/iscr_0028.html
interscript/doc/iscr_0029.html
interscript/doc/iscr_0030.html
interscript/doc/iscr_0031.html
interscript/doc/iscr_0032.html
interscript/doc/iscr_0033.html
interscript/doc/iscr_0034.html
interscript/doc/iscr_0035.html
interscript/doc/iscr_0036.html
interscript/doc/iscr_0037.html
interscript/doc/iscr_0038.html
interscript/doc/iscr_0039.html
interscript/doc/iscr_0040.html
interscript/doc/iscr_0041.html
interscript/doc/iscr_0042.html
interscript/doc/iscr_0043.html
interscript/doc/iscr_0044.html
interscript/doc/iscr_0045.html
interscript/doc/iscr_0046.html
interscript/doc/iscr_0047.html
interscript/doc/iscr_0048.html
interscript/doc/iscr_0049.html
interscript/doc/iscr_0050.html
interscript/doc/iscr_0051.html
interscript/doc/iscr_0052.html
interscript/doc/iscr_0053.html
interscript/doc/iscr_0054.html
interscript/doc/iscr_0055.html
interscript/doc/iscr_0056.html
interscript/doc/iscr_0057.html
interscript/doc/iscr_0058.html
interscript/doc/iscr_0059.html
interscript/doc/iscr_0060.html
interscript/doc/iscr_0061.html
interscript/doc/iscr_0062.html
interscript/doc/iscr_0063.html
interscript/doc/iscr_0064.html
interscript/doc/iscr_0065.html
interscript/doc/iscr_0066.html
interscript/doc/iscr_0067.html
interscript/doc/iscr_0068.html
interscript/doc/iscr_0069.html
interscript/doc/iscr_0070.html
interscript/doc/iscr_0071.html
interscript/doc/iscr_0072.html
interscript/doc/iscr_0073.html
interscript/doc/iscr_0074.html
interscript/doc/iscr_0075.html
interscript/doc/iscr_0076.html
interscript/doc/iscr_0077.html
interscript/doc/iscr_0078.html
interscript/doc/iscr_0079.html
interscript/doc/iscr_0080.html
interscript/doc/iscr_0081.html
interscript/doc/iscr_0082.html
interscript/doc/iscr_0083.html
interscript/doc/iscr_0084.html
interscript/doc/iscr_0085.html
interscript/doc/iscr_0086.html
interscript/doc/iscr_0087.html
interscript/doc/iscr_0088.html
interscript/doc/iscr_0089.html
interscript/doc/iscr_0090.html
interscript/doc/iscr_0091.html
interscript/doc/iscr_0092.html
interscript/doc/iscr_0093.html
interscript/doc/iscr_0094.html
interscript/doc/iscr_0095.html
interscript/doc/iscr_0096.html
interscript/doc/iscr_0097.html
interscript/doc/iscr_0098.html
interscript/doc/iscr_0099.html
interscript/doc/iscr_0100.html
interscript/doc/iscr_0101.html
interscript/doc/iscr_0102.html
interscript/doc/iscr_0103.html
interscript/doc/iscr_0104.html
interscript/doc/iscr_0105.html
interscript/doc/iscr_0106.html
interscript/doc/iscr_0107.html
interscript/doc/iscr_0108.html
interscript/doc/iscr_0109.html
interscript/doc/iscr_0110.html
interscript/doc/iscr_0111.html
interscript/doc/iscr_0112.html
interscript/doc/iscr_0113.html
interscript/doc/iscr_0114.html
interscript/doc/iscr_0115.html
interscript/doc/iscr_0116.html
interscript/doc/iscr_0117.html
interscript/tests/output/mymodule2.py
interscript/doc/iscr_0118.html
interscript/tests/output/mymodule3.py
interscript/doc/iscr_0119.html
interscript/doc/iscr_0120.html
interscript/doc/iscr_0121.html
interscript/doc/iscr_0122.html
interscript/doc/iscr_0123.html
interscript/doc/iscr_0124.html
interscript/doc/iscr_0125.html
interscript/doc/iscr_0126.html
interscript/doc/iscr_0127.html
interscript/doc/iscr_0128.html
interscript/doc/iscr_0129.html
interscript/doc/iscr_0130.html
interscript/doc/iscr_0131.html
interscript/doc/iscr_0132.html
interscript/doc/iscr_0133.html
interscript/doc/iscr_0134.html
interscript/doc/iscr_0135.html
interscript/doc/iscr_0136.html
interscript/doc/iscr_0137.html
interscript/doc/iscr_0138.html
interscript/doc/iscr_0139.html
interscript/doc/iscr_0140.html
interscript/doc/iscr_0141.html
interscript/doc/iscr_0142.html
interscript/doc/iscr_0143.html
interscript/doc/iscr_0144.html
interscript/doc/iscr_0145.html
interscript/doc/iscr_0146.html
interscript/doc/iscr_0147.html
interscript/doc/iscr_0148.html
interscript/doc/iscr_0149.html
interscript/doc/iscr_0150.html
interscript/doc/iscr_0151.html
interscript/doc/iscr_0152.html
interscript/doc/iscr_0153.html
interscript/doc/iscr_0154.html
interscript/doc/iscr_0155.html
interscript/doc/iscr_0156.html
interscript/doc/iscr_0157.html
interscript/doc/iscr_0158.html
interscript/doc/iscr_0159.html
interscript/doc/iscr_0160.html
interscript/doc/iscr_0161.html
interscript.README
interscript.pth
interscript/__init__.py
interscript/doc/iscr_0162.html
interscript/doc/iscr_0163.html
interscript/doc/iscr_0164.html
interscript/doc/iscr_0165.html
interscript/core/__init__.py
interscript/doc/iscr_0166.html
interscript/core/sets.py
interscript/doc/iscr_0167.html
interscript/tests/test_sets.py
interscript/doc/iscr_0168.html
interscript/doc/iscr_0169.html
interscript/core/stacks.py
interscript/doc/iscr_0170.html
interscript/doc/iscr_0171.html
interscript/doc/iscr_0172.html
interscript/core/protocols.py
interscript/doc/iscr_0173.html
interscript/tests/test_protocol.py
interscript/doc/iscr_0174.html
interscript/drivers/__init__.py
interscript/doc/iscr_0175.html
interscript/doc/iscr_0176.html
interscript/drivers/sources/__init__.py
interscript/doc/iscr_0177.html
interscript/drivers/sources/base.py
interscript/doc/iscr_0178.html
interscript/doc/iscr_0179.html
interscript/doc/iscr_0180.html
interscript/drivers/sources/disk.py
interscript/doc/iscr_0181.html
interscript/drivers/sources/url.py
interscript/doc/iscr_0182.html
interscript/drivers/sources/ftp.py
interscript/doc/iscr_0183.html
interscript/drivers/sources/http.py
interscript/doc/iscr_0184.html
interscript/drivers/sources/stdin.py
interscript/doc/iscr_0185.html
interscript/drivers/sources/cache.py
interscript/doc/iscr_0186.html
interscript/drivers/sinks/__init__.py
interscript/drivers/sinks/util.py
interscript/doc/iscr_0187.html
interscript/drivers/sinks/base.py
interscript/doc/iscr_0188.html
interscript/drivers/sinks/null.py
interscript/doc/iscr_0189.html
interscript/drivers/sinks/tee.py
interscript/doc/iscr_0190.html
interscript/drivers/sinks/disk.py
interscript/doc/iscr_0191.html
interscript/drivers/sinks/bufdisk.py
interscript/doc/iscr_0192.html
interscript/drivers/sinks/stdout.py
interscript/doc/iscr_0193.html
interscript/drivers/sinks/cache.py
interscript/doc/iscr_0194.html
interscript/drivers/storage/__init__.py
interscript/doc/iscr_0195.html
interscript/drivers/storage/memory.py
interscript/doc/iscr_0196.html
interscript/drivers/storage/disk.py
interscript/doc/iscr_0197.html
interscript/weavers/__init__.py
interscript/doc/iscr_0198.html
interscript/weavers/base.py
interscript/doc/iscr_0199.html
interscript/weavers/raw.py
interscript/doc/iscr_0200.html
interscript/weavers/multiplexor.py
interscript/doc/iscr_0201.html
interscript/weavers/text.py
interscript/doc/iscr_0202.html
interscript/doc/iscr_0203.html
interscript/doc/iscr_0204.html
interscript/doc/iscr_0205.html
interscript/doc/iscr_0206.html
interscript/doc/iscr_0207.html
interscript/doc/iscr_0208.html
interscript/doc/iscr_0209.html
interscript/doc/iscr_0210.html
interscript/doc/iscr_0211.html
interscript/doc/iscr_0212.html
interscript/weavers/html.py
interscript/doc/iscr_0213.html
interscript/doc/iscr_0214.html
interscript/doc/iscr_0215.html
interscript/doc/iscr_0216.html
interscript/doc/iscr_0217.html
interscript/doc/iscr_0218.html
interscript/doc/iscr_0219.html
interscript/doc/iscr_0220.html
interscript/doc/iscr_0221.html
interscript/doc/iscr_0222.html
interscript/doc/iscr_0223.html
interscript/doc/iscr_0224.html
interscript/doc/iscr_0225.html
interscript/doc/iscr_0226.html
interscript/doc/iscr_0227.html
interscript/doc/iscr_0228.html
interscript/doc/iscr_0229.html
interscript/doc/iscr_0230.html
interscript/doc/iscr_0231.html
interscript/doc/iscr_0232.html
interscript/doc/iscr_0233.html
interscript/doc/iscr_0234.html
interscript/doc/iscr_0235.html
interscript/doc/interscript.css
interscript/doc/user.css
interscript/doc/iscr_0236.html
interscript/doc/iscr_0237.html
interscript/doc/iscr_0238.html
interscript/weavers/web.py
interscript/doc/iscr_0239.html
interscript/doc/iscr_0240.html
interscript/doc/iscr_0241.html
interscript/doc/iscr_0242.html
interscript/doc/iscr_0243.html
interscript/doc/iscr_0244.html
interscript/doc/iscr_0245.html
interscript/doc/iscr_0246.html
interscript/doc/iscr_0247.html
interscript/tests/test_stacking_weaver.pak
interscript/doc/iscr_0248.html
interscript/weavers/latex.py
interscript/doc/iscr_0249.html
interscript/doc/iscr_0250.html
interscript/doc/iscr_0251.html
interscript/doc/iscr_0252.html
interscript/doc/iscr_0253.html
interscript/doc/iscr_0254.html
interscript/doc/iscr_0255.html
interscript/doc/iscr_0256.html
interscript/doc/iscr_0257.html
interscript/doc/iscr_0258.html
interscript/doc/iscr_0259.html
interscript/doc/iscr_0260.html
interscript/doc/iscr_0261.html
interscript/doc/iscr_0262.html
interscript/doc/iscr_0263.html
interscript/doc/iscr_0264.html
interscript/doc/iscr_0265.html
interscript/doc/iscr_0266.html
interscript/doc/iscr_0267.html
interscript/doc/iscr_0268.html
interscript/doc/iscr_0269.html
interscript/doc/iscr_0270.html
interscript/doc/iscr_0271.html
interscript/doc/iscr_0272.html
interscript/doc/iscr_0273.html
interscript/doc/iscr_0274.html
interscript/weavers/auto.py
interscript/doc/iscr_0275.html
interscript/doc/iscr_0276.html
interscript/weavers/filter.py
interscript/doc/iscr_0277.html
interscript/doc/iscr_0278.html
interscript/tanglers/__init__.py
interscript/tanglers/base.py
interscript/doc/iscr_0279.html
interscript/doc/iscr_0280.html
interscript/tanglers/null.py
interscript/doc/iscr_0281.html
interscript/tanglers/doc.py
interscript/doc/iscr_0282.html
interscript/tanglers/data.py
interscript/doc/iscr_0283.html
interscript/tanglers/c.py
interscript/doc/iscr_0284.html
interscript/doc/iscr_0285.html
interscript/doc/iscr_0286.html
interscript/tanglers/cpp.py
interscript/doc/iscr_0287.html
interscript/doc/iscr_0288.html
interscript/doc/iscr_0289.html
interscript/tanglers/java.py
interscript/doc/iscr_0290.html
interscript/tanglers/tcl.py
interscript/doc/iscr_0291.html
interscript/tanglers/python.py
interscript/doc/iscr_0292.html
interscript/doc/iscr_0293.html
interscript/doc/iscr_0294.html
interscript/doc/iscr_0295.html
interscript/doc/iscr_0296.html
interscript/doc/iscr_0297.html
interscript/doc/iscr_0298.html
interscript/tanglers/perl.py
interscript/doc/iscr_0299.html
interscript/tokenisers/__init__.py
interscript/doc/iscr_0300.html
interscript/tokenisers/python.py
interscript/doc/iscr_0301.html
interscript/doc/iscr_0302.html
interscript/doc/iscr_0303.html
interscript/doc/iscr_0304.html
interscript/parsers/__init__.py
interscript/doc/iscr_0305.html
interscript/parsers/html.py
interscript/doc/iscr_0306.html
interscript/doc/iscr_0307.html
interscript/doc/iscr_0308.html
interscript/parsers/lalr1.py
interscript/doc/iscr_0309.html
interscript/doc/iscr_0310.html
interscript/doc/iscr_0311.html
interscript/doc/iscr_0312.html
interscript/doc/iscr_0313.html
interscript/doc/iscr_0314.html
interscript/doc/iscr_0315.html
interscript/doc/iscr_0316.html
interscript/doc/iscr_0317.html
interscript/doc/iscr_0318.html
interscript/doc/iscr_0319.html
interscript/doc/iscr_0320.html
interscript/doc/iscr_0321.html
interscript/doc/iscr_0322.html
interscript/doc/iscr_0323.html
interscript/doc/iscr_0324.html
interscript/doc/iscr_0325.html
interscript/doc/iscr_0326.html
interscript/doc/iscr_0327.html
interscript/doc/iscr_0328.html
interscript/doc/iscr_0329.html
interscript/doc/iscr_0330.html
interscript/doc/iscr_0331.html
interscript/doc/iscr_0332.html
interscript/doc/iscr_0333.html
interscript/doc/iscr_0334.html
interscript/tests/tgram.py
interscript/doc/iscr_0335.html
interscript/doc/iscr_0336.html
interscript/doc/iscr_0337.html
interscript/doc/iscr_0338.html
interscript/doc/iscr_0339.html
interscript/doc/iscr_0340.html
interscript/doc/iscr_0341.html
interscript/doc/iscr_0342.html
interscript/felix/__init__.py
interscript/felix/model/__init__.py
interscript/doc/iscr_0343.html
interscript/felix/model/basecat.py
interscript/doc/iscr_0344.html
interscript/felix/model/fincat.py
interscript/doc/iscr_0345.html
interscript/doc/iscr_0346.html
interscript/doc/iscr_0347.html
interscript/doc/iscr_0348.html
interscript/doc/iscr_0349.html
interscript/doc/iscr_0350.html
interscript/doc/iscr_0351.html
interscript/felix/model/stdcat.py
interscript/doc/iscr_0352.html
interscript/doc/iscr_0353.html
interscript/doc/iscr_0354.html
interscript/doc/iscr_0355.html
interscript/doc/iscr_0356.html
interscript/doc/iscr_0357.html
interscript/doc/iscr_0358.html
interscript/doc/iscr_0359.html
interscript/doc/iscr_0360.html
interscript/doc/iscr_0361.html
interscript/doc/iscr_0362.html
interscript/felix/tests/stdcat_test.py
interscript/doc/iscr_0363.html
interscript/doc/iscr_0364.html
interscript/felix/model/stdcat2.py
interscript/doc/iscr_0365.html
interscript/doc/iscr_0366.html
interscript/doc/iscr_0367.html
interscript/doc/iscr_0368.html
interscript/felix/model/funcat.py
interscript/doc/iscr_0369.html
interscript/doc/iscr_0370.html
interscript/doc/iscr_0371.html
interscript/doc/iscr_0372.html
interscript/doc/iscr_0373.html
interscript/doc/iscr_0374.html
interscript/doc/iscr_0375.html
interscript/doc/iscr_0376.html
interscript/doc/iscr_0377.html
interscript/felix/tests/func_test.py
interscript/doc/iscr_0378.html
interscript/doc/iscr_0379.html
interscript/felix/model/cons.py
interscript/doc/iscr_0380.html
interscript/doc/iscr_0381.html
interscript/doc/iscr_0382.html
interscript/doc/iscr_0383.html
interscript/doc/iscr_0384.html
interscript/doc/iscr_0385.html
interscript/doc/iscr_0386.html
interscript/doc/iscr_0387.html
interscript/frames/install.py
interscript/doc/iscr_0388.html
interscript/frames/user.py
interscript/doc/iscr_0389.html
interscript/frames/project.py
interscript/frames/__init__.py
interscript/doc/iscr_0390.html
interscript/frames/platform.py
interscript/doc/iscr_0391.html
interscript/frames/site.py
interscript/doc/iscr_0392.html
interscript/frames/processf.py
interscript/doc/iscr_0393.html
interscript/doc/iscr_0394.html
interscript/frames/masterf.py
interscript/doc/iscr_0395.html
interscript/doc/iscr_0396.html
interscript/frames/passf.py
interscript/doc/iscr_0397.html
interscript/doc/iscr_0398.html
interscript/frames/inputf.py
interscript/doc/iscr_0399.html
interscript/doc/iscr_0400.html
interscript/doc/iscr_0401.html
interscript/doc/iscr_0402.html
interscript/doc/iscr_0403.html
interscript/doc/iscr_0404.html
interscript/doc/iscr_0405.html
interscript/doc/iscr_0406.html
interscript/doc/iscr_0407.html
interscript/doc/iscr_0408.html
interscript/doc/iscr_0409.html
interscript/tests/test_beginend.pak
interscript/doc/iscr_0410.html
interscript/doc/iscr_0411.html
interscript/doc/iscr_0412.html
interscript/doc/iscr_0413.html
interscript/doc/iscr_0414.html
interscript/doc/iscr_0415.html
interscript/doc/iscr_0416.html
interscript/doc/iscr_0417.html
interscript/doc/iscr_0418.html
interscript/doc/iscr_0419.html
interscript/doc/iscr_0420.html
interscript/doc/iscr_0421.html
interscript/doc/iscr_0422.html
interscript/doc/iscr_0423.html
interscript/doc/iscr_0424.html
interscript/doc/iscr_0425.html
interscript/doc/iscr_0426.html
interscript/doc/iscr_0427.html
interscript/doc/iscr_0428.html
interscript/doc/iscr_0429.html
interscript/doc/iscr_0430.html
interscript/doc/iscr_0431.html
interscript/doc/iscr_0432.html
interscript/doc/iscr_0433.html
interscript/doc/iscr_0434.html
interscript/doc/iscr_0435.html
interscript/doc/iscr_0436.html
interscript/doc/iscr_0437.html
interscript/doc/iscr_0438.html
interscript/doc/iscr_0439.html
interscript/doc/iscr_0440.html
interscript/doc/iscr_0441.html
interscript/doc/iscr_0442.html
interscript/doc/iscr_0443.html
interscript/doc/iscr_0444.html
interscript/doc/iscr_0445.html
interscript/doc/iscr_0446.html
interscript/doc/iscr_0447.html
interscript/doc/iscr_0448.html
interscript/getoptions.py
interscript/doc/iscr_0449.html
interscript/doc/iscr_0450.html
interscript/getframes.py
interscript/doc/iscr_0451.html
interscript/doc/iscr_0452.html
interscript/doc/iscr_0453.html
interscript/utilities/__init__.py
interscript/tests/test_compilers.py
interscript/tests/example.c
interscript/compilers/c.py
interscript/compilers/cpp.py
interscript/compilers/cconfig.py
interscript/compilers/__init__.py
interscript/doc/iscr_0454.html
interscript/doc/iscr_0455.html
interscript/doc/iscr_0456.html
interscript/doc/iscr_0457.html
interscript/doc/iscr_0458.html
interscript/doc/iscr_0459.html
interscript/utilities/diff.py
interscript/doc/iscr_0460.html
interscript/tests/diff1.dat
interscript/tests/diff2.dat
interscript/tests/test_diff.py
interscript/doc/iscr_0461.html
interscript/doc/iscr_0462.html
interscript/doc/iscr_0463.html
interscript/utilities/commands.py
interscript/doc/iscr_0464.html
interscript/bin/__init__.py
interscript/doc/iscr_0465.html
interscript/bin/iscr.py
interscript/doc/iscr_0466.html
interscript/bin/iscr.bat
interscript/doc/iscr_0467.html
interscript/tests/__init__.py
interscript/doc/iscr_0468.html
interscript/doc/iscr_0469.html
interscript/doc/iscr_0470.html
interscript/doc/iscr_0471.html
interscript/doc/iscr_0472.html
interscript/doc/iscr_0473.html
interscript/doc/iscr_0474.html
interscript/doc/iscr_0475.html
interscript/doc/iscr_0476.html
interscript/doc/iscr_0477.html
interscript/doc/iscr_0478.html
interscript/doc/iscr_0479.html
interscript/doc/iscr_0480.html
interscript/doc/iscr_0481.html
interscript/doc/iscr_0482.html
interscript/doc/iscr_0483.html
interscript/doc/iscr_0484.html
interscript/doc/iscr_0485.html
interscript/doc/iscr_0486.html
interscript/doc/iscr_0487.html
interscript/doc/iscr_0488.html
interscript/doc/iscr_0489.html
interscript/doc/iscr_0490.html
interscript/doc/iscr_0491.html
interscript/doc/iscr_0492.html
interscript/doc/iscr_0493.html
interscript/doc/iscr_0494.html
interscript/tests/example.pak
interscript/doc/iscr_0495.html
interscript/doc/iscr_0496.html
interscript/doc/iscr_0497.html
interscript/doc/iscr_0498.html
interscript/doc/iscr_0499.html
interscript/doc/iscr_0500.html
interscript/doc/iscr_0501.html
interscript/doc/iscr_0502.html
interscript/doc/iscr_funcref.html
interscript/doc/iscr_classref.html
interscript/doc/iscr_identref.html
interscript/doc/iscr_toc.html
interscript/doc/iscr_testref.html
interscript/doc/iscr_sectionref.html
interscript/doc/iscr_sourceref.html
/mnt/user1/uestl/py/iscr/interscript/doc/iscr_filestatus.html

7.4. Source List

iscr.pak
introduction.ipk
requirements.ipk
design.ipk
tutorial.pak
faq.ipk
sets.ipk
stacks.ipk
protocols.ipk
drivers.ipk
source_drivers.ipk
sink_drivers.ipk
storage_drivers.ipk
weavers.ipk
text_weaver.ipk
html_weaver.ipk
web_weaver.ipk
latex_weaver.ipk
weaver_filters.ipk
tanglers.ipk
python_tangler.ipk
perl_tangler.ipk
tokenizers.ipk
python_tokeniser.ipk
parsers.ipk
html_parser.ipk
lalr1_parser.ipk
felix.pak
felix_protocol.ipk
felix_package.ipk
felix_fincat.ipk
felix_stdcat.ipk
felix_stdcat2.ipk
felix_func.ipk
felix_cons.ipk
frames.ipk
platform_frame.ipk
site_frame.ipk
process_frame.ipk
master_frame.ipk
pass_frame.ipk
input_frame.ipk
options.ipk
interscript_options.ipk
compilers.ipk
diff.ipk
commands.ipk
bugs.ipk
installation.ipk

7.5. Include List

    interscript: iscr.pak
       interscript: introduction.ipk
       interscript: requirements.ipk
       interscript: design.ipk
       interscript: tutorial.pak
          interscript: faq.ipk
       code: iscr.pak
       interscript: sets.ipk
       interscript: stacks.ipk
       interscript: protocols.ipk
       interscript: drivers.ipk
          interscript: source_drivers.ipk
          interscript: sink_drivers.ipk
          interscript: storage_drivers.ipk
       interscript: weavers.ipk
          interscript: text_weaver.ipk
          interscript: html_weaver.ipk
          interscript: web_weaver.ipk
          interscript: latex_weaver.ipk
       interscript: weaver_filters.ipk
       interscript: tanglers.ipk
          interscript: python_tangler.ipk
          interscript: perl_tangler.ipk
       interscript: tokenizers.ipk
          interscript: python_tokeniser.ipk
       interscript: parsers.ipk
          interscript: html_parser.ipk
          interscript: lalr1_parser.ipk
       interscript: felix.pak
          interscript: felix_protocol.ipk
          interscript: felix_package.ipk
             interscript: felix_fincat.ipk
             interscript: felix_stdcat.ipk
             interscript: felix_stdcat2.ipk
             interscript: felix_func.ipk
             interscript: felix_cons.ipk
       interscript: frames.ipk
          interscript: platform_frame.ipk
          interscript: site_frame.ipk
          interscript: process_frame.ipk
          interscript: master_frame.ipk
          interscript: pass_frame.ipk
          interscript: input_frame.ipk
       interscript: options.ipk
       interscript: interscript_options.ipk
       interscript: compilers.ipk
       interscript: diff.ipk
       interscript: commands.ipk
       interscript: bugs.ipk
       interscript: installation.ipk

7.6. Bugs (etc) for Version 1a7

As a new development, Interscript has a lot of bugs, design flaws, and omissions. Please send comments to
  skaller@maxtal.com.au

7.6.1. These debugging notes

These notes reflect current status. They're not date stamped, and there's no indication if a bug has been fixed (the comment, hopefully, just gets removed). This is hopeless for bug tracking.

What we need is more like a database with time and versions stamped comments, organised by topic so fixes can be noted.

These notes are written separately from the program and documentation. For a list generated by cummulating comments made by me throughout the source, see iscrbuglist.html for this information.

7.6.2. Control System

Keyboard interrupts are still dubious. This has been improved over the 1a1 release.

The frames described in the doco are now implemented, more or less. Still needs some work.

No threads yet, but the frame implementation is good preparation for supporting them.

The SGML input filter is too primitive.

There's no error handling system. There's error handling, but i wouldn't call it a 'system' :-)

The markup filters are in the wrong place.

7.6.3. Tangler Bugs

String tanglers add an extra space on the last line. It's not easy to stop this without buffering. Also, the Python string tangler is all wrong. Python doesn't concatenate a sequence of string literals like C does.

The python tangler currently tokenises the generated code file (as it is being generated). The tokeniser used is the standard one, tokeniser.py. Unfortunately, it has the wrong control interface, and we have to map it to one the tangler can drive. This requires coroutines, but Python doesn't have them, so we are forced to emulate them using threads.

The python tokeniser is now fully functional.

The control system has been almost completely redone. It still uses the lists of regular expressions paired with functions to execute, but the functions are now methods bound to frames, usually the current input frame.

The predefined methods are replaced for every input frame constructed. This means users cannot override them properly, since they're not inherited. Really, we should use the Guido hack: store functions in the user dictionary, and turn them into bound methods at the point of lookup.

Correct implementation of the scoping mechanism is severely hampered by Python's lack of suitable scoping.

7.6.4. Weaver Bugs

The table of identifiers gets wide under Latex, the items don't wrap.

7.6.5. Misc Bugs

Table of contents and file lists are now stored in memory and preserved between passes, so it is necessary to run two passes to get them to print out correctly. Because the storage is weaver independent, being generated by the multiplexor, there are no references in the table of contents. This needs to be fixed by allowing each weaver private storage persistent across passes. At this time this is not possible because there is no way to uniquely identifier a weaver instance (a new object is constructed each pass).

Heading numbers should have user controlled formats.

7.6.6. Design Issues

The interactions in this system are VERY complex. For example, consider an Interscript source which generates a Interscript source, or a shell archive. In this case multiple tanglers may be needed to generate a single file.

It should be possible to perform 'categorical' constructions on tanglers: chaining tanglers, writing to multiple outputs, writing to selected outputs, etc.

7.6.7. Omissions

7.6.7.1. Building

There's no build environment.

7.6.7.2. Scripting

The Tcl interface doesn't map variables.

There's no Perl interface.

7.6.7.3. Parsing

No support for Internationalisation.

to invoke Interscript this way. More generally, it would be nice if Interscript could 'automatically recognize' various input files.

It's tricky to change the warning character (default @). Perhaps the first character on the first line should be taken as the warning character (unless the first line starts with #!, in which case the second line is used. Curently, Interscript can't work unless some executable code is at the start of the primary source file (at least to set up the weaver).

Perl users will hate having @ as the escape character because it is the first character of all array identifiers. (Is that right?)

The parser is not modularised properly.

There's no XML filter.

There's no LaTeX filter (that's hard!)

7.6.7.4. Weaving

There's no weaver for plain TeX, Postscript, or Word, nroff, Lout.

The support for hypertext is primitive.

The identifier index uses HTML hyperlinks. What should be displayed as the anchor text: the input source reference or the output code reference? Or both? The input source is where editing would be done, but the output tells where the identifier ended up, which is probably more useful.

No pictures or drawings.

7.6.7.5. Tangling

There's no support for 'chunking' (noweb) or 'macros' (FunnelWeb): i.e. the ability to define code fragments to be included inside others, building the code heirarchical. This is an absolutely fundamental requirement, and it is not omitted by accident. There is some primitive macro support: you can tangle a file and read it in on the next pass, or you can tangle a memory sink and then use it as a source. It's easy to write commands that simplify use of these mechanisms, and I had some, but they've been removed.

The reason there's no chunking is that I'm not happy with any of the mechanisms yet, nor certain of the requirements. FunnelWeb, for example, tangles code after scanning the whole document, and so can include a macro A in a macro B, even if B is defined _before_ A. This isn't possible with a simple one pass dynamic system. On the other hand, it seems obvious that tanglers that generate chunks should perform language specific processing, such as formatting comments and introducing the #line directives, while the generated output should be included raw (since it has already been processed).

Unfortunately, this is a gross oversimplification of the requirements of a meta-programmable system. For example, a lot of programming would benefit from chunks with arguments, which FunnelWeb supports (and which is why they're called macros). As another example, FunnelWeb tracks usage of chunks, and requires every chunk be used exactly once, unless otherwise declared in chunk definition. Yet another example: templates, or skeleton. This is conceptually the same as a macro with arguments, but that is a lousy way to actually have to write the call. The correct method is to use co-routines (interleaving), diversions, continuations (etc).

So we see that generating code by expanding with substitutions, even the simplest kind of parameterless chunk substitutions, seems to be the thin end of the wedge leading to the development of a complete programming language --- and Interscript is already equipped with at least one of those.

Here's a final 'killer' example. One of the languages we are sure to want to tangle is ... Interscript.

If a tangler supports source cross references such as the #line directive, then there will always be such a directive as the first line of a code file. Unfortunately, some languages and systems have special requirements on what's in the first line. Cases I know of include:

  1. the Unix #! convention, which could be used by Python and Tcl programs,
  2. vi: set tabwidth type lines in text files (including programs),
  3. and quote a lot of typesetting other systems (including compilers) which require global flags to be set by pragmas and the like, right on the first line.
The solution is to have a special command to generate the first lines of a code file, which doesn't trigger generating the #line directive.

There's no tangler for many languages: Modula, Pascal, Cobol, Scheme, etc etc.

There's no support for bolding keywords.

There's no Tcl string tangler. The Perl string tangler is bogus.

7.6.8. New in 1a5

By far the most important improvement is the implementing of the frame architecture, and the repackaging of interscript as a python package.

The bulk of interscript is now built as a package in a tree structured directory. Using the frames architecture, the command line interface has been reduced to few lines, which will allow interscript to be embedded in other front end programs.

The web (stacking html) weaver now generates a table of contents which uses javascript to produce a dynamic tree under Internet Explorer.

There are also two home pages for a document, and two tables of contents. The alternate home page creates two framnes, and loads an alternate table of contents into the first frame, which targets the second frame.

The web weaver now generates <LINK> tags similar exhibiting the relationship between the documents.

Tcl script has been discarded completely.

The command line launcher now accepts an option '--test' which pushes the current directory onto the system path to force package loading to look in the current directory. This is the place interscript and user packages will often be built from. The purpose of this hack is to allow documents containing both code and tests for the code, to allow the test code to actually find the newly created modules before they're installed in standard places. By default, sys.path is not modified, so unix '#!/usr/local/bin/python' launched scripts will not search the current directory. This hopefully improves separation between reliable installed software and that under development.

If the first line of a Python output starts with '#!', line numbers are not generated until the next line.

The autoweaver for html and web now makes sinks which use carriage return linefeed pairs as end of line characters. This is to fix bugs in stupid Microsoft software such as Notepad and Wordpad, which refuses to recognize them as end of line. This is important for viewing HTML sources from Internet Explorer.

Sink drivers have been rearchitected to support standard python output file protocols so they can be used, for example, as the sys.stdout device. The Python line handling protocol sucks, stupidly returning the end of line characters at the end of lines on input, and requiring them to be there already on output. Interscript's own protocol returns lines without line terminators, adds them on output, and recognizes linefeed in strings (only) as it's internal end of line terminator.

Option processing now uses an interscript module (getopt wasn't up to it).

There are now four options, '--weaver_prefix', '--weaver_directory', '--tangler_prefix', '--tangler_directory', which allow output to be directed somewhere other than the current directory from the command line. See next item.

Interscript now fixes file names to use a subset of the Unix filename convention. All interscript filenames must use a sensible set of characters for component names, and separate them with '/'. Filename must be relative.

A filename given for a tangler or weaver constructed by the builtin tangler functions or autoweave is prefixed by the directory option before being split into components. Then the prefix is prepended to the first component.

Directories are built automatically (and somewhat prematurely).

The effect is that the prefix_* should usually denote an existing directory in native operating system format, with a directory separator at the end, and the directory_* should be a unix pathname with a '/' at the end.

One of the benefits of this arrangement is that Windows clients can specify output onto another drive, for example using the option:

  --weaver_prefix="d:\project\document files\"
Note the quotes!

7.6.8.1. Separate compilation

Interscript is now constructed in such a way that it is possible to tangle subdocuments to extract individual modules. For example, if a weaver is changed, it is possible to update that component by processing the ipk (included package) file without rebuilding all of interscript. If weaving is enabled, a separate document for that component will be generated, it will not be related to the pages for the same component generated as part of a full build. How would we get the right heading numbers? Or predict the filenames to be generated?

This needs to be fixed. The problem is one of design rather than implementation: the web weaver might be adapted to use filenames derived from the current input source, locking the structure of the generated documents to the input source structure. At present, these are independent except that breaks occur on headings.

Probably, 'include_file' is not enough to support what is required.

7.6.9. Under development and planned

Under development is a syntax driven LALR translator which I hope to use to replace the 'micky mouse' control system.

The patch/diff module is working. I still haven't figured out how to use it to implement version control.

A simple Tkinter front end is under development for launching interscript runs, as an alternative to the command line launcher 'iscr.py'.

The current prefix and directory options for tanglers and weavers is effective but too primitive. The interscript source contains a currently unused installation frame which illustrates the mechanism intended to replace this. Interscript filenames will be extended to full URI syntax, with the protocol 'iscr' being used to designate vectoring of the output to a directory which is the value of a dictionary keyed by the 'machine' component of the URI, together with a trust level assigned by the client.

This mechanism allows the author to identify an arbitrary set of logical file systems into which output is put, and the client to map these logical file systems onto actual output points.

For example, the client will output stuff to a project development structure during testing. When happy, the output will be remapped to the installation structure. For example, html documentation could be automatically posted to the live Internet web site.

The main impediment to actually implementing this, is that to use the mechanism, the user will have to set up the installation frame to use interscript. It is very difficult to provide sensible defaults (other than 'current directory'). Doing this requires non-trivial programming work by the client, constructing or modifying the installation frame. This is not so bad if it is done from a GUI interface.

Move to Java. Because advanced interscript use requires a GUI based architecture to manage whole projects (as opposed to just processing a single document at a time), interscript is likely to move to JPython. This is advance warning to users: try to get JPyton running! It is also going to use a lot more advanced HTML features like javascript, style sheets, and other stuff which is currently a nightmare due to the lack of a standard Document Object Model for browsers.

Interscript current supports Internet Explorer DOM, in lieu of a standard. Although it is possible to incorporate some Netscape DOM features, the principal feature needed -- outlining -- requires dynamically setting the display style of an element, something Netscape doesn't support at all (at the time of writing, and as far as I can tell). Therefore, Netscape is treated like a dumb browser, and enhanced DHTML features will only work on Internet Explorer.

The emphasis on GUI interfaces cannot be overemphasised. The move to dynamic, fully featured, control over browsing the generated documents, together with full scale meta data generation to facilitate clients such as search engines and web crawlers indexing the documents, is considered crucial to getting a viable literate programmed system running. Use of Java AWT for the input side seems inevitable, as this appears to be the only GUI which is likely to be widely supported, standardised, and which also allows interaction between output and input by way of browser applet plugins.

7.7. Installation Guide

How to install interscript on your computer.

7.7.1. What you need

You need a modern computer running a vaguely posix like operating system, C, and CPython 1.5.1. Interscript should run out of the box on a Linux system, and with minimal effort on most Unix boxes, and without too much effort on 32 bit MS-Windows systems. Some enhancements may require site dependent configuration. Please see below for more details.

7.7.2. Where to get it

You can ftp the interscript tar ball anonymously from ftp://ftp.triode.net.au/ftp/skaller/interscript.tgz which is a tarred, gziped, archive. WinZip should handle this format.

7.7.3. Instant install

Here are the quick installation instructions.

7.7.3.1. Unpack the archive

Unpack the tar ball somewhere Python will find it. The result will be
  • a directory "interscript"
  • a file "interscript.pth"

On my linux box, I use the directory:

  /usr/local/lib/python1.5/site-packages/

7.7.3.2. Unix: Make the command line launch script executable

Optional but recommended. Copy the file "interscript/bin/iscr.py" to someplace on you execution path, renaming it "iscr" and making it executable. For example, I use:
  cp /usr/local/lib/python1.5/site-packages/interscript/bin/iscr.py ~/bin/iscr
  chmod a+x iscr
You may need to edit the first line of this script, which is
  #!/usr/bin/env python

7.7.3.3. Windows: Make the command line launch script executable

Copy the file interscript/bin/iscr.bat to someplace on your execution path. You will (definitely!) need to edit this file, replacing "iscr.py" with the absolute pathname of the file "interscript/bin/iscr.py". You may also need to change the name of the python application executable. Note that this file only supports 9 arguments.

7.7.3.4. Mac: write a launch script

I am told the Mac does not have a shell tool. Interscript can be launched from any Python script by simply importing the module "interscript" and calling the function
  interscript.run_from_arguments(args)
where "args" is a python list of strings, each of which is a command line argument as would be parsed by a Unix system. You will need to write a Python scipt that gleans this information from somewhere such as a a popup edit window, or by reading a response file. I would be interested in including such a script with interscript if someone wanted to send it to me at mailto:skaller@maxtal.com.au

It is very likely that the current version of the interscript package will also require some changes to work on the Mac. Please email any advice to me at mailto:skaller@maxtal.com.au

I will be working to isolate platform dependencies better in the next version, and to try to provide pre-configured multi-platform support.

7.7.3.5. Install doco

If necessary copy, or move, the HTML documentation in interscript/doc to someplace on your local WWW server. You will need to copy all the ".html" files, and the file "interscript.css" if you want to use the interscript CSS1 cascading style sheet.

7.7.3.6. Test It

You can check interscript is installed from the command line like:
  iscr --weaver=html --passes=3 example.pak
where "example.pak" is any interscript master source file; for example, the file "interscript/tests/example.pak", which is displayed below.
Start python section to interscript/tests/example.pak[1] 1
     1: #line 101 "installation.ipk"
     2: 
     3: @head(1,'An Interscript Example')
     4: This is a minimal example of interscript at work.
     5: @head(2,'Tangling a litte script')
     6: @select(python_output('interscript/tests/example.py'))
     7: print 'Hello from an example python program'
     8: @head(2,'Executing the script')
     9: @print_python_output('interscript/tests/example.py')
    10: 
End python section to interscript/tests/example.pak[1]

7.7.4. Configuration

Interscript supports some options which may need configuration.

WARNING: There is currently no standard way to maintain the interscript package. Any changes you make may get wiped out by the next interscript installation. Please keep a copy somewhere to reconfigure interscript after the next installation! [I'm working on this.]

7.7.4.1. Compilers sub-package

This sub-package provides interscript with the ability to compile dynmically loadable python modules written in C or C++, and with the ability to build stand alone command lines tools using a command line C and C++ compiler.

The files "c.py", "cpp.py", and "cconfig.py" in "interscript/compilers/" are set up for my Linux box, and invoke "gcc" and "g++" with appropriate options for building python modules and command line executables. You may need to modify (or even rewrite) these modules to make them work at your site.

These modules are not required by interscript, but they do allow it to build some speedup code automatically, they're generally nice to have, and they will be used by me when distributing C or C++ code hosted by interscript (instead of makefiles).

These files are generated by interscript from the source "interscript/src/compilers.ipk".

7.7.4.2. Diff sub-package

This package provides the ability to diff and patch files. It is not required but is very strongly recommended! The script is "interscript/utilities/diff.py", and is sourced from "interscript/src/diff.ipk" and requires GNU diff and GNU patch.

7.7.4.3. Command line tool execution

The python module 'commands' is used to execute client commands, including python script, and capture its output. This module is theoretically optional ...

Note that when python is invoked, the string "sys.executable" is used to name it. This attribute is not documented in the python documentation.

7.7.4.4. Speedups

The module "interscript.core.iscrcopt" is an optional dynamically loadable C module which speeds up some of the character by character lexical processing that interscript has to do. If the compilers module works, a build of interscript, and in particular the source "interscript/src/iscrcopt.ipk", will generate the binary module. This module is already built for Redhat Linux 5. This file is completely platform independent (but the binary isn't, of course).

7.7.4.5. Other

There are currently a few other platform dependencies. I'm working on fixing this. That is, I will at least try to isolate such code in such a way that re-installation or upgrading of interscript will not clobber client modifications. This WILL happen at present!

7.7.5. Building Interscript

If you are keen, you can try to rebuild interscript.

YOU HAVE TO BE REALLY KEEN!

Whew. Now I've done my duty and tried to disuade you ..

The whole of the source is in "interscript/src". I recommend you create a development directory separate from the initial (pre-built) installation. Copy the sources into this directory and invoke the pre-built interscript command line tool 'iscr' on the file 'iscr.pak' like this:

  iscr iscr.pak
This should build a directory 'interscript' in the current directory. You may notice some 'errors'. Don't worry! Most of these are normal. Errors occur 'normally' when interscript tries to read files that don't exist yet, but get created later in the run.

Now issue the command

  iscr --test "--weavers='all'" --passes=4 iscr.pak
This should rebuild interscript, this time using the package built by the previous run, and also generating the documentation. If you have problems, try using the "-v" switch:
  iscr --test -v "--weavers='all'" --passes=4 iscr.pak
To capture the output, use the logfile option:
  iscr --test --logfile=iscr.log -v "--weavers='all'" --passes=4 iscr.pak
Note that the "--test" switch must come first, it is a command line tool option, not an interscript option. This option adds the current directory to the python path before trying to import the interscript module. If your build of interscript fails, you can edit the sources and rebuild without the "--test" option. You can't build with it (unless the build failed utterly-- or you delete the interscript directory or interscript.pth file first).

To install your new version of interscript, copy the interscript directory to your standard installation point. Don't do this unless you're sure it works! (If it doesn't, you may not be able to rebuild interscript without re-installing from the tar ball .. because you need a working copy of interscript to build interscript).

You can rebuild any code file by just running interscript on the ".ipk" file defining it. This won't rebuild the documentation correctly! But it is very much faster than rebuilding the whole package.

7.7.6. NT Issues

Interscript builds sucessfully under NT. You can expect to see a few of these:
  The name specified is not recognized as an
  internal or external command, operable program or batch file.
On the first pass building interscript, I try to get hold of the user and hostname using external command line tools. I use 'uname', for example, which isn't supported under NT. These tools are called using os.popen. NT writes an error message to the console if it cannot find the tool.