The Good Old Days Weren’t That Good
The Computer History Museum has published the source code to MacPaint and Quickdraw. This is pretty cool – I spent a lot of time hacking the Mac around that time, so it was interesting to me to see how this code was put together. I haven’t gone through all of it yet, but for grins, I pulled up the assembly source to MacPaint and started looking through the various routines. Here’s one I found:
;---------------------------------------------------------------------
;
; PROCEDURE MyGetItem(menu: menuHandle; item: INTEGER; VAR itemString: Str63)
;
;
; *** just type-coerce VAR Str255 to Str63 ***
;
JMP GetItem
To understand this, you need to understand Pascal strings. Pascal was the API language for the Macintosh, which presented a number of benefits and a number of problems. Brian Kernighan wrote a pretty good paper about the deficits of Pascal in 1981 covering the language pretty well. One of those problems centered around strings, which only halfway existed as a usable type in Pascal. I say halfway usable because there wasn’t really a string type in Pascal, even though you could type them in.
Most implementations of Pascal had some way to get strings into a packed array of char or some other type. On the Mac, they gave you a few types to work with: Str255, a 256 bytes array with the first byte being a length byte. Str63, a 64 byte array and a couple others.
Variables of type Str255 are wasteful – especially for menus. Most menu items (“Save”, “Quit”, “Cut”) are far shorter than 255 characters, but when you declare a Str255, you are saying that you have the full 256 bytes to work with. Since GetItem is declared as taking a Str255, you can’t pass it anything else. Bill Atkinson, decided to do a hard cast by writing assembly language glue to pass allow a Str63 to get passed in instead. While this will work most of the time and probably all the time in the first revision of MacOS, if a menu item exists with more than 63 characters in it, this will fail. And it will fail by silently overwriting either the stack or the heap. Both cases are bad.
The cause of this problem is several fold:
- Bill’s version of Pascal probably didn’t allow casting (which would’ve been unsafe anyway)
- Pascal strings are awful – certainly worse than C, which are pretty bad
- The Mac team didn’t insist on a reasonable string extension to Pascal to allow variable length strings (one version of Pascal I used allowed the declaration TYPE Str255 = VARYING[255] OF CHAR
- Memory resources were tight on MacPaint to require shorter strings
As a side note, in 1988 I wrote a version of MacPaint in C called StevePaint for SunOS. It handled 256 color images instead of black and white, better text handling, and image convolution (blur, etc). That code took me a semester with a full course load. It helped that the Suns I had access to were 68020 based machines running at a much better clip than the original Mac and that the UI was more or less designed for me. Still, never needing to drop into assembly language was a big win.