6.1.3. Listing of iscr.pak source

Here is the fully listings of the top level interscript source file, iscr.pak.
@# Interscript $Id: iscr.pak,v 1.6 2001/06/16 22:16:42 skaller Exp $
@# To build interscript, a production version of
@# interscript must already be installed.
@# cd into the workingdirectory containing
@# the directory 'interscript'.
@# Execute the command:
@# iscr interscript/src/iscr.pak
@# This builds the working version.
@# To test it on itself, execute the command
@# iscr --test interscript/src/iscr.pak
@# To build the system with documentation,
@# execute the command
@# iscr --language=en --weaver=web --weaver=latex \
@#   --weaver=text --weaver-prefix=doc/ \
@#   --passes=10
@# ALTERNATIVE: use the makefile provided.
@# make           -- make interscript
@# make doc       -- make documentation
@# make test      -- make interscript with working version
@# make fulltest  -- make the docs with the working version
@# make tarball   -- build a distribution
@add_author('John Skaller',
   address=['10/1 Toxteth Rd',
     'Glebe, NSW 2037',

@# 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.0a11'

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

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

@# --------------------------------------------------------------------
@# Try to get the hostname.
@# Should work on Unix, but don't worry if it fails.
@gen_hostname = 'unknown'
   f = os.popen('hostname','r')
   gen_hostname = string.strip(f.readline())
   print "Couldn't get hostname, probably not Unix."

@# --------------------------------------------------------------------
@# Try to get the username.
@# Should work on Unix, but don't worry if it fails.
@gen_username = 'unknown'
   gen_username = os.environ['USER']
     gen_username = os.environ['USERNAME']
       gen_username = os.environ['LOGNAME']
       print "Couldn't get username, probably not Unix."

@# --------------------------------------------------------------------
@# 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 'Running on',gen_hostname,'by',gen_username,'at',lfmtime
@print "and building Interscript",gen_version,'build',gen_buildno

@# markup coding scheme from Henk Jansen
@emph   = markup_filter(get_pass_frame(),"e!(.*)!",'begin_emphasize','end_emphasize',[get_weaver()])
@bold   = markup_filter(get_pass_frame(),"b!(.*)!",'begin_bold','end_bold',[emph])
@strong = markup_filter(get_pass_frame(),"s!(.*)!",'begin_strong','end_strong',[bold])
@italic = markup_filter(get_pass_frame(),"i!(.*)!",'begin_italic','end_italic',[strong])
@big    = markup_filter(get_pass_frame(),"B!(.*)!",'begin_big','end_big',[italic])
@small  = markup_filter(get_pass_frame(),"S!(.*)!",'begin_small','end_small',[big])
@code   = markup_filter(get_pass_frame(),"c!(.*)!",'begin_code','end_code', [small])
@master_weaver = code

@# --------------------------------------------------------------------
@# 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.
   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.

@# --------------------------------------------------------------------
@# Print the introduction and design principles chapters.

@# --------------------------------------------------------------------
@# Generate the source code and program documentation.
Literate programmed by itself, of course!

@head(2,'Interscript Module')
The top level interscript module.
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 HTML web documentation at


Find the text documentation at


Find the latex2e documentation at


Find the interscript home page at


@# below is a kludge, to prevet the time and date stopping convergence
@iscr_pkg = python_output(simple_named_file_sink(get_pass_frame(),'interscript/__init__.py'))
# interscript package
import string
def hexval(i):
  i = string.upper(i)
  if i[:2]=='0X': i = i[2:]
  a = 0
  for d in i:
    a = a * 16 + ord(d) - {0:ord('0'), 1:ord('A')-10}[d>'9']
  return a


import os
directory = os.path.split(__file__)[0]+os.sep
def bind_resource_name(*components):
  return directory + apply(os.path.join,components)

@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.
[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.

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.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.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
  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__

    import thread
    #print 'thread available'
    #print 'thread NOT available'

@head(3,'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
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.

# 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 define a routine to print the current version information
# wrapped in try/except clause in case any of the variables didn't get set
def print_version_info():
    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
@if debug_version:
# 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)
  del process

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

@head(2,'Core Subpackage',key='core')
# interscript core modules

@include_file('sets.ipk')     # sets
@include_file('stacks.ipk')   # stacks
@include_file('protocols.ipk')# protocols

@include_file('encoding.ipk')        # encode/decode
@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('frames.ipk')          # architecture
@include_file('options.ipk')         # generic option processing
@include_file('interscript_options.ipk')   # interscript option processing
@include_file('interscript_languages.ipk') # language translation

@head(2,'Utility Modules',key='util')
# interscript utilities


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

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

#!/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
  print 'Interscript directory is',interscript.directory
  import interscript

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

There's a better way in Windows NT!
Using the 'ASSOC' and 'FTYPE' commands,
you can specify the type of .pak files, and what to do with them:
  ASSOC .pak=Interscript.Master.Document
  FTYPE Interscript.Master.Document=D:\interscript\interscript\bin\iscr.py %*
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:
  set PATHEXT=.pak;%PATHEXT%
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')
# dummy interscript/test

@# --------------------------------------------------------------------
@# Print the table of identifiers and class reference
@head(2,'Make tarball')
@# --------------------------------------------------------------------
@tangle('rm -rf iscr_'+gen_version+'.tgz')
@tangle('tar -zcvf iscr_'+gen_version+'.tgz \\')
  interscript/*.py \
  interscript/frames/*.py \
  interscript/tanglers/*.py \
  interscript/weavers/*.py \
  interscript/compilers/*.py \
  interscript/core/*.py \
  interscript/drivers/*.py \
  interscript/drivers/sinks/*.py \
  interscript/drivers/sources/*.py \
  interscript/drivers/storage/*.py \
  interscript/languages/*.py \
  interscript/parsers/*.py \
  interscript/tokenisers/*.py \
  interscript/utilities/*.py \
  interscript/data/*.txt \
  interscript/doc/* \
  interscript/encoding/*.py  \
  interscript/encoding/*.dat  \
  interscript/src/*.ipk  \
@# --------------------------------------------------------------------
We have to explicitly 'tangle' a makefile,
since we can't output tabs any other way.

@tangle('\tiscr interscript/src/iscr.pak')
@tangle('\tiscr --language=en --weaver=web\\')
@tangle('\tiscr --test interscript/src/iscr.pak')
@tangle('\tiscr --test --language=en --weaver=web\\')
@tangle('\tsh mktgz')
@tangle('\trm -f interscript/src/*.cache')
@tangle('\trm -rf interscript/compilers/')
@tangle('\trm -rf interscript/core/')
@tangle('\trm -rf interscript/doc/')
@tangle('\trm -rf interscript/drivers/')
@tangle('\trm -rf interscript/encoding/')
@tangle('\trm -rf interscript/examples/')
@tangle('\trm -rf interscript/frames/')
@tangle('\trm -rf interscript/languages/')
@tangle('\trm -rf interscript/parsers/')
@tangle('\trm -rf interscript/tanglers/')
@tangle('\trm -rf interscript/test/')
@tangle('\trm -rf interscript/tests/')
@tangle('\trm -rf interscript/tokenisers/')
@tangle('\trm -rf interscript/utilities/')
@tangle('\trm -rf interscript/weavers/')
@print 'INTERSCRIPT '+gen_version+' BUILD COMPLETE'