1995-02-17 10:49:28 -04:00
|
|
|
Python and MPW
|
|
|
|
==============
|
1994-08-29 05:58:39 -03:00
|
|
|
|
1995-02-17 10:49:28 -04:00
|
|
|
There is conditional code in Python for MPW. This has been used with
|
|
|
|
different compilers at various points in time. Right now it is being
|
|
|
|
used to turn the entire interpreter into a shared library on 68K Macs,
|
1995-02-18 11:04:26 -04:00
|
|
|
so we can build "applets" (see below). I have used MPW 3.2 and the OpenDoc
|
1995-02-17 10:49:28 -04:00
|
|
|
development environment from an OpenDoc CD released in 1984. This
|
1995-02-18 11:04:26 -04:00
|
|
|
contains the Symantec C compiler for MPW (version 7.0.4), the
|
|
|
|
Universal Headers (version 2.0a1), and early versions of CFM-68K (version 1.0a1)
|
1995-02-17 10:49:28 -04:00
|
|
|
(the Code Fragment Manager ported back to the 68K Mac) and
|
1995-02-18 11:04:26 -04:00
|
|
|
MixedModeInit (version 1.0d12), which are required to use shared libraries.
|
1994-08-29 05:58:39 -03:00
|
|
|
|
1995-02-17 10:49:28 -04:00
|
|
|
I've created a Makefile that does everything, plus a three-line Build
|
|
|
|
script that calls Make and runs its output. The Makefile assumes that
|
|
|
|
it lives in a 1-deep subdirectory of the root, so e.g. the Python
|
|
|
|
Include directory can be referenced through "::Include". All object
|
|
|
|
files are collected in the subsubdirectory Objcode.
|
1994-08-29 05:58:39 -03:00
|
|
|
|
1995-02-17 10:49:28 -04:00
|
|
|
I use these feature test macros:
|
1994-08-29 05:58:39 -03:00
|
|
|
|
1995-02-18 11:04:26 -04:00
|
|
|
MPW for all MPW compilers (e.g. long double in <math.h>)
|
|
|
|
__SC__ for things specific to the Symantec C compiler
|
|
|
|
(e.g. doesn't like static forward)
|
|
|
|
__CFM68K__ for things specific to CFM-68K
|
|
|
|
(e.g. it requires the use of #pragma lib_export on|off)
|
|
|
|
HAVE_UNIVERSAL_HEADERS for things not yet in Think's headers (e.g. UPPs)
|
|
|
|
GENERATINGCFM for both PPC and 68K Code Fragment Manager
|
1994-08-29 05:58:39 -03:00
|
|
|
|
1995-02-17 10:49:28 -04:00
|
|
|
MPW is defined in config.h (if it finds that applec is defined);
|
|
|
|
HAVE_UNIVERSAL_HEADERS is defined in macglue.h depending on whether it
|
|
|
|
thinks we are using Universal Headers. The others are defined by the
|
|
|
|
compiler or by the system headers.
|
1994-08-29 05:58:39 -03:00
|
|
|
|
1995-02-17 10:49:28 -04:00
|
|
|
Compiler switches were a nightmare until I found I had to use -b.
|
|
|
|
This wasn't mentioned in the CFM-68K docs that came on the OpenDoc
|
1995-02-18 11:04:26 -04:00
|
|
|
CD-ROM. Apparently it is only needed for large projects...
|
1994-08-29 05:58:39 -03:00
|
|
|
|
1994-09-09 09:10:21 -03:00
|
|
|
|
1995-02-17 10:49:28 -04:00
|
|
|
Warning: Mixing Think C and MPW
|
|
|
|
===============================
|
1994-09-09 09:10:21 -03:00
|
|
|
|
1995-02-17 10:49:28 -04:00
|
|
|
(XXX Need to check what convention SC uses -- I hope it uses Think's.)
|
1994-09-09 09:10:21 -03:00
|
|
|
|
1995-02-17 10:49:28 -04:00
|
|
|
If you are mixing Think C and MPW, you may experience weird errors in
|
1994-09-16 08:08:31 -03:00
|
|
|
previously correct modules. These disappear when you throw away the
|
1994-09-09 09:10:21 -03:00
|
|
|
module's .pyc file. The errors usually have to do with string
|
|
|
|
literals containing '\n' or '\r'. The reason is an incompatibility
|
|
|
|
between their handling of '\n' and '\r' -- in MPW C, '\n' actually is
|
|
|
|
ASCII CR while '\r' is ASCII LF, which is the reverse situation from
|
|
|
|
any other ASCII based C implementation. This behaviour is inherited
|
1994-09-16 08:08:31 -03:00
|
|
|
by Python compiled with MPW C. This is normally not a problem, but
|
|
|
|
*binary* files written by one system will be mis-interpreted by the
|
|
|
|
other, and this is what happens to the .pyc files. There is no easy
|
|
|
|
way to fix this in the source. (This is a real shame, since the
|
|
|
|
format of .pyc files was carefully designed to be independent of byte
|
|
|
|
order and integer size -- deviations in the ASCII character codes were
|
|
|
|
never anticipated.)
|
1995-02-18 11:04:26 -04:00
|
|
|
|
|
|
|
|
|
|
|
Building "Applets" for the Mac
|
|
|
|
==============================
|
|
|
|
|
|
|
|
An "applet" is a tiny application that's written in a scripting language
|
|
|
|
but behaves like a real application. The behavior is much like that of
|
|
|
|
executable scripts in Unix -- but the implementation is entirely different.
|
|
|
|
|
|
|
|
The applet's file can be small because it doesn't contain the actual
|
|
|
|
interpreter for the scripting language -- this has to be installed in the
|
|
|
|
Extensions folder (usually) before the applet will work. The applet file
|
|
|
|
itself only contains a tiny bootstrap program and the script itself --
|
|
|
|
possibly "compiled" or otherwise encoded to save on parsing time and space,
|
|
|
|
and to make it harder to reverse engineer the script (some people care about
|
|
|
|
this).
|
|
|
|
|
|
|
|
In Python's case, the Python interpreter, without its main program, is built
|
|
|
|
as a shared library that is dropped in the Extensions folder. Some more
|
|
|
|
shared libraries must also be present -- these form the C run-time system.
|
|
|
|
[[XXX perhaps we should link these in statically with the Python library,
|
|
|
|
for simpler distribution???]] On the 68K Mac, two more extensions are needed:
|
|
|
|
CFM-68K (the Code Fragment Manager) and MixedModeInit. These provide
|
|
|
|
functionality that's built in the Power Mac's OS. It seems that System 7.1.1
|
|
|
|
or higher is also required.
|
|
|
|
|
|
|
|
The applet file contains a small main program program, plus a 'PYC ' resource
|
|
|
|
named __main__ which contains the "compiled" version of the script. A 'PYC '
|
|
|
|
resource contains exactly the same data as a ".pyc" file. (The advantage of
|
|
|
|
storing compiled modules as resources instead of files is that many modules
|
|
|
|
can be stored in a single file.) The applet's main
|
|
|
|
program initializes most of the toolbox managers (it uses the same sequence
|
|
|
|
as stdwin or the Think C console I/O library), then initializes Python,
|
|
|
|
then loads the resource and decodes it into a Python code object, and finally
|
|
|
|
passes the code object to the Python interpreter for execution. [[XXX Actually,
|
|
|
|
the applet's main program could be moved entirely to the shared library --
|
|
|
|
there's nothing in it that's dependent on the applet's configuration.
|
|
|
|
The applet itself could then be reduced to main() { applet_main(); } ]]
|
|
|
|
[[XXX I tried this but it only save 512 bytes on a total of 10K -- the rest
|
|
|
|
is boilerplate that the linker always seems to create. Wonder how this is on
|
|
|
|
the Power Mac...]]
|
|
|
|
|
|
|
|
A big restriction for applets is that they have no standard input and their
|
|
|
|
standard output and error streams are diverted to files called "stdout" and
|
|
|
|
"stderr". This means that in order to interact with the user, or even just
|
|
|
|
to provide some feedback while they're grinding along, they must make use of
|
|
|
|
Mac toolbox calls to create windows, etc. I plan to provide a library that at
|
|
|
|
least has the output functionality of the Think C Console I/O library or
|
|
|
|
CodeWarrior's SIOX.
|
|
|
|
|
|
|
|
The current procedure to create an applet is not as simple as it could be.
|
|
|
|
I have written a Python script (which itself can be -- and has been -- made
|
|
|
|
into an applet!) which asks for a Python source file (input) and an existing
|
|
|
|
applet file (output). It adds a 'PYC ' resource to the applet named __main__,
|
|
|
|
which contains the compiled code of the script (it compiles on the fly,
|
|
|
|
so you don't need to have a .pyc file for the script).
|
|
|
|
Although this seems fairly simple, the practical complication is that you need
|
|
|
|
to copy the applet template first -- if you specify the template as the output,
|
|
|
|
you will overwrite the template! [[XXX I guess a simplification could be made
|
|
|
|
by using the convention that the applet built from a script has the same name
|
|
|
|
as the script but with ".py" stripped; the applet-making script could then
|
|
|
|
search for the template in a few common locations (e.g. the Python module
|
|
|
|
search path) and copy it, reducing the user interaction to just indicating the
|
|
|
|
Python source file to be converted into an applet.]]
|