1
0
mirror of https://github.com/myhdl/myhdl.git synced 2024-12-14 07:44:38 +08:00

Merge pull request #66 from jck/cleanup

How did you fix this one? Seems there were no new commits?
This commit is contained in:
jandecaluwe 2015-04-28 21:29:39 +02:00
commit 6af8fa0b60
153 changed files with 1215 additions and 22925 deletions

2
.gitignore vendored
View File

@ -9,10 +9,12 @@ build/
__pycache__/
*egg-info/
dist/
.tox
# Cosim
*.o
*.vpi
*.so
# Simulator generated files
*.vcd

View File

@ -31,7 +31,7 @@ matrix:
- python: "3.4"
env: CI_TARGET=ghdl
script: ./ci.sh
script: ./scripts/ci.sh
notifications:
email: false

View File

@ -4,6 +4,12 @@ install:
localinstall:
python setup.py install --home=$(HOME)
docs:
tox -e docs html
livedocs:
tox -e docs livehtml
release:
- rm MANIFEST
- rm CHANGELOG.txt

View File

@ -19,6 +19,7 @@ I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " livehtml to make continuously updating standalone HTML files"
@echo " web to make files usable by Sphinx.web"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@ -41,6 +42,10 @@ html:
@echo
@echo "Build finished. The HTML pages are in build/html."
livehtml:
mkdir -p build/html build/doctrees
sphinx-autobuild -b html $(ALLSPHINXOPTS) build/html
web:
mkdir -p build/web build/doctrees
$(SPHINXBUILD) -b web $(ALLSPHINXOPTS) build/web

398
doc/source/whatsnew/0.3.rst Normal file
View File

@ -0,0 +1,398 @@
=======================
Whats New in MyHDL 0.3
=======================
:Author: Jan Decaluwe
VCD output for waveform viewing
===============================
|image|
MyHDL now has support for waveform viewing. During simulation, signal
changes can be written to a VCD output file that can be loaded into a
waveform viewer tool such as **gtkwave**.
The user interface of this feature consists of a single function,
:func:`traceSignals()`. To explain how it works, recall that in MyHDL,
an instance is created by assigning the result of a function call to an
instance name. For example:
::
tb_fsm = testbench()
To enable VCD tracing, the instance should be created as follows
instead:
::
tb_fsm = traceSignals(testbench)
All signals in the instance hierarchy will be traced in a VCD file
called . Note that first the argument of :func:`traceSignals()` consists
of the uncalled function. By calling the function under its control,
:func:`traceSignals()` gathers information about the hierarchy and the
signals to be traced. In addition to a function argument,
:func:`traceSignals()` accepts an arbitrary number of non-keyword and
keyword arguments that will be passed to the function call.
Signals are dumped in a suitable format. This format is inferred at the
:class:`Signal` construction time, from the type of the initial value.
In particular, :class:`bool` signals are dumped as single bits. (This
only works starting with Python 2.3, when :class:`bool` has become a
separate type). Likewise, :class:`intbv` signals with a defined bit
width are dumped as bit vectors. To support the general case, other
types of signals are dumped as a string representation, as returned by
the standard :func:`str()` function.
[warning] Support for literal string representations is not part of the
VCD standard. It is specific to **gtkwave**. To generate a standard VCD
file, you need to use signals with a defined bit width only.
Enumeration types
=================
It is often desirable to define a set of identifiers. A standard Python
idiom for this purpose is to assign a range of integers to a tuple of
identifiers, like so:
::
>>> SEARCH, CONFIRM, SYNC = range(3)
>>> CONFIRM
1
However, this technique has some drawbacks. Though it is clearly the
intention that the identifiers belong together, this information is lost
as soon as they are defined. Also, the identifiers evaluate to integers,
whereas a string representation of the identifiers would be preferable.
To solve these issues, we need an *enumeration type*.
MyHDL 0.3 supports enumeration types by providing a function
:func:`enum()`. The arguments to :func:`enum()` are the string
representations of the identifiers, and its return value is an
enumeration type. The identifiers are available as attributes of the
type. For example:
::
>>> from myhdl import enum
>>> t_State = enum('SEARCH', 'CONFIRM', 'SYNC')
>>> t_State
<Enum: SEARCH, CONFIRM, SYNC>
>>> t_State.CONFIRM
CONFIRM
Enumeration types are often used for the state variable in a finite
state machine. In the waveform in
Section \ `1 <#vcd-output-for-waveform-viewing>`__, you see a
:class:`Signal` called ``state``. Note how the waveforms show the string
representation of the enumeration type identifiers The ``state`` signal
has been constructed with an enumeration type identifier as its initial
value, as follows:
::
state = Signal(t_State.SEARCH)
Inferring the sensitivity list for combinatorial logic
======================================================
In MyHDL, combinatorial logic is described by a generator function with
a sensitivity list that contains all inputs signals (the signals that
are read inside the function).
It may be easy to forget some input signals, especially it there are a
lot of them or if the code is being modified. There are various ways to
solve this. One way is to use a sophisticated editor. Another way is
direct language support. For example, recent versions of Verilog have
the ``always @*`` construct, that infers all input signals. The
SystemVerilog 3.1 standard improves on this by introducing the
``always_comb`` block with slightly enhanced semantics.
MyHDL 0.3 provides a function called :func:`always_comb()` which is
named and modeled after the SystemVerilog counterpart.
:func:`always_comb()` takes a classic local function as its argument.
This function should specify the combinatorial logic behavior.
:func:`always_comb()` returns a generator that is sensitive to all
inputs, and that will run the function whenever an input changes.
For example, suppose that we have a mux module described as follows:
::
def mux(z, a, b, sel):
""" Multiplexer.
z -- mux output
a, b -- data inputs
sel -- control input
"""
def logic()
while 1:
yield a, b, sel
if sel == 1:
z.next = a
else:
z.next = b
mux_logic = logic()
return mux_logic
Using :func:`always_comb()`, we can describe it as follows instead:
::
def mux(z, a, b, sel):
""" Multiplexer.
z -- mux output
a, b -- data inputs
sel -- control input
"""
def logic()
if sel == 1:
z.next = a
else:
z.next = b
mux_logic = always_comb(logic)
return mux_logic
Note that in the first version, the sensitivity list is at the beginning
of the generator function code. This is traditionally done in
synthesizable RTL style modeling. However, the semantics of this style
are not entirely correct: at the start of the simulation, the
combinatorial output will not reflect the initial state of the inputs.
:func:`always_comb()` solves this by putting the sensitivity list at the
end of the code.
Inferring the list of instances
===============================
In MyHDL, the instances defined in a top level function need to be
returned explicitly. The following is a schematic example:
::
def top(...):
...
instance_1 = module_1(...)
instance_2 = module_2(...)
...
instance_n = module_n(...)
...
return instance_1, instance_2, ... , instance_n
It may be convenient to assemble the list of instances automatically,
especially if there are many instances. For this purpose, MyHDL 0.3
provides the function :func:`instances()`. It is used as follows:
::
from myhdl import instances
def top(...):
...
instance_1 = module_1(...)
instance_2 = module_2(...)
...
instance_n = module_n(...)
...
return instances()
Function :func:`instances()` uses introspection to inspect the type of
the local variables defined by the calling function. All variables that
comply with the definition of an instance are assembled in a list, and
that list is returned.
Inferring the list of processes
===============================
In addition to instances, a top level function may also define local
generators functions, which I will call *processes* because of the
analogy with VHDL. Like instances, processes need to be returned
explicitly, with the qualification that they have to be called first to
turn them into generators. The following is a schematic example:
::
def top(...):
...
def process_1():
...
def process_2():
...
...
def process_n():
...
...
return process_1(), process_2(), ..., process_n()
As for instances, it may be more convenient to assemble the list of
processes automatically. One option is to turn each process into an
instance by calling it and assigning the returned generator to a local
variable. Those instances will then be found by the :func:`instances()`
function described in
Section \ `4 <#inferring-the-list-of-instances>`__.
Another option is to use the function :func:`processes()` provided by
MyHDL 0.3. This function uses introspection to find the processes, calls
each of them, and assembles the returned generators into a list. It can
be used as follows:
::
from myhdl import processes
def top(...):
...
def process_1():
...
def process_2():
...
...
def process_n():
...
...
return processes()
To conclude, a top level function with both instances and processes can
use the following idiomatic code to return all of them:
::
return instances(), processes()
Class :class:`intbv` enhancements
=================================
Class :class:`intbv` has been enhanced with new features.
It is now possible to leave the left index of a slicing operation
unspecified. The meaning is to access “all” higher order bits. For
example:
::
>>> from myhdl import intbv
>>> n = intbv()
>>> hex(n)
'0x0'
>>> n[:] = 0xde
>>> hex(n)
'0xde'
>>> n[:8] = 0xfa
>>> hex(n)
'0xfade'
>>> n[8:] = 0xb4
>>> hex(n)
'0xfab4'
:class:`intbv` objects now have ``min`` and ``max`` attributes that can
be specified at construction time. The meaning is that only values
within ``range(min, max)`` are permitted. The default value for these
attributes is ``None``, meaning “infinite”. For example (traceback
output shortened for clarity):
::
>>> n = intbv(min=-17, max=53)
>>> n
intbv(0)
>>> n.min
-17
>>> n.max
53
>>> n[:] = 28
>>> n
intbv(28)
>>> n[:] = -18
Traceback (most recent call last):
....
ValueError: intbv value -18 < minimum -17
>>> n[:] = 53
Traceback (most recent call last):
....
ValueError: intbv value 53 >= maximum 53
When a slice is taken from an :class:`intbv` object, the return value is
a new :class:`intbv` object with a defined bit width. As in Verilog, the
value of the new :class:`intbv` object is always positive, regardless of
the sign of the original value. In addition, the ``min`` and ``max``
attributes are set implicitly:
::
>>> v = intbv()[6:]
>>> v
intbv(0)
>>> v.min
0
>>> v.max
64
Lastly, a small change was implemented with regard to binary operations.
In previous versions, both numeric and bit-wise operations always
returned a new :class:`intbv` object, even in mixed-mode operations with
:class:`int` objects. This has changed: numeric operations return an
:class:`int`, and bitwise operations return a :class:`intbv`. In this
way, the return value corresponds better to the nature of the operation.
Function :func:`concat()`
==========================
In previous versions, the :class:`intbv` class provided a method. This
method is no longer available. Instead, there is now a :func:`concat()`
function that supports a much broader range of objects.
A function is more natural because MyHDL objects of various types can be
concatenated: :class:`intbv` objects with a defined bit width,
:class:`bool` objects, the corresponding signal objects, and bit
strings. All these objects have a defined bit width. Moreover, the first
argument doesnt need to have a defined bit width. It can also be an
unsized :class:`intbv`, an :class:`int`, a :class:`long`, or a
corresponding signal object. Function :func:`concat()` returns an
:class:`intbv` object.
Python 2.3 support
==================
Python 2.3 was released on July 29, 2003, and as of this writing, it is
the latest stable Python release. MyHDL 0.3 works with both Python 2.2
and Python 2.3. In good Python tradition, MyHDL code developed with
Python 2.2 should run without changes or problems in Python 2.3.
In general, I am not that keen on early upgrading. However, as it
happens, the evolution of Python enables features that are really
important or even crucial to MyHDL. Python 2.2 generators are the best
example: they are the cornerstone of MyHDL. But Python 2.3 also has
significant benefits, which I will summarize below.
First, generators and the ``yield`` statement are a default Python 2.3
feature. This means that statements are no longer required.
Second, Python 2.3 has a :class:`bool` type, which is implemented as a
subtype of :class:`int`. For general Python use, the implications are
rather limited - the main difference is that logical result values will
print as ``False`` and ``True`` instead of ``0`` and ``1``. However, in
MyHDL, I can use the :class:`bool` type to infer a bit width. If a
:class:`Signal` is constructed with a :class:`bool` value, it is a
single bit :class:`Signal`. One application is waveform viewing as in
Section \ `1 <#vcd-output-for-waveform-viewing>`__ In the waveform, note
how single bit signals are displayed as level changes. With Python 2.2,
the waveforms of these signals would only show value changes, which is
not as clear for single bits.
Finally, Python 2.3 is significantly faster. MyHDL code runs 2535%
faster in Python 2.3. This is a very nice speedup compared to the small
burden of a straightforward upgrade.
Python is a very stable language, so upgrading to Python 2.3 is
virtually risk free. Given the additional benefits, I recommend
MyHDL users to do so as soon as possible. For the next major
MyHDLrelease, the new features will become required and only Python 2.3
(and higher) will be supported.
.. |image| image:: ../manual/tbfsm.png

791
doc/source/whatsnew/0.4.rst Normal file
View File

@ -0,0 +1,791 @@
=======================================
New in MyHDL 0.4: Conversion to Verilog
=======================================
:Author: Jan Decaluwe
Introduction
============
MyHDL 0.4 supports the automatic conversion of a subset of MyHDL code to
synthesizable Verilog code. This feature provides a direct path from
Python to an FPGA or ASIC implementation.
MyHDL aims to be a complete design language, for tasks such as high
level modeling and verification, but also for implementation. However,
prior to 0.4 a user had to translate MyHDL code manually to Verilog or
VHDL. Needless to say, this was inconvenient. With MyHDL0.4, this manual
step is no longer necessary.
Solution description
====================
The solution works as follows. The hardware description should be
modeled in MyHDL style, and satisfy certain constraints that are typical
for implementation-oriented hardware modeling. Subsequently, such a
design is converted to an equivalent model in the Verilog language,
using the function :func:`toVerilog` from the MyHDLlibrary. Finally, a
third-party *synthesis tool* is used to convert the Verilog design to a
gate implementation for an ASIC or FPGA. There are a number of Verilog
synthesis tools available, varying in price, capabilities, and target
implementation technology.
The conversion does not start from source files, but from a design that
has been *elaborated* by the Python interpreter. The converter uses the
Python profiler to track the interpreters operation and to infer the
design structure and name spaces. It then selectively compiles pieces of
source code for additional analysis and for conversion. This is done
using the Python compiler package.
Features
========
The design is converted after elaboration
-----------------------------------------
*Elaboration* refers to the initial processing of a hardware description
to achieve a representation of a design instance that is ready for
simulation or synthesis. In particular, structural parameters and
constructs are processed in this step. In MyHDL, the Python interpreter
itself is used for elaboration. A :class:`Simulation` object is
constructed with elaborated design instances as arguments. Likewise, the
Verilog conversion works on an elaborated design instance. The Python
interpreter is thus used as much as possible.
The structural description can be arbitrarily complex and hierarchical
----------------------------------------------------------------------
As the conversion works on an elaborated design instance, any modeling
constraints only apply to the leaf elements of the design structure,
that is, the co-operating generators. In other words, there are no
restrictions on the description of the design structure: Pythons full
power can be used for that purpose. Also, the design hierarchy can be
arbitrarily deep.
Generators are mapped to Verilog always or initial blocks
---------------------------------------------------------
The converter analyzes the code of each generator and maps it to a
Verilog ``always`` blocks if possible, and to an ``initial`` block
otherwise. The converted Verilog design will be a flat “net list of
blocks”.
The Verilog module interface is inferred from signal usage
----------------------------------------------------------
In MyHDL, the input or output direction of interface signals is not
explicitly declared. The converter investigates signal usage in the
design hierarchy to infer whether a signal is used as input, output, or
as an internal signal. Internal signals are given a hierarchical name in
the Verilog output.
Function calls are mapped to a unique Verilog function or task call
-------------------------------------------------------------------
The converter analyzes function calls and function code to see if they
should be mapped to Verilog functions or to tasks. Python functions are
much more powerful than Verilog subprograms; for example, they are
inherently generic, and they can be called with named association. To
support this power in Verilog, a unique Verilog function or task is
generated per Python function call.
If-then-else structures may be mapped to Verilog case statements
----------------------------------------------------------------
Python does not provide a case statement. However, the converter
recognizes if-then-else structures in which a variable is sequentially
compared to items of an enumeration type, and maps such a structure to a
Verilog case statement with the appropriate synthesis attributes.
Choice of encoding schemes for enumeration types
------------------------------------------------
The :func:`enum` function in MyHDL returns an enumeration type. This
function takes an additional parameter ``encoding`` that specifies the
desired encoding in the implementation: binary, one hot, or one cold.
The Verilog converter generates the appropriate code.
The convertible subset
======================
Introduction
------------
Unsurprisingly, not all MyHDL code can be converted to Verilog. In fact,
there are very important restrictions. As the goal of the conversion
functionality is implementation, this should not be a big issue: anyone
familiar with synthesis is used to similar restrictions in the
*synthesizable subset* of Verilog and VHDL. The converter attempts to
issue clear error messages when it encounters a construct that cannot be
converted.
In practice, the synthesizable subset usually refers to RTL synthesis,
which is by far the most popular type of synthesis today. There are
industry standards that define the RTL synthesis subset. However, those
were not used as a model for the restrictions of the MyHDL converter,
but as a minimal starting point. On that basis, whenever it was judged
easy or useful to support an additional feature, this was done. For
example, it is actually easier to convert :keyword:`while` loops than
:keyword:`for` loops even though they are not RTL-synthesizable. As
another example, :keyword:`print` is supported because its so useful
for debugging, even though its not synthesizable. In summary, the
convertible subset is a superset of the standard RTL synthesis subset,
and supports synthesis tools with more advanced capabilities, such as
behavioral synthesis.
Recall that any restrictions only apply to the design post elaboration.
In practice, this means that they apply only to the code of the
generators, that are the leaf functional blocks in a MyHDL design.
Coding style
------------
A natural restriction on convertible code is that it should be written
in MyHDL style: cooperating generators, communicating through signals,
and with ``yield`` statements specifying wait points and resume
conditions. Supported resume conditions are a signal edge, a signal
change, or a tuple of such conditions.
Supported types
---------------
The most important restriction regards object types. Verilog is an
almost typeless language, while Python is strongly (albeit dynamically)
typed. The converter has to infer the types of names used in the code,
and map those names to Verilog variables.
Only a limited amount of types can be converted. Python :class:`int` and
:class:`long` objects are mapped to Verilog integers. All other
supported types are mapped to Verilog regs (or wires), and therefore
need to have a defined bit width. The supported types are the Python
:class:`bool` type, the MyHDL :class:`intbv` type, and MyHDL enumeration
types returned by function :func:`enum`. The latter objects can also be
used as the base object of a :class:`Signal`.
:class:`intbv` objects must be constructed so that a bit width can be
inferred. This can be done by specifying minimum and maximum values,
e.g. as follows:
::
index = intbv(0, min=0, max=2**N)
Alternatively, a slice can be taken from an :class:`intbv` object as
follows:
::
index = intbv(0)[N:]
Such as slice returns a new :class:`intbv` object, with minimum value
``0`` , and maximum value ``2**N``.
Supported statements
--------------------
The following is a list of the statements that are supported by the
Verilog converter, possibly qualified with restrictions or usage notes.
The :keyword:`break` statement.
The :keyword:`continue` statement.
The :keyword:`def` statement.
The :keyword:`for` statement.
The only supported iteration scheme is iterating through sequences
of integers returned by built-in function :func:`range` or
MyHDLfunction :func:`downrange`. The optional :keyword:`else` clause
is not supported.
The :keyword:`if` statement.
:keyword:`if`, :keyword:`elif`, and :keyword:`else` clauses are
fully supported.
The :keyword:`pass` statement.
The :keyword:`print` statement.
When printing an interpolated string, the format specifiers are
copied verbatim to the Verilog output. Printing to a file (with
syntax ``>>``) is not supported.
The :keyword:`raise` statement.
This statement is mapped to Verilog statements that end the
simulation with an error message.
The :keyword:`return` statement.
The :keyword:`yield` statement.
The yielded expression can be a signal, a signal edge as specified
by MyHDL functions :func:`posedge` or :func:`negedge`, or a tuple of
signals and edge specifications.
The :keyword:`while` statement.
The optional :keyword:`else` clause is not supported.
Methodology notes
=================
Simulation
----------
In the Python philosophy, the run-time rules. The Python compiler
doesnt attempt to detect a lot of errors beyond syntax errors, which
given Pythons ultra-dynamic nature would be an almost impossible task
anyway. To verify a Python program, one should run it, preferably using
unit testing to verify each feature.
The same philosophy should be used when converting a MyHDL description
to Verilog: make sure the simulation runs fine first. Although the
converter checks many things and attempts to issue clear error messages,
there is no guarantee that it does a meaningful job unless the
simulation runs fine.
Conversion output verification
------------------------------
It is always prudent to verify the converted Verilog output. To make
this task easier, the converter also generates a test bench that makes
it possible to simulate the Verilog design using the Verilog
co-simulation interface. This permits to verify the Verilog code with
the same test bench used for the MyHDL code. This is also how the
Verilog converter development is being verified.
Assignment issues
-----------------
Name assignment in Python
~~~~~~~~~~~~~~~~~~~~~~~~~
Name assignment in Python is a different concept than in many other
languages. This point is very important for effective modeling in
Python, and even more so for synthesizable MyHDL code. Therefore, the
issues are discussed here explicitly.
Consider the following name assignments:
::
a = 4
a = ``a string''
a = False
In many languages, the meaning would be that an existing variable ``a``
gets a number of different values. In Python, such a concept of a
variable doesnt exist. Instead, assignment merely creates a new binding
of a name to a certain object, that replaces any previous binding. So in
the example, the name ``a`` is bound a number of different objects in
sequence.
The Verilog converter has to investigate name assignment and usage in
MyHDL code, and to map names to Verilog variables. To achieve that, it
tries to infer the type and possibly the bit width of each expression
that is assigned to a name.
Multiple assignments to the same name can be supported if it can be
determined that a consistent type and bit width is being used in the
assignments. This can be done for boolean expressions, numeric
expressions, and enumeration type literals. In Verilog, the
corresponding name is mapped to a single bit ``reg``, an ``integer``, or
a ``reg`` with the appropriate width, respectively.
In other cases, a single assignment should be used when an object is
created. Subsequent value changes are then achieved by modification of
an existing object. This technique should be used for :class:`Signal`
and :class:`intbv` objects.
Signal assignment
~~~~~~~~~~~~~~~~~
Signal assignment in MyHDL is implemented using attribute assignment to
attribute ``next``. Value changes are thus modeled by modification of
the existing object. The converter investigates the :class:`Signal`
object to infer the type and bit width of the corresponding Verilog
variable.
:class:`intbv` objects
~~~~~~~~~~~~~~~~~~~~~~
Type :class:`intbv` is likely to be the workhorse for synthesizable
modeling in MyHDL. An :class:`intbv` instance behaves like a (mutable)
integer whose individual bits can be accessed and modified. Also, it is
possible to constrain its set of values. In addition to error checking,
this makes it possible to infer a bit width, which is required for
implementation.
In Verilog, an :class:`intbv` instance will be mapped to a ``reg`` with
an appropriate width. As noted before, it is not possible to modify its
value using name assignment. In the following, we will show how it can
be done instead. Consider:
::
a = intbv(0)[8:]
This is an :class:`intbv` object with initial value ``0`` and bit width
8. The change its value to ``5``, we can use slice assignment:
::
a[8:] = 5
The same can be achieved by leaving the bit width unspecified, which has
the meaning to change “all” bits:
::
a[:] = 5
Often the new value will depend on the old one. For example, to
increment an :class:`intbv` with the technique above:
::
a[:] = a + 1
Python also provides *augmented* assignment operators, which can be used
to implement in-place operations. These are supported on :class:`intbv`
objects and by the converter, so that the increment can also be done as
follows:
::
a += 1
Converter usage
===============
We will demonstrate the conversion process by showing some examples.
A small design with a single generator
--------------------------------------
Consider the following MyHDL code for an incrementer module:
::
def inc(count, enable, clock, reset, n):
""" Incrementer with enable.
count -- output
enable -- control input, increment when 1
clock -- clock input
reset -- asynchronous reset input
n -- counter max value
"""
def incProcess():
while 1:
yield posedge(clock), negedge(reset)
if reset == ACTIVE_LOW:
count.next = 0
else:
if enable:
count.next = (count + 1) % n
return incProcess()
In Verilog terminology, function :func:`inc` corresponds to a module,
while generator function :func:`incProcess` roughly corresponds to an
always block.
Normally, to simulate the design, we would “elaborate” an instance as
follows:
::
m = 8
n = 2 ** m
count = Signal(intbv(0)[m:])
enable = Signal(bool(0))
clock, reset = [Signal(bool()) for i in range(2)]
inc_inst = inc(count, enable, clock, reset, n=n)
``incinst`` is an elaborated design instance that can be simulated. To
convert it to Verilog, we change the last line as follows:
::
inc_inst = toVerilog(inc, count, enable, clock, reset, n=n)
Again, this creates an instance that can be simulated, but as a side
effect, it also generates an equivalent Verilog module in file . The
Verilog code looks as follows:
::
module inc_inst (
count,
enable,
clock,
reset
);
output [7:0] count;
reg [7:0] count;
input enable;
input clock;
input reset;
always @(posedge clock or negedge reset) begin: _MYHDL1_BLOCK
if ((reset == 0)) begin
count <= 0;
end
else begin
if (enable) begin
count <= ((count + 1) % 256);
end
end
end
endmodule
You can see the module interface and the always block, as expected from
the MyHDL design.
Converting a generator directly
-------------------------------
It is also possible to convert a generator directly. For example,
consider the following generator function:
::
def bin2gray(B, G, width):
""" Gray encoder.
B -- input intbv signal, binary encoded
G -- output intbv signal, gray encoded
width -- bit width
"""
Bext = intbv(0)[width+1:]
while 1:
yield B
Bext[:] = B
for i in range(width):
G.next[i] = Bext[i+1] ^ Bext[i]
As before, you can create an instance and convert to Verilog as follows:
::
width = 8
B = Signal(intbv(0)[width:])
G = Signal(intbv(0)[width:])
bin2gray_inst = toVerilog(bin2gray, B, G, width)
The generated Verilog code looks as follows:
::
module bin2gray_inst (
B,
G
);
input [7:0] B;
output [7:0] G;
reg [7:0] G;
always @(B) begin: _MYHDL1_BLOCK
integer i;
reg [9-1:0] Bext;
Bext[9-1:0] = B;
for (i=0; i<8; i=i+1) begin
G[i] <= (Bext[(i + 1)] ^ Bext[i]);
end
end
endmodule
A hierarchical design
---------------------
The hierarchy of convertible designs can be arbitrarily deep.
For example, suppose we want to design an incrementer with Gray code
output. Using the designs from previous sections, we can proceed as
follows:
::
def GrayInc(graycnt, enable, clock, reset, width):
bincnt = Signal(intbv()[width:])
INC_1 = inc(bincnt, enable, clock, reset, n=2**width)
BIN2GRAY_1 = bin2gray(B=bincnt, G=graycnt, width=width)
return INC_1, BIN2GRAY_1
According to Gray code properties, only a single bit will change in
consecutive values. However, as the ``bin2gray`` module is
combinatorial, the output bits may have transient glitches, which may
not be desirable. To solve this, lets create an additional level of
hierarchy and add an output register to the design. (This will create an
additional latency of a clock cycle, which may not be acceptable, but we
will ignore that here.)
::
def GrayIncReg(graycnt, enable, clock, reset, width):
graycnt_comb = Signal(intbv()[width:])
GRAY_INC_1 = GrayInc(graycnt_comb, enable, clock, reset, width)
def reg():
while 1:
yield posedge(clock)
graycnt.next = graycnt_comb
REG_1 = reg()
return GRAY_INC_1, REG_1
We can convert this hierarchical design as before:
::
width = 8
graycnt = Signal(intbv()[width:])
enable, clock, reset = [Signal(bool()) for i in range(3)]
GRAY_INC_REG_1 = toVerilog(GrayIncReg, graycnt, enable, clock, reset, width)
The Verilog output code looks as follows:
::
module GRAY_INC_REG_1 (
graycnt,
enable,
clock,
reset
);
output [7:0] graycnt;
reg [7:0] graycnt;
input enable;
input clock;
input reset;
reg [7:0] graycnt_comb;
reg [7:0] _GRAY_INC_1_bincnt;
always @(posedge clock or negedge reset) begin: _MYHDL1_BLOCK
if ((reset == 0)) begin
_GRAY_INC_1_bincnt <= 0;
end
else begin
if (enable) begin
_GRAY_INC_1_bincnt <= ((_GRAY_INC_1_bincnt + 1) % 256);
end
end
end
always @(_GRAY_INC_1_bincnt) begin: _MYHDL4_BLOCK
integer i;
reg [9-1:0] Bext;
Bext[9-1:0] = _GRAY_INC_1_bincnt;
for (i=0; i<8; i=i+1) begin
graycnt_comb[i] <= (Bext[(i + 1)] ^ Bext[i]);
end
end
always @(posedge clock) begin: _MYHDL9_BLOCK
graycnt <= graycnt_comb;
end
endmodule
Note that the output is a flat “net list of blocks”, and that
hierarchical signal names are generated as necessary.
Optimizations for finite state machines
---------------------------------------
As often in hardware design, finite state machines deserve special
attention.
In Verilog and VHDL, finite state machines are typically described using
case statements. Python doesnt have a case statement, but the converter
recognizes particular if-then-else structures and maps them to case
statements. This optimization occurs when a variable whose type is an
enumerated type is sequentially tested against enumeration items in an
if-then-else structure. Also, the appropriate synthesis pragmas for
efficient synthesis are generated in the Verilog code.
As a further optimization, function :func:`enum` was enhanced to support
alternative encoding schemes elegantly, using an additional parameter
``encoding``. For example:
::
t_State = enum('SEARCH', 'CONFIRM', 'SYNC', encoding='one_hot')
The default encoding is ``binary``; the other possibilities are
``onehot`` and ``onecold``. This parameter only affects the
conversion output, not the behavior of the type. The generated Verilog
code for case statements is optimized for an efficient implementation
according to the encoding. Note that in contrast, a Verilog designer has
to make nontrivial code changes to implement a different encoding
scheme.
As an example, consider the following finite state machine, whose state
variable uses the enumeration type defined above:
::
FRAME_SIZE = 8
def FramerCtrl(SOF, state, syncFlag, clk, reset_n):
""" Framing control FSM.
SOF -- start-of-frame output bit
state -- FramerState output
syncFlag -- sync pattern found indication input
clk -- clock input
reset_n -- active low reset
"""
index = intbv(0, min=0, max=8) # position in frame
while 1:
yield posedge(clk), negedge(reset_n)
if reset_n == ACTIVE_LOW:
SOF.next = 0
index[:] = 0
state.next = t_State.SEARCH
else:
SOF.next = 0
if state == t_State.SEARCH:
index[:] = 0
if syncFlag:
state.next = t_State.CONFIRM
elif state == t_State.CONFIRM:
if index == 0:
if syncFlag:
state.next = t_State.SYNC
else:
state.next = t_State.SEARCH
elif state == t_State.SYNC:
if index == 0:
if not syncFlag:
state.next = t_State.SEARCH
SOF.next = (index == FRAME_SIZE-1)
else:
raise ValueError("Undefined state")
index[:]= (index + 1) % FRAME_SIZE
The conversion is done as before:
::
SOF = Signal(bool(0))
syncFlag = Signal(bool(0))
clk = Signal(bool(0))
reset_n = Signal(bool(1))
state = Signal(t_State.SEARCH)
framerctrl_inst = toVerilog(FramerCtrl, SOF, state, syncFlag, clk, reset_n)
The Verilog output looks as follows:
::
module framerctrl_inst (
SOF,
state,
syncFlag,
clk,
reset_n
);
output SOF;
reg SOF;
output [2:0] state;
reg [2:0] state;
input syncFlag;
input clk;
input reset_n;
always @(posedge clk or negedge reset_n) begin: _MYHDL1_BLOCK
reg [3-1:0] index;
if ((reset_n == 0)) begin
SOF <= 0;
index[3-1:0] = 0;
state <= 3'b001;
end
else begin
SOF <= 0;
// synthesis parallel_case full_case
casez (state)
3'b??1: begin
index[3-1:0] = 0;
if (syncFlag) begin
state <= 3'b010;
end
end
3'b?1?: begin
if ((index == 0)) begin
if (syncFlag) begin
state <= 3'b100;
end
else begin
state <= 3'b001;
end
end
end
3'b1??: begin
if ((index == 0)) begin
if ((!syncFlag)) begin
state <= 3'b001;
end
end
SOF <= (index == (8 - 1));
end
default: begin
$display("Verilog: ValueError(Undefined state)");
$finish;
end
endcase
index[3-1:0] = ((index + 1) % 8);
end
end
endmodule
Known issues
============
Negative values of :class:`intbv` instances are not supported.
The :class:`intbv` class is quite capable of representing negative
values. However, the ``signed`` type support in Verilog is
relatively recent and mapping to it may be tricky. In my judgment,
this was not the most urgent requirement, so I decided to leave this
for later.
Verilog integers are 32 bit wide
Usually, Verilog integers are 32 bit wide. In contrast, Python is
moving toward integers with undefined width. Python :class:`int` and
:class:`long` variables are mapped to Verilog integers; so for
values wider than 32 bit this mapping is incorrect.
Synthesis pragmas are specified as Verilog comments.
The recommended way to specify synthesis pragmas in Verilog is
through attribute lists. However, my Verilog simulator (Icarus)
doesnt support them for ``case`` statements (to specify
``parallelcase`` and ``fullcase`` pragmas). Therefore, I still used
the old but deprecated method of synthesis pragmas in Verilog
comments.
Inconsistent place of the sensitivity list inferred from ``alwayscomb``.
The semantics of ``alwayscomb``, both in Verilog and MyHDL, is to
have an implicit sensitivity list at the end of the code. However,
this may not be synthesizable. Therefore, the inferred sensitivity
list is put at the top of the corresponding ``always`` block. This
may cause inconsistent behavior at the start of the simulation. The
workaround is to create events at time 0.
Non-blocking assignments to task arguments dont work.
I didnt get non-blocking (signal) assignments to task arguments to
work. I dont know yet whether the issue is my own, a Verilog issue,
or an issue with my Verilog simulator Icarus. Ill need to check
this further.

View File

@ -1,426 +0,0 @@
# Makefile for Python documentation
# ---------------------------------
#
# See also the README file.
#
# This is a bit of a mess. The documents are identified by short names:
# api -- Python/C API Reference Manual
# doc -- Documenting Python
# ext -- Extending and Embedding the Python Interpreter
# lib -- Library Reference Manual
# mac -- Macintosh Library Modules
# ref -- Python Reference Manual
# tut -- Python Tutorial
# inst -- Installing Python Modules
# dist -- Distributing Python Modules
#
# The LaTeX sources for each of these documents are in subdirectories
# with the three-letter designations above as the directory names.
#
# The main target creates HTML for each of the documents. You can
# also do "make lib" (etc.) to create the HTML versions of individual
# documents.
#
# The document classes and styles are in the texinputs/ directory.
# These define a number of macros that are similar in name and intent
# as macros in Texinfo (e.g. \code{...} and \emph{...}), as well as a
# number of environments for formatting function and data definitions.
# Documentation for the macros is included in "Documenting Python"; see
# http://www.python.org/doc/current/doc/doc.html, or the sources for
# this document in the doc/ directory.
#
# Everything is processed by LaTeX. See the file `README' for more
# information on the tools needed for processing.
#
# There's a problem with generating the index which has been solved by
# a sed command applied to the index file. The shell script fix_hack
# does this (the Makefile takes care of calling it).
#
# Additional targets attempt to convert selected LaTeX sources to
# various other formats. These are generally site specific because
# the tools used are all but universal. These targets are:
#
# ps -- convert all documents from LaTeX to PostScript
# pdf -- convert all documents from LaTeX to the
# Portable Document Format
#
# See the README file for more information on these targets.
#
# The formatted output is located in subdirectories. For PDF and
# PostScript, look in the paper-$(PAPER)/ directory. For HTML, look in
# the html/ directory. If you want to fix the GNU info process, look
# in the info/ directory; please send patches to python-docs@python.org.
# This Makefile only includes information on how to perform builds; for
# dependency information, see Makefile.deps.
# Customization -- you *may* have to edit this
# You could set this to a4:
PAPER=a4
# Ideally, you shouldn't need to edit beyond this point
INFODIR= info
TOOLSDIR= tools
# This is the *documentation* release, and is used to construct the file
# names of the downloadable tarballs.
RELEASE=0.2
PYTHON= python
DVIPS= dvips -N0 -t $(PAPER)
MKDVI= $(PYTHON) ../tools/mkhowto --paper=$(PAPER) --dvi
MKHTML= $(PYTHON) tools/mkhowto --html --about html/myabout.dat \
--iconserver ../icons --favicon ../icons/pyfav.gif \
--address $(MYHDLDOCS) --up-link ../Overview.html \
--up-title "Overview" \
--dvips-safe
MKPDF= $(PYTHON) ../tools/mkhowto -l --paper=$(PAPER) --pdf
MKPS= $(PYTHON) ../tools/mkhowto --paper=$(PAPER) --ps
BUILDINDEX=$(TOOLSDIR)/buildindex.py
MYHDLDOCS="<i><a href=\"about.html\">About this document</a></i>"
HTMLBASE= file:`pwd`
# The emacs binary used to build the info docs. GNU Emacs 21 is required.
EMACS= emacs
# The end of this should reflect the major/minor version numbers of
# the release:
WHATSNEW=whatsnew04
# what's what
MANDVIFILES= paper-$(PAPER)/MyHDL.dvi
HOWTODVIFILES= paper-$(PAPER)/whatsnew03.dvi \
paper-$(PAPER)/whatsnew04.dvi
MANPDFFILES= paper-$(PAPER)/MyHDL.pdf
HOWTOPDFFILES= paper-$(PAPER)/whatsnew03.pdf \
paper-$(PAPER)/whatsnew04.pdf
MANPSFILES= paper-$(PAPER)/MyHDL.ps
HOWTOPSFILES= paper-$(PAPER)/whatsnew03.ps \
paper-$(PAPER)/whatsnew04.ps
DVIFILES= $(MANDVIFILES) $(HOWTODVIFILES)
PDFFILES= $(MANPDFFILES) $(HOWTOPDFFILES)
PSFILES= $(MANPSFILES) $(HOWTOPSFILES)
HTMLCSSFILES=html/manual/MyHDL.css \
html/whatsnew03/whatsnew03.css \
html/whatsnew04/whatsnew04.css
ALLCSSFILES=$(HTMLCSSFILES)
INDEXFILES=html/manual/MyHDL.html \
html/whatsnew03/whatsnew03.html \
html/whatsnew04/whatsnew04.html
ALLHTMLFILES=$(INDEXFILES)
COMMONPERL= perl/manual.perl perl/python.perl perl/l2hinit.perl
include Makefile.deps
# These must be declared phony since there
# are directories with matching names:
.PHONY: manual
.PHONY: html info
# Main target
default: all
all: html pdf
full: all ps
dvi: $(DVIFILES)
pdf: $(PDFFILES)
ps: $(PSFILES)
world: ps pdf html distfiles
# Rules to build PostScript and PDF formats
.SUFFIXES: .pdf .dvi .ps
#.dvi.ps:
# $(DVIPS) -o $@ $<
#.pdf.ps:
# pdf2ps $< $@
.pdf.ps:
xpdf $<
# Targets for each document:
# MyHDL Manual
paper-$(PAPER)/MyHDL.dvi: $(MANUALFILES)
cd paper-$(PAPER) && $(MKDVI) ../manual/MyHDL.tex
paper-$(PAPER)/MyHDL.pdf: $(MANUALFILES)
cd paper-$(PAPER) && $(MKPDF) ../manual/MyHDL.tex
# What's new
# in 0.3
paper-$(PAPER)/whatsnew03.dvi: whatsnew03/whatsnew03.tex
cd paper-$(PAPER) && $(MKDVI) ../whatsnew03/whatsnew03.tex
paper-$(PAPER)/whatsnew03.pdf: whatsnew03/whatsnew03.tex
cd paper-$(PAPER) && $(MKPDF) ../whatsnew03/whatsnew03.tex
# What's new
# in 0.4
paper-$(PAPER)/whatsnew04.dvi: whatsnew04/whatsnew04.tex whatsnew04/conversion.tex
cd paper-$(PAPER) && $(MKDVI) ../whatsnew04/whatsnew04.tex
paper-$(PAPER)/whatsnew04.pdf: whatsnew04/whatsnew04.tex whatsnew04/conversion.tex
cd paper-$(PAPER) && $(MKPDF) ../whatsnew04/whatsnew04.tex
# The remaining part of the Makefile is concerned with various
# conversions, as described above. See also the README file.
info:
cd $(INFODIR) && $(MAKE) EMACS=$(EMACS)
# Targets to convert the manuals to HTML using Nikos Drakos' LaTeX to
# HTML converter. For more info on this program, see
# <URL:http://cbl.leeds.ac.uk/nikos/tex2html/doc/latex2html/latex2html.html>.
# Note that LaTeX2HTML inserts references to an icons directory in
# each page that it generates. I have placed a copy of this directory
# in the distribution to simplify the process of creating a
# self-contained HTML distribution; for this purpose I have also added
# a (trivial) index.html. Change the definition of $ICONSERVER in
# perl/l2hinit.perl to use a different location for the icons directory.
# If you have the standard LaTeX2HTML icons installed, the versions shipped
# with this documentation should be stored in a separate directory and used
# instead. The standard set does *not* include all the icons used in the
# Python documentation.
$(ALLCSSFILES): html/style.css
cp $< $@
$(INDEXFILES): $(COMMONPERL) html/about.dat tools/node2label.pl
html/acks.html: ACKS $(TOOLSDIR)/support.py $(TOOLSDIR)/mkackshtml
$(PYTHON) $(TOOLSDIR)/mkackshtml --address $(PYTHONDOCS) \
--favicon icons/pyfav.gif \
--output html/acks.html <ACKS
# html/index.html is dependent on $(INDEXFILES) since we want the date
# on the front index to be updated whenever any of the child documents
# are updated and boilerplate.tex uses \today as the date. The index
# files are not used to actually generate content.
BOILERPLATE=texinputs/boilerplate.tex
html/index.html: $(INDEXFILES)
html/index.html: html/index.html.in $(BOILERPLATE) tools/rewrite.py
$(PYTHON) tools/rewrite.py $(BOILERPLATE) \
RELEASE=$(RELEASE) WHATSNEW=$(WHATSNEW) \
<$< >$@
html/modindex.html:
touch html/modindex.html
html: $(ALLHTMLFILES) $(HTMLCSSFILES)
manual: html/manual/MyHDL.html html/manual/MyHDL.css
html/manual/MyHDL.html: $(MANUALFILES)
$(MKHTML) --dir html/manual manual/MyHDL.tex
whatsnew03: html/whatsnew03/whatsnew03.html
html/whatsnew03/whatsnew03.html: whatsnew03/whatsnew03.tex
$(MKHTML) --dir html/whatsnew03 whatsnew03/whatsnew03.tex
whatsnew04: html/whatsnew04/whatsnew04.html
html/whatsnew04/whatsnew04.html: whatsnew04/whatsnew04.tex whatsnew04/conversion.tex
$(MKHTML) --dir html/whatsnew04 whatsnew04/whatsnew04.tex
# webchecker needs an extra flag to process the huge index from the libref
WEBCHECKER=$(PYTHON) ../Tools/webchecker/webchecker.py
HTMLBASE= file:`pwd`/html
webcheck: $(ALLHTMLFILES)
$(WEBCHECKER) $(HTMLBASE)/manual/
$(WEBCHECKER) $(HTMLBASE)/doc/
fastwebcheck: $(ALLHTMLFILES)
$(WEBCHECKER) -x $(HTMLBASE)/manual/
$(WEBCHECKER) -x $(HTMLBASE)/doc/
# Release packaging targets:
paper-$(PAPER)/README: $(PSFILES) $(TOOLSDIR)/getpagecounts
cd paper-$(PAPER) && ../$(TOOLSDIR)/getpagecounts -r $(RELEASE) >../$@
info-$(RELEASE).tgz: info
cd $(INFODIR) && tar cf - README python.dir python-*.info* \
| gzip -9 >$@
info-$(RELEASE).tar.bz2: info
cd $(INFODIR) && tar cf - README python.dir python-*.info* \
| bzip2 -9 >$@
latex-$(RELEASE).tgz:
$(PYTHON) $(TOOLSDIR)/mksourcepkg --gzip $(RELEASE)
latex-$(RELEASE).tar.bz2:
$(PYTHON) $(TOOLSDIR)/mksourcepkg --bzip2 $(RELEASE)
latex-$(RELEASE).zip:
rm -f $@
$(PYTHON) $(TOOLSDIR)/mksourcepkg --zip $(RELEASE)
pdf-$(PAPER)-$(RELEASE).tar: $(PDFFILES)
rm -f $@
mkdir Python-Docs-$(RELEASE)
cp paper-$(PAPER)/*.pdf Python-Docs-$(RELEASE)
tar cf $@ Python-Docs-$(RELEASE)
rm -r Python-Docs-$(RELEASE)
pdf-$(PAPER)-$(RELEASE).tgz: pdf-$(PAPER)-$(RELEASE).tar
gzip -9 <$? >$@
pdf-$(PAPER)-$(RELEASE).tar.bz2: pdf-$(PAPER)-$(RELEASE).tar
bzip2 -9 <$? >$@
pdf-$(PAPER)-$(RELEASE).zip: pdf
rm -f $@
mkdir Python-Docs-$(RELEASE)
cp paper-$(PAPER)/*.pdf Python-Docs-$(RELEASE)
zip -q -r -9 $@ Python-Docs-$(RELEASE)
rm -r Python-Docs-$(RELEASE)
postscript-$(PAPER)-$(RELEASE).tar: $(PSFILES) paper-$(PAPER)/README
rm -f $@
mkdir Python-Docs-$(RELEASE)
cp paper-$(PAPER)/*.ps Python-Docs-$(RELEASE)
cp paper-$(PAPER)/README Python-Docs-$(RELEASE)
tar cf $@ Python-Docs-$(RELEASE)
rm -r Python-Docs-$(RELEASE)
postscript-$(PAPER)-$(RELEASE).tar.bz2: postscript-$(PAPER)-$(RELEASE).tar
bzip2 -9 <$< >$@
postscript-$(PAPER)-$(RELEASE).tgz: postscript-$(PAPER)-$(RELEASE).tar
gzip -9 <$< >$@
postscript-$(PAPER)-$(RELEASE).zip: $(PSFILES) paper-$(PAPER)/README
rm -f $@
mkdir Python-Docs-$(RELEASE)
cp paper-$(PAPER)/*.ps Python-Docs-$(RELEASE)
cp paper-$(PAPER)/README Python-Docs-$(RELEASE)
zip -q -r -9 $@ Python-Docs-$(RELEASE)
rm -r Python-Docs-$(RELEASE)
HTMLPKGFILES=*.html */*.css */*.html */*.gif */*.txt
html-$(RELEASE).tar: $(ALLHTMLFILES) $(HTMLCSSFILES)
mkdir Python-Docs-$(RELEASE)
cd html && tar cf ../temp.tar $(HTMLPKGFILES)
cd Python-Docs-$(RELEASE) && tar xf ../temp.tar
rm temp.tar
tar cf html-$(RELEASE).tar Python-Docs-$(RELEASE)
rm -r Python-Docs-$(RELEASE)
html-$(RELEASE).tgz: html-$(RELEASE).tar
gzip -9 <$? >$@
html-$(RELEASE).tar.bz2: html-$(RELEASE).tar
bzip2 -9 <$? >$@
html-$(RELEASE).zip: $(ALLHTMLFILES) $(HTMLCSSFILES)
rm -f $@
mkdir Python-Docs-$(RELEASE)
cd html && tar cf ../temp.tar $(HTMLPKGFILES)
cd Python-Docs-$(RELEASE) && tar xf ../temp.tar
rm temp.tar
zip -q -r -9 $@ Python-Docs-$(RELEASE)
rm -r Python-Docs-$(RELEASE)
# convenience targets:
tarhtml: html-$(RELEASE).tgz
tarinfo: info-$(RELEASE).tgz
tarps: postscript-$(PAPER)-$(RELEASE).tgz
tarpdf: pdf-$(PAPER)-$(RELEASE).tgz
tarlatex: latex-$(RELEASE).tgz
tarballs: tarpdf tarps tarhtml
ziphtml: html-$(RELEASE).zip
zipps: postscript-$(PAPER)-$(RELEASE).zip
zippdf: pdf-$(PAPER)-$(RELEASE).zip
ziplatex: latex-$(RELEASE).zip
zips: zippdf zipps ziphtml
bziphtml: html-$(RELEASE).tar.bz2
bzipinfo: info-$(RELEASE).tar.bz2
bzipps: postscript-$(PAPER)-$(RELEASE).tar.bz2
bzippdf: pdf-$(PAPER)-$(RELEASE).tar.bz2
bziplatex: latex-$(RELEASE).tar.bz2
bzips: bzippdf bzipps bziphtml
disthtml: tarhtml bziphtml ziphtml
distinfo: tarinfo bzipinfo
distps: tarps bzipps zipps
distpdf: tarpdf bzippdf zippdf
distlatex: tarlatex bziplatex ziplatex
paperdist: distpdf distps
edist: disthtml
distfiles: paperdist edist
$(TOOLSDIR)/mksourcepkg --all $(RELEASE)
$(TOOLSDIR)/mkpkglist >pkglist.html
# Housekeeping targets
# Remove temporary files; all except the following:
# - sources: .tex, .bib, .sty, *.cls
# - useful results: .dvi, .pdf, .ps, .texi, .info
clean:
rm -f html-$(RELEASE).tar
cd $(INFODIR) && $(MAKE) clean
# Remove temporaries as well as final products
clobber:
rm -f html-$(RELEASE).tar
rm -f html-$(RELEASE).tgz info-$(RELEASE).tgz
rm -f pdf-$(RELEASE).tgz postscript-$(RELEASE).tgz
rm -f latex-$(RELEASE).tgz html-$(RELEASE).zip
rm -f pdf-$(RELEASE).zip postscript-$(RELEASE).zip
rm -f $(DVIFILES) $(PSFILES) $(PDFFILES)
cd $(INFODIR) && $(MAKE) clobber
rm -f paper-$(PAPER)/*.tex paper-$(PAPER)/*.ind paper-$(PAPER)/*.idx
rm -f paper-$(PAPER)/*.l2h paper-$(PAPER)/*.how paper-$(PAPER)/README
rm -rf html/index.html html/modindex.html html/acks.html
rm -rf html/manual/
rm -rf html/whatsnew03/
rm -rf html/whatsnew04/
realclean distclean: clobber

View File

@ -1,34 +0,0 @@
# LaTeX source dependencies.
COMMONSTYLES= texinputs/python.sty \
texinputs/pypaper.sty
INDEXSTYLES=texinputs/python.ist
COMMONTEX= texinputs/copyright.tex \
texinputs/license.tex \
texinputs/boilerplate.tex
MANSTYLES= texinputs/fncychap.sty \
texinputs/manual.cls \
$(COMMONSTYLES)
HOWTOSTYLES= texinputs/howto.cls \
$(COMMONSTYLES)
DOCFILES= $(HOWTOSTYLES) \
texinputs/boilerplate.tex \
texinputs/ltxmarkup.sty \
doc/doc.tex
# LaTeX source files for the MyHDL Manual
MANUALFILES= $(MANSTYLES) $(INDEXSTYLES) $(COMMONTEX) \
manual/MyHDL.tex \
manual/background.tex \
manual/intro.tex \
manual/modeling.tex \
manual/unittest.tex \
manual/cosimulation.tex \
manual/conversion.tex \
manual/reference.tex

View File

@ -1,231 +0,0 @@
Python standard documentation -- in LaTeX
-----------------------------------------
This directory contains the LaTeX sources to the Python documentation
and tools required to support the formatting process. The documents
now require LaTeX2e; LaTeX 2.09 compatibility has been dropped.
If you don't have LaTeX, or if you'd rather not format the
documentation yourself, you can ftp a tar file containing HTML, PDF,
or PostScript versions of all documents. Additional formats may be
available. These should be in the same place where you fetched the
main Python distribution (try <http://www.python.org/> or
<ftp://ftp.python.org/pub/python/>).
The following are the LaTeX source files:
api/*.tex Python/C API Reference Manual
doc/*.tex Documenting Python
ext/*.tex Extending and Embedding the Python Interpreter
lib/*.tex Python Library Reference
mac/*.tex Macintosh Library Modules
ref/*.tex Python Reference Manual
tut/*.tex Python Tutorial
inst/*.tex Installing Python Modules
dist/*.tex Distributing Python Modules
Most use the "manual" document class and "python" package, derived from
the old "myformat.sty" style file. The Macintosh Library Modules
document uses the "howto" document class instead. These contains many
macro definitions useful in documenting Python, and set some style
parameters.
There's a Makefile to call LaTeX and the other utilities in the right
order and the right number of times. By default, it will build the
HTML version of the documnetation, but DVI, PDF, and PostScript can
also be made. To view the generated HTML, point your favorite browser
at the top-level index (html/index.html) after running "make".
The Makefile can also produce DVI files for each document made; to
preview them, use xdvi. PostScript is produced by the same Makefile
target that produces the DVI files. This uses the dvips tool.
Printing depends on local conventions; at our site, we use lpr. For
example:
make paper-letter/lib.ps # create lib.dvi and lib.ps
xdvi paper-letter/lib.dvi # preview lib.dvi
lpr paper-letter/lib.ps # print on default printer
What if I find a bug?
---------------------
First, check that the bug is present in the development version of the
documentation at <http://python.sourceforge.net/devel-docs/>; we may
have already fixed it.
If we haven't, tell us about it. We'd like the documentation to be
complete and accurate, but have limited time. If you discover any
inconsistencies between the documentation and implementation, or just
have suggestions as to how to improve the documentation, let is know!
Specific bugs and patches should be reported using our bug & patch
databases at:
http://sourceforge.net/projects/python
Other suggestions or questions should be sent to the Python
Documentation Team:
python-docs@python.org
Thanks!
What happened to the Macintosh chapter of the Python Library Reference?
-----------------------------------------------------------------------
The directory mac/ contains the LaTeX sources for the "Macintosh
Library Modules" manual; this is built using the standard build
targets, so check the proper output directory for your chosen format
and paper size.
What tools do I need?
---------------------
You need to install Python; some of the scripts used to produce the
documentation are written in Python. You don't need this
documentation to install Python; instructions are included in the
README file in the Python distribution.
The simplest way to get the rest of the tools in the configuration we
used is to install the teTeX TeX distribution, versions 0.9 or newer.
More information is available on teTeX at <http://www.tug.org/tetex/>.
This is a Unix-only TeX distribution at this time. This documentation
release was tested with the 1.0.7 release, but there have been no
substantial changes since late in the 0.9 series, which we used
extensively for previous versions without any difficulty.
If you don't want to get teTeX, here is what you'll need:
To create DVI, PDF, or PostScript files:
- LaTeX2e, 1995/12/01 or newer. Older versions are likely to
choke.
- makeindex. This is used to produce the indexes for the
library reference and Python/C API reference.
To create PDF files:
- pdflatex. We used the one in the teTeX distribution (pdfTeX
version 3.14159-13d (Web2C 7.3.1) at the time of this
writing). Versions even a couple of patchlevels earlier are
highly likely to fail due to syntax changes for some of the
pdftex primitives.
To create PostScript files:
- dvips. Most TeX installations include this. If you don't
have one, check CTAN (<ftp://ctan.tug.org/tex-archive/>).
To create info files:
Note that info support is currently being revised using new
conversion tools by Michael Ernst <mernst@cs.washington.edu>.
- makeinfo. This is available from any GNU mirror.
- emacs or xemacs. Emacs is available from the same place as
makeinfo, and xemacs is available from ftp.xemacs.org.
- Perl. Find the software at
<http://language.perl.com/info/software.html>.
- HTML::Element. If you don't have this installed, you can get
this from CPAN. Use the command:
perl -e 'use CPAN; CPAN::install("HTML::Element");'
You may need to be root to do this.
To create HTML files:
- Perl 5.004_04 or newer. Find the software at
<http://language.perl.com/info/software.html>.
- LaTeX2HTML 99.2b8 or newer. Older versions are not
supported; each version changes enough that supporting
multiple versions is not likely to work. Many older
versions don't work with Perl 5.6 as well. This also screws
up code fragments. ;-( Releases are available at:
<http://www.latex2html.org/>.
What if Times fonts are not available?
--------------------------------------
As distributed, the LaTeX documents use PostScript Times fonts. This
is done since they are much better looking and produce smaller
PostScript files. If, however, your TeX installation does not support
them, they may be easily disabled. Edit the file
texinputs/pypaper.sty and comment out the line that starts
"\RequirePackage{times}" by inserting a "%" character at the beginning
of the line. If you're formatting the docs for A4 paper instead of
US-Letter paper, change paper-a4/pypaper.sty instead. An alternative
is to install the right fonts and LaTeX style file.
What if I want to use A4 paper?
-------------------------------
Instead of building the PostScript by giving the command "make ps",
give the command "make PAPER=a4 ps"; the output will be produced in
the paper-a4/ subdirectory. (You can use "make PAPER=a4 pdf" if you'd
rather have PDF output.)
Making HTML files
-----------------
The LaTeX documents can be converted to HTML using Nikos Drakos'
LaTeX2HTML converter. See the Makefile; after some twiddling, "make"
should do the trick.
What else is in here?
---------------------
There is a new LaTeX document class called "howto". This is used for
the new series of Python HOWTO documents which is being coordinated by
Andrew Kuchling <akuchlin@mems-exchange.org>. The file
templates/howto.tex is a commented example which may be used as a
template. A Python script to "do the right thing" to format a howto
document is included as tools/mkhowto. These documents can be
formatted as HTML, PDF, PostScript, or ASCII files. Use "mkhowto
--help" for information on using the formatting tool.
For authors of module documentation, there is a file
templates/module.tex which may be used as a template for a module
section. This may be used in conjunction with either the howto or
manual document class. Create the documentation for a new module by
copying the template to lib<mymodule>.tex and editing according to the
instructions in the comments.
Documentation on the authoring Python documentation, including
information about both style and markup, is available in the
"Documenting Python" manual.
Copyright notice
================
The Python source is copyrighted, but you can freely use and copy it
as long as you don't change or remove the copyright notice:
----------------------------------------------------------------------
Copyright (c) 2000-2002 Python Software Foundation.
All rights reserved.
Copyright (c) 2000 BeOpen.com.
All rights reserved.
Copyright (c) 1995-2000 Corporation for National Research Initiatives.
All rights reserved.
Copyright (c) 1991-1995 Stichting Mathematisch Centrum.
All rights reserved.
See the file "texinputs/license.tex" for information on usage and
redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
----------------------------------------------------------------------

View File

@ -1,8 +0,0 @@
Printing problems with pdf
--------------------------
Apparently there is a problem with Acrobat5 and the Python
documentation flow I am using. The symptom is that the some pages of
the MyHDL.pdf file don't print correctly. The workaround is to print
from Acrobat4, xpdf or ghostview. Alternatively, you can try the
postscript file MyHDL.ps.

View File

@ -1,24 +0,0 @@
<p> This document was generated using the <a
href="http://saftsack.fs.uni-bayreuth.de/;SPMtilde;latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> translator.
</p>
<p> <a
href="http://saftsack.fs.uni-bayreuth.de/;SPMtilde;latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> is Copyright &copy;
1993, 1994, 1995, 1996, 1997, <a
href="http://cbl.leeds.ac.uk/nikos/personal.html">Nikos
Drakos</a>, Computer Based Learning Unit, University of
Leeds, and Copyright &copy; 1997, 1998, <a
href="http://www.maths.mq.edu.au/;SPMtilde;ross/">Ross
Moore</a>, Mathematics Department, Macquarie University,
Sydney.
</p>
<p> The application of <a
href="http://saftsack.fs.uni-bayreuth.de/;SPMtilde;latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> to the Python
documentation has been heavily tailored by Fred L. Drake,
Jr. Original navigation icons were contributed by Christopher
Petrilli.
</p>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 649 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 529 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 253 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 511 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 316 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 577 B

View File

@ -1,38 +0,0 @@
<p> This document was generated using the <a
href="http://saftsack.fs.uni-bayreuth.de/;SPMtilde;latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> translator.
</p>
<p> <a
href="http://saftsack.fs.uni-bayreuth.de/;SPMtilde;latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> is Copyright &copy;
1993, 1994, 1995, 1996, 1997, <a
href="http://cbl.leeds.ac.uk/nikos/personal.html">Nikos
Drakos</a>, Computer Based Learning Unit, University of
Leeds, and Copyright &copy; 1997, 1998, <a
href="http://www.maths.mq.edu.au/;SPMtilde;ross/">Ross
Moore</a>, Mathematics Department, Macquarie University,
Sydney.
</p>
<p> The application of <a
href="http://saftsack.fs.uni-bayreuth.de/;SPMtilde;latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> to the Python
documentation has been heavily tailored by Fred L. Drake,
Jr. Original navigation icons were contributed by Christopher
Petrilli.
</p>
<p> Jan Decaluwe reused the Python documentation flow to generate
the MyHDL documentation as much as he could; his sincere thanks and
appreciation go out to all who contributed to this flow and
made this part of his life so much easier.
</p>
<hr>
<h2>Comments and Questions</h2>
<p> General comments, questions and bug reports regarding this document
may be sent to <a href="mailto:jan@jandecaluwe.com">Jan Decaluwe</a>.
</p>

View File

@ -1,157 +0,0 @@
/*
* The first part of this is the standard CSS generated by LaTeX2HTML,
* with the "empty" declarations removed.
*/
/* Century Schoolbook font is very similar to Computer Modern Math: cmmi */
.math { font-family: "Century Schoolbook", serif; }
.math i { font-family: "Century Schoolbook", serif;
font-weight: bold }
.boldmath { font-family: "Century Schoolbook", serif;
font-weight: bold }
/*
* Implement both fixed-size and relative sizes.
*
* I think these can be safely removed, as it doesn't appear that
* LaTeX2HTML ever generates these, even though these are carried
* over from the LaTeX2HTML stylesheet.
*/
small.xtiny { font-size : xx-small; }
small.tiny { font-size : x-small; }
small.scriptsize { font-size : smaller; }
small.footnotesize { font-size : small; }
big.xlarge { font-size : large; }
big.xxlarge { font-size : x-large; }
big.huge { font-size : larger; }
big.xhuge { font-size : xx-large; }
/*
* Document-specific styles come next;
* these are added for the Python documentation.
*
* Note that the size specifications for the H* elements are because
* Netscape on Solaris otherwise doesn't get it right; they all end up
* the normal text size.
*/
body { color: #000000;
background-color: #ffffff; }
a:active { color: #ff0000; }
a:link:hover { background-color: #bbeeff; }
a:visited:hover { background-color: #bbeeff; }
a:visited { color: #551a8b; }
a:link { color: #0000bb; }
h1, h2, h3, h4, h5, h6 { font-family: avantgarde, sans-serif;
font-weight: bold; }
h1 { font-size: 180%; }
h2 { font-size: 150%; }
h3, h4 { font-size: 120%; }
/* LaTeX2HTML insists on inserting <br> elements into headers which
* are marked with \label. This little bit of CSS magic ensures that
* these elements don't cause spurious whitespace to be added.
*/
h1>br, h2>br, h3>br,
h4>br, h5>br, h6>br { display: none; }
code, tt { font-family: "lucida typewriter", lucidatypewriter,
monospace; }
var { font-family: times, serif;
font-style: italic;
font-weight: normal; }
.typelabel { font-family: lucida, sans-serif; }
.navigation td { background-color: #99ccff;
font-weight: bold;
font-family: avantgarde, sans-serif;
font-size: 110%; }
div.warning { background-color: #fffaf0;
border: thin solid black;
padding: 1em;
margin-left: 2em;
margin-right: 2em; }
div.warning .label { font-family: sans-serif;
font-size: 110%;
margin-right: 0.5em; }
div.note { background-color: #fffaf0;
border: thin solid black;
padding: 1em;
margin-left: 2em;
margin-right: 2em; }
div.note .label { margin-right: 0.5em;
font-family: sans-serif; }
.release-info { font-style: italic; }
.titlegraphic { vertical-align: top; }
.verbatim pre { color: #00008b;
font-family: monospace;
font-size: 100%; }
.verbatim { margin-left: 2em; }
.verbatim .footer { padding: 0.05in;
font-size: 85%;
background-color: #99ccff;
margin-right: 0.5in; }
.grammar { background-color: #99ccff;
margin-right: 0.5in;
padding: 0.05in; }
.grammar-footer { padding: 0.05in;
font-size: 85%; }
.productions { background-color: #bbeeff; }
.productions a:active { color: #ff0000; }
.productions a:link:hover { background-color: #99ccff; }
.productions a:visited:hover { background-color: #99ccff; }
.productions a:visited { color: #551a8b; }
.productions a:link { color: #0000bb; }
.productions table { vertical-align: baseline; }
.email { font-family: avantgarde, sans-serif; }
.mailheader { font-family: avantgarde, sans-serif; }
.mimetype { font-family: avantgarde, sans-serif; }
.newsgroup { font-family: avantgarde, sans-serif; }
.url { font-family: avantgarde, sans-serif; }
.file { font-family: avantgarde, sans-serif; }
.menuselection { font-family: avantgarde, sans-serif; }
.tableheader { background-color: #99ccff;
font-family: avantgarde, sans-serif; }
.refcount-info { font-style: italic; }
.refcount-info .value { font-weight: bold;
color: #006600; }
/*
* Some decoration for the "See also:" blocks, in part inspired by some of
* the styling on Lars Marius Garshol's XSA pages.
* (The blue in the navigation bars is #99CCFF.)
*/
.seealso { background-color: #fffaf0;
border: thin solid black;
padding: 0pt 1em 4pt 1em; }
.seealso .heading { font-size: 110%; }
/*
* Class 'availability' is used for module availability statements at
* the top of modules.
*/
.availability .platform { font-weight: bold; }
/*
* Some specialization for printed output.
*/
@media print {
.online-navigation { display: none; }
}

View File

@ -1,2 +0,0 @@
*.info*
*.texi

View File

@ -1,70 +0,0 @@
# Generate the Python "info" documentation.
TOPDIR=..
TOOLSDIR=$(TOPDIR)/tools
HTMLDIR=$(TOPDIR)/html
# The emacs binary used to build the info docs. GNU Emacs 21 is required.
EMACS=emacs
MKINFO=$(TOOLSDIR)/mkinfo
SCRIPTS=$(TOOLSDIR)/checkargs.pm $(TOOLSDIR)/mkinfo $(TOOLSDIR)/py2texi.el
# set VERSION to code the VERSION number into the info file name
# allowing installation of more than one set of python info docs
# into the same directory
VERSION=
all: check-emacs-version \
python$(VERSION)-api.info python$(VERSION)-ext.info \
python$(VERSION)-lib.info python$(VERSION)-ref.info \
python$(VERSION)-tut.info python$(VERSION)-dist.info
# python$(VERSION)-doc.info python$(VERSION)-inst.info
# python$(VERSION)-mac.info
check-emacs-version:
@v="`$(EMACS) --version 2>&1 | egrep '^(GNU |X)Emacs [12]*'`"; \
if `echo "$$v" | grep '^GNU Emacs 21' >/dev/null 2>&1`; then \
echo "Using $(EMACS) to build the info docs"; \
else \
echo "GNU Emacs 21 is required to build the info docs"; \
echo "Found $$v"; \
false; \
fi
python$(VERSION)-api.info: ../api/api.tex $(SCRIPTS)
EMACS=$(EMACS) $(MKINFO) $< $*.texi $@
python$(VERSION)-ext.info: ../ext/ext.tex $(SCRIPTS)
EMACS=$(EMACS) $(MKINFO) $< $*.texi $@
python$(VERSION)-lib.info: ../lib/lib.tex $(SCRIPTS)
EMACS=$(EMACS) $(MKINFO) $< $*.texi $@
# Not built by default; the conversion doesn't really handle it well.
python$(VERSION)-mac.info: ../mac/mac.tex $(SCRIPTS)
EMACS=$(EMACS) $(MKINFO) $< $*.texi $@
python$(VERSION)-ref.info: ../ref/ref.tex $(SCRIPTS)
EMACS=$(EMACS) $(MKINFO) $< $*.texi $@
python$(VERSION)-tut.info: ../tut/tut.tex $(SCRIPTS)
EMACS=$(EMACS) $(MKINFO) $< $*.texi $@
# Not built by default; the conversion doesn't handle it at all.
python$(VERSION)-doc.info: ../doc/doc.tex $(SCRIPTS)
EMACS=$(EMACS) $(MKINFO) $< $*.texi $@
python$(VERSION)-dist.info: ../dist/dist.tex $(SCRIPTS)
EMACS=$(EMACS) $(MKINFO) $< $*.texi $@
# Not built by default; the conversion chokes on two @end multitable's
python$(VERSION)-inst.info: ../inst/inst.tex $(SCRIPTS)
EMACS=$(EMACS) $(MKINFO) $< $*.texi $@
clean:
rm -f *.texi~ *.texi
clobber: clean
rm -f *.texi python*-*.info python*-*.info-[0-9]*

View File

@ -1,21 +0,0 @@
This archive contains the standard Python documentation in GNU info
format. Five manuals are included:
python-ref.info* Python Reference Manual
python-mac.info* Python Macintosh Modules
python-lib.info* Python Library Reference
python-ext.info* Extending and Embedding the Python Interpreter
python-api.info* Python/C API Reference
python-tut.info* Python Tutorial
The file python.dir is a fragment of a "dir" file that can be used to
incorporate these documents into an existing GNU info installation:
insert the contents of this file into the "dir" or "localdir" file at
an appropriate point and copy the python-*.info* files to the same
directory.
Thanks go to Milan Zamazal <pdm@zamazal.org> for providing this
conversion to the info format.
Questions and comments on these documents should be directed to
python-docs@python.org.

View File

@ -1,12 +0,0 @@
Python Standard Documentation
* Python Library: (python-lib). Python Library Reference
* Python Mac Modules: (python-mac). Python Macintosh Modules
* Python Reference: (python-ref). Python Reference Manual
* Python API: (python-api). Python/C API Reference Manual
* Python Extending: (python-ext). Extending & Embedding Python
* Python Tutorial: (python-tut). Python Tutorial
* Documenting Python: (python-doc). Documenting Python
* Installing Modules: (python-inst). Installing Python Modules
* Distributing Modules: (python-dist). Distributing Python Modules

View File

@ -1,101 +0,0 @@
\documentclass{manual}
\usepackage{palatino}
\renewcommand{\ttdefault}{cmtt}
\renewcommand{\sfdefault}{cmss}
\newcommand{\myhdl}{\protect \mbox{MyHDL}}
\usepackage{graphicx}
\title{The \myhdl\ manual}
\input{boilerplate}
\makeindex
\begin{document}
\maketitle
\input{copyright}
\begin{abstract}
\noindent
The goal of the \myhdl{} project is to empower hardware designers with
the elegance and simplicity of the Python language.
\myhdl{} is a free, open-source (LGPL) package for using Python as a
hardware description and verification language. Python is a very high
level language, and hardware designers can use its full power to model
and simulate their designs. Moreover, \myhdl{} can convert a design to
Verilog. In combination with an external synthesis tool, it provides a
complete path from Python to a silicon implementation.
\emph{Modeling}
Python's power and clarity make \myhdl{} an ideal solution for high level
modeling. Python is famous for enabling elegant solutions to complex
modeling problems. Moreover, Python is outstanding for rapid
application development and experimentation.
The key idea behind \myhdl{} is the use of Python generators to model
hardware concurrency. Generators are best described as resumable
functions. In \myhdl{}, generators are used in a specific way so that
they become similar to always blocks in Verilog or processes in VHDL.
A hardware module is modeled as a function that returns any number of
generators. This approach makes it straightforward to support features
such as arbitrary hierarchy, named port association, arrays of
instances, and conditional instantiation.
Furthermore, \myhdl{} provides classes that implement traditional
hardware description concepts. It provides a signal class to support
communication between generators, a class to support bit oriented
operations, and a class for enumeration types.
\emph{Simulation and Verification}
The built-in simulator runs on top of the Python interpreter. It
supports waveform viewing by tracing signal changes in a VCD file.
With \myhdl{}, the Python unit test framework can be used on hardware
designs. Although unit testing is a popular modern software
verification technique, it is not yet common in the hardware design
world, making it one more area in which \myhdl{} innovates.
\myhdl{} can also be used as hardware verification language for VHDL and
Verilog designs, by co-simulation with traditional HDL simulators.
\emph{Conversion to Verilog}
The converter to Verilog works on an instantiated design that has been
fully elaborated. Consequently, the original design structure can be
arbitrarily complex.
The converter automates certain tasks that are tedious or hard in
Verilog directly. Notable features are the possibility to choose
between various FSM state encodings based on a single attribute, the
mapping of certain high-level objects to RAM and ROM descriptions, and
the automated handling of signed arithmetic issues.
\end{abstract}
\tableofcontents
\input{background.tex}
\input{intro.tex}
\input{modeling.tex}
\input{unittest.tex}
\input{cosimulation.tex}
\chapter{Conversion to Verilog\label{conv}}
\input{conversion.tex}
\input{reference.tex}
\input{MyHDL.ind}
\end{document}

View File

@ -1,167 +0,0 @@
\chapter{Background information \label{background}}
\section{Prerequisites \label{prerequisites}}
You need a basic understanding of Python to use \myhdl{}.
If you don't know Python, don't worry: it
it is one of the easiest programming languages to
learn~\footnote{You must be bored by such claims, but in Python's
case it's true.}. Learning Python is one of the best time
investments that engineering professionals can make~\footnote{I am not
biased.}.
For starters, \url{http://www.python.org/doc/current/tut/tut.html} is
probably the best choice for an on-line tutorial. For alternatives,
see \url{http://www.python.org/doc/Newbies.html}.
A working knowledge of a hardware description language such as Verilog
or VHDL is helpful.
Code examples in this manual are sometimes shortened for clarity.
Complete executable examples can be found in the distribution directory at
\file{example/manual/}.
\section{A small tutorial on generators \label{tutorial}}
\index{generators!tutorial on}
Generators are a relatively recent Python feature. They
were introduced in Python~2.2.
Because generators are the key concept in
\myhdl{}, a small tutorial is included a here.
Consider the following nonsensical function:
\begin{verbatim}
def function():
for i in range(5):
return i
\end{verbatim}
You can see why it doesn't make a lot of sense. As soon as the first
loop iteration is entered, the function returns:
\begin{verbatim}
>>> function()
0
\end{verbatim}
Returning is fatal for the function call. Further loop iterations
never get a chance, and nothing is left over from the function call
when it returns.
To change the function into a generator function, we replace
\keyword{return} with \keyword{yield}:
\begin{verbatim}
def generator():
for i in range(5):
yield i
\end{verbatim}
Now we get:
\begin{verbatim}
>>> generator()
<generator object at 0x815d5a8>
\end{verbatim}
When a generator function is called, it returns a generator object. A
generator object supports the iterator protocol, which is an expensive
way of saying that you can let it generate subsequent values by
calling its \function{next()} method:
\begin{verbatim}
>>> g = generator()
>>> g.next()
0
>>> g.next()
1
>>> g.next()
2
>>> g.next()
3
>>> g.next()
4
>>> g.next()
Traceback (most recent call last):
File "<stdin>", line 1, in ?
StopIteration
\end{verbatim}
Now we can generate the subsequent values from the for loop on demand,
until they are exhausted. What happens is that the
\keyword{yield} statement is like a
\keyword{return}, except that it is non-fatal: the generator remembers
its state and the point in the code when it yielded. A higher order
agent can decide when to get the next value by calling the
generator's \function{next()} method. We say that generators are
\dfn{resumable functions}.
If you are familiar with hardware description languages, this may ring
a bell. In hardware simulations, there is also a higher order agent,
the Simulator, that interacts with such resumable functions; they are
called
\index{VHDL!process}%
\dfn{processes} in VHDL and
\index{Verilog!always block}%
\dfn{always blocks} in
Verilog. Similarly, Python generators provide an elegant
and efficient method to model concurrency, without having to resort to
some form of threading.
The use of generators to model concurrency is the first key concept in
\myhdl{}. The second key concept is a related one: in \myhdl{}, the
yielded values are used to specify the conditions on which the
generator should wait before resuming. In other words, \keyword{yield}
statements work as general
\index{sensitivity list}%
sensitivity lists.
For more info about generators, consult the on-line Python
documentation, e.g. at \url{http://www.python.org/doc/2.2.2/whatsnew}.
\section{About decorators \label{deco}}
\index{decorators!about}
Python 2.4 introduced a new feature called decorators. MyHDL 0.5 takes
advantage of this new feature by defining a number of decorators that
facilitate hardware descriptions. However, many users may not yet be familiar with
decorators. Therefore, an introduction is included here.
A decorator consists of special syntax in front of a function
declaration. It refers to a decorator function. The decorator function
automatically transforms the declared function into some other
callable object.
A decorator function \function{deco} is used in a decorator statement as follows:
\begin{verbatim}
@deco
def func(arg1, arg2, ...):
<body>
\end{verbatim}
This code is equivalent to the following:
\begin{verbatim}
def func(arg1, arg2, ...):
<body>
func = deco(func)
\end{verbatim}
Note that the decorator statement goes directly in front of the
function declaration, and that the function name \function{func} is automatically
reused for the final result.
MyHDL 0.5 uses decorators to create ready-to-simulate generators
from local function definitions. Their functionality
and usage will be described extensively in this manual.
For more info about Python decorators, consult the on-line Python
documentation, e.g. at \url{http://www.python.org/doc/2.4/whatsnew/node6.html}.
\begin{notice}[warning]
Because MyHDL 0.5 uses decorators, it requires Python 2.4 or a
later version.
\end{notice}

File diff suppressed because it is too large Load Diff

View File

@ -1,416 +0,0 @@
\chapter{Co-simulation with Verilog and VHDL \label{cosim}}
\section{Introduction \label{cosim-intro}}
One of the most exciting possibilities of \myhdl\
is to use it as a hardware verification language (HVL).
A HVL is a language used to write test benches and
verification environments, and to control simulations.
Nowadays, it is generally acknowledged that HVLs should be equipped
with modern software techniques, such as object orientation. The
reason is that verification it the most complex and time-consuming
task of the design process. Consequently, every useful technique is
welcome. Moreover, test benches are not required to be
implementable. Therefore, unlike with synthesizable code, there
are no constraints on creativity.
Technically, verification of a design implemented in
another language requires co-simulation. \myhdl\ is
enabled for co-simulation with any HDL simulator that
has a procedural language interface (PLI). The \myhdl\
side is designed to be independent of a particular
simulator, On the other hand, for each HDL simulator a specific
PLI module will have to be written in C. Currently,
the \myhdl\ release contains a PLI module for
two Verilog simulators: Icarus and Cver.
\section{The HDL side \label{cosim-hdl}}
To introduce co-simulation, we will continue to use the Gray encoder
example from the previous chapters. Suppose that we want to
synthesize it and write it in Verilog for that purpose. Clearly we would
like to reuse our unit test verification environment.
To start, let's recall how the Gray encoder in \myhdl{} looks like:
\begin{verbatim}
def bin2gray(B, G, width):
""" Gray encoder.
B -- input intbv signal, binary encoded
G -- output intbv signal, gray encoded
width -- bit width
"""
@always_comb
def logic():
for i in range(width):
G.next[i] = B[i+1] ^ B[i]
return logic
\end{verbatim}
To show the co-simulation flow, we don't need the Verilog
implementation yet, but only the interface. Our Gray encoder in
Verilog would have the following interface:
\begin{verbatim}
module bin2gray(B, G);
parameter width = 8;
input [width-1:0] B;
output [width-1:0] G;
....
\end{verbatim}
To write a test bench, one creates a new module that instantiates the
design under test (DUT). The test bench declares nets and
regs (or signals in VHDL) that are attached to the DUT, and to
stimulus generators and response checkers. In an all-HDL flow, the
generators and checkers are written in the HDL itself, but we will
want to write them in \myhdl{}. To make the connection, we need to
declare which regs \& nets are driven and read by the \myhdl\
simulator. For our example, this is done as follows:
\begin{verbatim}
module dut_bin2gray;
reg [`width-1:0] B;
wire [`width-1:0] G;
initial begin
$from_myhdl(B);
$to_myhdl(G);
end
bin2gray dut (.B(B), .G(G));
defparam dut.width = `width;
endmodule
\end{verbatim}
The \code{\$from_myhdl} task call declares which regs are driven by
\myhdl{}, and the \code{\$to_myhdl} task call which regs \& nets are read
by it. These tasks take an arbitrary number of arguments. They are
defined in a PLI module written in C and made available in a
simulator-dependent manner. In Icarus Verilog, the tasks are defined
in a \code{myhdl.vpi} module that is compiled from C source code.
\section{The \myhdl\ side \label{cosim-myhdl}}
\myhdl\ supports co-simulation by a \code{Cosimulation} object.
A \code{Cosimulation} object must know how to run a HDL simulation.
Therefore, the first argument to its constructor is a command string
to execute a simulation.
The way to generate and run an simulation executable is simulator
dependent. For example, in Icarus Verilog, a simulation executable
for our example can be obtained obtained by running the
\code{iverilog} compiler as follows:
\begin{verbatim}
% iverilog -o bin2gray -Dwidth=4 bin2gray.v dut_bin2gray.v
\end{verbatim}
This generates a \code{bin2gray} executable for a parameter \code{width}
of 4, by compiling the contributing verilog files.
The simulation itself is run by the \code{vvp} command:
\begin{verbatim}
% vvp -m ./myhdl.vpi bin2gray
\end{verbatim}
This runs the \code{bin2gray} simulation, and specifies to use the
\code{myhdl.vpi} PLI module present in the current directory. (This is
just a command line usage example; actually simulating with the
\code{myhdl.vpi} module is only meaningful from a
\code{Cosimulation} object.)
We can use a \code{Cosimulation} object to provide a HDL
version of a design to the \myhdl\ simulator. Instead of a generator
function, we write a function that returns a \code{Cosimulation}
object. For our example and the Icarus Verilog simulator, this is done
as follows:
\begin{verbatim}
import os
from myhdl import Cosimulation
cmd = "iverilog -o bin2gray -Dwidth=%s bin2gray.v dut_bin2gray.v"
def bin2gray(B, G, width):
os.system(cmd % width)
return Cosimulation("vvp -m ./myhdl.vpi bin2gray", B=B, G=G)
\end{verbatim}
After the executable command argument, the \code{Cosimulation}
constructor takes an arbitrary number of keyword arguments. Those
arguments make the link between \myhdl\ Signals and HDL nets, regs, or
signals, by named association. The keyword is the name of an argument
in a \code{\$to_myhdl} or \code{\$from_myhdl} call; the argument is
a \myhdl\ Signal.
With all this in place, we can now use the existing unit test
to verify the Verilog implementation. Note that we kept the
same name and parameters for the the \code{bin2gray} function:
all we need to do is to provide this alternative definition
to the existing unit test.
Let's try it on the Verilog design:
\begin{verbatim}
module bin2gray(B, G);
parameter width = 8;
input [width-1:0] B;
output [width-1:0] G;
reg [width-1:0] G;
integer i;
wire [width:0] extB;
assign extB = {1'b0, B}; // zero-extend input
always @(extB) begin
for (i=0; i < width; i=i+1)
G[i] <= extB[i+1] ^ extB[i];
end
endmodule
\end{verbatim}
When we run our unit test, we get:
\begin{verbatim}
% python test_bin2gray.py
Check that only one bit changes in successive codewords ... ok
Check that all codewords occur exactly once ... ok
Check that the code is an original Gray code ... ok
----------------------------------------------------------------------
Ran 3 tests in 2.729s
OK
\end{verbatim}
\section{Restrictions \label{cosim-restr}}
In the ideal case, it should be possible to simulate
any HDL description seamlessly with \myhdl{}. Moreover
the communicating signals at each side should act
transparently as a single one, enabling fully race free
operation.
For various reasons, it may not be possible or desirable
to achieve full generality. As anyone that has developed
applications with the Verilog PLI can testify, the
restrictions in a particular simulator, and the
differences over various simulators, can be quite
frustrating. Moreover, full generality may require
a disproportionate amount of development work compared
to a slightly less general solution that may
be sufficient for the target application.
Consequently, I have tried to achieve a solution
which is simple enough so that one can reasonably
expect that any PLI-enabled simulator can support it,
and that is relatively easy to verify and maintain.
At the same time, the solution is sufficiently general
to cover the target application space.
The result is a compromise that places certain restrictions
on the HDL code. In this section, these restrictions
are presented.
\subsection{Only passive HDL can be co-simulated \label{cosim-pass}}
The most important restriction of the \myhdl\ co-simulation solution is
that only ``passive'' HDL can be co-simulated. This means that the HDL
code should not contain any statements with time delays. In other
words, the \myhdl\ simulator should be the master of time; in
particular, any clock signal should be generated at the \myhdl\ side.
At first this may seem like an important restriction, but if one
considers the target application for co-simulation, it probably
isn't.
\myhdl\ supports co-simulation so that test benches for HDL
designs can be written in Python. Let's consider the nature of the
target HDL designs. For high-level, behavioral models that are not
intended for implementation, it should come as no surprise that I
would recommend to write them in \myhdl\ directly; that is one of the
goals of the \myhdl\ effort. Likewise, gate level designs with
annotated timing are not the target application: static timing
analysis is a much better verification method for such designs.
Rather, the targeted HDL designs are naturally models that are
intended for implementation, most likely through synthesis. As time
delays are meaningless in synthesizable code, the restriction is
compatible with the target application.
\subsection{Race sensitivity issues \label{cosim-race}}
In a typical RTL code, some events cause other events to occur in the
same time step. For example, when a clock signal triggers some signals
may change in the same time step. For race-free operation, an HDL
must differentiate between such events within a time step. This is done
by the concept of ``delta'' cycles. In a fully general, race free
co-simulation, the co-simulators would communicate at the level of delta
cycles. However, in \myhdl\ co-simulation, this is not entirely the
case.
Delta cycles from the \myhdl\ simulator toward the HDL co-simulator are
preserved. However, in the opposite direction, they are not. The
signals changes are only returned to the \myhdl\ simulator after all delta
cycles have been performed in the HDL co-simulator.
What does this mean? Let's start with the good news. As explained in
the previous section, the concept behind \myhdl\ co-simulation implies
that clocks are generated at the \myhdl\ side. \emph{When using a
\myhdl\ clock and its corresponding HDL signal directly as a clock,
co-simulation is race free.} In other words, the case
that most closely reflects the \myhdl\ co-simulation approach, is race free.
The situation is different when you want to use a signal driven by the
HDL (and the corresponding MyHDL signal) as a clock.
Communication triggered by such a clock is not race free. The solution
is to treat such an interface as a chip interface instead of an RTL
interface. For example, when data is triggered at positive clock
edges, it can safely be sampled at negative clock edges.
Alternatively, the \myhdl\ data signals can be declared with a delay
value, so that they are guaranteed to change after the clock
edge.
\section{Implementation notes \label{cosim-impl}}
\begin{quote}
\em
This section requires some knowledge of PLI terminology.
\end{quote}
Enabling a simulator for co-simulation requires a PLI module written
in C. In Verilog, the PLI is part of the ``standard''. However,
different simulators implement different versions and portions of the
standard. Worse yet, the behavior of certain PLI callbacks is not
defined on some essential points. As a result, one should plan to
write or at least customize a specific PLI module for any simulator.
The release contains a PLI module for the open source Icarus
and Cver simulators.
This section documents the current approach and status of the PLI
module implementation and some reflections on future
implementations.
\subsection{Icarus Verilog \label{cosim-icarus}}
\subsubsection{Delta cycle implementation \label{cosim-icarus-delta}}
To make co-simulation work, a specific type of PLI callback is
needed. The callback should be run when all pending events have been
processed, while allowing the creation of new events in the current
time step (e.g. by the \myhdl\ simulator). In some Verilog
simulators, the \code{cbReadWriteSync} callback does exactly
that. However, in others, including Icarus, it does not. The
callback's behavior is not fully standardized; some simulators run the
callback before non-blocking assignment events have been processed.
Consequently, I had to look for a workaround. One half of the solution
is to use the \code{cbReadOnlySync} callback. This callback runs
after all pending events have been processed. However, it does not
permit to create new events in the current time step. The second half
of the solution is to map \myhdl\ delta cycles onto real Verilog time
steps. Note that fortunately I had some freedom here because of the
restriction that only passive HDL code can be co-simulated.
I chose to make the time granularity in the Verilog simulator a 1000
times finer than in the \myhdl{} simulator. For each \myhdl\ time
step, 1000 Verilog time steps are available for \myhdl\ delta
cycles. In practice, only a few delta cycles per time step should be
needed. Exceeding this limit almost certainly indicates a design error;
the limit is checked at run-time. The factor 1000 also makes it
easy to distinguish ``real'' time from delta cycle time when printing
out the Verilog time.
\subsubsection{Passive Verilog check \label{cosim-icarus-pass}}
As explained before, co-simulated Verilog should not contain delay
statements. Ideally, there should be a run-time check to flag
non-compliant code. However, there is currently no such check in the
Icarus module.
The check can be written using the \code{cbNextSimTime} VPI callback
in Verilog. However, Icarus 0.7 doesn't support this callback. In the
meantime, support for it has been added to the Icarus development
branch. When Icarus 0.8 is released, a check will be added.
In the mean time, just don't do this. It may appear to ``work'' but it
really won't as events will be missed over the co-simulation
interface.
\subsection{Cver \label{cosim-cver}}
MyHDL co-simulation is supported with the open source Verilog
simulator Cver. The PLI module is based on the one for Icarus
and basically has the same functionality. Only some cosmetic
modifications were required.
\subsection{Other Verilog simulators \label{cosim-impl-verilog}}
The Icarus module is written with VPI calls, which are provided by the
most recent generation of the Verilog PLI. Some simulators may only
support TF/ACC calls, requiring a complete redesign of the interface
module.
If the simulator supports VPI, the Icarus module should be reusable to
a large extent. However, it may be possible to improve on it. The
workaround to support delta cycles described in
Section~\ref{cosim-icarus-delta} may not be necessary. In some
simulators, the \code{cbReadWriteSync} callback occurs after all
events (including non-blocking assignments) have been processed. In
that case, the functionality can be supported without a finer time
granularity in the Verilog simulator.
There are also Verilog standardization efforts underway to resolve the
ambiguity of the \code{cbReadWriteSync} callback. The solution will be
to introduce new, well defined callbacks. From reading some proposals,
I conclude that the \code{cbEndOfSimTime} callback would provide the
required functionality.
The MyHDL project currently has no access to commercial Verilog
simulators, so progress in co-simulation support depends on external
interest and participation. Users have reported that they are using
MyHDL co-simulation with the simulators from Aldec and Modelsim.
\subsection{Interrupted system calls \label{cosim-impl-syscalls}}
The PLI module uses \code{read} and \code{write} system calls to
communicate between the co-simulators. The implementation assumes that
these calls are restarted automatically by the operating system when
interrupted. This is apparently what happens on the Linux box on which
MyHDL is developed.
It is known how non-restarted interrupted system calls should be
handled, but currently such code cannot be tested on the MyHDL
development platform. Also, it is not clear whether this is still a
relevant issue with modern operating systems. Therefore, this issue
has not been addressed at this moment. However, assertions have been
included that should trigger when this situation occurs.
Whenever an assertion fires in the PLI module, please report it. The
same holds for Python exceptions that cannot be easily explained.
\subsection{VHDL \label{cosim-impl-vhdl}}
It would be nice to have an interface to VHDL simulators such as the
Modelsim VHDL simulator. This will require a PLI module using the
PLI of the VHDL simulator.
The MyHDL project currently has no access to commercial VHDL
simulators, so progress in co-simulation support will depend on
external interest and participation.

View File

@ -1,555 +0,0 @@
\chapter{Introduction to \myhdl\ \label{intro}}
\section{A basic \myhdl\ simulation \label{intro-basic}}
We will introduce \myhdl\ with a classic \code{Hello World} style
example. All example code can be found in the distribution directory
under \file{example/manual/}. Here are the contents of a \myhdl\
simulation script called \file{hello1.py}:
\begin{verbatim}
from myhdl import Signal, delay, always, now, Simulation
def HelloWorld():
interval = delay(10)
@always(interval)
def sayHello():
print "%s Hello World!" % now()
return sayHello
inst = HelloWorld()
sim = Simulation(inst)
sim.run(30)
\end{verbatim}
When we run this simulation, we get the following output:
\begin{verbatim}
% python hello1.py
10 Hello World!
20 Hello World!
30 Hello World!
_SuspendSimulation: Simulated 30 timesteps
\end{verbatim}
The first line of the script imports a number of objects from the
\code{myhdl} package. In Python we can only use identifiers that are
literally defined in the source file
\footnote{The exception is the \samp{from module import *} syntax,
that imports all the symbols from a module. Although this is generally
considered bad practice, it can be tolerated for large modules that
export a lot of symbols. One may argue that
\code{myhdl} falls into that category.}.
Then, we define a function called \function{HelloWorld}. In MyHDL,
classic functions are used to model hardware modules. In particular,
the parameter list is used to define the interface. In this first
example, the interface is empty.
Inside the top level function we declare a local function called
\function{sayHello} that defines the desired behavior. This function
is decorated with an \function{always} decorator that has a delay
\index{decorator!\function{always}}
object as its parameter. The meaning is that the function will be
executed whenever the specified delay interval has expired.
Behind the curtains, the \function{always} decorator creates a Python
\emph{generator} and reuses the name of the decorated function for
it. Generators are the fundamental objects in MyHDL, and we will say
much more about them further on.
Finally, the top level function returns the local generator. This is
the simplest case of the basic MyHDL code pattern
to define the contents of a hardware module. We will describe the
general case further on.
In MyHDL, we create an \emph{instance} of a hardware module by calling
the corresponding function. In the example, variable \code{inst} refers
to an instance of \function{HelloWorld}. To simulate the instance, we
pass it as an argument to a \class{Simulation} object constructor. We
then run the simulation for the desired amount of timesteps.
\section{Signals, ports, and concurrency \label{intro-conc}}
In the previous section, we simulated a design with a single
generator and no concurrency. On the other hand, real hardware
descriptions are typically massively concurrent.
\myhdl\ supports this by allowing an
arbitrary number of concurrently running generators.
With concurrency comes the problem of deterministic
communication. Hardware languages use special objects to
support deterministic communication between concurrent code.
In particular, \myhdl\
has a \class{Signal} object which is roughly modeled after VHDL
signals.
We will demonstrate signals and concurrency
by extending and modifying our first example. We define two hardware
modules, one that drives a clock signal, and one that is sensitive
to a positive edge on a clock signal:
\begin{verbatim}
from myhdl import Signal, delay, always, now, Simulation
def ClkDriver(clk):
halfPeriod = delay(10)
@always(halfPeriod)
def driveClk():
clk.next = not clk
return driveClk
def HelloWorld(clk):
@always(clk.posedge)
def sayHello():
print "%s Hello World!" % now()
return sayHello
clk = Signal(0)
clkdriver_inst = ClkDriver(clk)
hello_inst = HelloWorld(clk)
sim = Simulation(clkdriver_inst, hello_inst)
sim.run(50)
\end{verbatim}
The clock driver function \function{ClkDriver} has a
clock signal as its parameter. This is how a
\emph{port} is modeled in MyHDL. The function
defines a generator
that continuously toggles a clock signal after a certain delay.
A new value of a signal is specified by assigning to its
\code{next} attribute. This is the \myhdl\ equivalent of
\index{VHDL!signal assignment}%
the VHDL signal assignment and the
\index{Verilog!non-blocking assignment}%
Verilog non-blocking assignment.
The \function{HelloWorld} function is modified from the
first example. It now also takes a clock signal as parameter.
Its generator is made sensitive to a rising
\index{wait!for a rising edge}%
edge of the clock signal. This is specified by the
\code{posedge} attribute of a signal. The edge
specifier is the argument of the \code{always}
decorator. As a result, the decorated function
will be executed on every rising clock edge.
The \code{clk} signal is constructed with an initial value
\code{0}. When creating an instance of each
hardware module, the same clock signal is passed as
the argument. The result is that the instances
are now connected through the clock signal.
The \class{Simulation} object is constructed with the
two instances.
When we run the simulation, we get:
\begin{verbatim}
% python hello2.py
10 Hello World!
30 Hello World!
50 Hello World!
_SuspendSimulation: Simulated 50 timesteps
\end{verbatim}
\section{Parameters and hierarchy \label{intro-hier}}
We have seen that MyHDL uses functions to model hardware
modules. We have also seen that ports are modeled by using
signals as parameters. To make designs reusable we will also
want to use other objects as parameters. For example, we can
change the clock generator function to make it more general
and reusable, by making the clock period parameterizable, as
follows:
\begin{verbatim}
from myhdl import Signal, delay, instance, always, now, Simulation
def ClkDriver(clk, period=20):
lowTime = int(period/2)
highTime = period - lowTime
@instance
def driveClk():
while True:
yield delay(lowTime)
clk.next = 1
yield delay(highTime)
clk.next = 0
return driveClk
\end{verbatim}
In addition to the clock signal, the clock
period is a parameter, with a default value of \code{20}.
As the low time of the clock may differ from the high time in case of
an odd period, we cannot use the \function{always} decorator with a
single delay value anymore. Instead, the \function{driveClk} function
is now a generator function with an explicit definition of the desired
behavior. It is decorated with the \function{instance} decorator.
\index{decorator!\function{instance}}
You can see that \function{driveClk} is a generator function
because it contains \code{yield} statements.
When a generator function is called, it returns a generator object.
This is basically what the \function{instance} decorator does. It
is less sophisticated than the \function{always} decorator,
but it can be used to create a generator from any local generator
function.
The \code{yield} statement is a general Python construct, but MyHDL
uses it in a dedicated way. In MyHDL, it has a similar meaning as the
wait statement in VHDL: the statement suspends execution of a
generator, and its clauses specify the conditions on which the
generator should wait before resuming. In this case, the generator
waits for a certain delay.
Note that to make sure that the generator runs ``forever'', we wrap its
behavior in a \code{while True} loop.
Similarly, we can define a general \function{Hello} function as follows:
\begin{verbatim}
def Hello(clk, to="World!"):
@always(clk.posedge)
def sayHello():
print "%s Hello %s" % (now(), to)
return sayHello
\end{verbatim}
We can create any number of instances by calling the functions with
the appropriate parameters. Hierarchy can be modeled by defining the
instances in a higher-level function, and returning them.
This pattern can be repeated for an arbitrary number of
hierarchical levels. Consequently, the general definition
of a \myhdl\ instance is recursive: an instance
\index{instance!defined}%
is either a sequence of instances, or a generator.
As an example, we will create a higher-level function with
four instances of the lower-level functions, and simulate it:
\begin{verbatim}
def greetings():
clk1 = Signal(0)
clk2 = Signal(0)
clkdriver_1 = ClkDriver(clk1) # positional and default association
clkdriver_2 = ClkDriver(clk=clk2, period=19) # named association
hello_1 = Hello(clk=clk1) # named and default association
hello_2 = Hello(to="MyHDL", clk=clk2) # named association
return clkdriver_1, clkdriver_2, hello_1, hello_2
inst = greetings()
sim = Simulation(inst)
sim.run(50)
\end{verbatim}
As in standard Python, positional or named parameter association can
be used in instantiations, or a mix of both\footnote{All positional
parameters have to go before any named parameter.}. All these styles
are demonstrated in the example above. Named association can be very
useful if there are a lot of parameters, as the argument order in the
call does not matter in that case.
The simulation produces the following output:
\begin{verbatim}
% python greetings.py
9 Hello MyHDL
10 Hello World!
28 Hello MyHDL
30 Hello World!
47 Hello MyHDL
50 Hello World!
_SuspendSimulation: Simulated 50 timesteps
\end{verbatim}
\begin{notice}[warning]
Some commonly used terminology has different meanings
in Python versus hardware design. Rather than artificially
changing terminology, I think it's best to keep it
and explicitly describing the differences.
A \dfn{module} in Python refers to all source code
in a particular file. A module can be reused by
other modules by importing. In hardware design,
\index{module!in Python versus hardware design}%
a module is a reusable block of hardware with
a well defined interface. It can be reused in
another module by \dfn{instantiating} it.
An \dfn{instance} in Python (and other object-oriented
languages) refers to the object created by a
\index{instance!in Python versus hardware design}%
class constructor. In hardware design, an instance
is a particular incarnation of a hardware module.
Normally, the meaning should be clear from
the context. Occasionally, I may qualify terms
with the words 'hardware' or '\myhdl{}' to
avoid ambiguity.
\end{notice}
\section{Bit oriented operations \label{intro-bit}}
Hardware design involves dealing with bits and bit-oriented
operations. The standard Python type \class{int} has most of the
desired features, but lacks support for indexing and slicing. For this
reason, \myhdl\ provides the \class{intbv} class. The name was chosen
to suggest an integer with bit vector flavor.
Class \class{intbv} works transparently with other
integer-like types. Like class \class{int}, it provides access to the
underlying two's complement representation for bitwise
operations. In addition, it is a mutable type that provides indexing
and slicing operations, and some additional bit-oriented support such
as concatenation.
\subsection{Bit indexing \label{intro-indexing}}
\index{bit indexing}
As an example, we will consider the design of a Gray encoder. The
following code is a Gray encoder modeled in \myhdl{}:
\begin{verbatim}
from myhdl import Signal, delay, Simulation, always_comb, instance, intbv, bin
def bin2gray(B, G, width):
""" Gray encoder.
B -- input intbv signal, binary encoded
G -- output intbv signal, gray encoded
width -- bit width
"""
@always_comb
def logic():
for i in range(width):
G.next[i] = B[i+1] ^ B[i]
return logic
\end{verbatim}
This code introduces a few new concepts. The string in triple quotes
at the start of the function is a \dfn{doc string}. This is standard
Python practice for structured documentation of code.
Furthermore, we introduce a third decorator: \function{always_comb}.
\index{decorator!\function{always_comb}}
It is used with a classic function and specifies that the
resulting generator should
\index{wait!for a signal value change}%
wait for a value change on any input signal. This is typically used to
describe
\index{combinatorial logic}%
combinatorial logic. The \function{always_comb} decorator
automatically infers which signals are used as inputs.
Finally, the code contains bit indexing operations and an exclusive-or
operator as required for a Gray encoder. By convention, the lsb of an
\class{intbv} object has index~\code{0}.
To verify the Gray encoder, we write a test bench that prints input
and output for all possible input values:
\begin{verbatim}
def testBench(width):
B = Signal(intbv(0))
G = Signal(intbv(0))
dut = bin2gray(B, G, width)
@instance
def stimulus():
for i in range(2**width):
B.next = intbv(i)
yield delay(10)
print "B: " + bin(B, width) + "| G: " + bin(G, width)
return dut, stimulus
\end{verbatim}
We use the conversion function \code{bin} to get a binary
string representation of the signal values. This function is exported
by the \code{myhdl} package and supplements the standard Python
\code{hex} and \code{oct} conversion functions.
As a demonstration, we set up a simulation for a small width:
\begin{verbatim}
sim = Simulation(testBench(width=3))
sim.run()
\end{verbatim}
The simulation produces the following output:
\begin{verbatim}
% python bin2gray.py
B: 000 | G: 000
B: 001 | G: 001
B: 010 | G: 011
B: 011 | G: 010
B: 100 | G: 110
B: 101 | G: 111
B: 110 | G: 101
B: 111 | G: 100
StopSimulation: No more events
\end{verbatim}
\subsection{Bit slicing \label{intro-slicing}}
\index{bit slicing}
For a change, we will use a traditional function as an example to illustrate
slicing. The following function calculates the HEC byte of an ATM
header.
\begin{verbatim}
from myhdl import intbv, concat
COSET = 0x55
def calculateHec(header):
""" Return hec for an ATM header, represented as an intbv.
The hec polynomial is 1 + x + x**2 + x**8.
"""
hec = intbv(0)
for bit in header[32:]:
hec[8:] = concat(hec[7:2],
bit ^ hec[1] ^ hec[7],
bit ^ hec[0] ^ hec[7],
bit ^ hec[7]
)
return hec ^ COSET
\end{verbatim}
The code shows how slicing access and assignment is supported on the
\class{intbv} data type. In accordance with the most common hardware
convention, and unlike standard Python, slicing ranges are
downward. The code also demonstrates concatenation of \class{intbv}
objects.
As in standard Python, the slicing range is half-open: the highest
index bit is not included. Unlike standard Python however, this index
corresponds to the \emph{leftmost} item. Both indices can be omitted
from the slice. If the leftmost index is omitted, the meaning is to
access ``all'' higher order bits. If the rightmost index is omitted,
it is \code{0} by default.
The half-openness of a slice may seem awkward at first, but it helps
to avoid one-off count issues in practice. For example, the slice
\code{hex[8:]} has exactly \code{8} bits. Likewise, the slice
\code{hex[7:2]} has \code{7-2=5} bits. You can think about it as
follows: for a slice \code{[i:j]}, only bits below index \code{i} are
included, and the bit with index \code{j} is the last bit included.
When an intbv object is sliced, a new intbv object is returned. This
new intbv object is always positive, even when the original object
was negative.
\section{Some remarks on \myhdl\ and Python \label{intro-python}}
To conclude this introductory chapter, it is useful to stress that
\myhdl\ is not a language in itself. The underlying language is Python,
and \myhdl\ is implemented as a Python package called \code{myhdl}.
Moreover, it is a design goal to keep the \code{myhdl} package as
minimalistic as possible, so that \myhdl\ descriptions are very much
``pure Python''.
To have Python as the underlying language is significant in several
ways:
\begin{itemize}
\item Python is a very powerful high level language. This translates
into high productivity and elegant solutions to complex problems.
\item Python is continuously improved by some very clever
minds, supported by a large and fast growing user base. Python profits
fully from the open source development model.
\item Python comes with an extensive standard library. Some
functionality is likely to be of direct interest to \myhdl\ users:
examples include string handling, regular expressions, random number
generation, unit test support, operating system interfacing and GUI
development. In addition, there are modules for mathematics, database
connections, networking programming, internet data handling, and so
on.
\item Python has a powerful C extension model. All built-in types are
written with the same C API that is available for custom
extensions. To a module user, there is no difference between a
standard Python module and a C extension module --- except
performance. The typical Python development model is to prototype
everything in Python until the application is stable, and (only) then
rewrite performance critical modules in C if necessary.
\end{itemize}
\section{Summary and perspective \label{intro-summary}}
Here is an overview of what we have learned in this chapter:
\begin{itemize}
\item Generators are the basic building blocks of MyHDL models. They
provide the way to model massive concurrency and sensitiviy lists.
\item MyHDL provides decorators that create useful generators from local functions.
\item Hardware structure and hierarchy is described with classic Python functions.
\item \code{Signal} objects are used to communicate between concurrent generators.
\item \code{intbv} objects are used to describe bit-oriented operations.
\item A \code{Simulation} object is used to simulate MyHDL models.
\end{itemize}
These concepts are sufficient to start describing and simulating MyHDL models.
However, there is much more to MyHDL. Here is an overview of what can
be learned from the following chapters:
\begin{itemize}
\item MyHDL supports sophisticated and high level modeling techniques.
This is described in Chapter~\ref{model}
\item MyHDL enables the use of modern software verfication techniques,
such as unit testing, on hardware designs. This is the topic of
Chapter~\ref{unittest}.
\item It is possible to co-simulate MyHDL models with other HDL
languages such as Verilog and VHDL. This is described in
Chapter~\ref{cosim}.
\item Last but not least, MyHDL models can be converted to
Verilog, providing a path to a silicon implementation. This
is the topic of Chapter~\ref{conv}.
\end{itemize}

File diff suppressed because it is too large Load Diff

View File

@ -1,554 +0,0 @@
\chapter{Reference \label{ref}}
\myhdl\ is implemented as a Python package called \code{myhdl}. This
chapter describes the objects that are exported by this package.
\section{Simulation \label{ref-sim}}
\subsection{The \class{Simulation} class \label{ref-simclass}}
\declaremodule{}{myhdl}
\begin{classdesc}{Simulation}{arg \optional{, arg \moreargs}}
Class to construct a new simulation. Each argument should be a
\myhdl\ instance. In \myhdl{}, an instance is recursively defined
as being either a sequence of instances, or a \myhdl\ generator, or a
Cosimulation object. See section~\ref{ref-gen} for the definition of
\myhdl\ generators and their interaction with a
\class{Simulation} object. See Section~\ref{ref-cosim}
for the \class{Cosimulation} object. At most one \class{Cosimulation}
object can be passed to a \class{Simulation} constructor.
\end{classdesc}
A \class{Simulation} object has the following method:
\begin{methoddesc}[Simulation]{run}{\optional{duration}}
Run the simulation forever (by default) or for a specified duration.
\end{methoddesc}
\subsection{Simulation support functions\label{ref-simsupport}}
\declaremodule{}{myhdl}
\begin{funcdesc}{now}{}
Returns the current simulation time.
\end{funcdesc}
\begin{excclassdesc}{StopSimulation}{}
Base exception that is caught by the \code{Simulation.run()} method to
stop a simulation.
\end{excclassdesc}
\subsection{Waveform tracing\label{ref-trace}}
\begin{funcdesc}{traceSignals}{func \optional{, *args} \optional{, **kwargs}}
Enables signal tracing to a VCD file for waveform viewing.
\var{func} is a function that returns an instance.
\function{traceSignals()} calls \var{func} under its control
and passes \var{*args} and \var{**kwargs} to the call. In this way, it
finds the hierarchy and the signals to be traced.
The return value is the same as would be returned by the call
\code{func(*args, **kwargs)}. The top-level instance name and the
basename of the VCD output filename is \code{func.func_name} by
default. If the VCD file exists already, it will be moved to a backup
file by attaching a timestamp to it, before creating the new file.
\end{funcdesc}
The \code{traceSignals} callable has the following attribute:
\begin{memberdesc}[traceSignals]{name}
This attribute is used to overwrite the default top-level instance
name and the basename of the VCD output filename.
\end{memberdesc}
\section{Modeling \label{ref-model}}
\subsection{The \class{Signal} class \label{ref-sig}}
\declaremodule{}{myhdl}
\begin{classdesc}{Signal}{\optional{val=None} \optional{, delay=0}}
This class is used to construct a new signal and to initialize its
value to \var{val}. Optionally, a delay can be specified.
\end{classdesc}
A \class{Signal} object has the following attributes:
\begin{memberdesc}[Signal]{posedge}
Attribute that represents the positive edge of a signal, to be
used in sensitivity lists.
\end{memberdesc}
\begin{memberdesc}[Signal]{negedge}
Attribute that represents the negative edge of a signal, to be
used in sensitivity lists.
\end{memberdesc}
\begin{memberdesc}[Signal]{next}
Read-write attribute that represents the next value of the signal.
\end{memberdesc}
\begin{memberdesc}[Signal]{val}
Read-only attribute that represents the current value of the signal.
This attribute is always available to access the current value;
however in many practical case it will not be needed. Whenever there
is no ambiguity, the Signal object's current value is used
implicitly. In particular, all Python's standard numeric, bit-wise,
logical and comparison operators are implemented on a Signal object by
delegating to its current value. The exception is augmented
assignment. These operators are not implemented as they would break
the rule that the current value should be a read-only attribute. In
addition, when a Signal object is assigned to the \code{next}
attribute of another Signal object, its current value is assigned
instead.
\end{memberdesc}
\begin{memberdesc}[Signal]{min}
Read-only attribute that is the minimum value (inclusive) of a
numeric signal, or \var{None} for no minimum.
\end{memberdesc}
\begin{memberdesc}[Signal]{max}
Read-only attribute that is the maximum value
(exclusive) of a numeric signal, or \var{None} for no
maximum.
\end{memberdesc}
\begin{memberdesc}[Signal]{driven}
Writable attribute that can be used to indicate that the signal
is supposed to be driven from the MyHDL code, and how it should
be declared in Verilog after conversion. The allowed values
are \code{'reg'} and \code{'wire'}.
This attribute is useful when the Verilog converter cannot
infer automatically whether and how a signal is driven. This
occurs when the signal is driven from user-defined Verilog code.
\end{memberdesc}
\subsection{\myhdl\ generators and trigger objects \label{ref-gen}}
\declaremodule{}{myhdl}
\myhdl\ generators are standard Python generators with specialized
\keyword{yield} statements. In hardware description languages, the equivalent
statements are called
\index{sensitivity list}%
\emph{sensitivity lists}. The general format
of \keyword{yield} statements in in \myhdl\ generators is:
\hspace{\leftmargin}\keyword{yield} \var{clause \optional{, clause ...}}
When a generator executes a \keyword{yield} statement, its
execution is suspended at that point. At the same time, each
\var{clause} is a \emph{trigger object} which defines the condition
upon which the generator should be resumed. However, per invocation of a
\keyword{yield} statement, the generator resumes exactly once,
regardless of the number of clauses. This happens on the
first trigger that occurs.
In this section, the trigger objects and their functionality will be
described.
Some MyHDL objects that are described elsewhere can directly be used
as trigger objects. In particular, a signal can be used as
a trigger object. Whenever a signal changes value, the generator
resumes. Likewise, the objects referred to by the signal attributes
\code{posedge} and \code{negedge} are trigger objects. The generator
resumes on the occurrence of a positive or a negative edge on the
signal, respectively. An edge occurs when there is a change from
false to true (positive) or vice versa (negative).
For the full description of the \class{Signal} class and its
attributes, see section~\ref{ref-sig}.
Furthermore, \myhdl\ generators can be used as clauses in \code{yield}
statements. Such a generator is forked, and starts operating
immediately, while the original generator
waits for it to complete. The original generator resumes when the
forked generator returns.
In addition, the following functions return trigger objects:
\begin{funcdesc}{delay}{t}
Return a trigger object that specifies that the generator should
resume after a delay \var{t}.
\end{funcdesc}
\begin{funcdesc}{join}{arg \optional{, arg \moreargs}}
Join a number of trigger objects together and return a joined
trigger object. The effect is that the joined trigger object will
trigger when \emph{all} of its arguments have triggered.
\end{funcdesc}
Finally, as a special case, the Python \code{None} object can be
present in a \code{yield} statement. It is the do-nothing
trigger object. The generator immediately resumes, as if no
\code{yield} statement were present. This can be useful if the
\code{yield} statement also has generator clauses: those generators
are forked, while the original generator resumes immediately.
\subsection{Decorator functions \label{ref-deco}}
\declaremodule{}{myhdl}
MyHDL defines a number of decorator functions, that make it easier to
create generators from local generator functions.
\begin{funcdesc}{instance}{}
The \function{instance} decorator is the most general decorator. It
automatically creates a generator by calling the decorated generator function.
It is used as follows:
\begin{verbatim}
def top(...):
...
@instance
def inst():
<generator body>
...
return inst, ...
\end{verbatim}
This is equivalent to:
\begin{verbatim}
def top(...):
...
def _gen_func():
<generator body>
...
inst = _gen_func()
...
return inst, ...
\end{verbatim}
\end{funcdesc}
\begin{funcdesc}{always}{arg \optional{, *args}}
The \function{always} decorator is a specialized decorator that targets a widely used
coding pattern. It is used as follows:
\begin{verbatim}
def top(...):
...
@always(event1, event2, ...)
def inst()
<body>
...
return inst, ...
\end{verbatim}
This is equivalent to the following:
\begin{verbatim}
def top(...):
...
def _func():
<body>
def _gen_func()
while True:
yield event1, event2, ...
_func()
...
inst = _gen_func()
...
return inst, ...
\end{verbatim}
The argument list of the decorator corresponds to the sensitivity
list. Only signals, edge specifiers, or delay objects are allowed.
The decorated function should be a classic function.
\end{funcdesc}
\begin{funcdesc}{always_comb}{}
The \function{always_comb} decorator is used to describe combinatorial
logic.
\begin{verbatim}
def top(...):
...
@always_comb
def comb_inst():
<combinatorial body>
...
return comb_inst, ...
\end{verbatim}
The \function{always_comb} decorator infers the inputs of the combinatorial
logic and the corresponding sensitivity list automatically.
The decorated function should be a classic function.
\end{funcdesc}
\subsection{The \class{intbv} class \label{ref-intbv}}
\declaremodule{}{myhdl}
\begin{classdesc}{intbv}{\optional{val=None} \optional{, min=None}
\optional{, max=None}}
This class represents \class{int}-like objects with some additional
features that make it suitable for hardware design. The \var{val}
argument can be an \class{int}, a \class{long}, an \class{intbv} or a
bit string (a string with only '0's or '1's). For a bit string
argument, the value is calculated as in \code{int(\var{bitstring},
2)}. The optional \var{min} and \var{max} arguments can be used to
specify the minimum and maximum value of the \class{intbv} object. As
in standard Python practice for ranges, the minimum value is inclusive
and the maximum value is exclusive.
\end{classdesc}
The minimum and maximum values of an \class{intbv} object
are available as attributes:
\begin{memberdesc}[intbv]{min}
Read-only attribute that is the minimum value (inclusive) of an
\class{intbv}, or \var{None} for no minimum.
\end{memberdesc}
\begin{memberdesc}[intbv]{max}
Read-only attribute that is the maximum value
(exclusive) of an \class{intbv}, or \var{None} for no
maximum.
\end{memberdesc}
Unlike \class{int} objects, \class{intbv} objects are mutable; this is
also the reason for their existence. Mutability is needed to support
assignment to indexes and slices, as is common in hardware design. For
the same reason, \class{intbv} is not a subclass from \class{int},
even though \class{int} provides most of the desired
functionality. (It is not possible to derive a mutable subtype from
an immutable base type.)
An \class{intbv} object supports the same comparison, numeric,
bitwise, logical, and conversion operations as \class{int} objects. See
\url{http://www.python.org/doc/current/lib/typesnumeric.html} for more
information on such operations. In all binary operations,
\class{intbv} objects can work together with \class{int} objects.
For mixed-type numeric operations, the result type is an \class{int}
or a \class{long}. For mixed-type bitwise operations, the result
type is an \class{intbv}.
In addition, \class{intbv} objects support indexing and slicing
operations:
\begin{tableiii}{clc}{code}{Operation}{Result}{Notes}
\lineiii{\var{bv}[\var{i}]}
{item \var{i} of \var{bv}}
{(1)}
\lineiii{\var{bv}[\var{i}] = \var{x}}
{item \var{i} of \var{bv} is replaced by \var{x}}
{(1)}
\lineiii{\var{bv}[\var{i}:\var{j}]}
{slice of \var{bv} from \var{i} downto \var{j}}
{(2)(3)}
\lineiii{\var{bv}[\var{i}:\var{j}] = \var{t}}
{slice of \var{bv} from \var{i} downto \var{j} is replaced
by \var{t}}
{(2)(4)}
\end{tableiii}
\begin{description}
\item[(1)] Indexing follows the most common hardware design
conventions: the lsb bit is the rightmost bit, and it has
index 0. This has the following desirable property: if the
\class{intbv} value is decomposed as a sum of powers of 2,
the bit with index \var{i} corresponds to the term
\code{2**i}.
\item[(2)] In contrast to standard Python sequencing conventions,
slicing range are downward. This is a consequence of the
indexing convention, combined with the common convention
that the most significant digits of a number are the
leftmost ones. The Python convention of half-open ranges is
followed: the bit with the highest index is not
included. However, it is the \emph{leftmost} bit in this
case. As in standard Python, this takes care of one-off
issues in many practical cases: in particular,
\code{bv[\var{i}:]} returns \var{i} bits;
\code{bv[\var{i}:\var{j}]} has \code{\var{i}-\var{j}}
bits. When the low index \var{j} is omitted, it defaults
to \code{0}. When the high index \var{i} is omitted, it
means ``all'' higher order bits.
\item[(3)] The object returned from a slicing access operation is always a
positive \class{intbv}; higher order bits are implicitly
assumed to be zero. The bit width is implicitly stored in
the return object, so that it can be used in concatenations
and as an iterator. In addition, for a bit width w, the
\var{min} and \var{max} attributes are implicitly set to
\code{0} and \code{2**w}, respectively.
\item[(4)] When setting a slice to a value, it is checked whether the
slice is wide enough.
\end{description}
In addition, an \class{intbv} object supports the iterator protocol. This
makes it possible to iterate over all its bits, from the high index to
index 0. This is only possible for \class{intbv} objects with a
defined bit width.
\subsection{Miscellaneous modeling support functions\label{ref-model-misc}}
\declaremodule{}{myhdl}
\begin{funcdesc}{bin}{num \optional{, width}}
Returns a bit string representation. If the optional \var{width}
is provided, and if it is larger than the width of the default
representation, the bit string is padded with the sign bit.
This function complements the standard Python conversion functions
\code{hex} and \code{oct}. A binary string representation is often
useful in hardware design.
\end{funcdesc}
\begin{funcdesc}{concat}{base \optional{, arg \moreargs}}
Returns an \class{intbv} object formed by concatenating the arguments.
The following argument types are supported: \class{intbv} objects with
a defined bit width, \class{bool} objects, signals of the previous
objects, and bit strings. All these objects have a defined bit
width. The first argument \var{base} is special as it doesn't need to
have a defined bit width. In addition to the previously mentioned
objects, unsized \class{intbv}, \class{int} and \class{long} objects
are supported, as well as signals of such objects.
\end{funcdesc}
\begin{funcdesc}{downrange}{high \optional{, low=0}}
Generates a downward range list of integers.
This function is modeled after the standard \code{range} function, but
works in the downward direction. The returned interval is half-open,
with the \var{high} index not included. \var{low} is optional and
defaults to zero. This function is especially useful in conjunction
with the \class{intbv} class, that also works with downward indexing.
\end{funcdesc}
\begin{funcdesc}{enum}{arg \optional{, arg \moreargs} \optional{, encoding='binary'}}
Returns an enumeration type.
The arguments should be string literals that represent the desired
names of the enumeration type attributes. The returned type should be
assigned to a type name. For example:
\begin{verbatim}
t_EnumType = enum('ATTR_NAME_1', 'ATTR_NAME_2', ...)
\end{verbatim}
The enumeration type identifiers are available as attributes of
the type name, for example: \code{t_EnumType.ATTR_NAME_1}
The optional keyword argument \var{encoding} specifies the encoding
scheme used in Verilog output. The available encodings are \code{'binary'},
\code{'one_hot'}, and \code{'one_cold'}.
\end{funcdesc}
\begin{funcdesc}{instances}{}
Looks up all \myhdl\ instances in the local name space and returns them
in a list.
\end{funcdesc}
\section{Co-simulation\label{ref-cosim}}
\declaremodule{}{myhdl}
\subsection{\myhdl\ \label{ref-cosim-myhdl}}
\begin{classdesc}{Cosimulation}{exe, **kwargs}
Class to construct a new Cosimulation object.
The \var{exe} argument is a command string to
execute an HDL simulation. The \var{kwargs} keyword
arguments provide a named association between signals
(regs \& nets) in the HDL simulator and signals in the
\myhdl\ simulator. Each keyword should be a name listed
in a \code{\$to_myhdl} or \code{\$from_myhdl} call in
the HDL code. Each argument should be a \class{Signal}
declared in the \myhdl\ code.
\end{classdesc}
\subsection{Verilog \label{ref-cosim-verilog}}
\begin{funcdesc}{\$to_myhdl}{arg, \optional{, arg \moreargs}}
Task that defines which signals (regs \& nets) should be
read by the \myhdl\ simulator.
This task should be called at the start of the simulation.
\end{funcdesc}
\begin{funcdesc}{\$from_myhdl}{arg, \optional{, arg \moreargs}}
Task that defines which signals should be
driven by the \myhdl\ simulator. In Verilog, only regs
can be specified.
This task should be called at the start of the simulation.
\end{funcdesc}
\subsection{VHDL \label{ref-cosim-vhdl}}
Not implemented yet.
\section{Conversion to Verilog\label{ref-conv}}
\declaremodule{}{myhdl}
\subsection{Conversion \label{ref-conv-conv}}
\begin{funcdesc}{toVerilog}{func \optional{, *args} \optional{, **kwargs}}
Converts a \myhdl\ design instance to equivalent Verilog
code, and also generates a test bench to verify it.
\var{func} is a function that returns an instance.
\function{toVerilog()} calls \var{func} under its control
and passes \var{*args} and \var{**kwargs} to the call.
The return value is the same as would be returned by the call
\code{func(*args, **kwargs)}. It should be assigned
to an instance name.
The top-level instance name and the basename of the Verilog output
filename is \code{func.func_name} by default.
For more information about the restrictions on convertible
\myhdl\ code, see section~\ref{conv-subset} in
Chapter~\ref{conv}.
\end{funcdesc}
The \function{toVerilog} callable has the following attribute:
\begin{memberdesc}[toVerilog]{name}
This attribute is used to overwrite the default top-level instance
name and the basename of the Verilog output filename.
\end{memberdesc}
\subsection{User-defined Verilog code \label{ref-conv-user}}
A user can insert user-defined code in the Verilog output
by using the \code{__verilog__} hook.
\begin{datadesc}{__verilog__}
When defined within a function under elaboration, the
\code{__verilog__} hook variable specifies user-defined code that
should be used instead of converted code for that function. The
user-defined code should be a Python format string that uses keys to
refer to the variables that should be interpolated in the string. Any
variable in the function context can be referred to.
Note that this hook cannot be used inside generator functions or
decorated local functions, as these are not elaborated.
\end{datadesc}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -1,379 +0,0 @@
\chapter{Unit testing \label{unittest}}
\section{Introduction \label{unittest-intro}}
Many aspects in the design flow of modern digital hardware design can
be viewed as a special kind of software development. From that
viewpoint, it is a natural question whether advances in software
design techniques can not also be applied to hardware design.
One software design approach that gets a lot of attention recently is
\index{extreme programming}%
\emph{Extreme Programming} (XP). It is a fascinating set of techniques and
guidelines that often seems to go against the conventional wisdom. On
other occasions, XP just seems to emphasize the common sense, which
doesn't always coincide with common practice. For example, XP stresses
the importance of normal workweeks, if we are to have the
fresh mind needed for good software development.
It is not my intention nor qualification to present a tutorial on
Extreme Programming. Instead, in this section I will highlight one XP
concept which I think is very relevant to hardware design: the
importance and methodology of unit testing.
\section{The importance of unit tests \label{unittest-why}}
Unit testing is one of the corner stones of Extreme Programming. Other
XP concepts, such as collective ownership of code and continuous
refinement, are only possible by having unit tests. Moreover, XP
emphasizes that writing unit tests should be automated, that they should
test everything in every class, and that they should run perfectly all
the time.
I believe that these concepts apply directly to hardware design. In
addition, unit tests are a way to manage simulation time. For example,
a state machine that runs very slowly on infrequent events may be
impossible to verify at the system level, even on the fastest
simulator. On the other hand, it may be easy to verify it exhaustively
in a unit test, even on the slowest simulator.
It is clear that unit tests have compelling advantages. On the other
hand, if we need to test everything, we have to write
lots of unit tests. So it should be easy and pleasant
to create, manage and run them. Therefore, XP emphasizes the need for
a unit test framework that supports these tasks. In this chapter,
we will explore the use of the \code{unittest} module from
the standard Python library for creating unit tests for hardware
designs.
\section{Unit test development \label{unittest-dev}}
In this section, we will informally explore the application of unit
test techniques to hardware design. We will do so by a (small)
example: testing a binary to Gray encoder as introduced in
section~\ref{intro-indexing}.
\subsection{Defining the requirements \label{unittest-req}}
We start by defining the requirements. For a Gray encoder, we want to
the output to comply with Gray code characteristics. Let's define a
\dfn{code} as a list of \dfn{codewords}, where a codeword is a bit
string. A code of order \code{n} has \code{2**n} codewords.
A well-known characteristic is the one that Gray codes are all about:
\newtheorem{reqGray}{Requirement}
\begin{reqGray}
Consecutive codewords in a Gray code should differ in a single bit.
\end{reqGray}
Is this sufficient? Not quite: suppose for example that an
implementation returns the lsb of each binary input. This would comply
with the requirement, but is obviously not what we want. Also, we don't
want the bit width of Gray codewords to exceed the bit width of the
binary codewords.
\begin{reqGray}
Each codeword in a Gray code of order n must occur exactly once in the
binary code of the same order.
\end{reqGray}
With the requirements written down we can proceed.
\subsection{Writing the test first \label{unittest-first}}
A fascinating guideline in the XP world is to write the unit test
first. That is, before implementing something, first write the test
that will verify it. This seems to go against our natural inclination,
and certainly against common practices. Many engineers like to
implement first and think about verification afterwards.
But if you think about it, it makes a lot of sense to deal with
verification first. Verification is about the requirements only --- so
your thoughts are not yet cluttered with implementation details. The
unit tests are an executable description of the requirements, so they
will be better understood and it will be very clear what needs to be
done. Consequently, the implementation should go smoother. Perhaps
most importantly, the test is available when you are done
implementing, and can be run anytime by anybody to verify changes.
Python has a standard \code{unittest} module that facilitates writing,
managing and running unit tests. With \code{unittest}, a test case is
written by creating a class that inherits from
\code{unittest.TestCase}. Individual tests are created by methods of
that class: all method names that start with \code{test} are
considered to be tests of the test case.
We will define a test case for the Gray code properties, and then
write a test for each of the requirements. The outline of the test
case class is as follows:
\begin{verbatim}
from unittest import TestCase
class TestGrayCodeProperties(TestCase):
def testSingleBitChange(self):
""" Check that only one bit changes in successive codewords """
....
def testUniqueCodeWords(self):
""" Check that all codewords occur exactly once """
....
\end{verbatim}
Each method will be a small test bench that tests a single
requirement. To write the tests, we don't need an implementation of
the Gray encoder, but we do need the interface of the design. We can
specify this by a dummy implementation, as follows:
\begin{verbatim}
def bin2gray(B, G, width):
### NOT IMPLEMENTED YET! ###
yield None
\end{verbatim}
For the first requirement, we will write a test bench that applies all
consecutive input numbers, and compares the current output with the
previous one for each input. Then we check that the difference is a
single bit. We will test all Gray codes up to a certain order
\code{MAX_WIDTH}.
\begin{verbatim}
def testSingleBitChange(self):
""" Check that only one bit changes in successive codewords """
def test(B, G, width):
B.next = intbv(0)
yield delay(10)
for i in range(1, 2**width):
G_Z.next = G
B.next = intbv(i)
yield delay(10)
diffcode = bin(G ^ G_Z)
self.assertEqual(diffcode.count('1'), 1)
for width in range(1, MAX_WIDTH):
B = Signal(intbv(-1))
G = Signal(intbv(0))
G_Z = Signal(intbv(0))
dut = bin2gray(B, G, width)
check = test(B, G, width)
sim = Simulation(dut, check)
sim.run(quiet=1)
\end{verbatim}
Note how the actual check is performed by a \code{self.assertEqual}
method, defined by the \code{unittest.TestCase} class.
Similarly, we write a test bench for the second requirement. Again, we
simulate all numbers, and put the result in a list. The requirement
implies that if we sort the result list, we should get a range of
numbers:
\begin{verbatim}
def testUniqueCodeWords(self):
""" Check that all codewords occur exactly once """
def test(B, G, width):
actual = []
for i in range(2**width):
B.next = intbv(i)
yield delay(10)
actual.append(int(G))
actual.sort()
expected = range(2**width)
self.assertEqual(actual, expected)
for width in range(1, MAX_WIDTH):
B = Signal(intbv(-1))
G = Signal(intbv(0))
dut = bin2gray(B, G, width)
check = test(B, G, width)
sim = Simulation(dut, check)
sim.run(quiet=1)
\end{verbatim}
\subsection{Test-driven implementation \label{unittest-impl}}
With the test written, we begin with the implementation. For
illustration purposes, we will intentionally write some incorrect
implementations to see how the test behaves.
The easiest way to run tests defined with the \code{unittest}
framework, is to put a call to its \code{main} method at the end of
the test module:
\begin{verbatim}
unittest.main()
\end{verbatim}
Let's run the test using the dummy Gray encoder shown earlier:
\begin{verbatim}
% python test_gray.py -v
Check that only one bit changes in successive codewords ... FAIL
Check that all codewords occur exactly once ... FAIL
<trace backs not shown>
\end{verbatim}
As expected, this fails completely. Let us try an incorrect
implementation, that puts the lsb of in the input on the output:
\begin{verbatim}
def bin2gray(B, G, width):
### INCORRECT - DEMO PURPOSE ONLY! ###
@always_comb
def logic():
G.next = B[0]
return logic
\end{verbatim}
Running the test produces:
\begin{verbatim}
% python test_gray.py -v
Check that only one bit changes in successive codewords ... ok
Check that all codewords occur exactly once ... FAIL
======================================================================
FAIL: Check that all codewords occur exactly once
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_gray.py", line 109, in testUniqueCodeWords
sim.run(quiet=1)
...
File "test_gray.py", line 104, in test
self.assertEqual(actual, expected)
File "/usr/local/lib/python2.2/unittest.py", line 286, in failUnlessEqual
raise self.failureException, \
AssertionError: [0, 0, 1, 1] != [0, 1, 2, 3]
----------------------------------------------------------------------
Ran 2 tests in 0.785s
\end{verbatim}
Now the test passes the first requirement, as expected, but fails the
second one. After the test feedback, a full traceback is shown that
can help to debug the test output.
Finally, if we use the correct implementation as in
section~\ref{intro-indexing}, the output is:
\begin{verbatim}
% python test_gray.py -v
Check that only one bit changes in successive codewords ... ok
Check that all codewords occur exactly once ... ok
----------------------------------------------------------------------
Ran 2 tests in 6.364s
OK
\end{verbatim}
\subsection{Changing requirements \label{unittest-change}}
In the previous section, we concentrated on the general requirements
of a Gray code. It is possible to specify these without specifying the
actual code. It is easy to see that there are several codes
that satisfy these requirements. In good XP style, we only tested
the requirements and nothing more.
It may be that more control is needed. For example, the requirement
may be for a particular code, instead of compliance with general
properties. As an illustration, we will show how to test for
\emph{the} original Gray code, which is one specific instance that
satisfies the requirements of the previous section. In this particular
case, this test will actually be easier than the previous one.
We denote the original Gray code of order \code{n} as \code{Ln}. Some
examples:
\begin{verbatim}
L1 = ['0', '1']
L2 = ['00', '01', '11', '10']
L3 = ['000', '001', '011', '010', '110', '111', '101', 100']
\end{verbatim}
It is possible to specify these codes by a recursive algorithm, as
follows:
\begin{enumerate}
\item L1 = ['0', '1']
\item Ln+1 can be obtained from Ln as follows. Create a new code Ln0 by
prefixing all codewords of Ln with '0'. Create another new code Ln1 by
prefixing all codewords of Ln with '1', and reversing their
order. Ln+1 is the concatenation of Ln0 and Ln1.
\end{enumerate}
Python is well-known for its elegant algorithmic
descriptions, and this is a good example. We can write the algorithm
in Python as follows:
\begin{verbatim}
def nextLn(Ln):
""" Return Gray code Ln+1, given Ln. """
Ln0 = ['0' + codeword for codeword in Ln]
Ln1 = ['1' + codeword for codeword in Ln]
Ln1.reverse()
return Ln0 + Ln1
\end{verbatim}
The code \samp{['0' + codeword for ...]} is called a \dfn{list
comprehension}. It is a concise way to describe lists built by short
computations in a for loop.
The requirement is now that the output code matches the
expected code Ln. We use the \code{nextLn} function to compute the
expected result. The new test case code is as follows:
\begin{verbatim}
class TestOriginalGrayCode(TestCase):
def testOriginalGrayCode(self):
""" Check that the code is an original Gray code """
Rn = []
def stimulus(B, G, n):
for i in range(2**n):
B.next = intbv(i)
yield delay(10)
Rn.append(bin(G, width=n))
Ln = ['0', '1'] # n == 1
for n in range(2, MAX_WIDTH):
Ln = nextLn(Ln)
del Rn[:]
B = Signal(intbv(-1))
G = Signal(intbv(0))
dut = bin2gray(B, G, n)
stim = stimulus(B, G, n)
sim = Simulation(dut, stim)
sim.run(quiet=1)
self.assertEqual(Ln, Rn)
\end{verbatim}
As it happens, our implementation is apparently an original Gray code:
\begin{verbatim}
% python test_gray.py -v TestOriginalGrayCode
Check that the code is an original Gray code ... ok
----------------------------------------------------------------------
Ran 1 tests in 3.091s
OK
\end{verbatim}

View File

@ -1,18 +0,0 @@
%
% Change this to say a4paper instead of letterpaper if you want A4. These
% are the latex defaults.
%
\newcommand{\py@paper}{a4paper}
\newcommand{\py@ptsize}{11pt}
% These set up the fonts for the documents.
%
% The "times" package makes the default font the PostScript Times
% font, which makes for smaller PostScript and a font that more people
% like.
%
% The "avant" package causes the AvantGarde font to be used for
% sans-serif text, instead of the uglier Helvetica set up by the "times"
% package.
%
% \RequirePackage{times}\typeout{Using Times instead of Computer Modern.}

View File

@ -1,18 +0,0 @@
%
% Change this to say a4paper instead of letterpaper if you want A4. These
% are the latex defaults.
%
\newcommand{\py@paper}{letterpaper}
\newcommand{\py@ptsize}{10pt}
% These set up the fonts for the documents.
%
% The "times" package makes the default font the PostScript Times
% font, which makes for smaller PostScript and a font that more people
% like.
%
% The "avant" package causes the AvantGarde font to be used for
% sans-serif text, instead of the uglier Helvetica set up by the "times"
% package.
%
% \RequirePackage{times}\typeout{Using Times instead of Computer Modern.}

View File

@ -1,95 +0,0 @@
package SynopsisTable;
sub new{
return bless {names=>'', info=>{}, file=>''};
}
sub declare{
my($self,$name,$key,$type) = @_;
if ($self->{names}) {
$self->{names} .= ",$name";
}
else {
$self->{names} .= "$name";
}
$self->{info}{$name} = "$key,$type,";
}
# The 'file' attribute is used to store the filename of the node in which
# the table will be presented; this assumes that each table will be presented
# only once, which works for the current use of this object.
sub set_file{
my($self, $filename) = @_;
$self->{file} = "$filename";
}
sub get_file{
my $self = shift;
return $self->{file};
}
sub set_synopsis{
my($self,$name,$synopsis) = @_;
my($key,$type,$unused) = split ',', $self->{info}{$name}, 3;
$self->{info}{$name} = "$key,$type,$synopsis";
}
sub get{
my($self,$name) = @_;
return split /,/, $self->{info}{$name}, 3;
}
sub show{
my $self = shift;
my $name;
print "names: ", $self->{names}, "\n\n";
foreach $name (split /,/, $self->{names}) {
my($key,$type,$synopsis) = $self->get($name);
print "$name($key) is $type: $synopsis\n";
}
}
sub tohtml{
my $self = shift;
my $oddrow = 1;
my $data = "<table class='synopsistable' valign='baseline'>\n";
my $name;
foreach $name (split /,/, $self->{names}) {
my($key,$type,$synopsis) = $self->get($name);
my $link = "<a href='module-$key.html'>";
$synopsis =~ s/<tex2html_percent_mark>/%/g;
$synopsis =~ s/<tex2html_ampersand_mark>/\&amp;/g;
$data .= (' <tr'
. ($oddrow ? " class='oddrow'>\n " : '>')
. "<td><b><tt class='module'>$link$name</a></tt></b></td>\n"
. " <td>\&nbsp;</td>\n"
. " <td class='synopsis'>$synopsis</td></tr>\n");
$oddrow = !$oddrow;
}
$data .= "</table>\n";
$data;
}
package testSynopsisTable;
sub test{
# this little test is mostly to debug the stuff above, since this is
# my first Perl "object".
my $st = SynopsisTable->new();
$st->declare("sample", "sample", "standard");
$st->set_synopsis("sample", "This is a little synopsis....");
$st->declare("copy_reg", "copyreg", "standard");
$st->set_synopsis("copy_reg", "pickle support stuff");
$st->show();
print "\n\n";
my $st2 = SynopsisTable->new();
$st2->declare("st2module", "st2module", "built-in");
$st2->set_synopsis("st2module", "silly little synopsis");
$st2->show();
}
1; # This must be the last line -- Perl is bogus!

View File

@ -1,21 +0,0 @@
# LaTeX2HTML support for distutils.sty.
package main;
sub do_cmd_command {
return use_wrappers(@_[0], '<code>', '</code>');
}
sub do_cmd_option {
return use_wrappers(@_[0], '<font face="sans-serif">', '</font>');
}
sub do_cmd_filevar {
return use_wrappers(@_[0], '<font face="sans-serif"><i>', '</i></font>');
}
sub do_cmd_XXX {
return use_wrappers(@_[0], '<b>** ', ' **</b>');
}
1;

View File

@ -1,12 +0,0 @@
# -*- perl -*-
#
# This implements the Python howto class. All it really needs to do it
# load the "python" style.
package main;
do_require_package("article");
do_require_package("alltt");
do_require_package("python");
1; # sheesh....

View File

@ -1,12 +0,0 @@
package main;
$USING_STYLES = 0;
$NO_NAVIGATION = 1;
$INDEX_COLUMNS = 1;
$MODULE_INDEX_COLUMNS = 1;
sub child_line {
return '';
}
1; # stupid perl...

View File

@ -1,672 +0,0 @@
# LaTeX2HTML support base for use with Python documentation.
package main;
use L2hos;
$HTML_VERSION = 4.0;
$MAX_LINK_DEPTH = 2;
$ADDRESS = '';
$NO_FOOTNODE = 1;
$NUMBERED_FOOTNOTES = 1;
# Python documentation uses section numbers to support references to match
# in the printed and online versions.
#
$SHOW_SECTION_NUMBERS = 1;
$ICONSERVER = '.';
$IMAGE_TYPE = 'gif';
# Control where the navigation bars should show up:
$TOP_NAVIGATION = 1;
$BOTTOM_NAVIGATION = 1;
$AUTO_NAVIGATION = 0;
$BODYTEXT = '';
$CHILDLINE = "\n<p><hr>\n";
$VERBOSITY = 0;
# default # of columns for the indexes
$INDEX_COLUMNS = 2;
$MODULE_INDEX_COLUMNS = 4;
$HAVE_MODULE_INDEX = 0;
$HAVE_GENERAL_INDEX = 0;
$HAVE_TABLE_OF_CONTENTS = 0;
$AESOP_META_TYPE = 'information';
# A little painful, but lets us clean up the top level directory a little,
# and not be tied to the current directory (as far as I can tell). Testing
# an existing definition of $mydir is needed since it cannot be computed when
# run under mkhowto with recent versions of LaTeX2HTML, since this file is
# not read directly by LaTeX2HTML any more. mkhowto is required to prepend
# the required definition at the top of the actual input file.
#
if (!defined $mydir) {
use Cwd;
use File::Basename;
($myname, $mydir, $myext) = fileparse(__FILE__, '\..*');
chop $mydir; # remove trailing '/'
$mydir = getcwd() . "$dd$mydir"
unless $mydir =~ s|^/|/|;
}
$LATEX2HTMLSTYLES = "$mydir$envkey$LATEX2HTMLSTYLES";
push (@INC, $mydir);
($myrootname, $myrootdir, $myext) = fileparse($mydir, '\..*');
chop $myrootdir;
# Hackish way to get the appropriate paper-*/ directory into $TEXINPUTS;
# pass in the paper size (a4 or letter) as the environment variable PAPER
# to add the right directory. If not given, the current directory is
# added instead for use with HOWTO processing.
#
if (defined $ENV{'PAPER'}) {
$mytexinputs = "$myrootdir${dd}paper-$ENV{'PAPER'}$envkey";
}
else {
$mytexinputs = getcwd() . $envkey;
}
$mytexinputs .= "$myrootdir${dd}texinputs";
# Change this variable to change the text added in "About this document...";
# this should be an absolute pathname to get it right.
#
$ABOUT_FILE = "$myrootdir${dd}html${dd}stdabout.dat";
sub custom_driver_hook {
#
# This adds the directory of the main input file to $TEXINPUTS; it
# seems to be sufficiently general that it should be fine for HOWTO
# processing.
#
my $file = $_[0];
my($jobname, $dir, $ext) = fileparse($file, '\..*');
$dir = L2hos->Make_directory_absolute($dir);
$dir =~ s/$dd$//;
$TEXINPUTS = "$dir$envkey$mytexinputs";
print "\nAdding $dir to \$TEXINPUTS\n";
}
$CUSTOM_BUTTONS = '';
sub make_nav_sectref($$) {
my($label, $title) = @_;
if ($title) {
if ($title =~ /\<[aA] /) {
$title =~ s/\<[aA] /<a class="sectref" /;
}
else {
$title = "<span class=\"sectref\">$title</span>";
}
return "<b class=\"navlabel\">$label:</b> $title\n";
}
return '';
}
@my_icon_tags = ();
$my_icon_tags{'next'} = 'Next Page';
$my_icon_tags{'next_page'} = 'Next Page';
$my_icon_tags{'previous'} = 'Previous Page';
$my_icon_tags{'previous_page'} = 'Previous Page';
$my_icon_tags{'up'} = 'Up One Level';
$my_icon_tags{'contents'} = 'Contents';
$my_icon_tags{'index'} = 'Index';
$my_icon_tags{'modules'} = 'Module Index';
@my_icon_names = ();
$my_icon_names{'previous_page'} = 'previous';
$my_icon_names{'next_page'} = 'next';
sub get_my_icon($) {
my $name = $_[0];
my $text = $my_icon_tags{$name};
if ($my_icon_names{$name}) {
$name = $my_icon_names{$name};
}
if ($text eq '') {
$name = 'blank';
}
my $iconserver = ($ICONSERVER eq '.') ? '' : "$ICONSERVER/";
return "<img src='$iconserver$name.$IMAGE_TYPE'\n border='0'"
. " height='32' alt='$text' width='32'>";
}
sub use_my_icon($) {
my $s = $_[0];
if ($s =~ /\<tex2html_([a-z_]+)_visible_mark\>/) {
my $r = get_my_icon($1);
$s =~ s/\<tex2html_[a-z_]+_visible_mark\>/$r/;
}
return $s;
}
sub make_nav_panel() {
my $s;
my $BLANK_ICON = get_my_icon('blank');
$NEXT = $NEXT_TITLE ? use_my_icon("$NEXT") : $BLANK_ICON;
$UP = $UP_TITLE ? use_my_icon("$UP") : $BLANK_ICON;
$PREVIOUS = $PREVIOUS_TITLE ? use_my_icon("$PREVIOUS") : $BLANK_ICON;
$CONTENTS = use_my_icon("$CONTENTS");
$INDEX = $INDEX ? use_my_icon("$INDEX") : $BLANK_ICON;
if (!$CUSTOM_BUTTONS) {
$CUSTOM_BUTTONS = $BLANK_ICON;
}
$s = ('<table align="center" width="100%" cellpadding="0" cellspacing="2">'
. "\n<tr>"
# left-hand side
. "\n<td>$PREVIOUS</td>"
. "\n<td>$UP</td>"
. "\n<td>$NEXT</td>"
# title box
. "\n<td align=\"center\" width=\"100%\">$t_title</td>"
# right-hand side
. "\n<td>$CONTENTS</td>"
. "\n<td>$CUSTOM_BUTTONS</td>" # module index
. "\n<td>$INDEX</td>"
. "\n</tr></table>\n"
# textual navigation
. make_nav_sectref("Previous", $PREVIOUS_TITLE)
. make_nav_sectref("Up", $UP_TITLE)
. make_nav_sectref("Next", $NEXT_TITLE)
);
# remove these; they are unnecessary and cause errors from validation
$s =~ s/ NAME="tex2html\d+"\n */ /g;
return $s;
}
sub add_child_links {
my $toc = add_real_child_links(@_);
$toc =~ s|\s*</[aA]>|</a>|g;
$toc =~ s/ NAME=\"tex2html\d+\"\s*href=/ href=/gi;
$toc =~ s|</UL>(\s*<BR>)?|</ul>|gi;
return $toc;
}
sub get_version_text() {
if ($PACKAGE_VERSION ne '' && $t_date) {
return ("<span class=\"release-info\">"
. "Release $PACKAGE_VERSION$RELEASE_INFO,"
. " documentation updated on $t_date.</span>");
}
if ($PACKAGE_VERSION ne '') {
return ("<span class=\"release-info\">"
. "Release $PACKAGE_VERSION$RELEASE_INFO.</span>");
}
if ($t_date) {
return ("<span class=\"release-info\">Documentation released on "
. "$t_date.</span>");
}
return '';
}
sub top_navigation_panel() {
return "\n"
. make_nav_panel()
. "<br><hr>\n";
}
sub bot_navigation_panel() {
return "\n<p><hr>\n"
. make_nav_panel()
. "<hr>\n"
. get_version_text()
. "\n";
}
sub add_link {
# Returns a pair (iconic link, textual link)
my($icon, $current_file, @link) = @_;
my($dummy, $file, $title) = split($delim,
$section_info{join(' ',@link)});
if ($icon =~ /\<tex2html_([_a-z]+)_visible_mark\>/) {
my $r = get_my_icon($1);
$icon =~ s/\<tex2html_[_a-z]+_visible_mark\>/$r/;
}
if ($title && ($file ne $current_file)) {
$title = purify($title);
$title = get_first_words($title, $WORDS_IN_NAVIGATION_PANEL_TITLES);
return (make_href($file, $icon), make_href($file, "$title"))
}
elsif ($icon eq get_my_icon('up') && $EXTERNAL_UP_LINK) {
return (make_href($EXTERNAL_UP_LINK, $icon),
make_href($EXTERNAL_UP_LINK, "$EXTERNAL_UP_TITLE"))
}
elsif ($icon eq get_my_icon('previous')
&& $EXTERNAL_PREV_LINK && $EXTERNAL_PREV_TITLE) {
return (make_href($EXTERNAL_PREV_LINK, $icon),
make_href($EXTERNAL_PREV_LINK, "$EXTERNAL_PREV_TITLE"))
}
elsif ($icon eq get_my_icon('next')
&& $EXTERNAL_DOWN_LINK && $EXTERNAL_DOWN_TITLE) {
return (make_href($EXTERNAL_DOWN_LINK, $icon),
make_href($EXTERNAL_DOWN_LINK, "$EXTERNAL_DOWN_TITLE"))
}
return (&inactive_img($icon), "");
}
sub add_special_link($$$) {
my($icon, $file, $current_file) = @_;
if ($icon =~ /\<tex2html_([_a-z]+)_visible_mark\>/) {
my $r = get_my_icon($1);
$icon =~ s/\<tex2html_[_a-z]+_visible_mark\>/$r/;
}
return (($file && ($file ne $current_file))
? make_href($file, $icon)
: undef)
}
# The img_tag() function seems only to be called with the parameter
# 'anchor_invisible_mark', which we want to turn into ''. Since
# replace_icon_marks() is the only interesting caller, and all it really
# does is call img_tag(), we can just define the hook alternative to be
# a no-op instead.
#
sub replace_icons_hook {}
sub do_cmd_arabic {
# get rid of that nasty <SPAN CLASS="arabic">...</SPAN>
my($ctr, $val, $id, $text) = &read_counter_value($_[0]);
return ($val ? farabic($val) : "0") . $text;
}
sub gen_index_id($$) {
# this is used to ensure common index key generation and a stable sort
my($str, $extra) = @_;
sprintf('%s###%s%010d', $str, $extra, ++$global{'max_id'});
}
sub insert_index($$$$$) {
my($mark, $datafile, $columns, $letters, $prefix) = @_;
my $prog = "$myrootdir/tools/buildindex.py";
my $index;
if ($letters) {
$index = `$prog --columns $columns --letters $datafile`;
}
else {
$index = `$prog --columns $columns $datafile`;
}
if (!s/$mark/$prefix$index/) {
print "\nCould not locate index mark: $mark";
}
}
sub add_idx() {
print "\nBuilding HTML for the index ...";
close(IDXFILE);
insert_index($idx_mark, 'index.dat', $INDEX_COLUMNS, 1, '');
}
$idx_module_mark = '<tex2html_idx_module_mark>';
$idx_module_title = 'Module Index';
sub add_module_idx() {
print "\nBuilding HTML for the module index ...";
my $key;
my $first = 1;
my $prevplat = '';
my $allthesame = 1;
my $prefix = '';
foreach $key (keys %Modules) {
$key =~ s/<tt>([a-zA-Z0-9._]*)<\/tt>/$1/;
my $plat = "$ModulePlatforms{$key}";
$plat = ''
if ($plat eq $IGNORE_PLATFORM_ANNOTATION);
if (!$first) {
$allthesame = 0
if ($prevplat ne $plat);
}
else { $first = 0; }
$prevplat = $plat;
}
open(MODIDXFILE, '>modindex.dat') || die "\n$!\n";
foreach $key (keys %Modules) {
# dump the line in the data file; just use a dummy seqno field
my $nkey = $1;
my $moditem = "$Modules{$key}";
my $plat = '';
$key =~ s/<tt>([a-zA-Z0-9._]*)<\/tt>/$1/;
if ($ModulePlatforms{$key} && !$allthesame) {
$plat = (" <em>(<span class=\"platform\">$ModulePlatforms{$key}"
. '</span>)</em>');
}
print MODIDXFILE $moditem . $IDXFILE_FIELD_SEP
. "<tt class=\"module\">$key</tt>$plat###\n";
}
close(MODIDXFILE);
if ($GLOBAL_MODULE_INDEX) {
$prefix = <<MODULE_INDEX_PREFIX;
<p> This index only lists modules documented in this manual.
The <em class="citetitle"><a href="$GLOBAL_MODULE_INDEX">Global Module
Index</a></em> lists all modules that are documented in this set
of manuals.</p>
MODULE_INDEX_PREFIX
}
if (!$allthesame) {
$prefix .= <<PLAT_DISCUSS;
<p> Some module names are followed by an annotation indicating what
platform they are available on.</p>
PLAT_DISCUSS
}
insert_index($idx_module_mark, 'modindex.dat', $MODULE_INDEX_COLUMNS, 0,
$prefix);
}
# replace both indexes as needed:
sub add_idx_hook {
add_idx() if (/$idx_mark/);
process_python_state();
if ($MODULE_INDEX_FILE) {
local ($_);
open(MYFILE, "<$MODULE_INDEX_FILE");
sysread(MYFILE, $_, 1024*1024);
close(MYFILE);
add_module_idx();
open(MYFILE,">$MODULE_INDEX_FILE");
print MYFILE $_;
close(MYFILE);
}
}
# In addition to the standard stuff, add label to allow named node files and
# support suppression of the page complete (for HTML Help use).
sub do_cmd_tableofcontents {
local($_) = @_;
$TITLE = $toc_title;
$tocfile = $CURRENT_FILE;
my($closures, $reopens) = preserve_open_tags();
anchor_label('contents', $CURRENT_FILE, $_); # this is added
join('', "<BR>\n\\tableofchildlinks[off]", $closures
, make_section_heading($toc_title, 'H2'), $toc_mark
, $reopens, $_);
}
# In addition to the standard stuff, add label to allow named node files.
sub do_cmd_listoffigures {
local($_) = @_;
$TITLE = $lof_title;
$loffile = $CURRENT_FILE;
my($closures, $reopens) = preserve_open_tags();
anchor_label('lof', $CURRENT_FILE, $_); # this is added
join('', "<BR>\n", $closures
, make_section_heading($lof_title, 'H2'), $lof_mark
, $reopens, $_);
}
# In addition to the standard stuff, add label to allow named node files.
sub do_cmd_listoftables {
local($_) = @_;
$TITLE = $lot_title;
$lotfile = $CURRENT_FILE;
my($closures, $reopens) = preserve_open_tags();
anchor_label('lot', $CURRENT_FILE, $_); # this is added
join('', "<BR>\n", $closures
, make_section_heading($lot_title, 'H2'), $lot_mark
, $reopens, $_);
}
# In addition to the standard stuff, add label to allow named node files.
sub do_cmd_textohtmlinfopage {
local($_) = @_;
if ($INFO) { #
anchor_label("about",$CURRENT_FILE,$_); # this is added
} #
my $the_version = ''; # and the rest is
if ($t_date) { # mostly ours
$the_version = ",\n$t_date";
if ($PACKAGE_VERSION) {
$the_version .= ", Release $PACKAGE_VERSION$RELEASE_INFO";
}
}
my $about;
open(ABOUT, "<$ABOUT_FILE") || die "\n$!\n";
sysread(ABOUT, $about, 1024*1024);
close(ABOUT);
$_ = (($INFO == 1)
? join('',
$close_all,
"<strong>$t_title</strong>$the_version\n",
$about,
$open_all, $_)
: join('', $close_all, $INFO,"\n", $open_all, $_));
$_;
}
# $idx_mark will be replaced with the real index at the end
sub do_cmd_textohtmlindex {
local($_) = @_;
$TITLE = $idx_title;
$idxfile = $CURRENT_FILE;
if (%index_labels) { make_index_labels(); }
if (($SHORT_INDEX) && (%index_segment)) { make_preindex(); }
else { $preindex = ''; }
my $heading = make_section_heading($idx_title, 'h2') . $idx_mark;
my($pre, $post) = minimize_open_tags($heading);
anchor_label('genindex',$CURRENT_FILE,$_); # this is added
return "<br>\n" . $pre . $_;
}
$MODULE_INDEX_FILE = '';
# $idx_module_mark will be replaced with the real index at the end
sub do_cmd_textohtmlmoduleindex {
local($_) = @_;
$TITLE = $idx_module_title;
anchor_label('modindex', $CURRENT_FILE, $_);
$MODULE_INDEX_FILE = "$CURRENT_FILE";
$_ = ('<p>' . make_section_heading($idx_module_title, 'h2')
. $idx_module_mark . $_);
return $_;
}
# The bibliography and the index should be treated as separate
# sections in their own HTML files. The \bibliography{} command acts
# as a sectioning command that has the desired effect. But when the
# bibliography is constructed manually using the thebibliography
# environment, or when using the theindex environment it is not
# possible to use the normal sectioning mechanism. This subroutine
# inserts a \bibliography{} or a dummy \textohtmlindex command just
# before the appropriate environments to force sectioning.
# XXX This *assumes* that if there are two {theindex} environments,
# the first is the module index and the second is the standard
# index. This is sufficient for the current Python documentation,
# but that's about it.
sub add_bbl_and_idx_dummy_commands {
my $id = $global{'max_id'};
if (/[\\]tableofcontents/) {
$HAVE_TABLE_OF_CONTENTS = 1;
}
s/([\\]begin\s*$O\d+$C\s*thebibliography)/$bbl_cnt++; $1/eg;
s/([\\]begin\s*$O\d+$C\s*thebibliography)/$id++; "\\bibliography$O$id$C$O$id$C $1"/geo;
my(@parts) = split(/\\begin\s*$O\d+$C\s*theindex/);
if (scalar(@parts) == 3) {
# Be careful to re-write the string in place, since $_ is *not*
# returned explicity; *** nasty side-effect dependency! ***
print "\nadd_bbl_and_idx_dummy_commands ==> adding general index";
print "\nadd_bbl_and_idx_dummy_commands ==> adding module index";
my $rx = "([\\\\]begin\\s*$O\\d+$C\\s*theindex[\\s\\S]*)"
. "([\\\\]begin\\s*$O\\d+$C\\s*theindex)";
s/$rx/\\textohtmlmoduleindex $1 \\textohtmlindex $2/o;
# Add a button to the navigation areas:
$CUSTOM_BUTTONS .= ('<a href="modindex.html" title="Module Index">'
. get_my_icon('modules')
. '</a>');
$HAVE_MODULE_INDEX = 1;
$HAVE_GENERAL_INDEX = 1;
}
elsif (scalar(@parts) == 2) {
print "\nadd_bbl_and_idx_dummy_commands ==> adding general index";
my $rx = "([\\\\]begin\\s*$O\\d+$C\\s*theindex)";
s/$rx/\\textohtmlindex $1/o;
$HAVE_GENERAL_INDEX = 1;
}
elsif (scalar(@parts) == 1) {
print "\nadd_bbl_and_idx_dummy_commands ==> no index found";
$CUSTOM_BUTTONS .= get_my_icon('blank');
$global{'max_id'} = $id; # not sure why....
s/([\\]begin\s*$O\d+$C\s*theindex)/\\textohtmlindex $1/o;
s/[\\]printindex/\\textohtmlindex /o;
}
else {
die "\n\nBad number of index environments!\n\n";
}
#----------------------------------------------------------------------
lib_add_bbl_and_idx_dummy_commands()
if defined(&lib_add_bbl_and_idx_dummy_commands);
}
# The bibliographic references, the appendices, the lists of figures
# and tables etc. must appear in the contents table at the same level
# as the outermost sectioning command. This subroutine finds what is
# the outermost level and sets the above to the same level;
sub set_depth_levels {
# Sets $outermost_level
my $level;
#RRM: do not alter user-set value for $MAX_SPLIT_DEPTH
foreach $level ("part", "chapter", "section", "subsection",
"subsubsection", "paragraph") {
last if (($outermost_level) = /\\($level)$delimiter_rx/);
}
$level = ($outermost_level ? $section_commands{$outermost_level} :
do {$outermost_level = 'section'; 3;});
#RRM: but calculate value for $MAX_SPLIT_DEPTH when a $REL_DEPTH was given
if ($REL_DEPTH && $MAX_SPLIT_DEPTH) {
$MAX_SPLIT_DEPTH = $level + $MAX_SPLIT_DEPTH;
} elsif (!($MAX_SPLIT_DEPTH)) { $MAX_SPLIT_DEPTH = 1 };
%unnumbered_section_commands = ('tableofcontents' => $level,
'listoffigures' => $level,
'listoftables' => $level,
'bibliography' => $level,
'textohtmlindex' => $level,
'textohtmlmoduleindex' => $level);
$section_headings{'textohtmlmoduleindex'} = 'h1';
%section_commands = (%unnumbered_section_commands,
%section_commands);
make_sections_rx();
}
# This changes the markup used for {verbatim} environments, and is the
# best way I've found that ensures the <dl> goes on the outside of the
# <pre>...</pre>.
#
# Note that this *must* be done in the init file, not the python.perl
# style support file. The %declarations must be set before
# initialize() is called in the main LaTeX2HTML script (which happens
# before style files are loaded).
#
%declarations = ('preform' => '<div class="verbatim"><pre></pre></div>',
%declarations);
# This is added to get rid of the long comment that follows the
# doctype declaration; MSIE5 on NT4 SP4 barfs on it and drops the
# content of the page.
$MY_PARTIAL_HEADER = '';
sub make_head_and_body($$) {
my($title, $body) = @_;
$body = " $body" unless ($body eq '');
my $DTDcomment = '';
my($version, $isolanguage) = ($HTML_VERSION, 'EN');
my %isolanguages = ( 'english', 'EN' , 'USenglish', 'EN.US'
, 'original', 'EN' , 'german' , 'DE'
, 'austrian', 'DE.AT', 'french' , 'FR'
, 'spanish', 'ES');
$isolanguage = $isolanguages{$default_language};
$isolanguage = 'EN' unless $isolanguage;
$title = &purify($title,1);
eval("\$title = ". $default_title ) unless ($title);
# allow user-modification of the <TITLE> tag; thanks Dan Young
if (defined &custom_TITLE_hook) {
$title = &custom_TITLE_hook($title, $toc_sec_title);
}
if ($DOCTYPE =~ /\/\/[\w\.]+\s*$/) { # language spec included
$DTDcomment = "<!DOCTYPE html PUBLIC \"$DOCTYPE\">\n";
} else {
$DTDcomment = "<!DOCTYPE html PUBLIC \"$DOCTYPE//"
. ($ISO_LANGUAGE ? $ISO_LANGUAGE : $isolanguage) . "\">\n";
}
if ($MY_PARTIAL_HEADER eq '') {
$STYLESHEET = $FILE.".css" unless $STYLESHEET;
$MY_PARTIAL_HEADER = join('',
($DOCTYPE ? $DTDcomment : ''),
"<html>\n<head>\n",
($BASE ? "<base href=\"$BASE\">\n" : ''),
"<link rel=\"STYLESHEET\" href=\"$STYLESHEET\" type='text/css'>\n",
($FAVORITES_ICON
? ('<link rel="SHORTCUT ICON" href="' . "$FAVORITES_ICON\">\n")
: ''),
($EXTERNAL_UP_LINK
? ('<link rel="start" href="' . "$EXTERNAL_UP_LINK\""
. ($EXTERNAL_UP_TITLE ? " title='$EXTERNAL_UP_TITLE'" : '')
. ">\n")
: ''),
"<link rel=\"first\" href=\"$FILE.html\"",
($t_title ? " title='$t_title'" : ''),
">\n",
($HAVE_TABLE_OF_CONTENTS
? ('<link rel="contents" href="contents.html" title="Contents">'
. ($HAVE_GENERAL_INDEX ? "\n" : ''))
: ''),
($HAVE_GENERAL_INDEX
? '<link rel="index" href="genindex.html" title="Index">' . "\n"
: ''),
# disable for now -- Mozilla doesn't do well with multiple indexes
# ($HAVE_MODULE_INDEX
# ? '<link rel="index" href="modindex.html" title="Module Index">'
# . "\n"
# : ''),
($INFO
# XXX We can do this with the Python tools since the About...
# page always gets copied to about.html, even when we use the
# generated node###.html page names. Won't work with the
# rest of the Python doc tools.
? ("<link rel='last' href='about.html'"
. " title='About this document...'>\n"
. "<link rel='help' href='about.html'"
. " title='About this document...'>\n")
: ''),
$more_links_mark,
"\n",
($CHARSET && $HTML_VERSION ge "2.1"
? ('<meta http-equiv="Content-Type" content="text/html; '
. "charset=$CHARSET\">\n")
: ''),
($AESOP_META_TYPE
? "<meta name='aesop' content='$AESOP_META_TYPE'>\n" : ''));
}
if (!$charset && $CHARSET) {
$charset = $CHARSET;
$charset =~ s/_/\-/go;
}
join('',
$MY_PARTIAL_HEADER,
&meta_information($title),
"<title>", $title, "</title>\n</head>\n<body$body>");
}
1; # This must be the last line

View File

@ -1,67 +0,0 @@
# LaTeX2HTML support for the ltxmarkup package. Doesn't do indexing.
package main;
sub ltx_next_argument{
my $param;
$param = missing_braces()
unless ((s/$next_pair_pr_rx/$param=$2;''/eo)
||(s/$next_pair_rx/$param=$2;''/eo));
return $param;
}
sub do_cmd_macro{
local($_) = @_;
my $macro = ltx_next_argument();
return "<tt class='macro'>&#92;$macro</tt>" . $_;
}
sub do_cmd_env{
local($_) = @_;
my $env = ltx_next_argument();
return "<tt class='environment'>&#92;$env</tt>" . $_;
}
sub ltx_process_params{
# Handle processing of \p and \op for parameter specifications for
# envdesc and macrodesc. It's done this way to avoid defining do_cmd_p()
# and do_cmd_op() functions, which would be interpreted outside the context
# in which these commands are legal, and cause LaTeX2HTML to think they're
# defined. This way, other uses of \p and \op are properly flagged as
# unknown macros.
my $s = @_[0];
$s =~ s%\\op<<(\d+)>>(.+)<<\1>>%<tt>[</tt><var>$2</var><tt>]</tt>%;
while ($s =~ /\\p<<(\d+)>>(.+)<<\1>>/) {
$s =~ s%\\p<<(\d+)>>(.+)<<\1>>%<tt>{</tt><var>$2</var><tt>}</tt>%;
}
return $s;
}
sub do_env_macrodesc{
local($_) = @_;
my $macro = ltx_next_argument();
my $params = ltx_process_params(ltx_next_argument());
return "\n<dl class='macrodesc'>"
. "\n<dt><b><tt class='macro'>&#92;$macro</tt></b>"
. "\n $params"
. "\n<dd>"
. $_
. "</dl>";
}
sub do_env_envdesc{
local($_) = @_;
my $env = ltx_next_argument();
my $params = ltx_process_params(ltx_next_argument());
return "\n<dl class='envdesc'>"
. "\n<dt><tt>&#92;begin{<b class='environment'>$env</b>}</tt>"
. "\n $params"
. "\n<br /><tt>&#92;end{<b class='environment'>$env</b>}</tt>"
. "\n<dd>"
. $_
. "</dl>";
}
1; # Must end with this, because Perl is bogus.

View File

@ -1,15 +0,0 @@
# -*- perl -*-
#
# This implements the Python manual class. All it really needs to do it
# load the "python" style. The style code is not moved into the class code
# at this time, since we expect additional document class to be developed
# for the Python documentation in the future. Appropriate relocations will
# be made at that time.
package main;
do_require_package("report");
do_require_package("alltt");
do_require_package("python");
1; # sheesh....

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +0,0 @@
# tex
TEXINPUTS=".:./texinputs:"
export TEXINPUTS

View File

@ -1,9 +0,0 @@
\author{Jan Decaluwe}
\authoraddress{
Email: \email{jan@jandecaluwe.com}
}
\date{May 1, 2006} % XXX update before release!
\release{0.5.1} % software release, not documentation
\setreleaseinfo{} % empty for final release
\setshortversion{0.5} % major.minor only for software

View File

@ -1,2 +0,0 @@
Copyright \copyright{} 2003-2006 Jan Decaluwe.
All rights reserved.

View File

@ -1,33 +0,0 @@
%
% LaTeX commands and macros needed for the two Distutils manuals,
% inst.tex and dist.tex.
%
% $Id$
%
% My gripe list about the Python style files:
% * I want italics in verbatim environments for variable
% text (verbatim.sty?)
% * I hate escaping underscores (url.sty fixes this)
% '\command' is for Distutils commands which, depending on your
% perspective, are just arguments to the setup script, or sub-
% commands of the setup script, or the classes that implement
% each "command".
\newcommand{\command}[1]{\code{#1}}
% '\option' is for Distutils options *in* the setup script. Command-
% line options *to* the setup script are marked up in the usual
% way, ie. with '\programopt' or '\longprogramopt'
\newcommand{\option}[1]{\textsf{\small{#1}}}
% '\filevar' is for variable components of file/path names -- eg.
% when you put 'prefix' in a pathname, you mark it up with
% '\filevar' so that it still looks pathname-ish, but is
% distinguished from the literal part of the path. Fred says
% this can be accomplished just fine with '\var', but I violently
% disagree. Pistols at dawn will sort this one out.
\newcommand{\filevar}[1]{{\textsl{\filenq{#1}}}}
% Just while the code and docs are still under development.
\newcommand{\XXX}[1]{\textbf{**#1**}}

View File

@ -1,329 +0,0 @@
% fancyhdr.sty version 1.99d
% Fancy headers and footers for LaTeX.
% Piet van Oostrum, Dept of Computer Science, University of Utrecht
% Padualaan 14, P.O. Box 80.089, 3508 TB Utrecht, The Netherlands
% Telephone: +31 30 2532180. Email: piet@cs.ruu.nl
% ========================================================================
% LICENCE: This is free software. You are allowed to use and distribute
% this software in any way you like. You are also allowed to make modified
% versions of it, but you can distribute a modified version only if you
% clearly indicate that it is a modified version and the person(s) who
% modified it. This indication should be in a prominent place, e.g. in the
% top of the file. If possible a contact address, preferably by email,
% should be given for these persons. If that is feasible the modifications
% should be indicated in the source code.
% ========================================================================
% MODIFICATION HISTORY:
% Sep 16, 1994
% version 1.4: Correction for use with \reversemargin
% Sep 29, 1994:
% version 1.5: Added the \iftopfloat, \ifbotfloat and \iffloatpage commands
% Oct 4, 1994:
% version 1.6: Reset single spacing in headers/footers for use with
% setspace.sty or doublespace.sty
% Oct 4, 1994:
% version 1.7: changed \let\@mkboth\markboth to
% \def\@mkboth{\protect\markboth} to make it more robust
% Dec 5, 1994:
% version 1.8: corrections for amsbook/amsart: define \@chapapp and (more
% importantly) use the \chapter/sectionmark definitions from ps@headings if
% they exist (which should be true for all standard classes).
% May 31, 1995:
% version 1.9: The proposed \renewcommand{\headrulewidth}{\iffloatpage...
% construction in the doc did not work properly with the fancyplain style.
% June 1, 1995:
% version 1.91: The definition of \@mkboth wasn't restored on subsequent
% \pagestyle{fancy}'s.
% June 1, 1995:
% version 1.92: The sequence \pagestyle{fancyplain} \pagestyle{plain}
% \pagestyle{fancy} would erroneously select the plain version.
% June 1, 1995:
% version 1.93: \fancypagestyle command added.
% Dec 11, 1995:
% version 1.94: suggested by Conrad Hughes <chughes@maths.tcd.ie>
% CJCH, Dec 11, 1995: added \footruleskip to allow control over footrule
% position (old hardcoded value of .3\normalbaselineskip is far too high
% when used with very small footer fonts).
% Jan 31, 1996:
% version 1.95: call \@normalsize in the reset code if that is defined,
% otherwise \normalsize.
% this is to solve a problem with ucthesis.cls, as this doesn't
% define \@currsize. Unfortunately for latex209 calling \normalsize doesn't
% work as this is optimized to do very little, so there \@normalsize should
% be called. Hopefully this code works for all versions of LaTeX known to
% mankind.
% April 25, 1996:
% version 1.96: initialize \headwidth to a magic (negative) value to catch
% most common cases that people change it before calling \pagestyle{fancy}.
% Note it can't be initialized when reading in this file, because
% \textwidth could be changed afterwards. This is quite probable.
% We also switch to \MakeUppercase rather than \uppercase and introduce a
% \nouppercase command for use in headers. and footers.
% May 3, 1996:
% version 1.97: Two changes:
% 1. Undo the change in version 1.8 (using the pagestyle{headings} defaults
% for the chapter and section marks. The current version of amsbook and
% amsart classes don't seem to need them anymore. Moreover the standard
% latex classes don't use \markboth if twoside isn't selected, and this is
% confusing as \leftmark doesn't work as expected.
% 2. include a call to \ps@empty in ps@@fancy. This is to solve a problem
% in the amsbook and amsart classes, that make global changes to \topskip,
% which are reset in \ps@empty. Hopefully this doesn't break other things.
% May 7, 1996:
% version 1.98:
% Added % after the line \def\nouppercase
% May 7, 1996:
% version 1.99: This is the alpha version of fancyhdr 2.0
% Introduced the new commands \fancyhead, \fancyfoot, and \fancyhf.
% Changed \headrulewidth, \footrulewidth, \footruleskip to
% macros rather than length parameters, In this way they can be
% conditionalized and they don't consume length registers. There is no need
% to have them as length registers unless you want to do calculations with
% them, which is unlikely. Note that this may make some uses of them
% incompatible (i.e. if you have a file that uses \setlength or \xxxx=)
% May 10, 1996:
% version 1.99a:
% Added a few more % signs
% May 10, 1996:
% version 1.99b:
% Changed the syntax of \f@nfor to be resistent to catcode changes of :=
% Removed the [1] from the defs of \lhead etc. because the parameter is
% consumed by the \@[xy]lhead etc. macros.
% June 24, 1997:
% version 1.99c:
% corrected \nouppercase to also include the protected form of \MakeUppercase
% \global added to manipulation of \headwidth.
% \iffootnote command added.
% Some comments added about \@fancyhead and \@fancyfoot.
% Aug 24, 1998
% version 1.99d
% Changed the default \ps@empty to \ps@@empty in order to allow
% \fancypagestyle{empty} redefinition.
\let\fancy@def\gdef
\def\if@mpty#1#2#3{\def\temp@ty{#1}\ifx\@empty\temp@ty #2\else#3\fi}
% Usage: \@forc \var{charstring}{command to be executed for each char}
% This is similar to LaTeX's \@tfor, but expands the charstring.
\def\@forc#1#2#3{\expandafter\f@rc\expandafter#1\expandafter{#2}{#3}}
\def\f@rc#1#2#3{\def\temp@ty{#2}\ifx\@empty\temp@ty\else
\f@@rc#1#2\f@@rc{#3}\fi}
\def\f@@rc#1#2#3\f@@rc#4{\def#1{#2}#4\f@rc#1{#3}{#4}}
% Usage: \f@nfor\name:=list\do{body}
% Like LaTeX's \@for but an empty list is treated as a list with an empty
% element
\newcommand{\f@nfor}[3]{\edef\@fortmp{#2}%
\expandafter\@forloop#2,\@nil,\@nil\@@#1{#3}}
% Usage: \def@ult \cs{defaults}{argument}
% sets \cs to the characters from defaults appearing in argument
% or defaults if it would be empty. All characters are lowercased.
\newcommand\def@ult[3]{%
\edef\temp@a{\lowercase{\edef\noexpand\temp@a{#3}}}\temp@a
\def#1{}%
\@forc\tmpf@ra{#2}%
{\expandafter\if@in\tmpf@ra\temp@a{\edef#1{#1\tmpf@ra}}{}}%
\ifx\@empty#1\def#1{#2}\fi}
%
% \if@in <char><set><truecase><falsecase>
%
\newcommand{\if@in}[4]{%
\edef\temp@a{#2}\def\temp@b##1#1##2\temp@b{\def\temp@b{##1}}%
\expandafter\temp@b#2#1\temp@b\ifx\temp@a\temp@b #4\else #3\fi}
\newcommand{\fancyhead}{\@ifnextchar[{\f@ncyhf h}{\f@ncyhf h[]}}
\newcommand{\fancyfoot}{\@ifnextchar[{\f@ncyhf f}{\f@ncyhf f[]}}
\newcommand{\fancyhf}{\@ifnextchar[{\f@ncyhf {}}{\f@ncyhf {}[]}}
% The header and footer fields are stored in command sequences with
% names of the form: \f@ncy<x><y><z> with <x> for [eo], <y> form [lcr]
% and <z> from [hf].
\def\f@ncyhf#1[#2]#3{%
\def\temp@c{}%
\@forc\tmpf@ra{#2}%
{\expandafter\if@in\tmpf@ra{eolcrhf,EOLCRHF}%
{}{\edef\temp@c{\temp@c\tmpf@ra}}}%
\ifx\@empty\temp@c\else
\ifx\PackageError\undefined
\errmessage{Illegal char `\temp@c' in fancyhdr argument:
[#2]}\else
\PackageError{Fancyhdr}{Illegal char `\temp@c' in fancyhdr argument:
[#2]}{}\fi
\fi
\f@nfor\temp@c{#2}%
{\def@ult\f@@@eo{eo}\temp@c
\def@ult\f@@@lcr{lcr}\temp@c
\def@ult\f@@@hf{hf}{#1\temp@c}%
\@forc\f@@eo\f@@@eo
{\@forc\f@@lcr\f@@@lcr
{\@forc\f@@hf\f@@@hf
{\expandafter\fancy@def\csname
f@ncy\f@@eo\f@@lcr\f@@hf\endcsname
{#3}}}}}}
% Fancyheadings version 1 commands. These are more or less deprecated,
% but they continue to work.
\newcommand{\lhead}{\@ifnextchar[{\@xlhead}{\@ylhead}}
\def\@xlhead[#1]#2{\fancy@def\f@ncyelh{#1}\fancy@def\f@ncyolh{#2}}
\def\@ylhead#1{\fancy@def\f@ncyelh{#1}\fancy@def\f@ncyolh{#1}}
\newcommand{\chead}{\@ifnextchar[{\@xchead}{\@ychead}}
\def\@xchead[#1]#2{\fancy@def\f@ncyech{#1}\fancy@def\f@ncyoch{#2}}
\def\@ychead#1{\fancy@def\f@ncyech{#1}\fancy@def\f@ncyoch{#1}}
\newcommand{\rhead}{\@ifnextchar[{\@xrhead}{\@yrhead}}
\def\@xrhead[#1]#2{\fancy@def\f@ncyerh{#1}\fancy@def\f@ncyorh{#2}}
\def\@yrhead#1{\fancy@def\f@ncyerh{#1}\fancy@def\f@ncyorh{#1}}
\newcommand{\lfoot}{\@ifnextchar[{\@xlfoot}{\@ylfoot}}
\def\@xlfoot[#1]#2{\fancy@def\f@ncyelf{#1}\fancy@def\f@ncyolf{#2}}
\def\@ylfoot#1{\fancy@def\f@ncyelf{#1}\fancy@def\f@ncyolf{#1}}
\newcommand{\cfoot}{\@ifnextchar[{\@xcfoot}{\@ycfoot}}
\def\@xcfoot[#1]#2{\fancy@def\f@ncyecf{#1}\fancy@def\f@ncyocf{#2}}
\def\@ycfoot#1{\fancy@def\f@ncyecf{#1}\fancy@def\f@ncyocf{#1}}
\newcommand{\rfoot}{\@ifnextchar[{\@xrfoot}{\@yrfoot}}
\def\@xrfoot[#1]#2{\fancy@def\f@ncyerf{#1}\fancy@def\f@ncyorf{#2}}
\def\@yrfoot#1{\fancy@def\f@ncyerf{#1}\fancy@def\f@ncyorf{#1}}
\newdimen\headwidth
\newcommand{\headrulewidth}{0.4pt}
\newcommand{\footrulewidth}{\z@skip}
\newcommand{\footruleskip}{.3\normalbaselineskip}
% Fancyplain stuff shouldn't be used anymore (rather
% \fancypagestyle{plain} should be used), but it must be present for
% compatibility reasons.
\newcommand{\plainheadrulewidth}{\z@skip}
\newcommand{\plainfootrulewidth}{\z@skip}
\newif\if@fancyplain \@fancyplainfalse
\def\fancyplain#1#2{\if@fancyplain#1\else#2\fi}
\headwidth=-123456789sp %magic constant
% Command to reset various things in the headers:
% a.o. single spacing (taken from setspace.sty)
% and the catcode of ^^M (so that epsf files in the header work if a
% verbatim crosses a page boundary)
% It also defines a \nouppercase command that disables \uppercase and
% \Makeuppercase. It can only be used in the headers and footers.
\def\fancy@reset{\restorecr
\def\baselinestretch{1}%
\def\nouppercase##1{{\let\uppercase\relax\let\MakeUppercase\relax
\expandafter\let\csname MakeUppercase \endcsname\relax##1}}%
\ifx\undefined\@newbaseline% NFSS not present; 2.09 or 2e
\ifx\@normalsize\undefined \normalsize % for ucthesis.cls
\else \@normalsize \fi
\else% NFSS (2.09) present
\@newbaseline%
\fi}
% Initialization of the head and foot text.
% The default values still contain \fancyplain for compatibility.
\fancyhf{} % clear all
% lefthead empty on ``plain'' pages, \rightmark on even, \leftmark on odd pages
% evenhead empty on ``plain'' pages, \leftmark on even, \rightmark on odd pages
\fancyhead[el,or]{\fancyplain{}{\sl\rightmark}}
\fancyhead[er,ol]{\fancyplain{}{\sl\leftmark}}
\fancyfoot[c]{\rm\thepage} % page number
% Put together a header or footer given the left, center and
% right text, fillers at left and right and a rule.
% The \lap commands put the text into an hbox of zero size,
% so overlapping text does not generate an errormessage.
% These macros have 5 parameters:
% 1. \@lodd or \@rodd % This determines at which side the header will stick
% out.
% 2. \f@ncyolh, \f@ncyelh, \f@ncyolf or \f@ncyelf. This is the left component.
% 3. \f@ncyoch, \f@ncyech, \f@ncyocf or \f@ncyecf. This is the middle comp.
% 4. \f@ncyorh, \f@ncyerh, \f@ncyorf or \f@ncyerf. This is the right component.
% 5. \@lodd or \@rodd % This determines at which side the header will stick
% out. This is the reverse of parameter nr. 1. One of them is always
% \relax and the other one is \hss (after expansion).
\def\@fancyhead#1#2#3#4#5{#1\hbox to\headwidth{\fancy@reset\vbox{\hbox
{\rlap{\parbox[b]{\headwidth}{\raggedright#2\strut}}\hfill
\parbox[b]{\headwidth}{\centering#3\strut}\hfill
\llap{\parbox[b]{\headwidth}{\raggedleft#4\strut}}}\headrule}}#5}
\def\@fancyfoot#1#2#3#4#5{#1\hbox to\headwidth{\fancy@reset\vbox{\footrule
\hbox{\rlap{\parbox[t]{\headwidth}{\raggedright#2\strut}}\hfill
\parbox[t]{\headwidth}{\centering#3\strut}\hfill
\llap{\parbox[t]{\headwidth}{\raggedleft#4\strut}}}}}#5}
\def\headrule{{\if@fancyplain\let\headrulewidth\plainheadrulewidth\fi
\hrule\@height\headrulewidth\@width\headwidth \vskip-\headrulewidth}}
\def\footrule{{\if@fancyplain\let\footrulewidth\plainfootrulewidth\fi
\vskip-\footruleskip\vskip-\footrulewidth
\hrule\@width\headwidth\@height\footrulewidth\vskip\footruleskip}}
\def\ps@fancy{%
\@ifundefined{@chapapp}{\let\@chapapp\chaptername}{}%for amsbook
%
% Define \MakeUppercase for old LaTeXen.
% Note: we used \def rather than \let, so that \let\uppercase\relax (from
% the version 1 documentation) will still work.
%
\@ifundefined{MakeUppercase}{\def\MakeUppercase{\uppercase}}{}%
\@ifundefined{chapter}{\def\sectionmark##1{\markboth
{\MakeUppercase{\ifnum \c@secnumdepth>\z@
\thesection\hskip 1em\relax \fi ##1}}{}}%
\def\subsectionmark##1{\markright {\ifnum \c@secnumdepth >\@ne
\thesubsection\hskip 1em\relax \fi ##1}}}%
{\def\chaptermark##1{\markboth {\MakeUppercase{\ifnum \c@secnumdepth>\m@ne
\@chapapp\ \thechapter. \ \fi ##1}}{}}%
\def\sectionmark##1{\markright{\MakeUppercase{\ifnum \c@secnumdepth >\z@
\thesection. \ \fi ##1}}}}%
%\csname ps@headings\endcsname % use \ps@headings defaults if they exist
\ps@@fancy
\gdef\ps@fancy{\@fancyplainfalse\ps@@fancy}%
% Initialize \headwidth if the user didn't
%
\ifdim\headwidth<0sp
%
% This catches the case that \headwidth hasn't been initialized and the
% case that the user added something to \headwidth in the expectation that
% it was initialized to \textwidth. We compensate this now. This loses if
% the user intended to multiply it by a factor. But that case is more
% likely done by saying something like \headwidth=1.2\textwidth.
% The doc says you have to change \headwidth after the first call to
% \pagestyle{fancy}. This code is just to catch the most common cases were
% that requirement is violated.
%
\global\advance\headwidth123456789sp\global\advance\headwidth\textwidth
\fi}
\def\ps@fancyplain{\ps@fancy \let\ps@plain\ps@plain@fancy}
\def\ps@plain@fancy{\@fancyplaintrue\ps@@fancy}
\let\ps@@empty\ps@empty
\def\ps@@fancy{%
\ps@@empty % This is for amsbook/amsart, which do strange things with \topskip
\def\@mkboth{\protect\markboth}%
\def\@oddhead{\@fancyhead\@lodd\f@ncyolh\f@ncyoch\f@ncyorh\@rodd}%
\def\@oddfoot{\@fancyfoot\@lodd\f@ncyolf\f@ncyocf\f@ncyorf\@rodd}%
\def\@evenhead{\@fancyhead\@rodd\f@ncyelh\f@ncyech\f@ncyerh\@lodd}%
\def\@evenfoot{\@fancyfoot\@rodd\f@ncyelf\f@ncyecf\f@ncyerf\@lodd}%
}
\def\@lodd{\if@reversemargin\hss\else\relax\fi}
\def\@rodd{\if@reversemargin\relax\else\hss\fi}
\newif\iffootnote
\let\latex@makecol\@makecol
\def\@makecol{\ifvoid\footins\footnotetrue\else\footnotefalse\fi
\let\topfloat\@toplist\let\botfloat\@botlist\latex@makecol}
\def\iftopfloat#1#2{\ifx\topfloat\empty #2\else #1\fi}
\def\ifbotfloat#1#2{\ifx\botfloat\empty #2\else #1\fi}
\def\iffloatpage#1#2{\if@fcolmade #1\else #2\fi}
\newcommand{\fancypagestyle}[2]{%
\@namedef{ps@#1}{\let\fancy@def\def#2\relax\ps@fancy}}

View File

@ -1,433 +0,0 @@
%%% Derived from the original fncychap.sty,
%%% but changed ``TWELV'' to ``TWELVE''.
%%% Copyright Ulf A. Lindgren
%%% Department of Applied Electronics
%%% Chalmers University of Technology
%%% S-412 96 Gothenburg, Sweden
%%% E-mail lindgren@ae.chalmers.se
%%%
%%% Note Permission is granted to modify this file under
%%% the condition that it is saved using another
%%% file and package name.
%%%
%%% Revision 1.1
%%%
%%% Jan. 8th Modified package name base date option
%%% Jan. 22th Modified FmN and FmTi for error in book.cls
%%% \MakeUppercase{#}->{\MakeUppercase#}
%%% Apr. 6th Modified Lenny option to prevent undesired
%%% skip of line.
%%% Nov. 8th Fixed \@chapapp for AMS
%%% Feb. 11th Fixed appendix problem related to Bjarne
%%% Last modified Feb. 11th 1998
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesPackage{fncychap}
[1997/04/06 v1.11
LaTeX package (Revised chapters)]
%%%% DEFINITION OF Chapapp variables
\newcommand{\CNV}{\huge\bfseries}
\newcommand{\ChNameVar}[1]{\renewcommand{\CNV}{#1}}
%%%% DEFINITION OF TheChapter variables
\newcommand{\CNoV}{\huge\bfseries}
\newcommand{\ChNumVar}[1]{\renewcommand{\CNoV}{#1}}
\newif\ifUCN
\UCNfalse
\newif\ifLCN
\LCNfalse
\def\ChNameLowerCase{\LCNtrue\UCNfalse}
\def\ChNameUpperCase{\UCNtrue\LCNfalse}
\def\ChNameAsIs{\UCNfalse\LCNfalse}
%%%%% Fix for AMSBook 971008
\@ifundefined{@chapapp}{\let\@chapapp\chaptername}{}
%%%%% Fix for Bjarne and appendix 980211
\newif\ifinapp
\inappfalse
\renewcommand\appendix{\par
\setcounter{chapter}{0}%
\setcounter{section}{0}%
\inapptrue%
\renewcommand\@chapapp{\appendixname}%
\renewcommand\thechapter{\@Alph\c@chapter}}
%%%%%
\newcommand{\FmN}[1]{%
\ifUCN
{\MakeUppercase#1}\LCNfalse
\else
\ifLCN
{\MakeLowercase#1}\UCNfalse
\else #1
\fi
\fi}
%%%% DEFINITION OF Title variables
\newcommand{\CTV}{\Huge\bfseries}
\newcommand{\ChTitleVar}[1]{\renewcommand{\CTV}{#1}}
%%%% DEFINITION OF the basic rule width
\newlength{\RW}
\setlength{\RW}{1pt}
\newcommand{\ChRuleWidth}[1]{\setlength{\RW}{#1}}
\newif\ifUCT
\UCTfalse
\newif\ifLCT
\LCTfalse
\def\ChTitleLowerCase{\LCTtrue\UCTfalse}
\def\ChTitleUpperCase{\UCTtrue\LCTfalse}
\def\ChTitleAsIs{\UCTfalse\LCTfalse}
\newcommand{\FmTi}[1]{%
\ifUCT
{\MakeUppercase#1}\LCTfalse
\else
\ifLCT
{\MakeLowercase#1}\UCTfalse
\else #1
\fi
\fi}
\newlength{\mylen}
\newlength{\myhi}
\newlength{\px}
\newlength{\py}
\newlength{\pyy}
\newlength{\pxx}
\def\mghrulefill#1{\leavevmode\leaders\hrule\@height #1\hfill\kern\z@}
\newcommand{\DOCH}{%
\CNV\FmN{\@chapapp}\space \CNoV\thechapter
\par\nobreak
\vskip 20\p@
}
\newcommand{\DOTI}[1]{%
\CTV\FmTi{#1}\par\nobreak
\vskip 40\p@
}
\newcommand{\DOTIS}[1]{%
\CTV\FmTi{#1}\par\nobreak
\vskip 40\p@
}
%%%%%% SONNY DEF
\DeclareOption{Sonny}{%
\ChNameVar{\Large\sf}
\ChNumVar{\Huge}
\ChTitleVar{\Large\sf}
\ChRuleWidth{0.5pt}
\ChNameUpperCase
\renewcommand{\DOCH}{%
\raggedleft
\CNV\FmN{\@chapapp}\space \CNoV\thechapter
\par\nobreak
\vskip 40\p@}
\renewcommand{\DOTI}[1]{%
\CTV\raggedleft\mghrulefill{\RW}\par\nobreak
\vskip 5\p@
\CTV\FmTi{#1}\par\nobreak
\mghrulefill{\RW}\par\nobreak
\vskip 40\p@}
\renewcommand{\DOTIS}[1]{%
\CTV\raggedleft\mghrulefill{\RW}\par\nobreak
\vskip 5\p@
\CTV\FmTi{#1}\par\nobreak
\mghrulefill{\RW}\par\nobreak
\vskip 40\p@}
}
%%%%%% LENNY DEF
\DeclareOption{Lenny}{%
\ChNameVar{\fontsize{14}{16}\usefont{OT1}{phv}{m}{n}\selectfont}
\ChNumVar{\fontsize{60}{62}\usefont{OT1}{ptm}{m}{n}\selectfont}
\ChTitleVar{\Huge\bfseries\rm}
\ChRuleWidth{1pt}
\renewcommand{\DOCH}{%
\settowidth{\px}{\CNV\FmN{\@chapapp}}
\addtolength{\px}{2pt}
\settoheight{\py}{\CNV\FmN{\@chapapp}}
\addtolength{\py}{1pt}
\settowidth{\mylen}{\CNV\FmN{\@chapapp}\space\CNoV\thechapter}
\addtolength{\mylen}{1pt}
\settowidth{\pxx}{\CNoV\thechapter}
\addtolength{\pxx}{-1pt}
\settoheight{\pyy}{\CNoV\thechapter}
\addtolength{\pyy}{-2pt}
\setlength{\myhi}{\pyy}
\addtolength{\myhi}{-1\py}
\par
\parbox[b]{\textwidth}{%
\rule[\py]{\RW}{\myhi}%
\hskip -\RW%
\rule[\pyy]{\px}{\RW}%
\hskip -\px%
\raggedright%
\CNV\FmN{\@chapapp}\space\CNoV\thechapter%
\hskip1pt%
\mghrulefill{\RW}%
\rule{\RW}{\pyy}\par\nobreak%
\vskip -\baselineskip%
\vskip -\pyy%
\hskip \mylen%
\mghrulefill{\RW}\par\nobreak%
\vskip \pyy}%
\vskip 20\p@}
\renewcommand{\DOTI}[1]{%
\raggedright
\CTV\FmTi{#1}\par\nobreak
\vskip 40\p@}
\renewcommand{\DOTIS}[1]{%
\raggedright
\CTV\FmTi{#1}\par\nobreak
\vskip 40\p@}
}
%%%%%%% GLENN DEF
\DeclareOption{Glenn}{%
\ChNameVar{\bfseries\Large\sf}
\ChNumVar{\Huge}
\ChTitleVar{\bfseries\Large\rm}
\ChRuleWidth{1pt}
\ChNameUpperCase
\ChTitleUpperCase
\renewcommand{\DOCH}{%
\settoheight{\myhi}{\CTV\FmTi{Test}}
\setlength{\py}{\baselineskip}
\addtolength{\py}{\RW}
\addtolength{\py}{\myhi}
\setlength{\pyy}{\py}
\addtolength{\pyy}{-1\RW}
\raggedright
\CNV\FmN{\@chapapp}\space\CNoV\thechapter
\hskip 3pt\mghrulefill{\RW}\rule[-1\pyy]{2\RW}{\py}\par\nobreak}
\renewcommand{\DOTI}[1]{%
\addtolength{\pyy}{-4pt}
\settoheight{\myhi}{\CTV\FmTi{#1}}
\addtolength{\myhi}{\py}
\addtolength{\myhi}{-1\RW}
\vskip -1\pyy
\rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt
\raggedleft\CTV\FmTi{#1}\par\nobreak
\vskip 80\p@}
\renewcommand{\DOTIS}[1]{%
\setlength{\py}{10pt}
\setlength{\pyy}{\py}
\addtolength{\pyy}{\RW}
\setlength{\myhi}{\baselineskip}
\addtolength{\myhi}{\pyy}
\mghrulefill{\RW}\rule[-1\py]{2\RW}{\pyy}\par\nobreak
% \addtolength{}{}
\vskip -1\baselineskip
\rule{2\RW}{\myhi}\mghrulefill{\RW}\hskip 2pt
\raggedleft\CTV\FmTi{#1}\par\nobreak
\vskip 60\p@}
}
%%%%%%% CONNY DEF
\DeclareOption{Conny}{%
\ChNameUpperCase
\ChTitleUpperCase
\ChNameVar{\centering\Huge\rm\bfseries}
\ChNumVar{\Huge}
\ChTitleVar{\centering\Huge\rm}
\ChRuleWidth{2pt}
\renewcommand{\DOCH}{%
\mghrulefill{3\RW}\par\nobreak
\vskip -0.5\baselineskip
\mghrulefill{\RW}\par\nobreak
\CNV\FmN{\@chapapp}\space \CNoV\thechapter
\par\nobreak
\vskip -0.5\baselineskip
}
\renewcommand{\DOTI}[1]{%
\mghrulefill{\RW}\par\nobreak
\CTV\FmTi{#1}\par\nobreak
\vskip 60\p@
}
\renewcommand{\DOTIS}[1]{%
\mghrulefill{\RW}\par\nobreak
\CTV\FmTi{#1}\par\nobreak
\vskip 60\p@
}
}
%%%%%%% REJNE DEF
\DeclareOption{Rejne}{%
\ChNameUpperCase
\ChTitleUpperCase
\ChNameVar{\centering\Large\rm}
\ChNumVar{\Huge}
\ChTitleVar{\centering\Huge\rm}
\ChRuleWidth{1pt}
\renewcommand{\DOCH}{%
\settoheight{\py}{\CNoV\thechapter}
\addtolength{\py}{-1pt}
\CNV\FmN{\@chapapp}\par\nobreak
\vskip 20\p@
\setlength{\myhi}{2\baselineskip}
\setlength{\px}{\myhi}
\addtolength{\px}{-1\RW}
\rule[-1\px]{\RW}{\myhi}\mghrulefill{\RW}\hskip
10pt\raisebox{-0.5\py}{\CNoV\thechapter}\hskip
10pt\mghrulefill{\RW}\rule[-1\px]{\RW}{\myhi}\par\nobreak
\vskip -1\p@
}
\renewcommand{\DOTI}[1]{%
\setlength{\mylen}{\textwidth}
\addtolength{\mylen}{-2\RW}
{\vrule width\RW}\parbox{\mylen}{\CTV\FmTi{#1}}{\vrule
width\RW}\par\nobreak
\vskip
-1pt\rule{\RW}{2\baselineskip}\mghrulefill{\RW}\rule{\RW}{2\baselineskip}
\vskip 60\p@
}
\renewcommand{\DOTIS}[1]{%
\setlength{\py}{\fboxrule}
\setlength{\fboxrule}{\RW}
\setlength{\mylen}{\textwidth}
\addtolength{\mylen}{-2\RW}
\fbox{\parbox{\mylen}{\vskip
2\baselineskip\CTV\FmTi{#1}\par\nobreak\vskip \baselineskip}}
\setlength{\fboxrule}{\py}
\vskip 60\p@
}
}
%%%%%%% BJARNE DEF
\DeclareOption{Bjarne}{%
\ChNameUpperCase
\ChTitleUpperCase
\ChNameVar{\raggedleft\normalsize\rm}
\ChNumVar{\raggedleft \bfseries\Large}
\ChTitleVar{\raggedleft \Large\rm}
\ChRuleWidth{1pt}
%% Note thechapter -> c@chapter fix appendix bug
\newcounter{AlphaCnt}
\newcounter{AlphaDecCnt}
\newcommand{\AlphaNo}{%
\ifcase\number\theAlphaCnt
\ifnum\c@chapter=0
ZERO\else{}\fi
\or ONE\or TWO\or THREE\or FOUR\or FIVE
\or SIX\or SEVEN\or EIGHT\or NINE\or TEN
\or ELEVEN\or TWELVE\or THIRTEEN\or FOURTEEN\or FIFTEEN
\or SIXTEEN\or SEVENTEEN\or EIGHTEEN\or NINETEEN\fi
}
\newcommand{\AlphaDecNo}{%
\setcounter{AlphaDecCnt}{0}
\@whilenum\number\theAlphaCnt>0\do
{\addtocounter{AlphaCnt}{-10}
\addtocounter{AlphaDecCnt}{1}}
\ifnum\number\theAlphaCnt=0
\else
\addtocounter{AlphaDecCnt}{-1}
\addtocounter{AlphaCnt}{10}
\fi
\ifcase\number\theAlphaDecCnt\or TEN\or TWENTY\or THIRTY\or
FORTY\or FIFTY\or SIXTY\or SEVENTY\or EIGHTY\or NINETY\fi
}
\newcommand{\TheAlphaChapter}{%
\ifinapp
\thechapter
\else
\setcounter{AlphaCnt}{\c@chapter}
\ifnum\c@chapter<20
\AlphaNo
\else
\AlphaDecNo\AlphaNo
\fi
\fi
}
\renewcommand{\DOCH}{%
\mghrulefill{\RW}\par\nobreak
\CNV\FmN{\@chapapp}\par\nobreak
\CNoV\TheAlphaChapter\par\nobreak
\vskip -1\baselineskip\vskip 5pt\mghrulefill{\RW}\par\nobreak
\vskip 20\p@
}
\renewcommand{\DOTI}[1]{%
\CTV\FmTi{#1}\par\nobreak
\vskip 40\p@
}
\renewcommand{\DOTIS}[1]{%
\CTV\FmTi{#1}\par\nobreak
\vskip 40\p@
}
}
\DeclareOption*{%
\PackageWarning{fancychapter}{unknown style option}
}
\ProcessOptions* \relax
\def\@makechapterhead#1{%
\vspace*{50\p@}%
{\parindent \z@ \raggedright \normalfont
\ifnum \c@secnumdepth >\m@ne
\DOCH
\fi
\interlinepenalty\@M
\DOTI{#1}
}}
\def\@schapter#1{\if@twocolumn
\@topnewpage[\@makeschapterhead{#1}]%
\else
\@makeschapterhead{#1}%
\@afterheading
\fi}
\def\@makeschapterhead#1{%
\vspace*{50\p@}%
{\parindent \z@ \raggedright
\normalfont
\interlinepenalty\@M
\DOTIS{#1}
\vskip 40\p@
}}
\endinput

View File

@ -1,106 +0,0 @@
%
% howto.cls for the Python documentation
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesClass{howto}
[1998/02/25 Document class (Python HOWTO)]
\RequirePackage{pypaper}
% Change the options here to get a different set of basic options, This
% is where to add things like "a4paper" or "10pt".
%
\LoadClass[\py@paper,\py@ptsize,twoside]{article}
\setcounter{secnumdepth}{1}
% Optional packages:
%
% If processing of these documents fails at your TeX installation,
% these may be commented out (independently) to make things work.
% These are both supplied with the current version of the teTeX
% distribution.
%
% The "fancyhdr" package makes nicer page footers reasonable to
% implement, and is used to put the chapter and section information in
% the footers.
%
\RequirePackage{fancyhdr}\typeout{Using fancier footers than usual.}
% Required package:
%
% This gives us all the Python-specific markup that we really want.
% This should come last. Do not change this.
%
\RequirePackage{python}
% support for module synopsis sections:
\newcommand{\py@ModSynopsisFilename}{\jobname.syn}
% need to do one of these....
\newcommand{\py@doHorizontalRule}{\rule{\textwidth}{1pt}}
% Change the title page to look a bit better, and fit in with the
% fncychap ``Bjarne'' style a bit better.
%
\renewcommand{\maketitle}{
\py@doHorizontalRule
\@ifundefined{pdfinfo}{}{{
% This \def is required to deal with multi-line authors; it
% changes \\ to ', ' (comma-space), making it pass muster for
% generating document info in the PDF file.
\def\\{, }
\pdfinfo{
/Author (\@author)
/Title (\@title)
}
}}
\begin{flushright}
{\rm\Huge\py@HeaderFamily \@title} \par
{\em\large\py@HeaderFamily \py@release\releaseinfo} \par
\vspace{25pt}
{\Large\py@HeaderFamily \@author} \par
\vspace{25pt}
\@date \par
\py@authoraddress \par
\end{flushright}
\@thanks
\setcounter{footnote}{0}
\let\thanks\relax\let\maketitle\relax
\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
}
\let\py@OldTableofcontents=\tableofcontents
\renewcommand{\tableofcontents}{
\begingroup
\parskip = 0mm
\py@OldTableofcontents
\endgroup
\py@doHorizontalRule
\vspace{12pt}
\py@doing@page@targetstrue
}
% Fix the theindex environment to add an entry to the Table of
% Contents; this is much nicer than just having to jump to the end of
% the book and flip around, especially with multiple indexes.
%
\let\py@OldTheindex=\theindex
\renewcommand{\theindex}{
\clearpage
\py@OldTheindex
\addcontentsline{toc}{section}{\indexname}
}
\@ifundefined{fancyhf}{
\pagestyle{plain}}{
\pagestyle{normal}} % start this way; change for
\pagenumbering{arabic} % ToC & chapters
\setcounter{secnumdepth}{2}
\thispagestyle{empty}

View File

@ -1,274 +0,0 @@
\section{History of the software}
Python was created in the early 1990s by Guido van Rossum at Stichting
Mathematisch Centrum (CWI, see \url{http://www.cwi.nl/}) in the Netherlands
as a successor of a language called ABC. Guido remains Python's
principal author, although it includes many contributions from others.
In 1995, Guido continued his work on Python at the Corporation for
National Research Initiatives (CNRI, see \url{http://www.cnri.reston.va.us/})
in Reston, Virginia where he released several versions of the
software.
In May 2000, Guido and the Python core development team moved to
BeOpen.com to form the BeOpen PythonLabs team. In October of the same
year, the PythonLabs team moved to Digital Creations (now Zope
Corporation; see \url{http://www.zope.com/}). In 2001, the Python
Software Foundation (PSF, see \url{http://www.python.org/psf/}) was
formed, a non-profit organization created specifically to own
Python-related Intellectual Property. Zope Corporation is a
sponsoring member of the PSF.
All Python releases are Open Source (see
\url{http://www.opensource.org/} for the Open Source Definition).
Historically, most, but not all, Python releases have also been
GPL-compatible; the table below summarizes the various releases.
\begin{tablev}{c|c|c|c|c}{textrm}{Release}{Derived from}{Year}{Owner}{GPL compatible?}
\linev{0.9.0 thru 1.2}{n/a}{1991-1995}{CWI}{yes}
\linev{1.3 thru 1.5.2}{1.2}{1995-1999}{CNRI}{yes}
\linev{1.6}{1.5.2}{2000}{CNRI}{no}
\linev{2.0}{1.6}{2000}{BeOpen.com}{no}
\linev{1.6.1}{1.6}{2001}{CNRI}{no}
\linev{2.1}{2.0+1.6.1}{2001}{PSF}{no}
\linev{2.0.1}{2.0+1.6.1}{2001}{PSF}{yes}
\linev{2.1.1}{2.1+2.0.1}{2001}{PSF}{yes}
\linev{2.2}{2.1.1}{2001}{PSF}{yes}
\linev{2.1.2}{2.1.1}{2002}{PSF}{yes}
\linev{2.1.3}{2.1.2}{2002}{PSF}{yes}
\linev{2.2.1}{2.2}{2002}{PSF}{yes}
\end{tablev}
\note{GPL-compatible doesn't mean that we're distributing
Python under the GPL. All Python licenses, unlike the GPL, let you
distribute a modified version without making your changes open source.
The GPL-compatible licenses make it possible to combine Python with
other software that is released under the GPL; the others don't.}
Thanks to the many outside volunteers who have worked under Guido's
direction to make these releases possible.
\section{Terms and conditions for accessing or otherwise using Python}
\centerline{\strong{PSF LICENSE AGREEMENT FOR PYTHON 2.3}}
\begin{enumerate}
\item
This LICENSE AGREEMENT is between the Python Software Foundation
(``PSF''), and the Individual or Organization (``Licensee'') accessing
and otherwise using Python \version{} software in source or binary
form and its associated documentation.
\item
Subject to the terms and conditions of this License Agreement, PSF
hereby grants Licensee a nonexclusive, royalty-free, world-wide
license to reproduce, analyze, test, perform and/or display publicly,
prepare derivative works, distribute, and otherwise use Python
\version{} alone or in any derivative version, provided, however, that
PSF's License Agreement and PSF's notice of copyright, i.e.,
``Copyright \copyright{} 2001, 2002 Python Software Foundation; All
Rights Reserved'' are retained in Python \version{} alone or in any
derivative version prepared by Licensee.
\item
In the event Licensee prepares a derivative work that is based on
or incorporates Python \version{} or any part thereof, and wants to
make the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python \version.
\item
PSF is making Python \version{} available to Licensee on an ``AS IS''
basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON \version{} WILL
NOT INFRINGE ANY THIRD PARTY RIGHTS.
\item
PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
\version{} FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR
LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON
\version, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE
POSSIBILITY THEREOF.
\item
This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
\item
Nothing in this License Agreement shall be deemed to create any
relationship of agency, partnership, or joint venture between PSF and
Licensee. This License Agreement does not grant permission to use PSF
trademarks or trade name in a trademark sense to endorse or promote
products or services of Licensee, or any third party.
\item
By copying, installing or otherwise using Python \version, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
\end{enumerate}
\centerline{\strong{BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0}}
\centerline{\strong{BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1}}
\begin{enumerate}
\item
This LICENSE AGREEMENT is between BeOpen.com (``BeOpen''), having an
office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
Individual or Organization (``Licensee'') accessing and otherwise
using this software in source or binary form and its associated
documentation (``the Software'').
\item
Subject to the terms and conditions of this BeOpen Python License
Agreement, BeOpen hereby grants Licensee a non-exclusive,
royalty-free, world-wide license to reproduce, analyze, test, perform
and/or display publicly, prepare derivative works, distribute, and
otherwise use the Software alone or in any derivative version,
provided, however, that the BeOpen Python License is retained in the
Software, alone or in any derivative version prepared by Licensee.
\item
BeOpen is making the Software available to Licensee on an ``AS IS''
basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
\item
BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
\item
This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
\item
This License Agreement shall be governed by and interpreted in all
respects by the law of the State of California, excluding conflict of
law provisions. Nothing in this License Agreement shall be deemed to
create any relationship of agency, partnership, or joint venture
between BeOpen and Licensee. This License Agreement does not grant
permission to use BeOpen trademarks or trade names in a trademark
sense to endorse or promote products or services of Licensee, or any
third party. As an exception, the ``BeOpen Python'' logos available
at http://www.pythonlabs.com/logos.html may be used according to the
permissions granted on that web page.
\item
By copying, installing or otherwise using the software, Licensee
agrees to be bound by the terms and conditions of this License
Agreement.
\end{enumerate}
\centerline{\strong{CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1}}
\begin{enumerate}
\item
This LICENSE AGREEMENT is between the Corporation for National
Research Initiatives, having an office at 1895 Preston White Drive,
Reston, VA 20191 (``CNRI''), and the Individual or Organization
(``Licensee'') accessing and otherwise using Python 1.6.1 software in
source or binary form and its associated documentation.
\item
Subject to the terms and conditions of this License Agreement, CNRI
hereby grants Licensee a nonexclusive, royalty-free, world-wide
license to reproduce, analyze, test, perform and/or display publicly,
prepare derivative works, distribute, and otherwise use Python 1.6.1
alone or in any derivative version, provided, however, that CNRI's
License Agreement and CNRI's notice of copyright, i.e., ``Copyright
\copyright{} 1995-2001 Corporation for National Research Initiatives;
All Rights Reserved'' are retained in Python 1.6.1 alone or in any
derivative version prepared by Licensee. Alternately, in lieu of
CNRI's License Agreement, Licensee may substitute the following text
(omitting the quotes): ``Python 1.6.1 is made available subject to the
terms and conditions in CNRI's License Agreement. This Agreement
together with Python 1.6.1 may be located on the Internet using the
following unique, persistent identifier (known as a handle):
1895.22/1013. This Agreement may also be obtained from a proxy server
on the Internet using the following URL:
\url{http://hdl.handle.net/1895.22/1013}.''
\item
In the event Licensee prepares a derivative work that is based on
or incorporates Python 1.6.1 or any part thereof, and wants to make
the derivative work available to others as provided herein, then
Licensee hereby agrees to include in any such work a brief summary of
the changes made to Python 1.6.1.
\item
CNRI is making Python 1.6.1 available to Licensee on an ``AS IS''
basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
INFRINGE ANY THIRD PARTY RIGHTS.
\item
CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
\item
This License Agreement will automatically terminate upon a material
breach of its terms and conditions.
\item
This License Agreement shall be governed by the federal
intellectual property law of the United States, including without
limitation the federal copyright law, and, to the extent such
U.S. federal law does not apply, by the law of the Commonwealth of
Virginia, excluding Virginia's conflict of law provisions.
Notwithstanding the foregoing, with regard to derivative works based
on Python 1.6.1 that incorporate non-separable material that was
previously distributed under the GNU General Public License (GPL), the
law of the Commonwealth of Virginia shall govern this License
Agreement only as to issues arising under or with respect to
Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
License Agreement shall be deemed to create any relationship of
agency, partnership, or joint venture between CNRI and Licensee. This
License Agreement does not grant permission to use CNRI trademarks or
trade name in a trademark sense to endorse or promote products or
services of Licensee, or any third party.
\item
By clicking on the ``ACCEPT'' button where indicated, or by copying,
installing or otherwise using Python 1.6.1, Licensee agrees to be
bound by the terms and conditions of this License Agreement.
\end{enumerate}
\centerline{ACCEPT}
\centerline{\strong{CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2}}
Copyright \copyright{} 1991 - 1995, Stichting Mathematisch Centrum
Amsterdam, The Netherlands. All rights reserved.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@ -1,40 +0,0 @@
% Created by Fred L. Drake, Jr. <fdrake@acm.org>, as part of the
% Python Documentation Project.
%
% Define some simple markup for the LaTeX command documentation:
\ProvidesPackage{ltxmarkup}
\RequirePackage{python} % fulllineitems environment
% These two macros are used in constructing the last parameter to the
% envdesc and macrodesc environments.
\newcommand{\py@ltx@optparam}[1]{{[}\var{#1}{]}}
\newcommand{\py@ltx@param}[1]{\{\var{#1}\}}
\newenvironment{envdesc}[2]{
\begin{fulllineitems}
\item[\code{\e begin\{{\bfseries #1}\}{%
\let\op=\py@ltx@optparam%
\let\p=\py@ltx@param%
\let\unspecified=\py@unspecified%
\let\moreargs=\py@moreargs%
#2}}]
\item[\code{\e end\{{\bfseries #1}\}}]
\index{#1 environment@\py@idxcode{#1} environment}
\index{environments!#1@\py@idxcode{#1}}
}{\end{fulllineitems}}
\newenvironment{macrodesc}[2]{
\begin{fulllineitems}
\item[\code{{\e\bfseries#1}{%
\let\op=\py@ltx@optparam%
\let\p=\py@ltx@param%
\let\unspecified=\py@unspecified%
\let\moreargs=\py@moreargs%
#2}}]
\index{#1@\py@idxcode{#1}}
}{\end{fulllineitems}}
\newcommand{\env}[1]{\code{#1}}
\newcommand{\macro}[1]{\code{\e#1}}

View File

@ -1,152 +0,0 @@
%
% manual.cls for the Python documentation
%
\NeedsTeXFormat{LaTeX2e}[1995/12/01]
\ProvidesClass{manual}
[1998/03/03 Document class (Python manual)]
\RequirePackage{pypaper}
% Change the options here to get a different set of basic options, but only
% if you have to. Paper and font size should be adjusted in pypaper.sty.
%
\LoadClass[\py@paper,\py@ptsize,twoside,openright]{report}
\setcounter{secnumdepth}{2}
% Optional packages:
%
% If processing of these documents fails at your TeX installation,
% these may be commented out (independently) to make things work.
% These are both supplied with the current version of the teTeX
% distribution.
%
% The "fancyhdr" package makes nicer page footers reasonable to
% implement, and is used to put the chapter and section information in
% the footers.
%
\RequirePackage{fancyhdr}\typeout{Using fancier footers than usual.}
% Required packages:
%
% The "fncychap" package is used to get the nice chapter headers. The
% .sty file is distributed with Python, so you should not need to disable
% it. You'd also end up with a mixed page style; uglier than stock LaTeX!
%
\RequirePackage[Bjarne]{fncychap}\typeout{Using fancy chapter headings.}
% Do horizontal rules it this way to match:
\newcommand{\py@doHorizontalRule}{\mghrulefill{\RW}}
%
%
% This gives us all the Python-specific markup that we really want.
% This should come last. Do not change this.
%
\RequirePackage{python}
% support for module synopsis sections:
\newcommand{\py@ModSynopsisFilename}{\jobname\thechapter.syn}
\let\py@OldChapter=\chapter
\renewcommand{\chapter}{
\py@ProcessModSynopsis
\py@closeModSynopsisFile
\py@OldChapter
}
% Change the title page to look a bit better, and fit in with the
% fncychap ``Bjarne'' style a bit better.
%
\renewcommand{\maketitle}{%
\begin{titlepage}%
\let\footnotesize\small
\let\footnoterule\relax
\py@doHorizontalRule%
\@ifundefined{pdfinfo}{}{{
% This \def is required to deal with multi-line authors; it
% changes \\ to ', ' (comma-space), making it pass muster for
% generating document info in the PDF file.
\def\\{, }
\pdfinfo{
/Author (\@author)
/Title (\@title)
}
}}
\begin{flushright}%
{\rm\Huge\py@HeaderFamily \@title \par}%
{\em\LARGE\py@HeaderFamily \py@release\releaseinfo \par}
\vfill
{\LARGE\py@HeaderFamily \@author \par}
\vfill\vfill
{\large
\@date \par
\vfill
\py@authoraddress \par
}%
\end{flushright}%\par
\@thanks
\end{titlepage}%
\setcounter{footnote}{0}%
\let\thanks\relax\let\maketitle\relax
\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
}
% Catch the end of the {abstract} environment, but here make sure the
% abstract is followed by a blank page if the 'openright' option is used.
%
\let\py@OldEndAbstract=\endabstract
\renewcommand{\endabstract}{
\if@openright
\ifodd\value{page}
\typeout{Adding blank page after the abstract.}
\vfil\pagebreak
\fi
\fi
\py@OldEndAbstract
}
% This wraps the \tableofcontents macro with all the magic to get the
% spacing right and have the right number of pages if the 'openright'
% option has been used. This eliminates a fair amount of crud in the
% individual document files.
%
\let\py@OldTableofcontents=\tableofcontents
\renewcommand{\tableofcontents}{%
\setcounter{page}{1}%
\pagebreak%
\pagestyle{plain}%
{%
\parskip = 0mm%
\py@OldTableofcontents%
\if@openright%
\ifodd\value{page}%
\typeout{Adding blank page after the table of contents.}%
\pagebreak\hspace{0pt}%
\fi%
\fi%
\cleardoublepage%
}%
\pagenumbering{arabic}%
\@ifundefined{fancyhf}{}{\pagestyle{normal}}%
\py@doing@page@targetstrue%
}
% This is needed to get the width of the section # area wide enough in the
% library reference. Doing it here keeps it the same for all the manuals.
%
\renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.6em}}
\renewcommand*\l@subsection{\@dottedtocline{2}{4.1em}{3.5em}}
\setcounter{tocdepth}{1}
% Fix the theindex environment to add an entry to the Table of
% Contents; this is much nicer than just having to jump to the end of
% the book and flip around, especially with multiple indexes.
%
\let\py@OldTheindex=\theindex
\renewcommand{\theindex}{
\cleardoublepage
\py@OldTheindex
\addcontentsline{toc}{chapter}{\indexname}
}

View File

@ -1,18 +0,0 @@
%
% Change this to say a4paper instead of letterpaper if you want A4. These
% are the latex defaults.
%
\newcommand{\py@paper}{letterpaper}
\newcommand{\py@ptsize}{11pt}
% These set up the fonts for the documents.
%
% The "times" package makes the default font the PostScript Times
% font, which makes for smaller PostScript and a font that more people
% like.
%
% The "avant" package causes the AvantGarde font to be used for
% sans-serif text, instead of the uglier Helvetica set up by the "times"
% package.
%
% \RequirePackage{times}\typeout{Using Times instead of Computer Modern.}

View File

@ -1,11 +0,0 @@
line_max 100
headings_flag 1
heading_prefix " \\bigletter "
preamble "\\begin{theindex}
\\def\\bigletter#1{{\\Large\\sffamily#1}\\nopagebreak\\vspace{1mm}}
"
symhead_positive "{Symbols}"
numhead_positive "{Numbers}"

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +0,0 @@
\label{reporting-bugs}
Python is a mature programming language which has established a
reputation for stability. In order to maintain this reputation, the
developers would like to know of any deficiencies you find in Python
or its documentation.
Before submitting a report, you will be required to log into SourceForge;
this will make it possible for the developers to contact you
for additional information if needed. It is not possible to submit a
bug report anonymously.
All bug reports should be submitted via the Python Bug Tracker on
SourceForge (\url{http://sourceforge.net/bugs/?group_id=5470}). The
bug tracker offers a Web form which allows pertinent information to be
entered and submitted to the developers.
The first step in filing a report is to determine whether the problem
has already been reported. The advantage in doing so, aside from
saving the developers time, is that you learn what has been done to
fix it; it may be that the problem has already been fixed for the next
release, or additional information is needed (in which case you are
welcome to provide it if you can!). To do this, search the bug
database using the search box near the bottom of the page.
If the problem you're reporting is not already in the bug tracker, go
back to the Python Bug Tracker
(\url{http://sourceforge.net/bugs/?group_id=5470}). Select the
``Submit a Bug'' link at the top of the page to open the bug reporting
form.
The submission form has a number of fields. The only fields that are
required are the ``Summary'' and ``Details'' fields. For the summary,
enter a \emph{very} short description of the problem; less than ten
words is good. In the Details field, describe the problem in detail,
including what you expected to happen and what did happen. Be sure to
include the version of Python you used, whether any extension modules
were involved, and what hardware and software platform you were using
(including version information as appropriate).
The only other field that you may want to set is the ``Category''
field, which allows you to place the bug report into a broad category
(such as ``Documentation'' or ``Library'').
Each bug report will be assigned to a developer who will determine
what needs to be done to correct the problem. You will
receive an update each time action is taken on the bug.
\begin{seealso}
\seetitle[http://www-mice.cs.ucl.ac.uk/multimedia/software/documentation/ReportingBugs.html]{How
to Report Bugs Effectively}{Article which goes into some
detail about how to create a useful bug report. This
describes what kind of information is useful and why it is
useful.}
\seetitle[http://www.mozilla.org/quality/bug-writing-guidelines.html]{Bug
Writing Guidelines}{Information about writing a good bug
report. Some of this is specific to the Mozilla project, but
describes general good practices.}
\end{seealso}

View File

@ -1,171 +0,0 @@
137,153d136
< % Set up abstract ways to get the normal and smaller font sizes that
< % work even in footnote context.
< \newif\ifpy@infootnote \py@infootnotefalse
< \let\py@oldmakefntext\@makefntext
< \def\@makefntext#1{%
< \bgroup%
< \py@infootnotetrue
< \py@oldmakefntext{#1}%
< \egroup%
< }
< \def\py@defaultsize{%
< \ifpy@infootnote\footnotesize\else\normalsize\fi%
< }
< \def\py@smallsize{%
< \ifpy@infootnote\scriptsize\else\small\fi%
< }
<
201,208c184,187
< \setlength{\parindent}{1cm}%
< % Calculate the text width for the minipage:
< \setlength{\py@codewidth}{\linewidth}%
< \addtolength{\py@codewidth}{-\parindent}%
< %
< \par\indent%
< \begin{minipage}[t]{\py@codewidth}%
< \small%
---
> \begingroup%
> \small%
> \begin{list}{}{\setlength{\leftmargin}{1cm}}
> \item%
213c192,193
< \end{minipage}%
---
> \end{list}%
> \endgroup
216,221c196
< {\setlength{\parindent}{1cm}%
< % Calculate the text width for the minipage:
< \setlength{\py@codewidth}{\linewidth}%
< \addtolength{\py@codewidth}{-\parindent}%
< %
< \small%
---
> {\small%
601,610d575
<
< \newlength{\py@argswidth}
< \newcommand{\py@sigparams}[1]{%
< \parbox[t]{\py@argswidth}{\py@varvars{#1}\code{)}}}
< \newcommand{\py@sigline}[2]{%
< \settowidth{\py@argswidth}{#1\code{(}}%
< \addtolength{\py@argswidth}{-2\py@argswidth}%
< \addtolength{\py@argswidth}{\textwidth}%
< \item[#1\code{(}\py@sigparams{#2}]}
<
615,618d579
< \newcommand{\cfuncline}[3]{
< \py@sigline{\code{#1 \bfcode{#2}}}{#3}%
< \index{#2@{\py@idxcode{#2()}}}
< }
621c582
< \cfuncline{#2}{#3}{#4}
---
> \item[\code{#2 \bfcode{#3}(\py@varvars{#4})}\index{#3@{\py@idxcode{#3()}}}]
646,656d606
< % C type fields ----------------------------------------------------------
< % \begin{cmemberdesc}{container type}{ctype}{membername}
< \newcommand{\cmemberline}[3]{
< \item[\code{#2 \bfcode{#3}}]
< \index{#3@{\py@idxcode{#3}} (#1 member)}
< }
< \newenvironment{cmemberdesc}[3]{
< \begin{fulllineitems}
< \cmemberline{#1}{#2}{#3}
< }{\end{fulllineitems}}
<
658c608
< % \begin{csimplemacrodesc}{name}
---
> % \begin{csimplemacro}{name}
676,677c626
< \newcommand{\funclineni}[2]{%
< \py@sigline{\bfcode{#1}}{#2}}
---
> \newcommand{\funclineni}[2]{\item[\code{\bfcode{#1}(\py@varvars{#2})}]}
689,690c638,639
< \py@sigline{\strong{class }\bfcode{#1}}{#2}%
< \index{#1@{\py@idxcode{#1}} (class in \py@thismodule)}
---
> \item[\strong{class }\code{\bfcode{#1}(\py@varvars{#2})}%
> \index{#1@{\py@idxcode{#1}} (class in \py@thismodule)}]
708,709c657,658
< \py@sigline{\strong{exception }\bfcode{#1}}{#2}%
< \index{#1@{\py@idxcode{#1}} (exception in \py@thismodule)}
---
> \item[\strong{exception }\code{\bfcode{#1}(\py@varvars{#2})}%
> \index{#1@{\py@idxcode{#1}} (exception in \py@thismodule)}]
741c690
< \py@sigline{\bfcode{#2}}{#3}}
---
> \item[\code{\bfcode{#2}(\py@varvars{#3})}]}
824d772
< % \menuselection{Start \sub Programs \sub Python}
834d781
< \newcommand{\csimplemacro}[1]{\code{#1}}
836a784,786
> % This weird definition of \var{} allows it to always appear in roman
> % italics, and won't get funky in code fragments when we play around
> % with fonts. This also works directly in math mode.
839c789
< \hbox{\py@defaultsize\textrm{\textit{#1\/}}}%
---
> \hbox{\normalsize\textrm{\textit{#1\/}}}%
841c791
< \py@defaultsize\textrm{\textit{#1\/}}%
---
> \normalsize\textrm{\textit{#1\/}}%
848,849c798,799
< \newcommand{\file}[1]{`\filenq{#1}'}
< \newcommand{\filenq}[1]{{\py@smallsize\textsf{#1}}}
---
> \newcommand{\file}[1]{`{\textsf{#1}}'}
> \newcommand{\filenq}[1]{{\textsf{#1}}}
858c808
< \py@smallsize\sf #1%
---
> \small\sf #1%
863c813
< \newcommand{\url}[1]{\mbox{\py@smallsize\textsf{#1}}}
---
> \newcommand{\url}[1]{\mbox{\small\textsf{#1}}}
865,866c815,816
< \newcommand{\email}[1]{{\py@smallsize\textsf{#1}}}
< \newcommand{\newsgroup}[1]{{\py@smallsize\textsf{#1}}}
---
> \newcommand{\email}[1]{{\small\textsf{#1}}}
> \newcommand{\newsgroup}[1]{{\small\textsf{#1}}}
902,903c852,853
< \newcommand{\mailheader}[1]{{\py@smallsize\textsf{#1:}}}
< \newcommand{\mimetype}[1]{{\py@smallsize\textsf{#1}}}
---
> \newcommand{\mailheader}[1]{{\small\textsf{#1:}}}
> \newcommand{\mimetype}[1]{{\small\textsf{#1}}}
907c857
< {\py@defaultsize\code{#1}}%
---
> {\normalsize\code{#1}}%
1105,1125d1054
<
< % XXX Don't think we can use this yet, though it cleans up some
< % tedious markup. There's no equivalent for the HTML transform yet,
< % and that needs to exist. I don't know how to write it.
< %
< % This should really have something that makes it easier to bind a
< % table's ``Notes'' column and an associated tablenotes environment,
< % and generates the right magic for getting the numbers right in the
< % table.
< %
< % So this is quite incomplete.
< %
< \newcounter{py@tablenotescounter}
< \newenvironment{tablenotes}{%
< \noindent Notes:
< \par
< \setcounter{py@tablenotescounter}{0}
< \begin{list}{(\arabic{py@tablenotescounter})}%
< {\usecounter{py@tablenotescounter}}
< }{\end{list}}
<

View File

@ -1,76 +0,0 @@
typedef struct _typeobject {
PyObject_VAR_HEAD
char *tp_name; /* For printing, in format "<module>.<name>" */
int tp_basicsize, tp_itemsize; /* For allocation */
/* Methods to implement standard operations */
destructor tp_dealloc;
printfunc tp_print;
getattrfunc tp_getattr;
setattrfunc tp_setattr;
cmpfunc tp_compare;
reprfunc tp_repr;
/* Method suites for standard classes */
PyNumberMethods *tp_as_number;
PySequenceMethods *tp_as_sequence;
PyMappingMethods *tp_as_mapping;
/* More standard operations (here for binary compatibility) */
hashfunc tp_hash;
ternaryfunc tp_call;
reprfunc tp_str;
getattrofunc tp_getattro;
setattrofunc tp_setattro;
/* Functions to access object as input/output buffer */
PyBufferProcs *tp_as_buffer;
/* Flags to define presence of optional/expanded features */
long tp_flags;
char *tp_doc; /* Documentation string */
/* Assigned meaning in release 2.0 */
/* call function for all accessible objects */
traverseproc tp_traverse;
/* delete references to contained objects */
inquiry tp_clear;
/* Assigned meaning in release 2.1 */
/* rich comparisons */
richcmpfunc tp_richcompare;
/* weak reference enabler */
long tp_weaklistoffset;
/* Added in release 2.2 */
/* Iterators */
getiterfunc tp_iter;
iternextfunc tp_iternext;
/* Attribute descriptor and subclassing stuff */
struct PyMethodDef *tp_methods;
struct PyMemberDef *tp_members;
struct PyGetSetDef *tp_getset;
struct _typeobject *tp_base;
PyObject *tp_dict;
descrgetfunc tp_descr_get;
descrsetfunc tp_descr_set;
long tp_dictoffset;
initproc tp_init;
allocfunc tp_alloc;
newfunc tp_new;
freefunc tp_free; /* Low-level free-memory routine */
inquiry tp_is_gc; /* For PyObject_IS_GC */
PyObject *tp_bases;
PyObject *tp_mro; /* method resolution order */
PyObject *tp_cache;
PyObject *tp_subclasses;
PyObject *tp_weaklist;
} PyTypeObject;

View File

@ -1,71 +0,0 @@
#! /usr/bin/env python
"""Add reference count annotations to the Python/C API Reference."""
__version__ = '$Revision$'
import getopt
import os
import sys
import refcounts
PREFIX_1 = r"\begin{cfuncdesc}{PyObject*}{"
PREFIX_2 = r"\begin{cfuncdesc}{PyVarObject*}{"
def main():
rcfile = os.path.join(os.path.dirname(refcounts.__file__), os.pardir,
"api", "refcounts.dat")
outfile = "-"
opts, args = getopt.getopt(sys.argv[1:], "o:r:", ["output=", "refcounts="])
for opt, arg in opts:
if opt in ("-o", "--output"):
outfile = arg
elif opt in ("-r", "--refcounts"):
rcfile = arg
rcdict = refcounts.load(rcfile)
if outfile == "-":
output = sys.stdout
else:
output = open(outfile, "w")
if not args:
args = ["-"]
for infile in args:
if infile == "-":
input = sys.stdin
else:
input = open(infile)
while 1:
line = input.readline()
if not line:
break
prefix = None
if line.startswith(PREFIX_1):
prefix = PREFIX_1
elif line.startswith(PREFIX_2):
prefix = PREFIX_2
if prefix:
s = line[len(prefix):].split('}', 1)[0]
try:
info = rcdict[s]
except KeyError:
sys.stderr.write("No refcount data for %s\n" % s)
else:
if info.result_type in ("PyObject*", "PyVarObject*"):
if info.result_refs is None:
rc = "Always \NULL{}"
else:
rc = info.result_refs and "New" or "Borrowed"
rc = rc + " reference"
line = (r"\begin{cfuncdesc}[%s]{%s}{"
% (rc, info.result_type)) \
+ line[len(prefix):]
output.write(line)
if infile != "-":
input.close()
if outfile != "-":
output.close()
if __name__ == "__main__":
main()

View File

@ -1,377 +0,0 @@
#! /usr/bin/env python
__version__ = '$Revision$'
import os.path
import re
import string
import sys
bang_join = "!".join
null_join = "".join
class Node:
__rmjunk = re.compile("<#\d+#>")
continuation = 0
def __init__(self, link, str, seqno):
self.links = [link]
self.seqno = seqno
# remove <#\d+#> left in by moving the data out of LaTeX2HTML
str = self.__rmjunk.sub('', str)
# build up the text
self.text = split_entry_text(str)
self.key = split_entry_key(str)
def __cmp__(self, other):
"""Comparison operator includes sequence number, for use with
list.sort()."""
return self.cmp_entry(other) or cmp(self.seqno, other.seqno)
def cmp_entry(self, other):
"""Comparison 'operator' that ignores sequence number."""
c = 0
for i in range(min(len(self.key), len(other.key))):
c = (cmp_part(self.key[i], other.key[i])
or cmp_part(self.text[i], other.text[i]))
if c:
break
return c or cmp(self.key, other.key) or cmp(self.text, other.text)
def __repr__(self):
return "<Node for %s (%s)>" % (bang_join(self.text), self.seqno)
def __str__(self):
return bang_join(self.key)
def dump(self):
return "%s\1%s###%s\n" \
% ("\1".join(self.links),
bang_join(self.text),
self.seqno)
def cmp_part(s1, s2):
result = cmp(s1, s2)
if result == 0:
return 0
l1 = s1.lower()
l2 = s2.lower()
minlen = min(len(s1), len(s2))
if len(s1) < len(s2) and l1 == l2[:len(s1)]:
result = -1
elif len(s2) < len(s1) and l2 == l1[:len(s2)]:
result = 1
else:
result = cmp(l1, l2) or cmp(s1, s2)
return result
def split_entry(str, which):
stuff = []
parts = str.split('!')
parts = [part.split('@') for part in parts]
for entry in parts:
if len(entry) != 1:
key = entry[which]
else:
key = entry[0]
stuff.append(key)
return stuff
_rmtt = re.compile(r"""(.*)<tt(?: class=['"][a-z0-9]+["'])?>(.*)</tt>(.*)$""",
re.IGNORECASE)
_rmparens = re.compile(r"\(\)")
def split_entry_key(str):
parts = split_entry(str, 1)
for i in range(len(parts)):
m = _rmtt.match(parts[i])
if m:
parts[i] = null_join(m.group(1, 2, 3))
else:
parts[i] = parts[i].lower()
# remove '()' from the key:
parts[i] = _rmparens.sub('', parts[i])
return map(trim_ignored_letters, parts)
def split_entry_text(str):
if '<' in str:
m = _rmtt.match(str)
if m:
str = null_join(m.group(1, 2, 3))
return split_entry(str, 1)
def load(fp):
nodes = []
rx = re.compile("(.*)\1(.*)###(.*)$")
while 1:
line = fp.readline()
if not line:
break
m = rx.match(line)
if m:
link, str, seqno = m.group(1, 2, 3)
nodes.append(Node(link, str, seqno))
return nodes
def trim_ignored_letters(s):
# ignore $ to keep environment variables with the
# leading letter from the name
if s.startswith("$"):
return s[1:].lower()
else:
return s.lower()
def get_first_letter(s):
if s.startswith("<tex2html_percent_mark>"):
return "%"
else:
return trim_ignored_letters(s)[0]
def split_letters(nodes):
letter_groups = []
if nodes:
group = []
append = group.append
letter = get_first_letter(nodes[0].text[0])
letter_groups.append((letter, group))
for node in nodes:
nletter = get_first_letter(node.text[0])
if letter != nletter:
letter = nletter
group = []
letter_groups.append((letter, group))
append = group.append
append(node)
return letter_groups
def group_symbols(groups):
entries = []
ident_letters = string.ascii_letters + "_"
while groups[0][0] not in ident_letters:
entries += groups[0][1]
del groups[0]
if entries:
groups.insert(0, ("Symbols", entries))
# need a function to separate the nodes into columns...
def split_columns(nodes, columns=1):
if columns <= 1:
return [nodes]
# This is a rough height; we may have to increase to avoid breaks before
# a subitem.
colheight = int(len(nodes) / columns)
numlong = int(len(nodes) % columns)
if numlong:
colheight = colheight + 1
else:
numlong = columns
cols = []
for i in range(numlong):
start = i * colheight
end = start + colheight
cols.append(nodes[start:end])
del nodes[:end]
colheight = colheight - 1
try:
numshort = int(len(nodes) / colheight)
except ZeroDivisionError:
cols = cols + (columns - len(cols)) * [[]]
else:
for i in range(numshort):
start = i * colheight
end = start + colheight
cols.append(nodes[start:end])
#
# If items continue across columns, make sure they are marked
# as continuations so the user knows to look at the previous column.
#
for i in range(len(cols) - 1):
try:
prev = cols[i][-1]
next = cols[i + 1][0]
except IndexError:
return cols
else:
n = min(len(prev.key), len(next.key))
for j in range(n):
if prev.key[j] != next.key[j]:
break
next.continuation = j + 1
return cols
DL_LEVEL_INDENT = " "
def format_column(nodes):
strings = ["<dl compact>"]
append = strings.append
level = 0
previous = []
for node in nodes:
current = node.text
count = 0
for i in range(min(len(current), len(previous))):
if previous[i] != current[i]:
break
count = i + 1
if count > level:
append("<dl compact>" * (count - level) + "\n")
level = count
elif level > count:
append("\n")
append(level * DL_LEVEL_INDENT)
append("</dl>" * (level - count))
level = count
# else: level == count
for i in range(count, len(current) - 1):
term = node.text[i]
level = level + 1
if node.continuation > i:
extra = " (continued)"
else:
extra = ""
append("\n<dt>%s%s\n<dd>\n%s<dl compact>"
% (term, extra, level * DL_LEVEL_INDENT))
append("\n%s<dt>%s%s</a>"
% (level * DL_LEVEL_INDENT, node.links[0], node.text[-1]))
for link in node.links[1:]:
append(",\n%s %s[Link]</a>" % (level * DL_LEVEL_INDENT, link))
previous = current
append("\n")
append("</dl>" * (level + 1))
return null_join(strings)
def format_nodes(nodes, columns=1):
strings = []
append = strings.append
if columns > 1:
colnos = range(columns)
colheight = int(len(nodes) / columns)
if len(nodes) % columns:
colheight = colheight + 1
colwidth = int(100 / columns)
append('<table width="100%"><tr valign="top">')
for col in split_columns(nodes, columns):
append('<td width="%d%%">\n' % colwidth)
append(format_column(col))
append("\n</td>")
append("\n</tr></table>")
else:
append(format_column(nodes))
append("\n<p>\n")
return null_join(strings)
def format_letter(letter):
if letter == '.':
lettername = ". (dot)"
elif letter == '_':
lettername = "_ (underscore)"
else:
lettername = letter.capitalize()
return "\n<hr>\n<h2><a name=\"letter-%s\">%s</a></h2>\n\n" \
% (letter, lettername)
def format_html_letters(nodes, columns, group_symbol_nodes):
letter_groups = split_letters(nodes)
if group_symbol_nodes:
group_symbols(letter_groups)
items = []
for letter, nodes in letter_groups:
s = "<b><a href=\"#letter-%s\">%s</a></b>" % (letter, letter)
items.append(s)
s = ["<hr><center>\n%s</center>\n" % " |\n".join(items)]
for letter, nodes in letter_groups:
s.append(format_letter(letter))
s.append(format_nodes(nodes, columns))
return null_join(s)
def format_html(nodes, columns):
return format_nodes(nodes, columns)
def collapse(nodes):
"""Collapse sequences of nodes with matching keys into a single node.
Destructive."""
if len(nodes) < 2:
return
prev = nodes[0]
i = 1
while i < len(nodes):
node = nodes[i]
if not node.cmp_entry(prev):
prev.links.append(node.links[0])
del nodes[i]
else:
i = i + 1
prev = node
def dump(nodes, fp):
for node in nodes:
fp.write(node.dump())
def process_nodes(nodes, columns, letters=0, group_symbol_nodes=0):
nodes.sort()
collapse(nodes)
if letters:
return format_html_letters(nodes, columns, group_symbol_nodes)
else:
return format_html(nodes, columns)
def main():
import getopt
ifn = "-"
ofn = "-"
columns = 1
letters = 0
group_symbol_nodes = 1
opts, args = getopt.getopt(sys.argv[1:], "c:lo:",
["columns=", "dont-group-symbols",
"group-symbols", "letters", "output="])
for opt, val in opts:
if opt in ("-o", "--output"):
ofn = val
elif opt in ("-c", "--columns"):
columns = int(val, 10)
elif opt in ("-l", "--letters"):
letters = 1
elif opt == "--group-symbols":
group_symbol_nodes = 1
elif opt == "--dont-group-symbols":
group_symbol_nodes = 0
if not args:
args = [ifn]
nodes = []
for fn in args:
nodes = nodes + load(open(fn))
num_nodes = len(nodes)
html = process_nodes(nodes, columns, letters, group_symbol_nodes)
program = os.path.basename(sys.argv[0])
if ofn == "-":
sys.stdout.write(html)
sys.stderr.write("\n%s: %d index nodes" % (program, num_nodes))
else:
open(ofn, "w").write(html)
print
print "%s: %d index nodes" % (program, num_nodes)
if __name__ == "__main__":
main()

View File

@ -1,112 +0,0 @@
#!/uns/bin/perl
package checkargs;
require 5.004; # uses "for my $var"
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(check_args check_args_range check_args_at_least);
use strict;
use Carp;
=head1 NAME
checkargs -- Provide rudimentary argument checking for perl5 functions
=head1 SYNOPSIS
check_args(cArgsExpected, @_)
check_args_range(cArgsMin, cArgsMax, @_)
check_args_at_least(cArgsMin, @_)
where "@_" should be supplied literally.
=head1 DESCRIPTION
As the first line of user-written subroutine foo, do one of the following:
my ($arg1, $arg2) = check_args(2, @_);
my ($arg1, @rest) = check_args_range(1, 4, @_);
my ($arg1, @rest) = check_args_at_least(1, @_);
my @args = check_args_at_least(0, @_);
These functions may also be called for side effect (put a call to one
of the functions near the beginning of the subroutine), but using the
argument checkers to set the argument list is the recommended usage.
The number of arguments and their definedness are checked; if the wrong
number are received, the program exits with an error message.
=head1 AUTHOR
Michael D. Ernst <F<mernst@cs.washington.edu>>
=cut
## Need to check that use of caller(1) really gives desired results.
## Need to give input chunk information.
## Is this obviated by Perl 5.003's declarations? Not entirely, I think.
sub check_args ( $@ )
{
my ($num_formals, @args) = @_;
my ($pack, $file_arg, $line_arg, $subname, $hasargs, $wantarr) = caller(1);
if (@_ < 1) { croak "check_args needs at least 7 args, got ", scalar(@_), ": @_\n "; }
if ((!wantarray) && ($num_formals != 0))
{ croak "check_args called in scalar context"; }
# Can't use croak below here: it would only go out to caller, not its caller
my $num_actuals = @args;
if ($num_actuals != $num_formals)
{ die "$file_arg:$line_arg: function $subname expected $num_formals argument",
(($num_formals == 1) ? "" : "s"),
", got $num_actuals",
(($num_actuals == 0) ? "" : ": @args"),
"\n"; }
for my $index (0..$#args)
{ if (!defined($args[$index]))
{ die "$file_arg:$line_arg: function $subname undefined argument ", $index+1, ": @args[0..$index-1]\n"; } }
return @args;
}
sub check_args_range ( $$@ )
{
my ($min_formals, $max_formals, @args) = @_;
my ($pack, $file_arg, $line_arg, $subname, $hasargs, $wantarr) = caller(1);
if (@_ < 2) { croak "check_args_range needs at least 8 args, got ", scalar(@_), ": @_"; }
if ((!wantarray) && ($max_formals != 0) && ($min_formals !=0) )
{ croak "check_args_range called in scalar context"; }
# Can't use croak below here: it would only go out to caller, not its caller
my $num_actuals = @args;
if (($num_actuals < $min_formals) || ($num_actuals > $max_formals))
{ die "$file_arg:$line_arg: function $subname expected $min_formals-$max_formals arguments, got $num_actuals",
($num_actuals == 0) ? "" : ": @args", "\n"; }
for my $index (0..$#args)
{ if (!defined($args[$index]))
{ die "$file_arg:$line_arg: function $subname undefined argument ", $index+1, ": @args[0..$index-1]\n"; } }
return @args;
}
sub check_args_at_least ( $@ )
{
my ($min_formals, @args) = @_;
my ($pack, $file_arg, $line_arg, $subname, $hasargs, $wantarr) = caller(1);
# Don't do this, because we want every sub to start with a call to check_args*
# if ($min_formals == 0)
# { die "Isn't it pointless to check for at least zero args to $subname?\n"; }
if (scalar(@_) < 1)
{ croak "check_args_at_least needs at least 1 arg, got ", scalar(@_), ": @_"; }
if ((!wantarray) && ($min_formals != 0))
{ croak "check_args_at_least called in scalar context"; }
# Can't use croak below here: it would only go out to caller, not its caller
my $num_actuals = @args;
if ($num_actuals < $min_formals)
{ die "$file_arg:$line_arg: function $subname expected at least $min_formals argument",
($min_formals == 1) ? "" : "s",
", got $num_actuals",
($num_actuals == 0) ? "" : ": @args", "\n"; }
for my $index (0..$#args)
{ if (!defined($args[$index]))
{ warn "$file_arg:$line_arg: function $subname undefined argument ", $index+1, ": @args[0..$index-1]\n"; last; } }
return @args;
}
1; # successful import
__END__

View File

@ -1,26 +0,0 @@
#! /bin/sh
# -*- ksh -*-
# This script *helps* locate lines of normal content that end in '}';
# this is useful since LaTeX2HTML (at least the old version that we
# use) breaks on many lines that end that way.
#
# Usage: cklatex files... | less
#
# *Read* the output looking for suspicious lines!
grep -n "[^ ]}\$" $@ | \
grep -v '\\begin{' | \
grep -v '\\end{' | \
grep -v '\\input{' | \
grep -v '\\documentclass{' | \
grep -v '\\title{' | \
grep -v '\\chapter{' | \
grep -v '\\chapter\*{' | \
grep -v '\\section{' | \
grep -v '\\subsection{' | \
grep -v '\\subsubsection{' | \
grep -v '\\sectionauthor{' | \
grep -v '\\moduleauthor{'
exit $?

View File

@ -1,78 +0,0 @@
# Generate custlib.tex, which is a site-specific library document.
# Phase I: list all the things that can be imported
import glob
import os.path
import sys
modules = {}
for modname in sys.builtin_module_names:
modules[modname] = modname
for dir in sys.path:
# Look for *.py files
filelist = glob.glob(os.path.join(dir, '*.py'))
for file in filelist:
path, file = os.path.split(file)
base, ext = os.path.splitext(file)
modules[base.lower()] = base
# Look for shared library files
filelist = (glob.glob(os.path.join(dir, '*.so')) +
glob.glob(os.path.join(dir, '*.sl')) +
glob.glob(os.path.join(dir, '*.o')) )
for file in filelist:
path, file = os.path.split(file)
base, ext = os.path.splitext(file)
if base[-6:] == 'module':
base = base[:-6]
modules[base.lower()] = base
# Minor oddity: the types module is documented in libtypes2.tex
if modules.has_key('types'):
del modules['types']
modules['types2'] = None
# Phase II: find all documentation files (lib*.tex)
# and eliminate modules that don't have one.
docs = {}
filelist = glob.glob('lib*.tex')
for file in filelist:
modname = file[3:-4]
docs[modname] = modname
mlist = modules.keys()
mlist = filter(lambda x, docs=docs: docs.has_key(x), mlist)
mlist.sort()
mlist = map(lambda x, docs=docs: docs[x], mlist)
modules = mlist
# Phase III: write custlib.tex
# Write the boilerplate
# XXX should be fancied up.
print """\documentstyle[twoside,11pt,myformat]{report}
\\title{Python Library Reference}
\\input{boilerplate}
\\makeindex % tell \\index to actually write the .idx file
\\begin{document}
\\pagenumbering{roman}
\\maketitle
\\input{copyright}
\\begin{abstract}
\\noindent This is a customized version of the Python Library Reference.
\\end{abstract}
\\pagebreak
{\\parskip = 0mm \\tableofcontents}
\\pagebreak\\pagenumbering{arabic}"""
for modname in mlist:
print "\\input{lib%s}" % (modname,)
# Write the end
print """\\input{custlib.ind} % Index
\\end{document}"""

View File

@ -1,81 +0,0 @@
"""Utility class and function to get information about the CVS repository
based on checked-out files.
"""
import os
def get_repository_list(paths):
d = {}
for name in paths:
if os.path.isfile(name):
dir = os.path.dirname(name)
else:
dir = name
rootfile = os.path.join(name, "CVS", "Root")
root = open(rootfile).readline().strip()
if not d.has_key(root):
d[root] = RepositoryInfo(dir), [name]
else:
d[root][1].append(name)
return d.values()
class RepositoryInfo:
"""Record holding information about the repository we want to talk to."""
cvsroot_path = None
branch = None
# type is '', ':ext', or ':pserver:'
type = ""
def __init__(self, dir=None):
if dir is None:
dir = os.getcwd()
dir = os.path.join(dir, "CVS")
root = open(os.path.join(dir, "Root")).readline().strip()
if root.startswith(":pserver:"):
self.type = ":pserver:"
root = root[len(":pserver:"):]
elif ":" in root:
if root.startswith(":ext:"):
root = root[len(":ext:"):]
self.type = ":ext:"
self.repository = root
if ":" in root:
host, path = root.split(":", 1)
self.cvsroot_path = path
else:
self.cvsroot_path = root
fn = os.path.join(dir, "Tag")
if os.path.isfile(fn):
self.branch = open(fn).readline().strip()[1:]
def get_cvsroot(self):
return self.type + self.repository
_repository_dir_cache = {}
def get_repository_file(self, path):
filename = os.path.abspath(path)
if os.path.isdir(path):
dir = path
join = 0
else:
dir = os.path.dirname(path)
join = 1
try:
repodir = self._repository_dir_cache[dir]
except KeyError:
repofn = os.path.join(dir, "CVS", "Repository")
repodir = open(repofn).readline().strip()
repodir = os.path.join(self.cvsroot_path, repodir)
self._repository_dir_cache[dir] = repodir
if join:
fn = os.path.join(repodir, os.path.basename(path))
else:
fn = repodir
return fn[len(self.cvsroot_path)+1:]
def __repr__(self):
return "<RepositoryInfo for %s>" % `self.get_cvsroot()`

View File

@ -1,161 +0,0 @@
#!/usr/bin/env python
"""Script to locate email addresses in the CVS logs."""
__version__ = '$Revision$'
import os
import re
import sys
import UserDict
import cvsinfo
class Acknowledgements(UserDict.UserDict):
def add(self, email, name, path):
d = self.data
d.setdefault(email, {})[path] = name
def open_cvs_log(info, paths=None):
cvsroot = info.get_cvsroot()
cmd = "cvs -q -d%s log " % cvsroot
if paths:
cmd += " ".join(paths)
return os.popen(cmd, "r")
email_rx = re.compile("<([a-z][-a-z0-9._]*@[-a-z0-9.]+)>", re.IGNORECASE)
def find_acks(f, acks):
prev = ''
filename = None
MAGIC_WORDS = ('van', 'von')
while 1:
line = f.readline()
if not line:
break
if line.startswith("Working file: "):
filename = line.split(None, 2)[2].strip()
prev = line
continue
m = email_rx.search(line)
if m:
words = prev.split() + line[:m.start()].split()
L = []
while words \
and (words[-1][0].isupper() or words[-1] in MAGIC_WORDS):
L.insert(0, words.pop())
name = " ".join(L)
email = m.group(1).lower()
acks.add(email, name, filename)
prev = line
def load_cvs_log_acks(acks, args):
repolist = cvsinfo.get_repository_list(args or [""])
for info, paths in repolist:
print >>sys.stderr, "Repository:", info.get_cvsroot()
f = open_cvs_log(info, paths)
find_acks(f, acks)
f.close()
def load_tex_source_acks(acks, args):
for path in args:
path = path or os.curdir
if os.path.isfile(path):
read_acks_from_tex_file(acks, path)
else:
read_acks_from_tex_dir(acks, path)
def read_acks_from_tex_file(acks, path):
f = open(path)
while 1:
line = f.readline()
if not line:
break
if line.startswith(r"\sectionauthor{"):
line = line[len(r"\sectionauthor"):]
name, line = extract_tex_group(line)
email, line = extract_tex_group(line)
acks.add(email, name, path)
def read_acks_from_tex_dir(acks, path):
stack = [path]
while stack:
p = stack.pop()
for n in os.listdir(p):
n = os.path.join(p, n)
if os.path.isdir(n):
stack.insert(0, n)
elif os.path.normpath(n).endswith(".tex"):
read_acks_from_tex_file(acks, n)
def extract_tex_group(s):
c = 0
for i in range(len(s)):
if s[i] == '{':
c += 1
elif s[i] == '}':
c -= 1
if c == 0:
return s[1:i], s[i+1:]
def print_acks(acks):
first = 1
for email, D in acks.items():
if first:
first = 0
else:
print
L = D.items()
L.sort()
prefname = L[0][1]
for file, name in L[1:]:
if name != prefname:
prefname = ""
break
if prefname:
print prefname, "<%s>:" % email
else:
print email + ":"
for file, name in L:
if name == prefname:
print " " + file
else:
print " %s (as %s)" % (file, name)
def print_ack_names(acks):
names = []
for email, D in acks.items():
L = D.items()
L.sort()
prefname = L[0][1]
for file, name in L[1:]:
prefname = prefname or name
names.append(prefname or email)
def f(s1, s2):
s1 = s1.lower()
s2 = s2.lower()
return cmp((s1.split()[-1], s1),
(s2.split()[-1], s2))
names.sort(f)
for name in names:
print name
def main():
args = sys.argv[1:]
acks = Acknowledgements()
load_cvs_log_acks(acks, args)
load_tex_source_acks(acks, args)
print_ack_names(acks)
if __name__ == "__main__":
main()

View File

@ -1,136 +0,0 @@
#! /usr/bin/env python
import errno
import os
import re
import sys
if __name__ == "__main__":
_base = sys.argv[0]
else:
_base = __file__
_script_home = os.path.abspath(os.path.dirname(_base))
srcdir = os.path.dirname(os.path.dirname(_script_home))
EXCLUDES = ["bitset.h", "cStringIO.h", "graminit.h", "grammar.h",
"longintrepr.h", "metagrammar.h",
"node.h", "opcode.h", "osdefs.h", "pgenheaders.h",
"py_curses.h", "parsetok.h", "symtable.h", "token.h"]
def list_headers():
"""Return a list of headers."""
incdir = os.path.join(srcdir, "Include")
return [fn for fn in os.listdir(incdir)
if fn.endswith(".h") and fn not in EXCLUDES]
def matcher(pattern):
return re.compile(pattern).match
MATCHERS = [
matcher(r"\\begin\{cfuncdesc\}\{[^{]*\}\{(?P<sym>[^{]*)\}"),
matcher(r"\\cfuncline\{[^{]*\}\{(?P<sym>[^{]*)\}"),
matcher(r"\\begin\{ctypedesc\}(\[[^{]*\])?\{(?P<sym>[^{]*)\}"),
matcher(r"\\begin\{cvardesc\}\{[^{]*\}\{(?P<sym>[^{]*)\}"),
matcher(r"\\begin\{cmemberdesc\}\{[^{]*\}\{(?P<sym>[^{]*)\}"),
matcher(r"\\cmemberline\{[^{]*\}\{(?P<sym>[^{]*)\}"),
matcher(r"\\begin\{csimplemacrodesc\}\{(?P<sym>[^{]*)\}"),
]
def list_documented_items():
"""Return a list of everything that's already documented."""
apidir = os.path.join(srcdir, "Doc", "api")
files = [fn for fn in os.listdir(apidir) if fn.endswith(".tex")]
L = []
for fn in files:
fullname = os.path.join(apidir, fn)
for line in open(fullname):
line = line.lstrip()
if not line.startswith("\\"):
continue
for matcher in MATCHERS:
m = matcher(line)
if m:
L.append(m.group("sym"))
break
return L
def split_documented(all, documented):
"""Split the list of all symbols into documented and undocumented
categories."""
doc = []
undoc = []
for t in all:
if t[0] in documented:
doc.append(t)
else:
undoc.append(t)
return doc, undoc
def print_list(L, title=None):
"""Dump a list to stdout."""
if title:
print title + ":"
print "-" * (len(title) + 1)
w = 0
for sym, filename in L:
w = max(w, len(sym))
if w % 4 == 0:
w += 4
else:
w += (4 - (w % 4))
for sym, filename in L:
print "%-*s%s" % (w, sym, filename)
_spcjoin = ' '.join
def main():
args = sys.argv[1:]
if args:
headers = args
documented = []
else:
os.chdir(os.path.join(srcdir, "Include"))
headers = list_headers()
documented = list_documented_items()
cmd = ("ctags -f - --file-scope=no --c-types=dgpstux "
"-Istaticforward -Istatichere=static "
+ _spcjoin(headers))
fp = os.popen(cmd)
L = []
prevsym = None
while 1:
line = fp.readline()
if not line:
break
sym, filename = line.split()[:2]
if sym == prevsym:
continue
if not sym.endswith("_H"):
L.append((sym, filename))
prevsym = sym
L.sort()
fp.close()
try:
if documented:
documented, undocumented = split_documented(L, documented)
print_list(documented, "Documented symbols")
if undocumented:
print
print_list(undocumented, "Undocumented symbols")
else:
print_list(L)
except IOError, e:
if e.errno != errno.EPIPE:
raise
if __name__ == "__main__":
main()

View File

@ -1,63 +0,0 @@
#! /usr/bin/env python
# -*- Python -*-
import fileinput
import getopt
import glob
import os
import re
import sys
declare_rx = re.compile(
r"\\declaremodule(?:\[[a-zA-Z0-9]*\]*)?{[a-zA-Z_0-9]+}{([a-zA-Z_0-9]+)}")
module_rx = re.compile(r"\\module{([a-zA-Z_0-9]+)}")
def main():
try:
just_list = 0
print_lineno = 0
opts, args = getopt.getopt(sys.argv[1:], "ln", ["list", "number"])
for opt, arg in opts:
if opt in ("-l", "--list"):
just_list = 1
elif opt in ("-n", "--number"):
print_lineno = 1
files = args
if not files:
files = glob.glob("*.tex")
files.sort()
modulename = None
for line in fileinput.input(files):
if line[:9] == r"\section{":
modulename = None
continue
if line[:16] == r"\modulesynopsys{":
continue
m = declare_rx.match(line)
if m:
modulename = m.group(1)
continue
if not modulename:
continue
m = module_rx.search(line)
if m:
name = m.group(1)
if name != modulename:
filename = fileinput.filename()
if just_list:
print filename
fileinput.nextfile()
modulename = None
elif print_lineno:
print "%s(%d):%s" \
% (filename, fileinput.filelineno(), line[:-1])
else:
print "%s:%s" % (filename, line[:-1])
except KeyboardInterrupt:
sys.exit(1)
if __name__ == "__main__":
main()

View File

@ -1,128 +0,0 @@
#!/usr/bin/env python
# Released to the public domain by Skip Montanaro, 28 March 2002
"""
findsyms.py - try to identify undocumented symbols exported by modules
Usage: findsyms.py librefdir
For each lib*.tex file in the libref manual source directory, identify which
module is documented, import the module if possible, then search the LaTeX
source for the symbols global to that module. Report any that don't seem to
be documented.
Certain exceptions are made to the list of undocumented symbols:
* don't mention symbols in which all letters are upper case on the
assumption they are manifest constants
* don't mention symbols that are themselves modules
* don't mention symbols that match those exported by os, math, string,
types, or __builtin__ modules
Finally, if a name is exported by the module but fails a getattr() lookup,
that anomaly is reported.
"""
import __builtin__
import getopt
import glob
import math
import os
import re
import string
import sys
import types
import warnings
def usage():
print >> sys.stderr, """
usage: %s dir
where 'dir' is the Library Reference Manual source directory.
""" % os.path.basename(sys.argv[0])
def main():
try:
opts, args = getopt.getopt(sys.argv[1:], "")
except getopt.error:
usage()
return
if not args:
usage()
return
libdir = args[0]
warnings.filterwarnings("error")
pat = re.compile(r"\\declaremodule\s*{[^}]*}\s*{([^}]*)}")
missing = []
filelist = glob.glob(os.path.join(libdir, "lib*.tex"))
filelist.sort()
for f in filelist:
mod = f[3:-4]
if not mod: continue
data = open(f).read()
mods = re.findall(pat, data)
if not mods:
print "No module declarations found in", f
continue
for modname in mods:
# skip special modules
if modname.startswith("__"):
continue
try:
mod = __import__(modname)
except ImportError:
missing.append(modname)
continue
except DeprecationWarning:
print "Deprecated module:", modname
continue
if hasattr(mod, "__all__"):
all = mod.__all__
else:
all = [k for k in dir(mod) if k[0] != "_"]
mentioned = 0
all.sort()
for name in all:
if data.find(name) == -1:
# certain names are predominantly used for testing
if name in ("main","test","_test"):
continue
# is it some sort of manifest constant?
if name.upper() == name:
continue
try:
item = getattr(mod, name)
except AttributeError:
print " ", name, "exposed, but not an attribute"
continue
# don't care about modules that might be exposed
if type(item) == types.ModuleType:
continue
# check a few modules which tend to be import *'d
isglobal = 0
for m in (os, math, string, __builtin__, types):
if hasattr(m, name) and item == getattr(m, name):
isglobal = 1
break
if isglobal: continue
if not mentioned:
print "Not mentioned in", modname, "docs:"
mentioned = 1
print " ", name
if missing:
missing.sort()
print "Could not import:"
print " ", ", ".join(missing)
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
pass

View File

@ -1,2 +0,0 @@
#!/bin/sh
sed -e 's/{\\ptt[ ]*\\char[ ]*'"'"'137}/_/g' <"$1" > "@$1" && mv "@$1" $1

View File

@ -1,3 +0,0 @@
#! /bin/sed -f
s/{\\tt \\hackscore {}\\hackscore {}/\\sectcode{__/
s/\\hackscore {}\\hackscore {}/__/

View File

@ -1,15 +0,0 @@
(defun fix-python-texinfo ()
(goto-char (point-min))
(replace-regexp "\\(@setfilename \\)\\([-a-z]*\\)$"
"\\1python-\\2.info")
(replace-string "@node Front Matter\n@chapter Abstract\n"
"@node Abstract\n@section Abstract\n")
(mark-whole-buffer)
(texinfo-master-menu 'update-all-nodes)
(save-buffer)
) ;; fix-python-texinfo
;; now really do it:
(find-file (car command-line-args-left))
(fix-python-texinfo)
(kill-emacs)

View File

@ -1,97 +0,0 @@
#! /usr/bin/env python
"""Generate a page count report of the PostScript version of the manuals."""
__version__ = '$Revision$'
import getopt
import sys
class PageCounter:
def __init__(self):
self.doclist = []
self.total = 0
self.title_width = 0
self.version = ""
def add_document(self, prefix, title):
count = count_pages(prefix + ".ps")
self.doclist.append((title, prefix, count))
self.title_width = max(self.title_width, len(title))
self.total = self.total + count
def dump(self):
fmt = "%%-%ds (%%s.ps, %%d pages)" % self.title_width
for item in self.doclist:
print fmt % item
print
print " Total page count: %d" % self.total
def parse_options(self):
opts, args = getopt.getopt(sys.argv[1:], "r:", ["release="])
assert not args
for opt, arg in opts:
if opt in ("-r", "--release"):
self.version = arg
def run(self):
self.parse_options()
if self.version:
version = self.version[:3]
self.add_document("whatsnew" + version.replace(".", ""),
"What's New in Python " + version)
for prefix, title in [
("api", "Python/C API"),
("ext", "Extending and Embedding the Python Interpreter"),
("lib", "Python Library Reference"),
("mac", "Macintosh Module Reference"),
("ref", "Python Reference Manual"),
("tut", "Python Tutorial"),
("doc", "Documenting Python"),
("inst", "Installing Python Modules"),
("dist", "Distributing Python Modules"),
]:
self.add_document(prefix, title)
print self.PREFIX
self.dump()
print self.SUFFIX
PREFIX = """\
This is the PostScript version of the standard Python documentation.
If you plan to print this, be aware that some of the documents are
long. It is formatted for printing on two-sided paper; if you do plan
to print this, *please* print two-sided if you have a printer capable
of it! To locate published copies of the larger manuals, or other
Python reference material, consult the Python Bookstore at:
http://www.amk.ca/bookstore/
The following manuals are included in this package:
"""
SUFFIX = """\
If you have any questions, comments, or suggestions regarding these
documents, please send them via email to python-docs@python.org.
"""
def count_pages(filename):
fp = open(filename)
count = 0
while 1:
lines = fp.readlines(1024*40)
if not lines:
break
for line in lines:
if line[:7] == "%%Page:":
count = count + 1
fp.close()
return count
def main():
PageCounter().run()
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@ -1,100 +0,0 @@
#! /usr/bin/env python
"""Combine similar index entries into an entry and subentries.
For example:
\item {foobar} (in module flotz), 23
\item {foobar} (in module whackit), 4323
becomes
\item {foobar}
\subitem in module flotz, 23
\subitem in module whackit, 4323
Note that an item which matches the format of a collapsable item but which
isn't part of a group of similar items is not modified.
"""
__version__ = '$Revision$'
import re
import StringIO
import sys
def cmp_entries(e1, e2):
return cmp(e1[1].lower(), e2[1].lower()) or cmp(e1, e2)
def dump_entries(write, entries):
if len(entries) == 1:
write(" \\item %s (%s)%s\n" % entries[0])
return
write(" \item %s\n" % entries[0][0])
# now sort these in a case insensitive manner:
if len(entries) > 0:
entries.sort(cmp_entries)
for xxx, subitem, pages in entries:
write(" \subitem %s%s\n" % (subitem, pages))
breakable_re = re.compile(
r" \\item (.*) [(](.*)[)]((?:(?:, \d+)|(?:, \\[a-z]*\{\d+\}))+)")
def process(ifn, ofn=None):
if ifn == "-":
ifp = sys.stdin
else:
ifp = open(ifn)
if ofn is None:
ofn = ifn
ofp = StringIO.StringIO()
entries = []
match = breakable_re.match
write = ofp.write
while 1:
line = ifp.readline()
if not line:
break
m = match(line)
if m:
entry = m.group(1, 2, 3)
if entries and entries[-1][0] != entry[0]:
dump_entries(write, entries)
entries = []
entries.append(entry)
elif entries:
dump_entries(write, entries)
entries = []
write(line)
else:
write(line)
del write
del match
ifp.close()
data = ofp.getvalue()
ofp.close()
if ofn == "-":
ofp = sys.stdout
else:
ofp = open(ofn, "w")
ofp.write(data)
ofp.close()
def main():
import getopt
outfile = None
opts, args = getopt.getopt(sys.argv[1:], "o:")
for opt, val in opts:
if opt in ("-o", "--output"):
outfile = val
filename = args[0]
outfile = outfile or filename
process(filename, outfile)
if __name__ == "__main__":
main()

View File

@ -1,19 +0,0 @@
#! /usr/bin/env python
# This Python program sorts and reformats the table of keywords in ref2.tex
l = []
try:
while 1:
l = l + raw_input().split()
except EOFError:
pass
l.sort()
for x in l[:]:
while l.count(x) > 1: l.remove(x)
ncols = 5
nrows = (len(l)+ncols-1)/ncols
for i in range(nrows):
for j in range(i, len(l), nrows):
print l[j].ljust(10),
print

View File

@ -1,183 +0,0 @@
#! /usr/bin/env python
# -*- Python -*-
#
# This script can be used to identify undocumented modules in the Python
# standard library. Use it like this:
#
# .../Doc/tools/listmodules --ignore-from .../Doc/paper-<paper>/modlib.idx
"""%(program)s - list modules in the Python standard library
-a, --annotate Annotate the module names with the subdirectory they
live in
-c, --categorize Group the modules by subdirectory
-i <file>,
--ignore-from <file> Ignore the modules listed in <file>. <file> may
contain a list of module names or a module index file
as produced when formatting the Python documentation
(.idx or .html flavor).
If neither -a nor -c are given, the modules are listed in alphabetical
order.
Note that -a and -c are mutually exclusive.
Limitation: Modules loadable as shared objects may not be listed,
though this script attempts to locate such modules.
"""
__version__ = '$Revision$'
import getopt
import glob
import os
import re
import string
import sys
REMOVE_DIRS = ["dos-8x3", "encodings", "distutils",
"lib-old", "lib-stdwin", "test"]
def main():
args = sys.argv[1:]
annotate = 0
builtin = 0
categorize = 0
ignore_dict = {}
ignore = ignore_dict.has_key
try:
opts, args = getopt.getopt(
args, "abchi:",
["annotate", "built-in", "categorize", "help", "ignore-from="])
except getopt.error, msg:
sys.stdout = sys.stderr
print msg
print
usage()
sys.exit(2)
for opt, arg in opts:
if opt in ("-a", "--annotate"):
annotate = 1
elif opt in ("-b", "--built-in"):
builtin = 1
elif opt in ("-c", "--categorize"):
categorize = 1
elif opt in ("-h", "--help"):
usage()
sys.exit()
elif opt in ("-i", "--ignore-from"):
data = open(arg).read()
if data[:1] == "\\":
ignore_from_idx(data, ignore_dict)
else:
ignore_from_modulelist(data, ignore_dict)
if args or (annotate and categorize):
usage()
sys.exit(2)
#
# Populate the database:
#
srcdir = os.path.normpath(os.path.join(
os.path.dirname(sys.argv[0]), os.pardir, os.pardir))
os.chdir(srcdir)
modules_by_name = {}
modules_by_dir = {}
if builtin:
l = []
modules_by_dir["<builtin>"] = l
for name in sys.builtin_module_names:
if not ignore(name):
modules_by_name[name] = "<built-in>"
l.append(name)
rx = re.compile("Lib/plat-[a-zA-Z0-9]*/")
fp = os.popen("find Lib -name \*.py -print", "r")
while 1:
line = fp.readline()
if not line:
break
m = rx.match(line)
if m:
line = "Lib/plat-*/" + line[m.end():]
line = line[4:-4] # strip off 'Lib/' and '.py\n'
dir, name = os.path.split(line)
dir = dir or "<standard>"
if ignore(name):
continue
if dir not in REMOVE_DIRS:
modules_by_name[name] = dir
l = modules_by_dir.get(dir, [])
modules_by_dir[dir] = l
if name not in l:
l.append(name)
# load up extension modules:
pwd = os.getcwd()
try:
os.chdir("Modules")
dir = "<extension>"
for line in glob.glob("*module.c"):
name = line[:-8]
if ignore(name) or modules_by_name.has_key(name) or name == "xx":
continue
modules_by_name[name] = dir
l = modules_by_dir.get(dir, [])
modules_by_dir[dir] = l
if name not in l:
l.append(name)
finally:
os.chdir(pwd)
#
# Dump the results:
#
if annotate:
modules = modules_by_name.items()
modules.sort()
width = max(map(len, modules_by_name.keys()))
format = "%%-%ds %%s" % width
for name, dir in modules:
if dir and dir[0] != "<":
print format % (name, dir)
else:
print name
elif categorize:
modules = modules_by_dir.items()
modules.sort()
width = max(map(len, modules_by_dir.keys()))
format = "%%-%ds %%s" % width
for dir, names in modules:
names.sort()
print format % (dir, names[0])
for name in names[1:]:
print format % ('', name)
print
else:
modules = modules_by_name.keys()
modules.sort()
print string.join(modules, "\n")
def ignore_from_modulelist(data, ignore_dict):
for name in string.split(data):
ignore_dict[name] = name
def ignore_from_idx(data, ignore_dict):
data = string.replace(data, r"\hackscore {}", "_")
rx = re.compile(r"\\indexentry\s*{([^@]*)@")
for line in string.split(data, "\n"):
m = rx.match(line)
if m:
name = m.group(1)
ignore_dict[name] = name
def usage():
vars = {}
vars["program"] = os.path.basename(sys.argv[0])
print __doc__ % vars
if __name__ == "__main__":
main()

View File

@ -1,129 +0,0 @@
#!/bin/bash
# Simple little checker for individual libref manual sections
#
# usage: makesec.sh section
#
# This script builds the minimal file necessary to run a single section
# through latex, does so, then converts the resulting dvi file to ps or pdf
# and feeds the result into a viewer. It's by no means foolproof, but seems
# to work okay for me (knock wood). It sure beats manually commenting out
# most of the man lib.tex file and running everything manually.
# It attempts to locate an appropriate dvi converter and viewer for the
# selected output format. It understands the following environment
# variables:
#
# PYSRC - refers to the root of your build tree (dir containing Doc)
# DVICVT - refers to a dvi converter like dvips or dvipdf
# VIEWER - refers to an appropriate viewer for the ps/pdf file
#
# Of the three, only PYSRC is currently required. The other two can be set
# to specify unusual tools which perform those tasks.
# Known issues:
# - It would be nice if the script could determine PYSRC on its own.
# - Something about \seealso{}s blows the latex stack, so they need
# to be commented out for now.
if [ x$PYSRC = x ] ; then
echo "PYSRC must refer to the Python source tree" 1>&2
exit 1
fi
if [ ! -d $PYSRC/Doc ] ; then
echo "Can't find a Doc subdirectory in $PYSRC" 1>&2
exit 1
fi
if [ "$#" -ne 1 ] ; then
echo "Must specify a single libref manual section on cmd line" 1>&2
exit 1
fi
# settle on a dvi converter
if [ x$DVICVT != x ] ; then
converter=$DVICVT
ext=`echo $DVICVT | sed -e 's/^dvi//'`
result=lib.$ext
elif [ x`which dvipdf` != x ] ; then
converter=`which dvipdf`
ext=.pdf
elif [ x`which dvips` != x ] ; then
converter=`which dvips`
ext=.ps
else
echo "Can't find a reasonable dvi converter" 1>&2
echo "Set DVICVT to refer to one" 1>&2
exit 1
fi
# how about a viewer?
if [ x$VIEWER != x ] ; then
viewer=$VIEWER
elif [ $ext = ".ps" -a x`which gv` != x ] ; then
viewer=gv
elif [ $ext = ".ps" -a x`which gs` != x ] ; then
viewer=gs
elif [ $ext = ".pdf" -a x`which acroread` != x ] ; then
viewer=acroread
elif [ $ext = ".pdf" -a "`uname`" = "Darwin" -a x`which open` != x ] ; then
viewer=open
elif [ $ext = ".pdf" -a x`which acroread` != x ] ; then
viewer=acroread
else
echo "Can't find a reasonable viewer" 1>&2
echo "Set VIEWER to refer to one" 1>&2
exit 1
fi
# make sure necessary links are in place
for f in howto.cls pypaper.sty ; do
rm -f $f
ln -s $PYSRC/Doc/$f
done
export TEXINPUTS=.:$PYSRC/Doc/texinputs:
# strip extension in case they gave full filename
inp=`basename $1 .tex`
# create the minimal framework necessary to run section through latex
tmpf=lib.tex
cat > $tmpf <<EOF
\documentclass{manual}
% NOTE: this file controls which chapters/sections of the library
% manual are actually printed. It is easy to customize your manual
% by commenting out sections that you are not interested in.
\title{Python Library Reference}
\input{boilerplate}
\makeindex % tell \index to actually write the
% .idx file
\makemodindex % ... and the module index as well.
\begin{document}
\maketitle
\ifhtml
\chapter*{Front Matter\label{front}}
\fi
\input{$inp}
\end{document}
EOF
latex $tmpf
$converter lib
$viewer lib.pdf
rm -f $tmpf howto.cls pypaper.sty *.idx *.syn
rm -f lib.{aux,log}

View File

@ -1,66 +0,0 @@
#! /usr/bin/env python
# -*- Python -*-
import string
import support
import sys
def collect(fp):
names = []
while 1:
line = fp.readline()
if not line:
break
line = string.strip(line)
if line:
names.append(line)
else:
names = []
return names
def main():
options = support.Options()
options.columns = 4
options.variables["title"] = "Acknowledgements"
options.parse(sys.argv[1:])
names = collect(sys.stdin)
percol = (len(names) + options.columns - 1) / options.columns
colnums = []
for i in range(options.columns):
colnums.append(percol*i)
options.aesop_type = "information"
fp = options.get_output_file()
fp.write(string.rstrip(options.get_header()) + "\n")
fp.write(THANKS + "\n")
fp.write('<table width="100%" align="center">\n')
for i in range(percol):
fp.write(" <tr>\n")
for j in colnums:
try:
fp.write(" <td>%s</td>\n" % names[i + j])
except IndexError:
pass
fp.write(" </tr>\n")
fp.write("</table>\n")
fp.write(string.rstrip(options.get_footer()) + "\n")
fp.close()
THANKS = '''\
<p>These people have contributed in some way to the Python
documentation. This list is probably not complete -- if you feel that
you or anyone else should be on this list, please let us know (send
email to <a
href="mailto:python-docs@python.org">python-docs@python.org</a>), and
we will be glad to correct the problem.</p>
<p>It is only with the input and contributions of the Python community
that Python has such wonderful documentation -- <b>Thank You!</b></p>
'''
if __name__ == "__main__":
main()

View File

@ -1,665 +0,0 @@
#! /usr/bin/env python
# -*- Python -*-
"""usage: %(program)s [options...] file ...
Options specifying formats to build:
--html HyperText Markup Language (default)
--pdf Portable Document Format
--ps PostScript
--dvi 'DeVice Indepentent' format from TeX
--text ASCII text (requires lynx)
More than one output format may be specified, or --all.
HTML options:
--address, -a Specify an address for page footers.
--dir Specify the directory for HTML output.
--link Specify the number of levels to include on each page.
--split, -s Specify a section level for page splitting, default: %(max_split_depth)s.
--iconserver, -i Specify location of icons (default: ./).
--image-type Specify the image type to use in HTML output;
values: gif (default), png.
--numeric Don't rename the HTML files; just keep node#.html for
the filenames.
--style Specify the CSS file to use for the output (filename,
not a URL).
--up-link URL to a parent document.
--up-title Title of a parent document.
--favicon Icon to display in the browsers location bar.
Other options:
--a4 Format for A4 paper.
--letter Format for US letter paper (the default).
--help, -H Show this text.
--logging, -l Log stdout and stderr to a file (*.how).
--debugging, -D Echo commands as they are executed.
--keep, -k Keep temporary files around.
--quiet, -q Do not print command output to stdout.
(stderr is also lost, sorry; see *.how for errors)
"""
import getopt
import glob
import os
import re
import shutil
import string
import sys
if not hasattr(os.path, "abspath"):
# Python 1.5.1 or earlier
def abspath(path):
"""Return an absolute path."""
if not os.path.isabs(path):
path = os.path.join(os.getcwd(), path)
return os.path.normpath(path)
os.path.abspath = abspath
MYDIR = os.path.abspath(sys.path[0])
TOPDIR = os.path.dirname(MYDIR)
ISTFILE = os.path.join(TOPDIR, "texinputs", "python.ist")
NODE2LABEL_SCRIPT = os.path.join(MYDIR, "node2label.pl")
L2H_INIT_FILE = os.path.join(TOPDIR, "perl", "l2hinit.perl")
BIBTEX_BINARY = "bibtex"
DVIPS_BINARY = "dvips"
LATEX_BINARY = "latex"
LATEX2HTML_BINARY = "latex2html"
LYNX_BINARY = "lynx"
MAKEINDEX_BINARY = "makeindex"
PDFLATEX_BINARY = "pdflatex"
PERL_BINARY = "perl"
PYTHON_BINARY = "python"
def usage(options):
print __doc__ % options
def error(options, message, err=2):
sys.stdout = sys.stderr
print message
print
usage(options)
sys.exit(2)
class Options:
program = os.path.basename(sys.argv[0])
#
address = ''
builddir = None
debugging = 0
discard_temps = 1
have_temps = 0
icon_server = "."
image_type = "gif"
logging = 0
max_link_depth = 3
max_split_depth = 6
paper = "letter"
quiet = 0
runs = 0
numeric = 0
global_module_index = None
style_file = os.path.join(TOPDIR, "html", "style.css")
about_file = os.path.join(TOPDIR, "html", "about.dat")
up_link = None
up_title = None
favicon = None
#
# 'dvips_safe' is a weird option. It is used mostly to make
# LaTeX2HTML not try to be too smart about protecting the user
# from a bad version of dvips -- some versions would core dump if
# the path to the source DVI contained a dot, and it's appearantly
# difficult to determine if the version available has that bug.
# This option gets set when PostScript output is requested
# (because we're going to run dvips regardless, and we'll either
# know it succeeds before LaTeX2HTML is run, or we'll have
# detected the failure and bailed), or the user asserts that it's
# safe from the command line.
#
# So, why does LaTeX2HTML think it appropriate to protect the user
# from a dvips that's only potentially going to core dump? Only
# because they want to avoid doing a lot of work just to have to
# bail later with no useful intermediates. Unfortunately, they
# bail *before* they know whether dvips will be needed at all.
# I've gone around the bush a few times with the LaTeX2HTML
# developers over whether this is appropriate behavior, and they
# don't seem interested in changing their position.
#
dvips_safe = 0
#
DEFAULT_FORMATS = ("html",)
ALL_FORMATS = ("dvi", "html", "pdf", "ps", "text")
def __init__(self):
self.formats = []
self.l2h_init_files = []
def __getitem__(self, key):
# This is used when formatting the usage message.
try:
return getattr(self, key)
except AttributeError:
raise KeyError, key
def parse(self, args):
opts, args = getopt.getopt(args, "Hi:a:s:lDkqr:",
["all", "postscript", "help", "iconserver=",
"address=", "a4", "letter", "l2h-init=",
"link=", "split=", "logging", "debugging",
"keep", "quiet", "runs=", "image-type=",
"about=", "numeric", "style=", "paper=",
"up-link=", "up-title=", "dir=",
"global-module-index=", "dvips-safe",
"favicon="]
+ list(self.ALL_FORMATS))
for opt, arg in opts:
if opt == "--all":
self.formats = list(self.ALL_FORMATS)
self.dvips_safe = "ps" in self.formats
elif opt in ("-H", "--help"):
usage(self)
sys.exit()
elif opt == "--iconserver":
self.icon_server = arg
elif opt in ("-a", "--address"):
self.address = arg
elif opt == "--a4":
self.paper = "a4"
elif opt == "--letter":
self.paper = "letter"
elif opt == "--link":
self.max_link_depth = int(arg)
elif opt in ("-s", "--split"):
self.max_split_depth = int(arg)
elif opt in ("-l", "--logging"):
self.logging = self.logging + 1
elif opt in ("-D", "--debugging"):
self.debugging = self.debugging + 1
elif opt in ("-k", "--keep"):
self.discard_temps = 0
elif opt in ("-q", "--quiet"):
self.quiet = 1
elif opt in ("-r", "--runs"):
self.runs = int(arg)
elif opt == "--image-type":
self.image_type = arg
elif opt == "--about":
# always make this absolute:
self.about_file = os.path.normpath(
os.path.abspath(arg))
elif opt == "--numeric":
self.numeric = 1
elif opt == "--style":
self.style_file = os.path.abspath(arg)
elif opt == "--l2h-init":
self.l2h_init_files.append(os.path.abspath(arg))
elif opt == "--favicon":
self.favicon = arg
elif opt == "--up-link":
self.up_link = arg
elif opt == "--up-title":
self.up_title = arg
elif opt == "--global-module-index":
self.global_module_index = arg
elif opt == "--dir":
if os.sep == "\\":
arg = re.sub("/", "\\", arg)
self.builddir = os.path.expanduser(arg)
elif opt == "--paper":
self.paper = arg
elif opt == "--dvips-safe":
self.dvips_safe = 1
#
# Format specifiers:
#
elif opt[2:] in self.ALL_FORMATS:
self.add_format(opt[2:])
elif opt == "--postscript":
# synonym for --ps
self.add_format("ps")
self.initialize()
#
# return the args to allow the caller access:
#
return args
def add_format(self, format):
"""Add a format to the formats list if not present."""
if not format in self.formats:
if format == "ps":
# assume this is safe since we're going to run it anyway
self.dvips_safe = 1
self.formats.append(format)
def initialize(self):
"""Complete initialization. This is needed if parse() isn't used."""
# add the default format if no formats were specified:
if not self.formats:
self.formats = self.DEFAULT_FORMATS
# determine the base set of texinputs directories:
texinputs = string.split(os.environ.get("TEXINPUTS", ""), os.pathsep)
if not texinputs:
texinputs = ['']
self.base_texinputs = [
os.path.join(TOPDIR, "paper-" + self.paper),
os.path.join(TOPDIR, "texinputs"),
] + texinputs
if self.builddir:
self.builddir = os.path.abspath(self.builddir)
class Job:
latex_runs = 0
def __init__(self, options, path):
self.options = options
self.doctype = get_doctype(path)
self.filedir, self.doc = split_pathname(path)
self.builddir = os.path.abspath(options.builddir or self.doc)
if ("html" in options.formats or "text" in options.formats):
if not os.path.exists(self.builddir):
os.mkdir(self.builddir)
self.log_filename = os.path.join(self.builddir, self.doc + ".how")
else:
self.log_filename = os.path.abspath(self.doc + ".how")
if os.path.exists(self.log_filename):
os.unlink(self.log_filename)
l2hconf = self.doc + ".l2h"
if os.path.exists(l2hconf):
if os.path.exists(l2hconf + "~"):
os.unlink(l2hconf + "~")
os.rename(l2hconf, l2hconf + "~")
self.l2h_aux_init_file = self.doc + ".l2h"
self.write_l2h_aux_init_file()
def build(self):
self.setup_texinputs()
formats = self.options.formats
if "dvi" in formats or "ps" in formats:
self.build_dvi()
if "pdf" in formats:
self.build_pdf()
if "ps" in formats:
self.build_ps()
if "html" in formats:
self.require_temps()
self.build_html(self.builddir)
if self.options.icon_server == ".":
pattern = os.path.join(TOPDIR, "html", "icons",
"*." + self.options.image_type)
imgs = glob.glob(pattern)
if not imgs:
self.warning(
"Could not locate support images of type %s."
% `self.options.image_type`)
for fn in imgs:
new_fn = os.path.join(self.builddir, os.path.basename(fn))
shutil.copyfile(fn, new_fn)
if "text" in formats:
self.require_temps()
tempdir = self.doc
need_html = "html" not in formats
if self.options.max_split_depth != 1:
fp = open(self.l2h_aux_init_file, "a")
fp.write("# re-hack this file for --text:\n")
l2hoption(fp, "MAX_SPLIT_DEPTH", "1")
fp.write("1;\n")
fp.close()
tempdir = self.doc + "-temp-html"
need_html = 1
if need_html:
self.build_html(tempdir, max_split_depth=1)
self.build_text(tempdir)
if self.options.discard_temps:
self.cleanup()
def setup_texinputs(self):
texinputs = [self.filedir] + list(self.options.base_texinputs)
os.environ["TEXINPUTS"] = string.join(texinputs, os.pathsep)
self.message("TEXINPUTS=" + os.environ["TEXINPUTS"])
def build_aux(self, binary=None):
if binary is None:
binary = LATEX_BINARY
new_index( "%s.ind" % self.doc, "genindex")
new_index("mod%s.ind" % self.doc, "modindex")
self.run("%s %s" % (binary, self.doc))
self.use_bibtex = check_for_bibtex(self.doc + ".aux")
self.latex_runs = 1
def build_dvi(self):
self.use_latex(LATEX_BINARY)
def build_pdf(self):
self.use_latex(PDFLATEX_BINARY)
def use_latex(self, binary):
self.require_temps(binary=binary)
if self.latex_runs < 2:
if os.path.isfile("mod%s.idx" % self.doc):
self.run("%s mod%s.idx" % (MAKEINDEX_BINARY, self.doc))
use_indfix = 0
if os.path.isfile(self.doc + ".idx"):
use_indfix = 1
# call to Doc/tools/fix_hack omitted; doesn't appear necessary
self.run("%s %s.idx" % (MAKEINDEX_BINARY, self.doc))
import indfix
indfix.process(self.doc + ".ind")
if self.use_bibtex:
self.run("%s %s" % (BIBTEX_BINARY, self.doc))
self.process_synopsis_files()
self.run("%s %s" % (binary, self.doc))
self.latex_runs = self.latex_runs + 1
if os.path.isfile("mod%s.idx" % self.doc):
self.run("%s -s %s mod%s.idx"
% (MAKEINDEX_BINARY, ISTFILE, self.doc))
if use_indfix:
self.run("%s -s %s %s.idx"
% (MAKEINDEX_BINARY, ISTFILE, self.doc))
indfix.process(self.doc + ".ind")
self.process_synopsis_files()
#
# and now finish it off:
#
if os.path.isfile(self.doc + ".toc") and binary == PDFLATEX_BINARY:
import toc2bkm
if self.doctype == "manual":
bigpart = "chapter"
else:
bigpart = "section"
toc2bkm.process(self.doc + ".toc", self.doc + ".bkm", bigpart)
if self.use_bibtex:
self.run("%s %s" % (BIBTEX_BINARY, self.doc))
self.run("%s %s" % (binary, self.doc))
self.latex_runs = self.latex_runs + 1
def process_synopsis_files(self):
synopsis_files = glob.glob(self.doc + "*.syn")
for path in synopsis_files:
uniqify_module_table(path)
def build_ps(self):
self.run("%s -N0 -o %s.ps %s" % (DVIPS_BINARY, self.doc, self.doc))
def build_html(self, builddir, max_split_depth=None):
if max_split_depth is None:
max_split_depth = self.options.max_split_depth
texfile = None
for p in string.split(os.environ["TEXINPUTS"], os.pathsep):
fn = os.path.join(p, self.doc + ".tex")
if os.path.isfile(fn):
texfile = fn
break
if not texfile:
self.warning("Could not locate %s.tex; aborting." % self.doc)
sys.exit(1)
# remove leading ./ (or equiv.); might avoid problems w/ dvips
if texfile[:2] == os.curdir + os.sep:
texfile = texfile[2:]
# build the command line and run LaTeX2HTML:
if not os.path.isdir(builddir):
os.mkdir(builddir)
else:
for fname in glob.glob(os.path.join(builddir, "*.html")):
os.unlink(fname)
args = [LATEX2HTML_BINARY,
"-init_file", self.l2h_aux_init_file,
"-dir", builddir,
texfile
]
self.run(string.join(args)) # XXX need quoting!
# ... postprocess
shutil.copyfile(self.options.style_file,
os.path.join(builddir, self.doc + ".css"))
shutil.copyfile(os.path.join(builddir, self.doc + ".html"),
os.path.join(builddir, "index.html"))
if max_split_depth != 1:
label_file = os.path.join(builddir, "labels.pl")
fp = open(label_file)
about_node = None
target = " = q/about/;\n"
x = len(target)
while 1:
line = fp.readline()
if not line:
break
if line[-x:] == target:
line = fp.readline()
m = re.search(r"\|(node\d+\.[a-z]+)\|", line)
about_node = m.group(1)
shutil.copyfile(os.path.join(builddir, about_node),
os.path.join(builddir, "about.html"))
break
if not self.options.numeric:
pwd = os.getcwd()
try:
os.chdir(builddir)
self.run("%s %s *.html" % (PERL_BINARY, NODE2LABEL_SCRIPT))
finally:
os.chdir(pwd)
# These files need to be cleaned up here since builddir there
# can be more than one, so we clean each of them.
if self.options.discard_temps:
for fn in ("images.tex", "images.log", "images.aux"):
safe_unlink(os.path.join(builddir, fn))
def build_text(self, tempdir=None):
if tempdir is None:
tempdir = self.doc
indexfile = os.path.join(tempdir, "index.html")
self.run("%s -nolist -dump %s >%s.txt"
% (LYNX_BINARY, indexfile, self.doc))
def require_temps(self, binary=None):
if not self.latex_runs:
self.build_aux(binary=binary)
def write_l2h_aux_init_file(self):
options = self.options
fp = open(self.l2h_aux_init_file, "w")
d = string_to_perl(os.path.dirname(L2H_INIT_FILE))
fp.write("package main;\n"
"push (@INC, '%s');\n"
"$mydir = '%s';\n"
% (d, d))
fp.write(open(L2H_INIT_FILE).read())
for filename in options.l2h_init_files:
fp.write("\n# initialization code incorporated from:\n# ")
fp.write(filename)
fp.write("\n")
fp.write(open(filename).read())
fp.write("\n"
"# auxillary init file for latex2html\n"
"# generated by mkhowto\n"
"$NO_AUTO_LINK = 1;\n"
)
l2hoption(fp, "ABOUT_FILE", options.about_file)
l2hoption(fp, "ICONSERVER", options.icon_server)
l2hoption(fp, "IMAGE_TYPE", options.image_type)
l2hoption(fp, "ADDRESS", options.address)
l2hoption(fp, "MAX_LINK_DEPTH", options.max_link_depth)
l2hoption(fp, "MAX_SPLIT_DEPTH", options.max_split_depth)
l2hoption(fp, "EXTERNAL_UP_LINK", options.up_link)
l2hoption(fp, "EXTERNAL_UP_TITLE", options.up_title)
l2hoption(fp, "FAVORITES_ICON", options.favicon)
l2hoption(fp, "GLOBAL_MODULE_INDEX", options.global_module_index)
l2hoption(fp, "DVIPS_SAFE", options.dvips_safe)
fp.write("1;\n")
fp.close()
def cleanup(self):
self.__have_temps = 0
for pattern in ("%s.aux", "%s.log", "%s.out", "%s.toc", "%s.bkm",
"%s.idx", "%s.ilg", "%s.ind", "%s.pla",
"%s.bbl", "%s.blg",
"mod%s.idx", "mod%s.ind", "mod%s.ilg",
):
safe_unlink(pattern % self.doc)
map(safe_unlink, glob.glob(self.doc + "*.syn"))
for spec in ("IMG*", "*.pl", "WARNINGS", "index.dat", "modindex.dat"):
pattern = os.path.join(self.doc, spec)
map(safe_unlink, glob.glob(pattern))
if "dvi" not in self.options.formats:
safe_unlink(self.doc + ".dvi")
if os.path.isdir(self.doc + "-temp-html"):
shutil.rmtree(self.doc + "-temp-html", ignore_errors=1)
if not self.options.logging:
os.unlink(self.log_filename)
if not self.options.debugging:
os.unlink(self.l2h_aux_init_file)
def run(self, command):
self.message(command)
if sys.platform.startswith("win"):
rc = os.system(command)
else:
rc = os.system("(%s) </dev/null >>%s 2>&1"
% (command, self.log_filename))
if rc:
self.warning(
"Session transcript and error messages are in %s."
% self.log_filename)
if hasattr(os, "WIFEXITED"):
if os.WIFEXITED(rc):
self.warning("Exited with status %s." % os.WEXITSTATUS(rc))
else:
self.warning("Killed by signal %s." % os.WSTOPSIG(rc))
else:
self.warning("Return code: %s" % rc)
sys.stderr.write("The relevant lines from the transcript are:\n")
sys.stderr.write("-" * 72 + "\n")
sys.stderr.writelines(get_run_transcript(self.log_filename))
sys.exit(rc)
def message(self, msg):
msg = "+++ " + msg
if not self.options.quiet:
print msg
self.log(msg + "\n")
def warning(self, msg):
msg = "*** %s\n" % msg
sys.stderr.write(msg)
self.log(msg)
def log(self, msg):
fp = open(self.log_filename, "a")
fp.write(msg)
fp.close()
def get_run_transcript(filename):
"""Return lines from the transcript file for the most recent run() call."""
fp = open(filename)
lines = fp.readlines()
fp.close()
lines.reverse()
L = []
for line in lines:
L.append(line)
if line[:4] == "+++ ":
break
L.reverse()
return L
def safe_unlink(path):
"""Unlink a file without raising an error if it doesn't exist."""
try:
os.unlink(path)
except os.error:
pass
def split_pathname(path):
path = os.path.abspath(path)
dirname, basename = os.path.split(path)
if basename[-4:] == ".tex":
basename = basename[:-4]
return dirname, basename
_doctype_rx = re.compile(r"\\documentclass(?:\[[^]]*\])?{([a-zA-Z]*)}")
def get_doctype(path):
fp = open(path)
doctype = None
while 1:
line = fp.readline()
if not line:
break
m = _doctype_rx.match(line)
if m:
doctype = m.group(1)
break
fp.close()
return doctype
def main():
options = Options()
try:
args = options.parse(sys.argv[1:])
except getopt.error, msg:
error(options, msg)
if not args:
# attempt to locate single .tex file in current directory:
args = glob.glob("*.tex")
if not args:
error(options, "No file to process.")
if len(args) > 1:
error(options, "Could not deduce which files should be processed.")
#
# parameters are processed, let's go!
#
for path in args:
Job(options, path).build()
def l2hoption(fp, option, value):
if value:
fp.write('$%s = "%s";\n' % (option, string_to_perl(str(value))))
_to_perl = {}
for c in map(chr, range(1, 256)):
_to_perl[c] = c
_to_perl["@"] = "\\@"
_to_perl["$"] = "\\$"
_to_perl['"'] = '\\"'
def string_to_perl(s):
return string.join(map(_to_perl.get, s), '')
def check_for_bibtex(filename):
fp = open(filename)
pos = string.find(fp.read(), r"\bibdata{")
fp.close()
return pos >= 0
def uniqify_module_table(filename):
lines = open(filename).readlines()
if len(lines) > 1:
if lines[-1] == lines[-2]:
del lines[-1]
open(filename, "w").writelines(lines)
def new_index(filename, label="genindex"):
fp = open(filename, "w")
fp.write(r"""\
\begin{theindex}
\label{%s}
\end{theindex}
""" % label)
fp.close()
if __name__ == "__main__":
main()

View File

@ -1,63 +0,0 @@
#! /bin/sh
# -*- Ksh -*-
# Script to drive the HTML-info conversion process.
# Pass in upto three parameters:
# - the name of the main tex file
# - the name of the output file in texi format (optional)
# - the name of the output file in info format (optional)
#
# Written by Fred L. Drake, Jr. <fdrake@acm.org>
EMACS=${EMACS:-emacs}
MAKEINFO=${MAKEINFO:-makeinfo}
# Normalize file name since something called by html2texi.pl seems to
# screw up with relative path names.
FILENAME="$1"
DOCDIR=`dirname "$FILENAME"`
DOCFILE=`basename "$FILENAME"`
DOCNAME=`basename "$FILENAME" .tex`
if [ $# -gt 1 ]; then
TEXINAME="$2"
else
TEXINAME="python-$DOCNAME.texi"
fi
if [ $# -gt 2 ]; then
INFONAME="$3"
else
INFONAME="python-$DOCNAME.info"
fi
# Now build the real directory names, and locate our support stuff:
WORKDIR=`pwd`
cd `dirname $0`
TOOLSDIR=`pwd`
cd $DOCDIR
DOCDIR=`pwd`
cd $WORKDIR
run() {
# show what we're doing, like make does:
echo "$*"
"$@" || exit $?
}
# generate the Texinfo file:
run $EMACS -batch -q --no-site-file -l $TOOLSDIR/py2texi.el \
--eval "(setq py2texi-dirs '(\"./\" \"../texinputs/\" \"$DOCDIR\"))" \
--eval "(setq py2texi-texi-file-name \"$TEXINAME\")" \
--eval "(setq py2texi-info-file-name \"$INFONAME\")" \
--eval "(py2texi \"$DOCDIR/$DOCFILE\")" \
-f kill-emacs
echo Done
# generate the .info files:
run $MAKEINFO --footnote-style end --fill-column 72 \
--paragraph-indent 0 --output=$INFONAME $TEXINAME

View File

@ -1,158 +0,0 @@
#! /usr/bin/env python
# -*- Python -*-
"""usage: %(program)s [options] file...
Supported options:
--address addr
-a addr Set the address text to include at the end of the generated
HTML; this should be used for contact information.
--columns cols
-c cols Set the number of columns each index section should be
displayed in. The default is 1.
--help
-h Display this help message.
--letters
-l Split the output into sections by letter.
--output file
-o file Write output to 'file' instead of standard out.
--iconserver is Use 'is' as the directory containing icons for the
navigation bar. The default is 'icons'.
--title str Set the page title to 'str'. The default is 'Global
Module Index'.
--uplink url Set the upward link URL. The default is './'.
--uptitle str Set the upward link title. The default is 'Python
Documentation Index'.
"""
import os
import re
import sys
from xml.sax.saxutils import quoteattr
import buildindex
import support
class IndexOptions(support.Options):
aesop_type = "links"
def __init__(self):
support.Options.__init__(self)
self.add_args("l", ["letters"])
self.letters = 0
def handle_option(self, opt, val):
if opt in ("-l", "--letters"):
self.letters = 1
def usage(self):
program = os.path.basename(sys.argv[0])
print __doc__ % {"program": program}
links = [
('author', 'acks.html', 'Acknowledgements'),
('help', 'about.html', 'About the Python Documentation'),
]
def get_header(self):
header = support.Options.get_header(self)
s = ''
for rel, href, title in self.links:
s += '<link rel="%s" href="%s"' % (rel, href)
if title:
s += ' title=' + quoteattr(title)
s += '>\n '
return header.replace("<link ", s + "<link ", 1)
class Node(buildindex.Node):
def __init__(self, link, str, seqno, platinfo):
self.annotation = platinfo or None
if str[0][-5:] == "</tt>":
str = str[:-5]
self.modname = str
buildindex.Node.__init__(self, link, self.modname, seqno)
if platinfo:
s = '<tt class="module">%s</tt> %s' \
% (self.modname, self.annotation)
else:
s = '<tt class="module">%s</tt>' % str
self.text = [s]
def __str__(self):
if self.annotation:
return '<tt class="module">%s</tt> %s' \
% (self.modname, self.annotation)
else:
return '<tt class="module">%s</tt>' % self.modname
_rx = re.compile(
"<dt><a href=['\"](module-.*\.html)(?:#l2h-\d+)?['\"]>"
"<tt class=['\"]module['\"]>([a-zA-Z_][a-zA-Z0-9_.]*)</tt>\s*(<em>"
"\(<span class=['\"]platform['\"]>.*</span>\)</em>)?</a>")
def main():
options = IndexOptions()
options.variables["title"] = "Global Module Index"
options.parse(sys.argv[1:])
args = options.args
if not args:
args = ["-"]
#
# Collect the input data:
#
nodes = []
has_plat_flag = 0
for ifn in args:
if ifn == "-":
ifp = sys.stdin
dirname = ''
else:
ifp = open(ifn)
dirname = os.path.dirname(ifn)
while 1:
line = ifp.readline()
if not line:
break
m = _rx.match(line)
if m:
# This line specifies a module!
basename, modname, platinfo = m.group(1, 2, 3)
has_plat_flag = has_plat_flag or platinfo
linkfile = os.path.join(dirname, basename)
nodes.append(Node('<a href="%s">' % linkfile, modname,
len(nodes), platinfo))
ifp.close()
#
# Generate all output:
#
num_nodes = len(nodes)
# Here's the HTML generation:
parts = [options.get_header(),
buildindex.process_nodes(nodes, options.columns, options.letters),
options.get_footer(),
]
if has_plat_flag:
parts.insert(1, PLAT_DISCUSS)
html = ''.join(parts)
program = os.path.basename(sys.argv[0])
fp = options.get_output_file()
fp.write(html.rstrip() + "\n")
if options.outputfile == "-":
sys.stderr.write("%s: %d index nodes\n" % (program, num_nodes))
else:
print
print "%s: %d index nodes" % (program, num_nodes)
PLAT_DISCUSS = """
<p> Some module names are followed by an annotation indicating what
platform they are available on.</p>
"""
if __name__ == "__main__":
main()

View File

@ -1,90 +0,0 @@
#! /usr/bin/env python
#
# Simple script to create the table that lists the packages available
# for download. This expects the downloadable files and the Makefile
# to be in the current directory.
#
# The output of this script can be pasted directly into the download
# page for the documentation.
import os
import sys
from os.path import isfile
PKG_TYPES = [
# human name, filename prefix
("HTML", "html"),
("PDF (US-Letter)", "pdf-letter"),
("PDF (A4)", "pdf-a4"),
("PostScript (US-Letter)", "postscript-letter"),
("PostScript (A4)", "postscript-a4"),
("GNU info", "info"),
("iSilo", "isilo"),
("LaTeX", "latex"),
]
fp = open("Makefile")
for line in fp:
line = line.replace('=', ' ', 1)
parts = line.split()
if parts[:1] == ["RELEASE"]:
release = parts[1]
break
else:
print >>sys.stderr, "Could not locate RELEASE in Makefile."
sys.exit(1)
print '''\
<table border="1" cellpadding="3" align="center">
<thead>
<tr bgcolor="#99ccff"><th rowspan="2">Content</th>
<th colspan="3">Format</th>
</tr>
<tr bgcolor="#99ccff"><th>ZIP</th><th>GZip</th><th>BZip2</th>
</thead>
<tbody>'''
# formatted using FILE_TEMPLATE % (release, prefix, release, extension)
FILE_TEMPLATE = '''\
<td><a href="../../ftp/python/doc/%s/%s-%s%s"
>%dK</a></td>'''
NO_FILE_TEMPLATE = '''\
<td>&nbsp;</td>'''
def get_size(prefix, ext):
fn = "%s-%s%s" % (prefix, release, ext)
return int(round(os.path.getsize(fn) / 1024.0))
def get_file_cell(prefix, ext, have):
if have:
kb = get_size(prefix, ext)
return FILE_TEMPLATE % (release, prefix, release, ext, kb)
else:
return NO_FILE_TEMPLATE
for name, prefix in PKG_TYPES:
zip_fn = "%s-%s.zip" % (prefix, release)
tgz_fn = "%s-%s.tgz" % (prefix, release)
bz2_fn = "%s-%s.tar.bz2" % (prefix, release)
have_zip = isfile(zip_fn)
have_tgz = isfile(tgz_fn)
have_bz2 = isfile(bz2_fn)
if have_zip or have_tgz or have_bz2:
print " <tr><td>%s</td>" % name
print get_file_cell(prefix, ".zip", have_zip)
print get_file_cell(prefix, ".tgz", have_tgz)
print get_file_cell(prefix, ".tar.bz2", have_bz2)
print " </tr>"
print '''\
</tbody>
</table>
'''

View File

@ -1,164 +0,0 @@
#! /usr/bin/env python
# -*- Python -*-
"""%(program)s - script to create the latex source distribution
usage:
%(program)s [-t|--tools] release [tag]
with -t|--tools: doesn't include the documents, only the framework
without [tag]: generate from the current version that's checked in
(*NOT* what's in the current directory!)
with [tag]: generate from the named tag
"""
#* should be modified to get the Python version number automatically
# from the Makefile or someplace.
import getopt
import glob
import os
import re
import shutil
import sys
import tempfile
import cvsinfo
quiet = 0
rx = re.compile(r":ext:(?:[a-zA-Z0-9]+)@cvs\.([a-zA-Z0-9]+).sourceforge.net:"
r"/cvsroot/\1")
def main():
global quiet
try:
opts, args = getopt.getopt(sys.argv[1:], "abgtzq",
["all", "bzip2", "gzip", "tools", "zip",
"quiet"])
except getopt.error, e:
usage(warning=str(e))
sys.exit(2)
if len(args) not in (1, 2):
usage(warning="wrong number of parameters")
sys.exit(2)
tools = 0
formats = {}
for opt, arg in opts:
if opt in ("-t", "--tools"):
tools = 1
elif opt in ("-q", "--quiet"):
quiet = quiet + 1
elif opt in ("-b", "--bzip2"):
formats["bzip2"] = 1
elif opt in ("-g", "--gzip"):
formats["gzip"] = 1
elif opt in ("-z", "--zip"):
formats["zip"] = 1
elif opt in ("-a", "--all"):
formats["bzip2"] = 1
formats["gzip"] = 1
formats["zip"] = 1
if formats:
# make order human-predictable
formats = formats.keys()
formats.sort()
else:
formats = ["gzip"]
release = args[0]
cvstag = None
if len(args) > 1:
cvstag = args[1]
tempdir = tempfile.mktemp()
os.mkdir(tempdir)
pkgdir = os.path.join(tempdir, "Python-Docs-" + release)
os.mkdir(pkgdir)
pwd = os.getcwd()
mydir = os.path.abspath(os.path.dirname(sys.argv[0]))
info = cvsinfo.RepositoryInfo(mydir)
cvsroot = info.get_cvsroot()
m = rx.match(cvsroot)
if m:
# If this is an authenticated SourceForge repository, convert to
# anonymous usage for the export/checkout, since that avoids the
# SSH overhead.
group = m.group(1)
cvsroot = ":pserver:anonymous@cvs.%s.sourceforge.net:/cvsroot/%s" \
% (group, group)
# For some reason, SourceForge/CVS doesn't seem to care that we
# might not have done a "cvs login" to the anonymous server.
# That avoids a lot of painful gunk here.
os.chdir(tempdir)
if not quiet:
print "--- current directory is:", pkgdir
if cvstag:
run("cvs -d%s export -r %s -d Python-Docs-%s python/dist/src/Doc"
% (cvsroot, cvstag, release))
else:
run("cvs -Q -d%s checkout -d Python-Docs-%s python/dist/src/Doc"
% (cvsroot, release))
# remove CVS directories
for p in ('*/CVS', '*/*/CVS', '*/*/*/CVS'):
map(shutil.rmtree, glob.glob(p))
for f in ('.cvsignore', '*/.cvsignore'):
map(os.unlink, glob.glob(f))
LICENSE = os.path.normpath(
os.path.join(mydir, os.pardir, os.pardir, "LICENSE"))
shutil.copyfile(LICENSE, "LICENSE")
if tools:
archive = "doctools-" + release
# we don't want the actual documents in this case:
for d in ("api", "dist", "doc", "ext", "inst",
"lib", "mac", "ref", "tut"):
shutil.rmtree(os.path.join(pkgdir, d))
else:
archive = "latex-" + release
# XXX should also remove the .cvsignore files at this point
os.chdir(tempdir)
archive = os.path.join(pwd, archive)
for format in formats:
if format == "bzip2":
run("tar cf - Python-Docs-%s | bzip2 -9 >%s.tar.bz2"
% (release, archive))
elif format == "gzip":
run("tar cf - Python-Docs-%s | gzip -9 >%s.tgz"
% (release, archive))
elif format == "zip":
if os.path.exists(archive + ".zip"):
os.unlink(archive + ".zip")
run("zip -q -r9 %s.zip Python-Docs-%s"
% (archive, release))
# clean up the work area:
os.chdir(pwd)
shutil.rmtree(tempdir)
def run(cmd):
if quiet < 2:
print "+++", cmd
if quiet:
cmd = "%s >/dev/null" % cmd
rc = os.system(cmd)
if rc:
sys.exit(rc)
def usage(warning=None):
stdout = sys.stdout
sys.stdout = sys.stderr
program = os.path.basename(sys.argv[0])
try:
if warning:
print "%s: %s\n" % (program, warning)
print __doc__ % {"program": program}
finally:
sys.stdout = stdout
if __name__ == "__main__":
main()

View File

@ -1,71 +0,0 @@
#! /usr/bin/env perl
# On Cygwin, we actually have to generate a temporary file when doing
# the inplace edit, or we'll get permission errors. Not sure who's
# bug this is, except that it isn't ours. To deal with this, we
# generate backups during the edit phase and remove them at the end.
#
use English;
$INPLACE_EDIT = '.bak';
# read the labels, then reverse the mappings
require "labels.pl";
%nodes = ();
my $key;
# sort so that we get a consistent assignment for nodes with multiple labels
foreach $label (sort keys %external_labels) {
#
# If the label can't be used as a filename on non-Unix platforms,
# skip it. Such labels may be used internally within the documentation,
# but will never be used for filename generation.
#
if ($label =~ /^([-.a-zA-Z0-9]+)$/) {
$key = $external_labels{$label};
$key =~ s|^/||;
$nodes{$key} = $label;
}
}
# This adds the "internal" labels added for indexing. These labels will not
# be used for file names.
require "intlabels.pl";
foreach $label (keys %internal_labels) {
$key = $internal_labels{$label};
$key =~ s|^/||;
if (defined($nodes{$key})) {
$nodes{$label} = $nodes{$key};
}
}
# collect labels that have been used
%newnames = ();
while (<>) {
# don't want to do one s/// per line per node
# so look for lines with hrefs, then do s/// on nodes present
if (/(HREF|href)=[\"\']node\d+\.html[\#\"\']/) {
@parts = split(/(HREF|href)\=[\"\']/);
shift @parts;
for $node (@parts) {
$node =~ s/[\#\"\'].*$//g;
chomp($node);
if (defined($nodes{$node})) {
$label = $nodes{$node};
if (s/(HREF|href)=([\"\'])$node([\#\"\'])/href=$2$label.html$3/g) {
s/(HREF|href)=([\"\'])$label.html/href=$2$label.html/g;
$newnames{$node} = "$label.html";
}
}
}
}
print;
}
foreach $oldname (keys %newnames) {
rename($oldname, $newnames{$oldname});
}
foreach $filename (glob('*.bak')) {
unlink($filename);
}

View File

@ -1,471 +0,0 @@
"""
Makes the necesary files to convert from plain html of
Python 1.5 and 1.5.x Documentation to
Microsoft HTML Help format version 1.1
Doesn't change the html's docs.
by hernan.foffani@iname.com
no copyright and no responsabilities.
modified by Dale Nagata for Python 1.5.2
Renamed from make_chm.py to prechm.py, and checked into the Python
project, 19-Apr-2002 by Tim Peters. Assorted modifications by Tim
and Fred Drake. Obtained from Robin Dunn's .chm packaging of the
Python 2.2 docs, at <http://alldunn.com/python/>.
"""
import sys
import os
from formatter import NullWriter, AbstractFormatter
from htmllib import HTMLParser
import getopt
import cgi
usage_mode = '''
Usage: make_chm.py [-c] [-k] [-p] [-v 1.5[.x]] filename
-c: does not build filename.hhc (Table of Contents)
-k: does not build filename.hhk (Index)
-p: does not build filename.hhp (Project File)
-v 1.5[.x]: makes help for the python 1.5[.x] docs
(default is python 1.5.2 docs)
'''
# Project file (*.hhp) template. 'arch' is the file basename (like
# the pythlp in pythlp.hhp); 'version' is the doc version number (like
# the 2.2 in Python 2.2).
# The magical numbers in the long line under [WINDOWS] set most of the
# user-visible features (visible buttons, tabs, etc).
# About 0x10384e: This defines the buttons in the help viewer. The
# following defns are taken from htmlhelp.h. Not all possibilities
# actually work, and not all those that work are available from the Help
# Workshop GUI. In particular, the Zoom/Font button works and is not
# available from the GUI. The ones we're using are marked with 'x':
#
# 0x000002 Hide/Show x
# 0x000004 Back x
# 0x000008 Forward x
# 0x000010 Stop
# 0x000020 Refresh
# 0x000040 Home x
# 0x000080 Forward
# 0x000100 Back
# 0x000200 Notes
# 0x000400 Contents
# 0x000800 Locate x
# 0x001000 Options x
# 0x002000 Print x
# 0x004000 Index
# 0x008000 Search
# 0x010000 History
# 0x020000 Favorites
# 0x040000 Jump 1
# 0x080000 Jump 2
# 0x100000 Zoom/Font x
# 0x200000 TOC Next
# 0x400000 TOC Prev
project_template = '''
[OPTIONS]
Compiled file=%(arch)s.chm
Contents file=%(arch)s.hhc
Default Window=%(arch)s
Default topic=index.html
Display compile progress=No
Full text search stop list file=%(arch)s.stp
Full-text search=Yes
Index file=%(arch)s.hhk
Language=0x409
Title=Python %(version)s Documentation
[WINDOWS]
%(arch)s="Python %(version)s Documentation","%(arch)s.hhc","%(arch)s.hhk",\
"index.html","index.html",,,,,0x63520,220,0x10384e,[271,372,740,718],,,,,,,0
[FILES]
'''
contents_header = '''\
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<HTML>
<HEAD>
<meta name="GENERATOR" content="Microsoft&reg; HTML Help Workshop 4.1">
<!-- Sitemap 1.0 -->
</HEAD><BODY>
<OBJECT type="text/site properties">
<param name="Window Styles" value="0x801227">
<param name="ImageType" value="Folder">
</OBJECT>
<UL>
'''
contents_footer = '''\
</UL></BODY></HTML>
'''
object_sitemap = '''\
<OBJECT type="text/sitemap">
<param name="Name" value="%s">
<param name="Local" value="%s">
</OBJECT>
'''
# List of words the full text search facility shouldn't index. This
# becomes file ARCH.stp. Note that this list must be pretty small!
# Different versions of the MS docs claim the file has a maximum size of
# 256 or 512 bytes (including \r\n at the end of each line).
# Note that "and", "or", "not" and "near" are operators in the search
# language, so no point indexing them even if we wanted to.
stop_list = '''
a and are as at
be but by
for
if in into is it
near no not
of on or
such
that the their then there these they this to
was will with
'''
# s is a string or None. If None or empty, return None. Else tack '.html'
# on to the end, unless it's already there.
def addhtml(s):
if s:
if not s.endswith('.html'):
s += '.html'
return s
# Convenience class to hold info about "a book" in HTMLHelp terms == a doc
# directory in Python terms.
class Book:
def __init__(self, directory, title, firstpage,
contentpage=None, indexpage=None):
self.directory = directory
self.title = title
self.firstpage = addhtml(firstpage)
self.contentpage = addhtml(contentpage)
self.indexpage = addhtml(indexpage)
# Library Doc list of books:
# each 'book' : (Dir, Title, First page, Content page, Index page)
supported_libraries = {
'2.2':
[
Book('.', 'Main page', 'index'),
Book('.', 'Global Module Index', 'modindex'),
Book('whatsnew', "What's New", 'index', 'contents'),
Book('tut','Tutorial','tut','node2'),
Book('lib','Library Reference','lib','contents','genindex'),
Book('ref','Language Reference','ref','contents','genindex'),
Book('mac','Macintosh Reference','mac','contents','genindex'),
Book('ext','Extending and Embedding','ext','contents'),
Book('api','Python/C API','api','contents','genindex'),
Book('doc','Documenting Python','doc','contents'),
Book('inst','Installing Python Modules', 'inst', 'index'),
Book('dist','Distributing Python Modules', 'dist', 'index'),
],
'2.1.1':
[
Book('.', 'Main page', 'index'),
Book('.', 'Global Module Index', 'modindex'),
Book('tut','Tutorial','tut','node2'),
Book('lib','Library Reference','lib','contents','genindex'),
Book('ref','Language Reference','ref','contents','genindex'),
Book('mac','Macintosh Reference','mac','contents','genindex'),
Book('ext','Extending and Embedding','ext','contents'),
Book('api','Python/C API','api','contents','genindex'),
Book('doc','Documenting Python','doc','contents'),
Book('inst','Installing Python Modules', 'inst', 'index'),
Book('dist','Distributing Python Modules', 'dist', 'index'),
],
'2.0.0':
[
Book('.', 'Global Module Index', 'modindex'),
Book('tut','Tutorial','tut','node2'),
Book('lib','Library Reference','lib','contents','genindex'),
Book('ref','Language Reference','ref','contents','genindex'),
Book('mac','Macintosh Reference','mac','contents','genindex'),
Book('ext','Extending and Embedding','ext','contents'),
Book('api','Python/C API','api','contents','genindex'),
Book('doc','Documenting Python','doc','contents'),
Book('inst','Installing Python Modules', 'inst', 'contents'),
Book('dist','Distributing Python Modules', 'dist', 'contents'),
],
# <dnagata@creo.com> Apr 17/99: library for 1.5.2 version:
# <hernan.foffani@iname.com> May 01/99: library for 1.5.2 (04/30/99):
'1.5.2':
[
Book('tut','Tutorial','tut','node2'),
Book('lib','Library Reference','lib','contents','genindex'),
Book('ref','Language Reference','ref','contents','genindex'),
Book('mac','Macintosh Reference','mac','contents','genindex'),
Book('ext','Extending and Embedding','ext','contents'),
Book('api','Python/C API','api','contents','genindex'),
Book('doc','Documenting Python','doc','contents')
],
# library for 1.5.1 version:
'1.5.1':
[
Book('tut','Tutorial','tut','contents'),
Book('lib','Library Reference','lib','contents','genindex'),
Book('ref','Language Reference','ref-1','ref-2','ref-11'),
Book('ext','Extending and Embedding','ext','contents'),
Book('api','Python/C API','api','contents','genindex')
],
# library for 1.5 version:
'1.5':
[
Book('tut','Tutorial','tut','node1'),
Book('lib','Library Reference','lib','node1','node268'),
Book('ref','Language Reference','ref-1','ref-2','ref-11'),
Book('ext','Extending and Embedding','ext','node1'),
Book('api','Python/C API','api','node1','node48')
]
}
# AlmostNullWriter doesn't print anything; it just arranges to save the
# text sent to send_flowing_data(). This is used to capture the text
# between an anchor begin/end pair, e.g. for TOC entries.
class AlmostNullWriter(NullWriter):
def __init__(self):
NullWriter.__init__(self)
self.saved_clear()
def send_flowing_data(self, data):
stripped = data.strip()
if stripped: # don't bother to save runs of whitespace
self.saved.append(stripped)
# Forget all saved text.
def saved_clear(self):
self.saved = []
# Return all saved text as a string.
def saved_get(self):
return ' '.join(self.saved)
class HelpHtmlParser(HTMLParser):
def __init__(self, formatter, path, output):
HTMLParser.__init__(self, formatter)
self.path = path # relative path
self.ft = output # output file
self.indent = 0 # number of tabs for pretty printing of files
self.proc = False # True when actively processing, else False
# (headers, footers, etc)
# XXX This shouldn't need to be a stack -- anchors shouldn't nest.
# XXX See SF bug <http://www.python.org/sf/546579>.
self.hrefstack = [] # stack of hrefs from anchor begins
def begin_group(self):
self.indent += 1
self.proc = True
def finish_group(self):
self.indent -= 1
# stop processing when back to top level
self.proc = self.indent > 0
def anchor_bgn(self, href, name, type):
if self.proc:
# XXX See SF bug <http://www.python.org/sf/546579>.
# XXX index.html for the 2.2.1 language reference manual contains
# XXX nested <a></a> tags in the entry for the section on blank
# XXX lines. We want to ignore the nested part completely.
if len(self.hrefstack) == 0:
self.saved_clear()
self.hrefstack.append(href)
def anchor_end(self):
if self.proc:
# XXX See XXX above.
if self.hrefstack:
title = cgi.escape(self.saved_get(), True)
path = self.path + '/' + self.hrefstack.pop()
self.tab(object_sitemap % (title, path))
def start_dl(self, atr_val):
self.begin_group()
def end_dl(self):
self.finish_group()
def do_dt(self, atr_val):
# no trailing newline on purpose!
self.tab("<LI>")
# Write text to output file.
def write(self, text):
self.ft.write(text)
# Write text to output file after indenting by self.indent tabs.
def tab(self, text=''):
self.write('\t' * self.indent)
if text:
self.write(text)
# Forget all saved text.
def saved_clear(self):
self.formatter.writer.saved_clear()
# Return all saved text as a string.
def saved_get(self):
return self.formatter.writer.saved_get()
class IdxHlpHtmlParser(HelpHtmlParser):
# nothing special here, seems enough with parent class
pass
class TocHlpHtmlParser(HelpHtmlParser):
def start_dl(self, atr_val):
self.begin_group()
self.tab('<UL>\n')
def end_dl(self):
self.finish_group()
self.tab('</UL>\n')
def start_ul(self, atr_val):
self.begin_group()
self.tab('<UL>\n')
def end_ul(self):
self.finish_group()
self.tab('</UL>\n')
def do_li(self, atr_val):
# no trailing newline on purpose!
self.tab("<LI>")
def index(path, indexpage, output):
parser = IdxHlpHtmlParser(AbstractFormatter(AlmostNullWriter()),
path, output)
f = open(path + '/' + indexpage)
parser.feed(f.read())
parser.close()
f.close()
def content(path, contentpage, output):
parser = TocHlpHtmlParser(AbstractFormatter(AlmostNullWriter()),
path, output)
f = open(path + '/' + contentpage)
parser.feed(f.read())
parser.close()
f.close()
def do_index(library, output):
output.write('<UL>\n')
for book in library:
print '\t', book.title, '-', book.indexpage
if book.indexpage:
index(book.directory, book.indexpage, output)
output.write('</UL>\n')
def do_content(library, version, output):
output.write(contents_header)
for book in library:
print '\t', book.title, '-', book.firstpage
path = book.directory + "/" + book.firstpage
output.write('<LI>')
output.write(object_sitemap % (book.title, path))
if book.contentpage:
content(book.directory, book.contentpage, output)
output.write(contents_footer)
# Fill in the [FILES] section of the project (.hhp) file.
# 'library' is the list of directory description tuples from
# supported_libraries for the version of the docs getting generated.
def do_project(library, output, arch, version):
output.write(project_template % locals())
pathseen = {}
for book in library:
directory = book.directory
path = directory + '\\%s\n'
for page in os.listdir(directory):
if page.endswith('.html') or page.endswith('.css'):
fullpath = path % page
if fullpath not in pathseen:
output.write(fullpath)
pathseen[fullpath] = True
def openfile(file):
try:
p = open(file, "w")
except IOError, msg:
print file, ":", msg
sys.exit(1)
return p
def usage():
print usage_mode
sys.exit(0)
def do_it(args = None):
if not args:
args = sys.argv[1:]
if not args:
usage()
try:
optlist, args = getopt.getopt(args, 'ckpv:')
except getopt.error, msg:
print msg
usage()
if not args or len(args) > 1:
usage()
arch = args[0]
version = None
for opt in optlist:
if opt[0] == '-v':
version = opt[1]
break
if not version:
usage()
library = supported_libraries[version]
if not (('-p','') in optlist):
fname = arch + '.stp'
f = openfile(fname)
print "Building stoplist", fname, "..."
words = stop_list.split()
words.sort()
for word in words:
print >> f, word
f.close()
f = openfile(arch + '.hhp')
print "Building Project..."
do_project(library, f, arch, version)
if version == '2.0.0':
for image in os.listdir('icons'):
f.write('icons'+ '\\' + image + '\n')
f.close()
if not (('-c','') in optlist):
f = openfile(arch + '.hhc')
print "Building Table of Content..."
do_content(library, version, f)
f.close()
if not (('-k','') in optlist):
f = openfile(arch + '.hhk')
print "Building Index..."
do_index(library, f)
f.close()
if __name__ == '__main__':
do_it()

View File

@ -1,90 +0,0 @@
#! /bin/sh
# Script to push docs from my development area to SourceForge, where the
# update-docs.sh script unpacks them into their final destination.
TARGETHOST=www.python.org
TARGETDIR=/usr/home/fdrake/tmp
TARGET="$TARGETHOST:$TARGETDIR"
ADDRESSES='python-dev@python.org doc-sig@python.org python-list@python.org'
VERSION=`echo '$Revision$' | sed 's/[$]Revision: \(.*\) [$]/\1/'`
EXTRA=`echo "$VERSION" | sed 's/^[0-9][0-9]*\.[0-9][0-9]*//'`
if [ "$EXTRA" ] ; then
DOCLABEL="maintenance"
DOCTYPE="maint"
else
DOCLABEL="development"
DOCTYPE="devel"
fi
EXPLANATION=''
ANNOUNCE=true
while [ "$#" -gt 0 ] ; do
case "$1" in
-m)
EXPLANATION="$2"
shift 2
;;
-q)
ANNOUNCE=false
shift 1
;;
-t)
DOCTYPE="$2"
shift 2
;;
-F)
EXPLANATION="`cat $2`"
shift 2
;;
-*)
echo "Unknown option: $1" >&2
exit 2
;;
*)
break
;;
esac
done
if [ "$1" ] ; then
if [ "$EXPLANATION" ] ; then
echo "Explanation may only be given once!" >&2
exit 2
fi
EXPLANATION="$1"
shift
fi
START="`pwd`"
MYDIR="`dirname $0`"
cd "$MYDIR"
MYDIR="`pwd`"
cd ..
# now in .../Doc/
make --no-print-directory bziphtml || exit $?
RELEASE=`grep '^RELEASE=' Makefile | sed 's|RELEASE=||'`
PACKAGE="html-$RELEASE.tar.bz2"
scp "$PACKAGE" tools/update-docs.sh $TARGET/ || exit $?
ssh "$TARGETHOST" tmp/update-docs.sh $DOCTYPE $PACKAGE '&&' rm tmp/update-docs.sh || exit $?
if $ANNOUNCE ; then
sendmail $ADDRESSES <<EOF
To: $ADDRESSES
From: "Fred L. Drake" <fdrake@acm.org>
Subject: [$DOCLABEL doc updates]
X-No-Archive: yes
The $DOCLABEL version of the documentation has been updated:
http://$TARGETHOST/dev/doc/$DOCTYPE/
$EXPLANATION
EOF
exit $?
fi

View File

@ -1,920 +0,0 @@
;;; py2texi.el -- Conversion of Python LaTeX documentation to Texinfo
;; Copyright (C) 1998, 1999, 2001, 2002 Milan Zamazal
;; Author: Milan Zamazal <pdm@zamazal.org>
;; Version: $Id$
;; Keywords: python
;; COPYRIGHT NOTICE
;;
;; This program is free software; you can redistribute it and/or modify it
;; under the terms of the GNU General Public License as published by the Free
;; Software Foundation; either version 2, or (at your option) any later
;; version.
;;
;; This program is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
;; for more details.
;;
;; You can find the GNU General Public License at
;; http://www.gnu.org/copyleft/gpl.html
;; or you can write to the Free Software Foundation, Inc., 59 Temple Place,
;; Suite 330, Boston, MA 02111-1307, USA.
;;; Commentary:
;; This is a Q&D hack for conversion of Python manuals to on-line help format.
;; I desperately needed usable online documenta for Python, so I wrote this.
;; The result code is ugly and need not contain complete information from
;; Python manuals. I apologize for my ignorance, especially ignorance to
;; python.sty. Improvements of this convertor are welcomed.
;; How to use it:
;; Load this file and apply `M-x py2texi'. You will be asked for name of a
;; file to be converted.
;; Where to find it:
;; New versions of this code might be found at
;; http://www.zamazal.org/software/python/py2texi/ .
;;; Code:
(require 'texinfo)
(eval-when-compile
(require 'cl))
(defvar py2texi-python-version "2.2"
"What to substitute for the \\version macro.")
(defvar py2texi-python-short-version
(progn
(string-match "[0-9]+\\.[0-9]+" py2texi-python-version)
(match-string 0 py2texi-python-version))
"Short version number, usually set by the LaTeX commands.")
(defvar py2texi-texi-file-name nil
"If non-nil, that string is used as the name of the Texinfo file.
Otherwise a generated Texinfo file name is used.")
(defvar py2texi-info-file-name nil
"If non-nil, that string is used as the name of the Info file.
Otherwise a generated Info file name is used.")
(defvar py2texi-stop-on-problems nil
"*If non-nil, stop when you encouter soft problem.")
(defconst py2texi-environments
'(("abstract" 0 "@quotation" "@end quotation\n")
("center" 0 "" "")
("cfuncdesc" 3
(progn (setq findex t)
"\n@table @code\n@item \\1 \\2(\\3)\n@findex \\2\n")
"@end table\n")
("cmemberdesc" 3
"\n@table @code\n@item \\2 \\3\n"
"@end table\n")
("classdesc" 2
(progn (setq obindex t)
"\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
"@end table\n")
("classdesc*" 1
(progn (setq obindex t)
"\n@table @code\n@item \\1\n@obindex \\1\n")
"@end table\n")
("csimplemacrodesc" 1
(progn (setq cindex t)
"\n@table @code\n@item \\1\n@cindex \\1\n")
"@end table\n")
("ctypedesc" 1
(progn (setq cindex t)
"\n@table @code\n@item \\1\n@cindex \\1\n")
"@end table\n")
("cvardesc" 2
(progn (setq findex t)
"\n@table @code\n@item \\1 \\2\n@findex \\2\n")
"@end table\n")
("datadesc" 1
(progn (setq findex t)
"\n@table @code\n@item \\1\n@findex \\1\n")
"@end table\n")
("datadescni" 1 "\n@table @code\n@item \\1\n" "@end table\n")
("definitions" 0 "@table @dfn" "@end table\n")
("description" 0 "@table @samp" "@end table\n")
("displaymath" 0 "" "")
("document" 0
(concat "@defcodeindex mo\n"
"@defcodeindex ob\n"
"@titlepage\n"
(format "@title " title "\n")
(format "@author " author "\n")
"@page\n"
author-address
"@end titlepage\n"
"@node Top, , , (dir)\n")
(concat "@indices\n"
"@contents\n"
"@bye\n"))
("enumerate" 0 "@enumerate" "@end enumerate")
("excdesc" 1
(progn (setq obindex t)
"\n@table @code\n@item \\1\n@obindex \\1\n")
"@end table\n")
("excclassdesc" 2
(progn (setq obindex t)
"\n@table @code\n@item \\1(\\2)\n@obindex \\1\n")
"@end table\n")
("flushleft" 0 "" "")
("fulllineitems" 0 "\n@table @code\n" "@end table\n")
("funcdesc" 2
(progn (setq findex t)
"\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
"@end table\n")
("funcdescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table\n")
("itemize" 0 "@itemize @bullet" "@end itemize\n")
("list" 2 "\n@table @code\n" "@end table\n")
("longtableii" 4 (concat "@multitable @columnfractions .5 .5\n"
"@item \\3 @tab \\4\n"
"@item ------- @tab ------ \n")
"@end multitable\n")
("longtableiii" 5 (concat "@multitable @columnfractions .33 .33 .33\n"
"@item \\3 @tab \\4 @tab \\5\n"
"@item ------- @tab ------ @tab ------\n")
"@end multitable\n")
("memberdesc" 1
(progn (setq findex t)
"\n@table @code\n@item \\1\n@findex \\1\n")
"@end table\n")
("memberdescni" 1 "\n@table @code\n@item \\1\n" "@end table\n")
("methoddesc" 2
(progn (setq findex t)
"\n@table @code\n@item \\1(\\2)\n@findex \\1\n")
"@end table\n")
("methoddescni" 2 "\n@table @code\n@item \\1(\\2)\n" "@end table\n")
("notice" 0 "@emph{Notice:} " "")
("opcodedesc" 2
(progn (setq findex t)
"\n@table @code\n@item \\1 \\2\n@findex \\1\n")
"@end table\n")
("productionlist" 0 "\n@table @code\n" "@end table\n")
("quotation" 0 "@quotation" "@end quotation")
("seealso" 0 "See also:\n@table @emph\n" "@end table\n")
("seealso*" 0 "@table @emph\n" "@end table\n")
("sloppypar" 0 "" "")
("small" 0 "" "")
("tableii" 4 (concat "@multitable @columnfractions .5 .5\n"
"@item \\3 @tab \\4\n"
"@item ------- @tab ------ \n")
"@end multitable\n")
("tableiii" 5 (concat "@multitable @columnfractions .33 .33 .33\n"
"@item \\3 @tab \\4 @tab \\5\n"
"@item ------- @tab ------ @tab ------\n")
"@end multitable\n")
("tableiv" 6 (concat
"@multitable @columnfractions .25 .25 .25 .25\n"
"@item \\3 @tab \\4 @tab \\5 @tab \\6\n"
"@item ------- @tab ------- @tab ------- @tab -------\n")
"@end multitable\n")
("tablev" 7 (concat
"@multitable @columnfractions .20 .20 .20 .20 .20\n"
"@item \\3 @tab \\4 @tab \\5 @tab \\6 @tab \\7\n"
"@item ------- @tab ------- @tab ------- @tab ------- @tab -------\n")
"@end multitable\n"))
"Associative list defining substitutions for environments.
Each list item is of the form (ENVIRONMENT ARGNUM BEGIN END) where:
- ENVIRONMENT is LaTeX environment name
- ARGNUM is number of (required) macro arguments
- BEGIN is substitution for \begin{ENVIRONMENT}
- END is substitution for \end{ENVIRONMENT}
Both BEGIN and END are evaled. Moreover, you can reference arguments through
\N regular expression notation in strings of BEGIN.")
(defconst py2texi-commands
'(("ABC" 0 "ABC")
("appendix" 0 (progn (setq appendix t) ""))
("ASCII" 0 "ASCII")
("author" 1 (progn (setq author (match-string 1 string)) ""))
("authoraddress" 1
(progn (setq author-address (match-string 1 string)) ""))
("b" 1 "@w{\\1}")
("bf" 0 "@destroy")
("bifuncindex" 1 (progn (setq findex t) "@findex{\\1}"))
("C" 0 "C")
("c" 0 "@,")
("catcode" 0 "")
("cdata" 1 "@code{\\1}")
("centerline" 1 "@center \\1")
("cfuncline" 3 "@itemx \\1 \\2(\\3)\n@findex \\2")
("cfunction" 1 "@code{\\1}")
("chapter" 1 (format "@node \\1\n@%s \\1\n"
(if appendix "appendix" "chapter")))
("chapter*" 1 "@node \\1\n@unnumbered \\1\n")
("character" 1 "@samp{\\1}")
("citetitle" 1 "@ref{Top,,,\\1}")
("class" 1 "@code{\\1}")
("cmemberline" 3 "@itemx \\2 \\3\n")
("code" 1 "@code{\\1}")
("command" 1 "@command{\\1}")
("constant" 1 "@code{\\1}")
("copyright" 1 "@copyright{}")
("Cpp" 0 "C++")
("csimplemacro" 1 "@code{\\1}")
("ctype" 1 "@code{\\1}")
("dataline" 1 (progn (setq findex t) "@item \\1\n@findex \\1\n"))
("date" 1 "\\1")
("declaremodule" 2 (progn (setq cindex t) "@label{\\2}@cindex{\\2}"))
("deprecated" 2 "@emph{This is deprecated in Python \\1. \\2}")
("dfn" 1 "@dfn{\\1}")
("documentclass" 1 py2texi-magic)
("e" 0 "@backslash{}")
("else" 0 (concat "@end ifinfo\n@" (setq last-if "iftex")))
("EOF" 0 "@code{EOF}")
("email" 1 "@email{\\1}")
("emph" 1 "@emph{\\1}")
("envvar" 1 "@samp{\\1}")
("exception" 1 "@code{\\1}")
("exindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
("fi" 0 (concat "@end " last-if))
("file" 1 "@file{\\1}")
("filevar" 1 "@file{@var{\\1}}")
("footnote" 1 "@footnote{\\1}")
("frac" 0 "")
("funcline" 2 (progn (setq findex t) "@item \\1 \\2\n@findex \\1"))
("funclineni" 2 "@item \\1 \\2")
("function" 1 "@code{\\1}")
("grammartoken" 1 "@code{\\1}")
("hline" 0 "")
("ifhtml" 0 (concat "@" (setq last-if "ifinfo")))
("iftexi" 0 (concat "@" (setq last-if "ifinfo")))
("index" 1 (progn (setq cindex t) "@cindex{\\1}"))
("indexii" 2 (progn (setq cindex t) "@cindex{\\1 \\2}"))
("indexiii" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3}"))
("indexiv" 3 (progn (setq cindex t) "@cindex{\\1 \\2 \\3 \\4}"))
("infinity" 0 "@emph{infinity}")
("it" 0 "@destroy")
("kbd" 1 "@key{\\1}")
("keyword" 1 "@code{\\1}")
("kwindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
("label" 1 "@label{\\1}")
("Large" 0 "")
("LaTeX" 0 "La@TeX{}")
("large" 0 "")
("ldots" 0 "@dots{}")
("leftline" 1 "\\1")
("lineii" 2 "@item \\1 @tab \\2")
("lineiii" 3 "@item \\1 @tab \\2 @tab \\3")
("lineiv" 4 "@item \\1 @tab \\2 @tab \\3 @tab \\4")
("linev" 5 "@item \\1 @tab \\2 @tab \\3 @tab \\4 @tab \\5")
("localmoduletable" 0 "")
("longprogramopt" 1 "@option{--\\1}")
("mailheader" 1 "@code{\\1}")
("makeindex" 0 "")
("makemodindex" 0 "")
("maketitle" 0 (concat "@top " title "\n"))
("makevar" 1 "@code{\\1}")
("manpage" 2 "@samp{\\1(\\2)}")
("mbox" 1 "@w{\\1}")
("member" 1 "@code{\\1}")
("memberline" 1 "@item \\1\n@findex \\1\n")
("menuselection" 1 "@samp{\\1}")
("method" 1 "@code{\\1}")
("methodline" 2 (progn (setq moindex t) "@item \\1(\\2)\n@moindex \\1\n"))
("methodlineni" 2 "@item \\1(\\2)\n")
("mimetype" 1 "@samp{\\1}")
("module" 1 "@samp{\\1}")
("moduleauthor" 2 "")
("modulesynopsis" 1 "\\1")
("moreargs" 0 "@dots{}")
("n" 0 "@backslash{}n")
("newcommand" 2 "")
("newsgroup" 1 "@samp{\\1}")
("nodename" 1
(save-excursion
(save-match-data
(re-search-backward "^@node "))
(delete-region (point) (save-excursion (end-of-line) (point)))
(insert "@node " (match-string 1 string))
""))
("noindent" 0 "@noindent ")
("note" 1 "@emph{Note:} \\1")
("NULL" 0 "@code{NULL}")
("obindex" 1 (progn (setq obindex t) "@obindex{\\1}"))
("opindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
("option" 1 "@option{\\1}")
("optional" 1 "[\\1]")
("pep" 1 (progn (setq cindex t) "PEP@ \\1@cindex PEP \\1\n"))
("pi" 0 "pi")
("platform" 1 "")
("plusminus" 0 "+-")
("POSIX" 0 "POSIX")
("production" 2 "@item \\1 \\2")
("productioncont" 1 "@item @w{} \\1")
("program" 1 "@command{\\1}")
("programopt" 1 "@option{\\1}")
("protect" 0 "")
("pytype" 1 "@code{\\1}")
("ref" 1 "@ref{\\1}")
("refbimodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
("refmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
("refmodule" 1 "@samp{\\1}")
("refstmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
("regexp" 1 "\"\\1\"")
("release" 1
(progn (setq py2texi-python-version (match-string 1 string)) ""))
("renewcommand" 2 "")
("rfc" 1 (progn (setq cindex t) "RFC@ \\1@cindex RFC \\1\n"))
("rm" 0 "@destroy")
("samp" 1 "@samp{\\1}")
("section" 1 (let ((str (match-string 1 string)))
(save-match-data
(if (string-match "\\(.*\\)[ \t\n]*---[ \t\n]*\\(.*\\)"
str)
(format
"@node %s\n@section %s\n"
(py2texi-backslash-quote (match-string 1 str))
(py2texi-backslash-quote (match-string 2 str)))
"@node \\1\n@section \\1\n"))))
("sectionauthor" 2 "")
("seemodule" 2 "@ref{\\1} \\2")
("seepep" 3 "\n@table @strong\n@item PEP\\1 \\2\n\\3\n@end table\n")
("seerfc" 3 "\n@table @strong\n@item RFC\\1 \\2\n\\3\n@end table\n")
("seetext" 1 "\\1")
("seetitle" 1 "@cite{\\1}")
("seeurl" 2 "\n@table @url\n@item \\1\n\\2\n@end table\n")
("setindexsubitem" 1 (progn (setq cindex t) "@cindex \\1"))
("setreleaseinfo" 1 (progn (setq py2texi-releaseinfo "")))
("setshortversion" 1
(progn (setq py2texi-python-short-version (match-string 1 string)) ""))
("shortversion" 0 py2texi-python-short-version)
("sqrt" 0 "")
("stindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
("stmodindex" 1 (progn (setq moindex t) "@moindex{\\1}"))
("strong" 1 "@strong{\\1}")
("sub" 0 "/")
("subsection" 1 "@node \\1\n@subsection \\1\n")
("subsubsection" 1 "@node \\1\n@subsubsection \\1\n")
("sum" 0 "")
("tableofcontents" 0 "")
("term" 1 "@item \\1")
("textasciitilde" 0 "~")
("textasciicircum" 0 "^")
("textbackslash" 0 "@backslash{}")
("textgreater" 0 ">")
("textless" 0 "<")
("textrm" 1 "\\1")
("texttt" 1 "@code{\\1}")
("textunderscore" 0 "_")
("title" 1 (progn (setq title (match-string 1 string)) "@settitle \\1"))
("today" 0 "@today{}")
("token" 1 "@code{\\1}")
("tt" 0 "@destroy")
("ttindex" 1 (progn (setq cindex t) "@cindex{\\1}"))
("u" 0 "@backslash{}u")
("ulink" 2 "\\1")
("UNIX" 0 "UNIX")
("unspecified" 0 "@dots{}")
("url" 1 "@url{\\1}")
("usepackage" 1 "")
("var" 1 "@var{\\1}")
("verbatiminput" 1 "@code{\\1}")
("version" 0 py2texi-python-version)
("versionadded" 1 "@emph{Added in Python version \\1}")
("versionchanged" 1 "@emph{Changed in Python version \\1}")
("vskip" 1 "")
("vspace" 1 "")
("warning" 1 "@emph{\\1}")
("withsubitem" 2 "\\2")
("XXX" 1 "@strong{\\1}"))
"Associative list of command substitutions.
Each list item is of the form (COMMAND ARGNUM SUBSTITUTION) where:
- COMMAND is LaTeX command name
- ARGNUM is number of (required) command arguments
- SUBSTITUTION substitution for the command. It is evaled and you can
reference command arguments through the \\N regexp notation in strings.")
(defvar py2texi-magic "@documentclass\n"
"\"Magic\" string for auxiliary insertion at the beginning of document.")
(defvar py2texi-dirs '("./" "../texinputs/")
"Where to search LaTeX input files.")
(defvar py2texi-buffer "*py2texi*"
"The name of a buffer where Texinfo is generated.")
(defconst py2texi-xemacs (string-match "^XEmacs" (emacs-version))
"Running under XEmacs?")
(defmacro py2texi-search (regexp &rest body)
`(progn
(goto-char (point-min))
(while (re-search-forward ,regexp nil t)
,@body)))
(defmacro py2texi-search-safe (regexp &rest body)
`(py2texi-search ,regexp
(unless (py2texi-protected)
,@body)))
(defun py2texi-message (message)
"Report message and stop if `py2texi-stop-on-problems' is non-nil."
(if py2texi-stop-on-problems
(error message)
(message message)))
(defun py2texi-backslash-quote (string)
"Double backslahes in STRING."
(let ((i 0))
(save-match-data
(while (setq i (string-match "\\\\" string i))
(setq string (replace-match "\\\\\\\\" t nil string))
(setq i (+ i 2))))
string))
(defun py2texi (file)
"Convert Python LaTeX documentation FILE to Texinfo."
(interactive "fFile to convert: ")
(switch-to-buffer (get-buffer-create py2texi-buffer))
(erase-buffer)
(insert-file file)
(let ((case-fold-search nil)
(title "")
(author "")
(author-address "")
(appendix nil)
(findex nil)
(obindex nil)
(cindex nil)
(moindex nil)
last-if)
(py2texi-process-verbatims)
(py2texi-process-comments)
(py2texi-process-includes)
(py2texi-process-funnyas)
(py2texi-process-environments)
(py2texi-process-commands)
(py2texi-fix-indentation)
(py2texi-fix-nodes)
(py2texi-fix-references)
(py2texi-fix-indices)
(py2texi-process-simple-commands)
(py2texi-fix-fonts)
(py2texi-fix-braces)
(py2texi-fix-backslashes)
(py2texi-destroy-empties)
(py2texi-fix-newlines)
(py2texi-adjust-level))
(let* ((texi-file-name (or py2texi-texi-file-name
(py2texi-texi-file-name file)))
(info-file-name (or py2texi-info-file-name
(py2texi-info-file-name texi-file-name))))
(goto-char (point-min))
(when (looking-at py2texi-magic)
(delete-region (point) (progn (beginning-of-line 2) (point)))
(insert "\\input texinfo @c -*-texinfo-*-\n")
(insert "@setfilename " info-file-name))
(when (re-search-forward "@chapter" nil t)
(texinfo-all-menus-update t))
(goto-char (point-min))
(write-file texi-file-name)
(message (format "You can apply `makeinfo %s' now." texi-file-name))))
(defun py2texi-texi-file-name (filename)
"Generate name of Texinfo file from original file name FILENAME."
(concat filename
(if (string-match "\\.tex$" filename) "i" ".texi")))
(defun py2texi-info-file-name (filename)
"Generate name of info file from original file name FILENAME."
(setq filename (expand-file-name filename))
(let ((directory (file-name-directory filename))
(basename (file-name-nondirectory filename)))
(concat directory "python-"
(substring basename 0 (- (length basename) 4)) "info")))
(defun py2texi-process-verbatims ()
"Process and protect verbatim environments."
(let (delimiter
beg
end)
(py2texi-search-safe "\\\\begin{\\(verbatim\\|displaymath\\)}"
(replace-match "@example")
(setq beg (copy-marker (point) nil))
(re-search-forward "\\\\end{\\(verbatim\\|displaymath\\)}")
(setq end (copy-marker (match-beginning 0) nil))
(replace-match "@end example")
(py2texi-texinfo-escape beg end)
(put-text-property (- beg (length "@example"))
(+ end (length "@end example"))
'py2texi-protected t))
(py2texi-search-safe "\\\\verb\\([^a-z]\\)"
(setq delimiter (match-string 1))
(replace-match "@code{")
(setq beg (copy-marker (point) nil))
(re-search-forward (regexp-quote delimiter))
(setq end (copy-marker (match-beginning 0) nil))
(replace-match "}")
(put-text-property (- beg (length "@code{")) (+ end (length "}"))
'py2texi-protected t)
(py2texi-texinfo-escape beg end))))
(defun py2texi-process-comments ()
"Remove comments."
(let (point)
(py2texi-search-safe "%"
(setq point (point))
(when (save-excursion
(re-search-backward "\\(^\\|[^\\]\\(\\\\\\\\\\)*\\)%\\=" nil t))
(delete-region (1- point)
(save-excursion (beginning-of-line 2) (point)))))))
(defun py2texi-process-includes ()
"Include LaTeX input files.
Do not include .ind files."
(let ((path (file-name-directory file))
filename
dirs
includefile)
(py2texi-search-safe "\\\\input{\\([^}]+\\)}"
(setq filename (match-string 1))
(unless (save-match-data (string-match "\\.tex$" filename))
(setq filename (concat filename ".tex")))
(setq includefile (save-match-data
(string-match "\\.ind\\.tex$" filename)))
(setq dirs py2texi-dirs)
(while (and (not includefile) dirs)
(setq includefile (concat path (car dirs) filename))
(unless (file-exists-p includefile)
(setq includefile nil)
(setq dirs (cdr dirs))))
(if includefile
(save-restriction
(narrow-to-region (match-beginning 0) (match-end 0))
(delete-region (point-min) (point-max))
(when (stringp includefile)
(insert-file-contents includefile)
(goto-char (point-min))
(insert "\n")
(py2texi-process-verbatims)
(py2texi-process-comments)
(py2texi-process-includes)))
(replace-match (format "\\\\emph{Included file %s}" filename))
(py2texi-message (format "Input file %s not found" filename))))))
(defun py2texi-process-funnyas ()
"Convert @s."
(py2texi-search-safe "@"
(replace-match "@@")))
(defun py2texi-process-environments ()
"Process LaTeX environments."
(let ((stack ())
kind
environment
parameter
arguments
n
string
description)
(py2texi-search-safe (concat "\\\\\\(begin\\|end\\|item\\)"
"\\({\\([^}]*\\)}\\|[[]\\([^]]*\\)[]]\\|\\)")
(setq kind (match-string 1)
environment (match-string 3)
parameter (match-string 4))
(replace-match "")
(cond
((string= kind "begin")
(setq description (assoc environment py2texi-environments))
(if description
(progn
(setq n (cadr description))
(setq description (cddr description))
(setq string (py2texi-tex-arguments n))
(string-match (py2texi-regexp n) string)
; incorrect but sufficient
(insert (replace-match (eval (car description))
t nil string))
(setq stack (cons (cadr description) stack)))
(py2texi-message (format "Unknown environment: %s" environment))
(setq stack (cons "" stack))))
((string= kind "end")
(insert (eval (car stack)))
(setq stack (cdr stack)))
((string= kind "item")
(insert "\n@item " (or parameter "") "\n"))))
(when stack
(py2texi-message (format "Unclosed environment: %s" (car stack))))))
(defun py2texi-process-commands ()
"Process LaTeX commands."
(let (done
command
command-info
string
n)
(while (not done)
(setq done t)
(py2texi-search-safe "\\\\\\([a-zA-Z*]+\\)\\(\\[[^]]*\\]\\)?"
(setq command (match-string 1))
(setq command-info (assoc command py2texi-commands))
(if command-info
(progn
(setq done nil)
(replace-match "")
(setq command-info (cdr command-info))
(setq n (car command-info))
(setq string (py2texi-tex-arguments n))
(string-match (py2texi-regexp n) string)
; incorrect but sufficient
(insert (replace-match (eval (cadr command-info))
t nil string)))
(py2texi-message (format "Unknown command: %s (not processed)"
command)))))))
(defun py2texi-argument-pattern (count)
(let ((filler "\\(?:[^{}]\\|\\\\{\\|\\\\}\\)*"))
(if (<= count 0)
filler
(concat filler "\\(?:{"
(py2texi-argument-pattern (1- count))
"}" filler "\\)*" filler))))
(defconst py2texi-tex-argument
(concat
"{\\("
(py2texi-argument-pattern 10) ;really at least 10!
"\\)}[ \t%@c\n]*")
"Regexp describing LaTeX command argument including argument separators.")
(defun py2texi-regexp (n)
"Make regexp matching N LaTeX command arguments."
(if (= n 0)
""
(let ((regexp "^[^{]*"))
(while (> n 0)
(setq regexp (concat regexp py2texi-tex-argument))
(setq n (1- n)))
regexp)))
(defun py2texi-tex-arguments (n)
"Remove N LaTeX command arguments and return them as a string."
(let ((point (point))
(i 0)
result
match)
(if (= n 0)
(progn
(when (re-search-forward "\\=\\({}\\| *\\)" nil t)
(replace-match ""))
"")
(while (> n 0)
(unless (re-search-forward
"\\(\\=\\|[^\\\\]\\)\\(\\\\\\\\\\)*\\([{}]\\)" nil t)
(debug))
(if (string= (match-string 3) "{")
(setq i (1+ i))
(setq i (1- i))
(when (<= i 0)
(setq n (1- n)))))
(setq result (buffer-substring-no-properties point (point)))
(while (string-match "\n[ \t]*" result)
(setq result (replace-match " " t nil result)))
(delete-region point (point))
result)))
(defun py2texi-process-simple-commands ()
"Replace single character LaTeX commands."
(let (char)
(py2texi-search-safe "\\\\\\([^a-z]\\)"
(setq char (match-string 1))
(replace-match (format "%s%s"
(if (or (string= char "{")
(string= char "}")
(string= char " "))
"@"
"")
(if (string= char "\\")
"\\\\"
char))))))
(defun py2texi-fix-indentation ()
"Remove white space at the beginning of lines."
(py2texi-search-safe "^[ \t]+"
(replace-match "")))
(defun py2texi-fix-nodes ()
"Remove unwanted characters from nodes and make nodes unique."
(let ((nodes (make-hash-table :test 'equal))
id
counter
string
label
index)
(py2texi-search "^@node +\\(.*\\)$"
(setq string (match-string 1))
(if py2texi-xemacs
(replace-match "@node " t)
(replace-match "" t nil nil 1))
(while (string-match "@label{[^}]*}" string)
(setq label (match-string 0 string))
(setq string (replace-match "" t nil string)))
(while (string-match "@..?index{[^}]*}" string)
(setq index (match-string 0 string))
(setq string (replace-match "" t nil string)))
(while (string-match "@[a-zA-Z]+\\|[{}():]\\|``\\|''" string)
(setq string (replace-match "" t nil string)))
(while (string-match " -- " string)
(setq string (replace-match " - " t nil string)))
(while (string-match "\\." string)
(setq string (replace-match "" t nil string)))
(when (string-match " +$" string)
(setq string (replace-match "" t nil string)))
(when (string-match "^\\(Built-in\\|Standard\\) Module \\|The " string)
(setq string (replace-match "" t nil string)))
(string-match "^[^,]+" string)
(setq id (match-string 0 string))
(setq counter (gethash id nodes))
(if counter
(progn
(setq counter (1+ counter))
(setq string (replace-match (format "\\& %d" counter)
t nil string)))
(setq counter 1))
(setf (gethash id nodes) counter)
(insert string)
(beginning-of-line 3)
(when label
(insert label "\n"))
(when index
(insert index "\n")))))
(defun py2texi-fix-references ()
"Process labels and make references to point to appropriate nodes."
(let ((labels ())
node)
(py2texi-search-safe "@label{\\([^}]*\\)}"
(setq node (save-excursion
(save-match-data
(and (re-search-backward "@node +\\([^,\n]+\\)" nil t)
(match-string 1)))))
(when node
(setq labels (cons (cons (match-string 1) node) labels)))
(replace-match ""))
(py2texi-search-safe "@ref{\\([^}]*\\)}"
(setq node (assoc (match-string 1) labels))
(replace-match "")
(when node
(insert (format "@ref{%s}" (cdr node)))))))
(defun py2texi-fix-indices ()
"Remove unwanted characters from @*index commands and create final indices."
(py2texi-search-safe "@..?index\\>[^\n]*\\(\\)\n"
(replace-match "" t nil nil 1))
(py2texi-search-safe "@..?index\\>[^\n]*\\(\\)"
(replace-match "\n" t nil nil 1))
(py2texi-search-safe "@..?index\\({\\)\\([^}]+\\)\\(}+\\)"
(replace-match " " t nil nil 1)
(replace-match "" t nil nil 3)
(let ((string (match-string 2)))
(save-match-data
(while (string-match "@[a-z]+{" string)
(setq string (replace-match "" nil nil string)))
(while (string-match "{" string)
(setq string (replace-match "" nil nil string))))
(replace-match string t t nil 2)))
(py2texi-search-safe "@..?index\\>.*\\([{}]\\|@[a-z]*\\)"
(replace-match "" t nil nil 1)
(goto-char (match-beginning 0)))
(py2texi-search-safe "[^\n]\\(\\)@..?index\\>"
(replace-match "\n" t nil nil 1))
(goto-char (point-max))
(re-search-backward "@indices")
(replace-match "")
(insert (if moindex
(concat "@node Module Index\n"
"@unnumbered Module Index\n"
"@printindex mo\n")
"")
(if obindex
(concat "@node Class-Exception-Object Index\n"
"@unnumbered Class, Exception, and Object Index\n"
"@printindex ob\n")
"")
(if findex
(concat "@node Function-Method-Variable Index\n"
"@unnumbered Function, Method, and Variable Index\n"
"@printindex fn\n")
"")
(if cindex
(concat "@node Miscellaneous Index\n"
"@unnumbered Miscellaneous Index\n"
"@printindex cp\n")
"")))
(defun py2texi-fix-backslashes ()
"Make backslashes from auxiliary commands."
(py2texi-search-safe "@backslash{}"
(replace-match "\\\\")))
(defun py2texi-fix-fonts ()
"Remove garbage after unstructured font commands."
(let (string)
(py2texi-search-safe "@destroy"
(replace-match "")
(when (eq (preceding-char) ?{)
(forward-char -1)
(setq string (py2texi-tex-arguments 1))
(insert (substring string 1 (1- (length string))))))))
(defun py2texi-fix-braces ()
"Escape braces for Texinfo."
(let (string)
(py2texi-search "{"
(unless (or (py2texi-protected)
(save-excursion
(re-search-backward
"@\\([a-zA-Z]*\\|multitable.*\\){\\=" nil t)))
(forward-char -1)
(setq string (py2texi-tex-arguments 1))
(insert "@" (substring string 0 (1- (length string))) "@}")))))
(defun py2texi-fix-newlines ()
"Remove extra newlines."
(py2texi-search "\n\n\n+"
(replace-match "\n\n"))
(py2texi-search-safe "@item.*\n\n"
(delete-backward-char 1))
(py2texi-search "@end example"
(unless (looking-at "\n\n")
(insert "\n"))))
(defun py2texi-destroy-empties ()
"Remove all comments.
This avoids some makeinfo errors."
(py2texi-search "@c\\>"
(unless (eq (py2texi-protected) t)
(delete-region (- (point) 2) (save-excursion (end-of-line) (point)))
(cond
((looking-at "\n\n")
(delete-char 1))
((save-excursion (re-search-backward "^[ \t]*\\=" nil t))
(delete-region (save-excursion (beginning-of-line) (point))
(1+ (point))))))))
(defun py2texi-adjust-level ()
"Increase heading level to @chapter, if needed.
This is only needed for distutils, so it has a very simple form only."
(goto-char (point-min))
(unless (re-search-forward "@chapter\\>" nil t)
(py2texi-search-safe "@section\\>"
(replace-match "@chapter" t))
(py2texi-search-safe "@\\(sub\\)\\(sub\\)?section\\>"
(replace-match "" nil nil nil 1))))
(defun py2texi-texinfo-escape (beg end)
"Escape Texinfo special characters in region."
(save-excursion
(goto-char beg)
(while (re-search-forward "[@{}]" end t)
(replace-match "@\\&"))))
(defun py2texi-protected ()
"Return protection status of the point before current point."
(get-text-property (1- (point)) 'py2texi-protected))
;;; Announce
(provide 'py2texi)
;;; py2texi.el ends here

View File

@ -1,98 +0,0 @@
"""Support functions for loading the reference count data file."""
__version__ = '$Revision$'
import os
import sys
# Determine the expected location of the reference count file:
try:
p = os.path.dirname(__file__)
except NameError:
p = os.path.dirname(sys.argv[0])
p = os.path.normpath(os.path.join(os.getcwd(), p, os.pardir,
"api", "refcounts.dat"))
DEFAULT_PATH = p
del p
def load(path=DEFAULT_PATH):
return loadfile(open(path))
def loadfile(fp):
d = {}
while 1:
line = fp.readline()
if not line:
break
line = line.strip()
if line[:1] in ("", "#"):
# blank lines and comments
continue
parts = line.split(":", 4)
if len(parts) != 5:
raise ValueError("Not enough fields in " + `line`)
function, type, arg, refcount, comment = parts
if refcount == "null":
refcount = None
elif refcount:
refcount = int(refcount)
else:
refcount = None
#
# Get the entry, creating it if needed:
#
try:
entry = d[function]
except KeyError:
entry = d[function] = Entry(function)
#
# Update the entry with the new parameter or the result information.
#
if arg:
entry.args.append((arg, type, refcount))
else:
entry.result_type = type
entry.result_refs = refcount
return d
class Entry:
def __init__(self, name):
self.name = name
self.args = []
self.result_type = ''
self.result_refs = None
def dump(d):
"""Dump the data in the 'canonical' format, with functions in
sorted order."""
items = d.items()
items.sort()
first = 1
for k, entry in items:
if first:
first = 0
else:
print
s = entry.name + ":%s:%s:%s:"
if entry.result_refs is None:
r = ""
else:
r = entry.result_refs
print s % (entry.result_type, "", r)
for t, n, r in entry.args:
if r is None:
r = ""
print s % (t, n, r)
def main():
d = load()
dump(d)
if __name__ == "__main__":
main()

View File

@ -1,54 +0,0 @@
"""Simple script to replace @DATE@ and friends with real information.
Usage: rewrite.py boilerplate.tex [VAR=value] ... <template >output
"""
import sys
import time
def get_info(fp):
s = fp.read()
d = {}
start = s.find(r"\date{")
if start >= 0:
end = s.find("}", start)
date = s[start+6:end]
if date == r"\today":
date = time.strftime("%B %d, %Y", time.localtime(time.time()))
d["DATE"] = date
return d
def main():
s = sys.stdin.read()
if "@" in s:
# yes, we actully need to load the replacement values
d = get_info(open(sys.argv[1]))
for arg in sys.argv[2:]:
name, value = arg.split("=", 1)
d[name] = value
start = 0
while 1:
start = s.find("@", start)
if start < 0:
break
end = s.find("@", start+1)
name = s[start+1:end]
if name:
value = d.get(name)
if value is None:
start = end + 1
else:
s = s[:start] + value + s[end+1:]
start = start + len(value)
else:
# "@@" --> "@"
s = s[:start] + s[end:]
start = end
sys.stdout.write(s)
if __name__ == "__main__":
main()

View File

@ -1,67 +0,0 @@
# Simple makefile to control XML generation for the entire document tree.
# This should be used from the top-level directory (Doc/), not the directory
# that actually contains this file:
#
# $ pwd
# .../Doc
# $ make -f tools/sgmlconv/Makefile
TOPDIR=.
TOOLSDIR=tools
SGMLRULES=../$(TOOLSDIR)/sgmlconv/make.rules
# The 'inst' and 'tut' directories break the conversion, so skip them for now.
SUBDIRS=api dist ext lib mac ref
SUBMAKE=$(MAKE) -f $(SGMLRULES) TOOLSDIR=../$(TOOLSDIR)
all: xml
.PHONY: esis xml
.PHONY: $(SUBDIRS)
xml:
for DIR in $(SUBDIRS) ; do \
(cd $$DIR && $(SUBMAKE) xml) || exit $$? ; done
esis:
for DIR in $(SUBDIRS) ; do \
(cd $$DIR && $(SUBMAKE) esis) || exit $$? ; done
esis1:
for DIR in $(SUBDIRS) ; do \
(cd $$DIR && $(SUBMAKE) esis1) || exit $$? ; done
tarball: xml
tar cf - tools/sgmlconv */*.xml | gzip -9 >xml-1.5.2b2.tgz
api:
cd api && $(SUBMAKE)
dist:
cd dist && $(SUBMAKE)
ext:
cd ext && $(SUBMAKE)
inst:
cd inst && $(SUBMAKE)
lib:
cd lib && $(SUBMAKE)
mac:
cd mac && $(SUBMAKE)
ref:
cd ref && $(SUBMAKE)
tut:
cd tut && $(SUBMAKE)
clean:
for DIR in $(SUBDIRS) ; do \
(cd $$DIR && $(SUBMAKE) clean) || exit $$? ; done
clobber:
for DIR in $(SUBDIRS) ; do \
(cd $$DIR && $(SUBMAKE) clobber) || exit $$? ; done

View File

@ -1,58 +0,0 @@
These scripts and Makefile fragment are used to convert the Python
documentation in LaTeX format to XML.
This material is preliminary and incomplete. Python 2.0 is required.
To convert all documents to XML:
cd Doc/
make -f tools/sgmlconv/Makefile
To convert one document to XML:
cd Doc/<document-dir>
make -f ../tools/sgmlconv/make.rules TOOLSDIR=../tools
Please send comments and bug reports to python-docs@python.org.
What do the tools do?
---------------------
latex2esis.py
Reads in a conversion specification written in XML
(conversion.xml), reads a LaTeX document fragment, and interprets
the markup according to the specification. The output is a stream
of ESIS events like those created by the nsgmls SGML parser, but
is *not* guaranteed to represent a single tree! This is done to
allow conversion per entity rather than per document. Since many
of the LaTeX files for the Python documentation contain two
sections on closely related modules, it is important to allow both
of the resulting <section> elements to exist in the same output
stream. Additionally, since comments are not supported in ESIS,
comments are converted to <COMMENT> elements, which might exist at
the same level as the top-level content elements.
The output of latex2esis.py gets saved as <filename>.esis1.
docfixer.py
This is the really painful part of the conversion. Well, it's the
second really painful part, but more of the pain is specific to
the structure of the Python documentation and desired output
rather than to the parsing of LaTeX markup.
This script loads the ESIS data created by latex2esis.py into a
DOM document *fragment* (remember, the latex2esis.py output may
not be well-formed). Once loaded, it walks over the tree many
times looking for a variety of possible specific
micro-conversions. Most of the code is not in any way "general".
After processing the fragment, a new ESIS data stream is written
out. Like the input, it may not represent a well-formed
document, but does represent a parsed entity.
The output of docfixer.py is what gets saved in <filename>.esis.
esis2sgml.py
Reads an ESIS stream and convert to SGML or XML. This also
converts <COMMENT> elements to real comments. This works quickly
because there's not much to actually do.

Some files were not shown because too many files have changed in this diff Show More