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 $
@set_native_language('en')
@#
@# 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
@#
@set_title('Interscript')
@add_author('John Skaller',
mail='mailto:skaller@maxtal.com.au',
homepage='http://www.maxtal.com.au',
address=['10/1 Toxteth Rd',
'Glebe, NSW 2037',
'Australia'],
phone='+61-2-9660-0850')
@# 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.
@try:
gen_buildno = 0
temp = open('iscrbldn.dat','r')
line = temp.readline()
line = line[:-1]
gen_buildno = int(line)
temp.close()
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:
f = os.popen('hostname','r')
gen_hostname = string.strip(f.readline())
f.close()
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:
gen_username = os.environ['USER']
except:
try:
gen_username = os.environ['USERNAME']
except:
try:
gen_username = os.environ['LOGNAME']
except:
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
@print 'Running on',gen_hostname,'by',gen_username,'at',lfmtime
@print "and building Interscript",gen_version,'build',gen_buildno
@print
@# 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
@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 HTML web documentation at
interscript/doc/en_iscr_top.html
Find the text documentation at
interscript/doc/en_iscr.txt
Find the latex2e documentation at
interscript/doc/en_iscr.tex
Find the interscript home page at
http://interscript.sourceforge.net
@select(data_output('interscript.pth'))
interscript
@# 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'))
@select(iscr_pkg)
# 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
__builtins__['hexval']=hexval
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:
print 'TANGLING DEBUG VERSION'
# announce the version when the module is imported.
tangle('print "Interscript Package: version '+gen_version+'",')
tangle('print "build '+str(gen_buildno)+'"')
else:
print 'TANGLING PRODUCTION VERSION'
@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.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__
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 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():
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
@if debug_version:
print 'TANGLING DEBUG VERSION'
tangle("""print_version_info()""")
# 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',key='core')
@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('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
@pop_head()
@head(2,'Utility Modules',key='util')
@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
print 'Interscript directory is',interscript.directory
else:
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',key='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()
@head(2,'Make tarball')
@# --------------------------------------------------------------------
@select(tangler('mktgz'))
@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 \
interscript/bin/*
@doc()
@head(2,'Makefile')
@# --------------------------------------------------------------------
We have to explicitly 'tangle' a makefile,
since we can't output tabs any other way.
@select(tangler('makefile'))
@tangle('all:')
@tangle('\tiscr interscript/src/iscr.pak')
@tangle('')
@tangle('doc:')
@tangle('\tiscr --language=en --weaver=web\\')
@tangle('\t\t--weaver=latex\\')
@tangle('\t\t--weaver=text\\')
@tangle('\t\t--passes=10\\')
@tangle('\t\t--weaver-prefix=interscript/doc/\\')
@tangle('\t\tinterscript/src/iscr.pak')
@tangle('')
@tangle('test:')
@tangle('\tiscr --test interscript/src/iscr.pak')
@tangle('')
@tangle('fulltest:')
@tangle('\tiscr --test --language=en --weaver=web\\')
@tangle('\t\t--weaver=latex\\')
@tangle('\t\t--weaver=text\\')
@tangle('\t\t--passes=10\\')
@tangle('\t\t--weaver-prefix=interscript/doc/\\')
@tangle('\t\tinterscript/src/iscr.pak')
@tangle('')
@tangle('tarball:')
@tangle('\tsh mktgz')
@tangle('clean:')
@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/')
@doc()
@print 'INTERSCRIPT '+gen_version+' BUILD COMPLETE'