diff --git a/Mac/Relnotes-1.1 b/Mac/Relnotes-1.1 new file mode 100644 index 00000000000..3c67fb759f3 --- /dev/null +++ b/Mac/Relnotes-1.1 @@ -0,0 +1,131 @@ +PYTHON RELEASE NOTES FOR THE MACINTOSH + +VERSION 1.0.2 + +For the most part, Python on the Mac works just like Python under UNIX. +The most important differences are: + +- Since there is no shell environment on the Mac, the start-up file + has a fixed name: PythonStartup. If a file by this name exists + (either in the current folder or in the system folder) it is executed + when an interactive interpreter is started. + +- The default search path for modules is different: first the current + directory is searched, then the subdirectories 'lib', 'lib:stdwin' and + 'demo'. As always, you can change this (e.g. in your PythonStartup + file) by assigning or appending to sys.path -- use Macintosh pathnames! + (The default contains no absolute paths because these are unlikely + to make sense on other people's hard disks.) + +- The user interface for typing interactive commands is different. + This is actually the THINK C console I/O module, which is based on + the Mac toolbox TextEdit. A standard Edit menu provides Cut, Copy, + Paste and Clear (Undo is only there for Desk Accessories). A minimal + File menu provides Quit, which immediately exits the application, + without the usual cleanup. You can Copy from previous output, + but you can't scroll back beyond the 24x80 screen. The TAB key + always brings you to the end of the current input line; indentation + must be entered with spaces (a single space is enough). + End-of-file is generated by Command-D; Command-Period interrupts. + There is an annoying limit in the length of an input line to a single + screen line (less the prompt). Use \ to input long statements. + Change your program if it requires long lines typed on input. + Even though there is no resize box, the window can be resized by + dragging its bottom right corner, but the maximum size is 24x80. + +- Tabs in module files are interpreted as 4 (four!) spaces. This is + consistent with most Mac editors that I know. For individual files + you can change the tab size with a comment like + + # vi:set tabsize=8: + + (exactly as shown here, including the colons!). If you are consistent + in always using tabs for indentation on UNIX, your files will be + parsed correctly on the Mac, although they may look funny if you + have nicely lined-up comments or tables using tabs. Never using tabs + also works. Mixing tabs and spaces to simulate 4-character indentation + levels is likely to fail. + +- You can start a script from the Finder by selecting the script and + the Python interpreter together and then double clicking. If you + make the owner of the script PYTH (the type should always be TEXT) + Python will be launched if you double click it! + There is no way to pass command line arguments to Python scripts. + +- The set of built-in modules is different: + + = Operating system functions for the 'os' module is provided by the + built-in module 'mac', not 'posix'. This doesn't have all the + functions from posix, for obvious reasons (if you know the Mac + O/S a little bit). The functions in os.path are provided by + macpath, they know about Mac pathnames etc. + + = None of the UNIX specific modules ('socket', 'pwd', 'grp' etc.) + exists. + + = Module 'stdwin' is always available. It uses the Mac version of + STDWIN, which interfaces directly with the Mac toolbox. The most + important difference is in the font names; setfont() has a second + argument specifying the point size and an optional third one + specifying the variation: a single letter character string, + 'i' for italics, 'b' for bold. Note that when STDWIN is waiting + for events, the standard File and Edit menus are inactive but + still visible, and (most annoyingly) the Apple menu is also inactive; + conversely, menus put up by STDWIN are not active when the Python is + reading from the keyboard. If you open Python together with a text + file containing a Python script, the script will be executed and + a console window is only generated when the script uses standard + input or output. A script that uses STDWIN exclusively for its I/O + will have a working Apple menu and no extraneous File/Edit menus. + (This is because both stdwin and stdio try to initialize the + windowing environment; whoever gets there first owns the Apple menu.) + LIMITATIONS: a few recent additions to STDWIN for X11 have not yet + been added to the Mac version. There are no bitmap objects, and + the setwinpos() and setwinsize() methods are non--functional. + +- Because launching an application on the Mac is so tedious, you will + want to edit your program with a desk accessory editor (e.g., Sigma + edit) and test the changed version without leaving Python. This is + possible but requires some care. Make sure the program is a module + file (filename must be a Python identifier followed by '.py'). You + can then import it when you test it for the first time. There are + now three possibilities: it contains a syntax error; it gets a runtime + error (unhandled exception); or it runs OK but gives wrong results. + (If it gives correct results, you are done testing and don't need + to read the rest of this paragraph. :-) Note that the following + is not Mac-specific -- it's just that on UNIX it's easier to restart + the entire script so it's rarely useful. + + Recovery from a syntax error is easy: edit the file and import it + again. + + Recovery from wrong output is almost as easy: edit the file and, + instead of importing it, call the function reload() with the module + name as argument (e.g., if your module is called foo, type + "reload(foo)"). + + Recovery from an exception is trickier. Once the syntax is correct, + a 'module' entry is placed in an internal table, and following import + statements will not re-read the file, even if the module's initialization + terminated with an error (one reason why this is done is so that + mutually recursive modules are initialized only once). You must + therefore force re-reading the module with reload(), however, if this + happens the first time you try to import the module, the import statement + itself has not completed, and your workspace does not know the module + name (even though the internal table of moduesl does!). The trick is + to first import the module again, then reload it. For instance, + "import foo; reload(foo)". Because the module object already exists + internally, the import statement does not attempt to execute the + module again -- it just places it in your workspace. + + When you edit a module you don't have to worry about the corresponding + '.pyc' file (a "compiled" version of the module, which loads much faster + than the textual version): the interpreter notices that the '.py' file + has changed (because its modification time has changed) and ignores the + '.pyc' file. When parsing is successful, a new '.pyc' file is written; + if this fails (no write permission, disk full or whatever) it is + silently skipped but attempted again the next time the same module + is loaded. (Thus, if you plan to place a Python library on a read-only + disk, it is advisable to "warm the cache" by making the disk writable + and importing all modules once. The standard module 'importall' helps + in doing this.) diff --git a/Mac/USING b/Mac/USING new file mode 100644 index 00000000000..3c67fb759f3 --- /dev/null +++ b/Mac/USING @@ -0,0 +1,131 @@ +PYTHON RELEASE NOTES FOR THE MACINTOSH + +VERSION 1.0.2 + +For the most part, Python on the Mac works just like Python under UNIX. +The most important differences are: + +- Since there is no shell environment on the Mac, the start-up file + has a fixed name: PythonStartup. If a file by this name exists + (either in the current folder or in the system folder) it is executed + when an interactive interpreter is started. + +- The default search path for modules is different: first the current + directory is searched, then the subdirectories 'lib', 'lib:stdwin' and + 'demo'. As always, you can change this (e.g. in your PythonStartup + file) by assigning or appending to sys.path -- use Macintosh pathnames! + (The default contains no absolute paths because these are unlikely + to make sense on other people's hard disks.) + +- The user interface for typing interactive commands is different. + This is actually the THINK C console I/O module, which is based on + the Mac toolbox TextEdit. A standard Edit menu provides Cut, Copy, + Paste and Clear (Undo is only there for Desk Accessories). A minimal + File menu provides Quit, which immediately exits the application, + without the usual cleanup. You can Copy from previous output, + but you can't scroll back beyond the 24x80 screen. The TAB key + always brings you to the end of the current input line; indentation + must be entered with spaces (a single space is enough). + End-of-file is generated by Command-D; Command-Period interrupts. + There is an annoying limit in the length of an input line to a single + screen line (less the prompt). Use \ to input long statements. + Change your program if it requires long lines typed on input. + Even though there is no resize box, the window can be resized by + dragging its bottom right corner, but the maximum size is 24x80. + +- Tabs in module files are interpreted as 4 (four!) spaces. This is + consistent with most Mac editors that I know. For individual files + you can change the tab size with a comment like + + # vi:set tabsize=8: + + (exactly as shown here, including the colons!). If you are consistent + in always using tabs for indentation on UNIX, your files will be + parsed correctly on the Mac, although they may look funny if you + have nicely lined-up comments or tables using tabs. Never using tabs + also works. Mixing tabs and spaces to simulate 4-character indentation + levels is likely to fail. + +- You can start a script from the Finder by selecting the script and + the Python interpreter together and then double clicking. If you + make the owner of the script PYTH (the type should always be TEXT) + Python will be launched if you double click it! + There is no way to pass command line arguments to Python scripts. + +- The set of built-in modules is different: + + = Operating system functions for the 'os' module is provided by the + built-in module 'mac', not 'posix'. This doesn't have all the + functions from posix, for obvious reasons (if you know the Mac + O/S a little bit). The functions in os.path are provided by + macpath, they know about Mac pathnames etc. + + = None of the UNIX specific modules ('socket', 'pwd', 'grp' etc.) + exists. + + = Module 'stdwin' is always available. It uses the Mac version of + STDWIN, which interfaces directly with the Mac toolbox. The most + important difference is in the font names; setfont() has a second + argument specifying the point size and an optional third one + specifying the variation: a single letter character string, + 'i' for italics, 'b' for bold. Note that when STDWIN is waiting + for events, the standard File and Edit menus are inactive but + still visible, and (most annoyingly) the Apple menu is also inactive; + conversely, menus put up by STDWIN are not active when the Python is + reading from the keyboard. If you open Python together with a text + file containing a Python script, the script will be executed and + a console window is only generated when the script uses standard + input or output. A script that uses STDWIN exclusively for its I/O + will have a working Apple menu and no extraneous File/Edit menus. + (This is because both stdwin and stdio try to initialize the + windowing environment; whoever gets there first owns the Apple menu.) + LIMITATIONS: a few recent additions to STDWIN for X11 have not yet + been added to the Mac version. There are no bitmap objects, and + the setwinpos() and setwinsize() methods are non--functional. + +- Because launching an application on the Mac is so tedious, you will + want to edit your program with a desk accessory editor (e.g., Sigma + edit) and test the changed version without leaving Python. This is + possible but requires some care. Make sure the program is a module + file (filename must be a Python identifier followed by '.py'). You + can then import it when you test it for the first time. There are + now three possibilities: it contains a syntax error; it gets a runtime + error (unhandled exception); or it runs OK but gives wrong results. + (If it gives correct results, you are done testing and don't need + to read the rest of this paragraph. :-) Note that the following + is not Mac-specific -- it's just that on UNIX it's easier to restart + the entire script so it's rarely useful. + + Recovery from a syntax error is easy: edit the file and import it + again. + + Recovery from wrong output is almost as easy: edit the file and, + instead of importing it, call the function reload() with the module + name as argument (e.g., if your module is called foo, type + "reload(foo)"). + + Recovery from an exception is trickier. Once the syntax is correct, + a 'module' entry is placed in an internal table, and following import + statements will not re-read the file, even if the module's initialization + terminated with an error (one reason why this is done is so that + mutually recursive modules are initialized only once). You must + therefore force re-reading the module with reload(), however, if this + happens the first time you try to import the module, the import statement + itself has not completed, and your workspace does not know the module + name (even though the internal table of moduesl does!). The trick is + to first import the module again, then reload it. For instance, + "import foo; reload(foo)". Because the module object already exists + internally, the import statement does not attempt to execute the + module again -- it just places it in your workspace. + + When you edit a module you don't have to worry about the corresponding + '.pyc' file (a "compiled" version of the module, which loads much faster + than the textual version): the interpreter notices that the '.py' file + has changed (because its modification time has changed) and ignores the + '.pyc' file. When parsing is successful, a new '.pyc' file is written; + if this fails (no write permission, disk full or whatever) it is + silently skipped but attempted again the next time the same module + is loaded. (Thus, if you plan to place a Python library on a read-only + disk, it is advisable to "warm the cache" by making the disk writable + and importing all modules once. The standard module 'importall' helps + in doing this.) diff --git a/Mac/fopenRF.c b/Mac/fopenRF.c new file mode 100644 index 00000000000..f18f7d9a667 --- /dev/null +++ b/Mac/fopenRF.c @@ -0,0 +1,399 @@ + +/* + * fopenRF.c -- Clone of fopen.c to open Mac resource forks. + * + * Copyright (c) 1989 Symantec Corporation. All rights reserved. + * + */ + +#include "stdio.h" +#include "errno.h" +#include "string.h" +#include "ansi_private.h" + +FILE *fopenRF(char *, char *); +FILE *freopenRF(char *, char *, FILE *); +FILE *__openRF(char *, int, int, FILE *); + +#include + +#define fcbVPtr(fcb) (* (VCB **) (fcb + 20)) +#define fcbDirID(fcb) (* (long *) (fcb + 58)) +#define fcbCName(fcb) (fcb + 62) + +static void setfiletype(StringPtr, int); +static void stdio_exit(void); +static int fileio(FILE *, int); +static int close(FILE *); +static void replace(unsigned char *, size_t, int, int); + + +FILE * +fopenRF(filename, mode) +char *filename, *mode; +{ + return(freopenRF(filename, mode, __getfile())); +} + + +FILE * +freopenRF(filename, mode, fp) +char *filename; +register char *mode; +register FILE *fp; +{ + int omode, oflag; + + /* interpret "rwa" */ + + if (mode[0] == 'r') { + omode = fsRdPerm; + oflag = 0; + } + else if (mode[0] == 'w') { + omode = fsWrPerm; + oflag = F_CREAT+F_TRUNC; + } + else if (mode[0] == 'a') { + omode = fsWrPerm; + oflag = F_CREAT+F_APPEND; + } + else { + errno = EINVAL; + return(NULL); + } + + /* interpret "b+" */ + + if (mode[1] == 'b') { + oflag |= F_BINARY; + if (mode[2] == '+') + omode = fsRdWrPerm; + } + else if (mode[1] == '+') { + omode = fsRdWrPerm; + if (mode[2] == 'b') + oflag |= F_BINARY; + } + + /* open the file */ + + return(__openRF(filename, omode, oflag, fp)); +} + + +FILE * +__openRF(filename, omode, oflag, fp) +char *filename; +int omode, oflag; +register FILE *fp; +{ + ioParam pb; + char pname[FILENAME_MAX]; + + if (fp == NULL) + return(NULL); + fclose(fp); + + /* set up pb */ + + pb.ioNamePtr = __c2p(filename, pname); + pb.ioVRefNum = 0; + pb.ioVersNum = 0; + pb.ioPermssn = omode; + pb.ioMisc = 0; + + /* create file */ + + if (oflag & F_CREAT) { + asm { + lea pb,a0 + _PBCreate + } + if (pb.ioResult == noErr) + oflag &= ~F_TRUNC; + else if (pb.ioResult == dupFNErr && !(oflag & F_EXCL)) + oflag &= ~F_CREAT; + else { + errno = pb.ioResult; + return(NULL); + } + } + + /* open resource file */ + + asm { + lea pb,a0 + _PBOpenRF + } + if (pb.ioResult) { + errno = pb.ioResult; + if (oflag & F_CREAT) asm { + lea pb,a0 + _PBDelete + } + return(NULL); + } + fp->refnum = pb.ioRefNum; + + /* get/set file length */ + + if (oflag & F_TRUNC) asm { + lea pb,a0 + _PBSetEOF + } + else if (!(oflag & F_CREAT)) asm { + lea pb,a0 + _PBGetEOF + } + fp->len = (fpos_t) pb.ioMisc; + + /* initialize rest of FILE structure */ + + if (oflag & F_APPEND) { + fp->append = 1; + fp->pos = fp->len; + } + if (oflag & F_BINARY) + fp->binary = 1; + setvbuf(fp, NULL, _IOFBF, BUFSIZ); + fp->proc = fileio; + + /* set file type */ + + if (oflag & (F_CREAT|F_TRUNC)) + setfiletype(pb.ioNamePtr, oflag); + + /* done */ + + __atexit_stdio(stdio_exit); + return(fp); +} + + +/* + * setfiletype - set type/creator of new file + * + */ + +static void +setfiletype(name, oflag) +StringPtr name; +int oflag; +{ + fileParam pb; + + pb.ioNamePtr = name; + pb.ioVRefNum = 0; + pb.ioFVersNum = 0; + pb.ioFDirIndex = 0; + asm { + lea pb,a0 + _PBGetFInfo + bmi.s @1 + } + pb.ioFlFndrInfo.fdType = pb.ioFlFndrInfo.fdCreator = '????'; + if (!(oflag & F_BINARY)) + pb.ioFlFndrInfo.fdType = 'TEXT'; + asm { + lea pb,a0 + _PBSetFInfo +@1 } +} + + +/* + * stdio_exit - stdio shutdown routine + * + */ + +static void +stdio_exit() +{ + register FILE *fp; + int n; + + for (fp = &__file[0], n = FOPEN_MAX; n--; fp++) + fclose(fp); +} + + +/* + * fileio - I/O handler proc for files and devices + * + */ + +static int +fileio(fp, i) +register FILE *fp; +int i; +{ + ioParam pb; + + pb.ioRefNum = fp->refnum; + switch (i) { + + /* read */ + + case 0: + pb.ioBuffer = (Ptr) fp->ptr; + pb.ioReqCount = fp->cnt; + pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark; + pb.ioPosOffset = fp->pos - fp->cnt; + asm { + lea pb,a0 + _PBRead + } + if (pb.ioResult == eofErr) { + fp->pos = pb.ioPosOffset; + if (fp->cnt = pb.ioActCount) + pb.ioResult = 0; + else { + fp->eof = 1; + return(EOF); + } + } + if (pb.ioResult) { + fp->pos -= fp->cnt; + fp->cnt = 0; + } + else if (!fp->binary) + replace(fp->ptr, fp->cnt, '\r', '\n'); + break; + + /* write */ + + case 1: + pb.ioBuffer = (Ptr) fp->ptr; + pb.ioReqCount = fp->cnt; + pb.ioPosMode = fp->refnum > 0 ? fsFromStart : fsAtMark; + if ((pb.ioPosOffset = fp->pos - fp->cnt) > fp->len) { + pb.ioMisc = (Ptr) pb.ioPosOffset; + asm { + lea pb,a0 + _PBSetEOF + bmi.s @1 + } + } + if (!fp->binary) + replace(fp->ptr, fp->cnt, '\n', '\r'); + asm { + lea pb,a0 + _PBWrite +@1 } + if (pb.ioResult) { + fp->pos -= fp->cnt; + fp->cnt = 0; + } + else if (pb.ioPosOffset > fp->len) + fp->len = pb.ioPosOffset; + break; + + /* close */ + + case 2: + pb.ioResult = close(fp); + break; + } + + /* done */ + + if (pb.ioResult) { + fp->err = 1; + errno = pb.ioResult; + return(EOF); + } + return(0); +} + + +static int +close(fp) +register FILE *fp; +{ + HFileParam pb; + Str255 buf; + register char *fcb = FCBSPtr + fp->refnum; + VCB *vcb = fcbVPtr(fcb); + register char *s; + + pb.ioNamePtr = buf; + pb.ioFRefNum = fp->refnum; + pb.ioVRefNum = vcb->vcbVRefNum; + pb.ioFVersNum = 0; + + /* close temporary file - HFS */ + + if (fp->delete && vcb->vcbSigWord == 0x4244) { + pb.ioDirID = fcbDirID(fcb); + s = fcbCName(fcb); + asm { + lea buf,a0 + moveq #0,d0 + move.b (s),d0 +@1 move.b (s)+,(a0)+ + dbra d0,@1 + lea pb,a0 + _PBClose + bmi.s @9 + _PBHDelete + } + } + + /* close temporary file - MFS */ + + else if (fp->delete && vcb->vcbSigWord == 0xD2D7) { + pb.ioFDirIndex = 1; + do asm { + lea pb,a0 + _PBGetFInfo + bmi.s @2 + addq.w #1,pb.ioFDirIndex + } while (pb.ioFRefNum != fp->refnum); + asm { + lea pb,a0 + _PBClose + bmi.s @9 + _PBDelete + } + } + + /* normal case - just close file */ + + else { + asm { +@2 lea pb,a0 + _PBClose + bmi.s @9 + } + } + + /* flush volume buffer */ + + pb.ioNamePtr = 0; + asm { + lea pb,a0 + _PBFlshVol +@9 } + return(pb.ioResult); +} + + +/* + * replace - routine for doing CR/LF conversion + * + */ + +static void +replace(s, n, c1, c2) +register unsigned char *s; +register size_t n; +register int c1, c2; +{ + register unsigned char *t; + + for (; n && (t = memchr(s, c1, n)); s = t) { + *t++ = c2; + n -= t - s; + } +} diff --git a/Mac/scripts/crlf.py b/Mac/scripts/crlf.py new file mode 100755 index 00000000000..f52867a34ea --- /dev/null +++ b/Mac/scripts/crlf.py @@ -0,0 +1,25 @@ +#! /usr/local/bin/python + +import sys +import os +import string + +def main(): + args = sys.argv[1:] + if not args: + print 'no files' + sys.exit(1) + for file in args: + print file, '...' + data = open(file, 'r').read() + lines = string.splitfields(data, '\r') + newdata = string.joinfields(lines, '\n') + if newdata != data: + print 'rewriting...' + os.rename(file, file + '~') + open(file, 'w').write(newdata) + print 'done.' + else: + print 'no change.' + +main()