| Python and MPW |
| ============== |
| |
| 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, |
| so we can build "applets" (see below). I have used MPW 3.2 and the OpenDoc |
| development environment from an OpenDoc CD released in 1984. This |
| 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) |
| (the Code Fragment Manager ported back to the 68K Mac) and |
| MixedModeInit (version 1.0d12), which are required to use shared libraries. |
| |
| 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. |
| |
| I use these feature test macros: |
| |
| 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 |
| |
| 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. |
| |
| 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 |
| CD-ROM. Apparently it is only needed for large projects... |
| |
| |
| Warning: Mixing Think C and MPW |
| =============================== |
| |
| (XXX Need to check what convention SC uses -- I hope it uses Think's.) |
| |
| If you are mixing Think C and MPW, you may experience weird errors in |
| previously correct modules. These disappear when you throw away the |
| 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 |
| 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.) |
| |
| |
| 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.]] |