Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Design

The Macintosh Programmer's Workshop


SP 88: THE MACINTOSH PROGRAMMER'S WORKSHOP

This article contains the following executables: BENCHMRK.ARC

Dan Allen is a software explorer for Apple Computer where he has worked on several projects, including MacApp, HFS, MacPlus, MacsBug, and MPW. He is currently working with Bill Atkinson on HyperCard. Dan can be reached at Apple Computer Inc., 20525 Mariani Ave., MS: 27E, Cupertino, CA 95014.


As a professional environment for developing Macintosh software, the Macintosh Programmer's Workshop (MPW) is versatile. MPW was designed primarily for developing stand-alone, double-clickable applications, and many successful applications, including Hypercard, MacDraw, and More, have been developed with it. (See the sidebar, "Background, History, and Credits," for a glimpse of the people who have contributed to MPW.)

MPW supports integrated tools, which are generic line-oriented applications that run inside the MPW environment. Integrated tools include language translators, text tools, and other nongraphical tools. Unlike with standard applications, integrated tools can use the MPW shell environment and resources, which frees programmers from having to write a Macintosh application every time the need for a small utility arises.

Code is usually disguised as a resource of some kind in the Macintosh. Macintosh files contain two forks: a resource fork and a data fork. MPW is able to create many different resources, such as INITs, PACKs, MDEFs, WDEFs, DRVRs, and desk accessories. In fact, the Macintosh ROMs themselves are built entirely with MPW. A new resource type, the HyperCard XCMD, allows HyperTalk to be extended by calling compiled resources. (For more information see "Introduction HyperCard Programming," page 56.

The MPW Interface

MPW is a mixture of Smalltalk and the Unix system.

From Smalltalk, it inherits an integrated environment as well as the ability to interpret any text when users select it and press the Enter key. Because of effective use of RAM, the disk-based editor can quickly edit multimegabyte files. The editor is mainly mouse-based, but it also supports cursor keys and several keyboard shortcuts. The editor is built-in and other text editors do not work as effectively, which is annoying for those who have strong preferences about editors. The advantages of the integrated environment, however, outweigh the disadvantages of the built-in editor.

From Unix, MPW inherits the notion of a command shell. The command interpreter includes support for aliases, shell variables, structured constructs, I/O redirection, pipes, shell scripts, and the sublaunching of tools and applications from MPW. The command interpreter's history mechanism is simple and easy to use: Commands are maintained in the Worksheet, a window that is always open. The editor handles the Worksheet as it does any other open file. To execute a prior command, you simply scroll back to the start of the Worksheet, select the line (triple-clicking is a shortcut), and then press Enter or click with the mouse on the lowerleft corner of the window. You can execute commands from any window, not just the Worksheet. MPW supports up to 12 open windows in addition to the Worksheet.

A window is a view into a file of the same name--a powerful concept when combined with I/O redirection. If the output of a tool is redirected to a currently open file, for example, the output will go to the window as well as to the file. It is easy to analyze tool output because one window contains various shell commands and a second, adjacent window contains the output from the commands.

MPW supports three types of commands: built-ins, tools, and scripts. If it receives a command that it does not recognize as a built-in, it searches a user-definable search path of directories, looking for a file of the same name. If the file is a regular MPW text file (a file of type TEXT), MPW interprets it as a shell-command script. If the file is an MPW tool (a file of type MPST), then MPW runs it as executable code.

Find-and-replace commands work on open windows, either in a literal mode similar to that found on most word processors or in a selection-expression mode in which you can issue complicated, cryptic commands (reminiscent of Unix's regular expressions) to do powerful text processing. Numeric and string expressions are evaluated in a similar way to the pattern portion of an awk script. You can specify regular expressions as you do in grep, and selections allow you to specify ranges of text in windows in powerful ways. Selection expressions are the most arcane aspect of MPW and have a steep learning curve, which is why they are underused by most programmers.

MPW inherits the ability to extend the system from both Smalltalk and Unix. From customizing a UserStartup shell script to designing custom menus and keyboard equivalents that are tied into shell commands all the way to writing new tools, MPW is designed to be configured the way the programmer wants it to be.

The Command Language

When you press the Enter key (or equivalent), MPW uses seven steps to interpret a command: alias substitution, evaluation of structured constructs, variable and command substitution, blank interpretation, filename generation, I/O redirection, and execution.

Alias substitution allows you to define command names. Variables are referred to in braces. Command substitution, a powerful mechanism, occurs through the use of backquotes. File-name generation is available to all commands and is used to specify files through the use of selection expressions. I/O redirection allows you to send stdin, stdout, and stderr to arbitrary destinations, also specified by selection expressions. It is possible, for example, to run a tool on a selected portion of text in an open window.

The MPW shell's built-in command language consists of traditional Unix-like commands (see Table 1, page 22) and Mac-like commands (see Table 2, this page). The tables do not include the many command-line options that are applicable to each command.

Table 1: Traditional Unix-system-like commands

  Structured Commands
  -----------------------------------------------------------------
  Begin               # group commands
  Break               # break from For or Loop
  Continue            # continue with next iteration of For or Loop
  Evaluate            # evaluate an expression
  Execute             # execute command file in current scope
  Exit                # exit from command file
  For                 # repeat commands once per parameter
  If                  # conditional command execution
  Loop                # repeat commands until Break

  Variable/Parameter Commands
  -----------------------------------------------------------------
  Ailas               # define and write command aliases
  Export              # make variables available to commands
  Set                 # define or write Shell variables
  Unalias             # remove aliases
  Unexport            # remove variables available to commands
  Unset               # remove Shell variable definitions
  Parameters          # write parameters
  Shift               # renumber command file positional parameters
  Echo                # echo parameters
  Quote               # echo quoted parameters

  File System Commands
  -----------------------------------------------------------------
  Catenate            # concatenate files
  Delete              # delete files and directories
  Directory           # set or write the default directory
  Duplicate           # duplicate files and directories
  Eject               # eject volumes
  Equal               # compare files and directories
  Erase               # initialize volumes
  Exists              # test existence of a file or directory
  Files               # list files and directories
  Mount               # mount volumes
  Move                # move files and directories
  Newer               # compare modification dates of files
  NewFolder           # create folder
  Rename              # rename files and directories
  Setfile             # set file attributes
  Unmount             # unmount volumes
  Volumes             # list mounted volumes
  Which               # determine what file the shell will execute

  Misc. Commands
  -----------------------------------------------------------------
  Beep                # generate tones
  Date                # write the date and time
  Help                # write summary information
  Quit                # quit MPW
  Shutdown            # shutdown/reboot the machine

Table 2: Macintosh-like commands

  Window Commands
  -----------------------------------------------------------------
  New                 # open new file in window
  Open                # open file in window
  Target              # make window the target window
  Close               # close a window
  Save                # save contents of window
  Revert              # revert to saved document
  MoveWindow          # move window to x,y
  SizeWindow          # make window be x by y
  StackWindows        # arrange windows stacked
  TileWindows         # arrange windows to be tiled
  ZoomWindow          # zoom target window to full size
  Windows             # list open windows

  Menu Commands
  -----------------------------------------------------------------
  Add Menu            # add user-defined menu item
  Delete Menu         # delete user-defined menus and items

  Dialog Commands
  -----------------------------------------------------------------
  Alert               # display alert box
  Confirm             # display confirmation dialog
  Request             # request text from a dialog

  Text Commands
  -----------------------------------------------------------------
  Find                # find and select a text pattern
  Replace             # replace the selection
  Mark                # set a marker in a window
  Unmark              # delete a marker in a window
  Tab                 # set tab setting of a window
  Font                # set font setting of a window
  Adjust              # adjust lines
  Align               # align text to left margin

  Clipboard Commands
  -----------------------------------------------------------------
  Undo                # undo last edit in target window
  Cut                 # copy selection to Clipboard and delete it
  Copy                # copy selection to Clipboard
  Paste               # replace selection with Clipboard contents
  Clear               # clear the selection

The structured commands in Table 1 provide the basic constructs that support iteration and conditional branching in scripts. The variable/parameter commands allow scripts to pass information to and from each other in various ways. Scripts can call each other recursively and can support both local and global variables as well as multiple scoping levels.

The commands in Table 1 also provide a way to programmatically accomplish most of the operations that can be done in the Finder, such as copying and renaming files. For those with a Unix background, Files is very similar to ls, Directory to cd, and NewFolder to mkdir. MPW also includes a file of Unix aliases to make Unix users feel at home.

As Table 2 illustrates, MPW provides built-in scriptable commands for most of the actions that you would normally do with the mouse or keyboard, thus facilitating build scripts that automate the production of software.

MPW Tools

The advent of the MPW shell has produced MPW tools, a new class of applications that are distinct from normal applications or desk accessories. An MPW tool is similar to a standard Macintosh application, but it runs as part of the MPW shell and benefits from many services that the shell provides. An MPW tool is actually a coroutine that resides within the MPW shell's heap. The rules for writing tools are short. Tools do not need to initialize the various Mac Toolbox managers or deal with menus or events because these services are performed for them by the MPW shell.

How are tools launched and how does an MPW tool fit into the Macintosh architecture? A major portion of the shell continues to be active and resident in memory during the execution of a tool, so the first step is to unload any code segments that are not needed during the execution of a tool in order to allow it more available heap space.

The second step is to open the tool's resource fork and allocate a cache entry. Tools are cached in memory when they are first executed, and therefore subsequent executions of a cached tool are much quicker. This speed advantage is noticeable when correcting a compilation error and recompiling code. Up to ten tools can be cached in RAM, with the oldest tools being purged from memory as additional space is required.

The third step in the launching of an MPW tool is to create a separate and distinct A5 World for the tool. (An A5 World consists of areas of memory that depend upon the value contained in the A5 register of the 68xxx micro processor. Such areas include the application's globals, QuickDraw's globals, and the intersegment jump table.) What this means is that the MPW shell does a type of context switch by setting up an area for the tool in the shell's own application heap that contains the tool's own A5 World. The MPW shell takes care of allocating a nonrelocatable block for the globals and also sets up the jump table (code segment 0 of any Mac application or tool). The tool's stack area, however, is shared with the stack of the MPW shell, which reduces memory requirements.

The fourth step is to set up the environment area, which is an area in memory containing the parameters being passed to the tool from the shell. These are accessed in C, for example, via the standard argv/argc convention.

Finally, the shell does a quick check of the heap for consistency and then calls the first routine in the tool's jump table. The MPW tool then effectively becomes the application in control.

Many of the common routines that an MPW tool may call, such as the file system and memory allocation routines, are patched out or intercepted by the MPW shell, thus allowing it to do I/O redirection and perform its windows-over-files abstraction. When these routines are called by a tool, or when a readln or printf instruction is called, the flow of execution returns to the shell while it handles the tool's request. Typical tools contain many instances in which the path of execution is transferred back and forth (transparently to the programmer) between the MPW shell and the MPW tool.

After the tool terminates, the shell automatically performs several cleanup operations. It retrieves the status from the environment area, closes any files left open by the tool, and then frees up any memory that was allocated by the tool. These operations are possible because the shell intercepts the memory allocation and file system calls. Future tools are thus given a clean environment in which to run. If a tool goes into an infinite loop, or if you want to terminate the execution of a tool, the shell provides a periodic vertical blanking (VBL) task that checks for a command period keyboard sequence, which will force a tool to be aborted and the environment to be cleaned up.

The real utility of an MPW tool is that generic code written for more traditional tty environments runs in the Macintosh environment without any additional code support. readln, writeln, scanf, and printf all work without the programmer's having to write a set of special QuickDraw commands to support them. Most utilities written for the Unix environment are especially good candidates for an easy port to MPW tools.

Standard MPW Tools

MPW includes many standard tools. It supports several languages, including assembly language, C, Pascal, and a special resource-oriented language called Rez. Various text tools, such as search, count, canon, compare, backup, entab, and translate help maintain source files. It also has a variety of linker-oriented tools, including a librarian, and various disassemble tools for examining generated object code. Also available is a performance package that makes profiling code possible. Table 3, this page, lists the tools that make up the MPW system.{1}

Table 3: Tools for the Macintosh Programmer's Workshop

  Asm                 # 68020 macro assembler
  Backup              # generates list of dup cmds based on file dates
  C                   # 68020 C compiler
  Canon               # spell checks indentifiers based on canonical list
  Commando            # dialog interface to MPW tools
  Compare             # compares two text files, prints list of differences
  Count               # counts characters and lines
  DeRez               # de-compiles resourses to Rez format
  DumpCode            # disassembles resources
  DumpObj             # disassembles object code modules
  Entab               # converts between spaces & tabs
  FileDiv             # splits up large text files into many small files
  GetErrorText        # display error msgs based on msg number
  GetFileName         # display a Standard File dialog box
  GetListItem         # display items for selection in a dialog box
  Lib                 # object code librarian
  Link                # links object files: strips dead code
  MacsBug             # assembly level debugger/disassembler
  Make                # generates build commands based on file dates
  MakeErrorFile       # creates error message textfile
  Pascal              # 68xxx Pascal & Object Pascal compiler
  PasMat              # text pretty-printer for Pascal sources
  PasRef              # generates full xref listing for Pascal sources
  PerformReport       # generates a performance report
  Print               # prints files to LaserWriter & ImageWriter
  ProcNames           # displays Pascal procedure and function names
  ResEdit             # edits resources interactively (application)
  ResEqual            # compares the resources in two files
  Rez                 # compiles resources from text description
  RezDet              # lists resources: detects bad resources
  Search              # searches multiple files for text pattern
  SetVersion          # maintains version and revision number
  Translate           # translates characters

MPW Assembly Language

The premier language of MPW is Asm, written by Ira Ruben. Asm generates code for the entire 68xxx line of processors, including the 68000, 68010, 68020, 68030, 68851, 68881, and 68882 processors. MPW also includes a full set of equates files that support the Toolbox (MPW 2.0 also supports the Mac SE and Mac II) as well as sample programs in assembly language for an application, a desk accessory, and a tool. One entire volume of the documentation that comes with MPW is devoted to the many features and options Asm contains.{2} Asm is fast: It assembles instructions at rates greater than 40,000 lines per minute on a Mac II.{3}

A highlight of Asm is its powerful macro processor, written by Fred Forsman. Using macros provides for a higher level of abstraction than is normally available when using assembly language. Included with MPW are a set of structured macros (written by Ira Ruben) that implement many of the structured constructs that are available to C and Pascal programmers. When using the structured macros, assembly-language code looks similar to Pascal and yet retains the efficiency of assembly language. Asm also supports the use of interactive assembly, by which lines of assembly-language code can be typed in and assembled on the fly. This is made possible by the tight coupling between Asm and the shell. (Any tool that supports stdin can do this.)

Another interesting use of Asm's macro processor is illustrated by a set of macros that implement object assembly language. These object macros were written by Ken Doyle, who also wrote the object extensions to MPW Pascal. Object assembly language is 68xxx assembly-language code that is interlanguage callable with Object Pascal. These object macros are also included with MPW and allow time-critical portions of object-oriented programs to be recoded in assembly language for greater speed.

MPW C

MPW C is a version of the Green Hills C compiler designed specially for Apple and is similar to the version that was available for the Lisa Workshop. It has the usual obligatory post-K&R extensions to C (such as enum) that are described well in Harbison and Steele.{4} MPW C is similar to C compilers found on VAXs in that it uses 32-bit integers, and although some consider it an inefficiency, this feature makes porting C code from the Unix world effortless. MPW C is particularly good in its global register allocation strategy that results in above-average generated code. Version 2.0 of MPW C introduced support for generating 68020 and 68881 code.

MPW C is not without its quirks, however. It has a proclivity for allocating global data--a problem for those writing special types of code such as drivers and desk accessories. Using a literal string or even a floating-point literal causes global data to be allocated! Its compilation time is slow, and occasionally its generated code is unneeded (not inaccurate, just wasted). The compiler is big (233K), and its generated code, although fast, can also be big, especially when the C libraries are added.

The manual for MPW C contains a good delta description of the language as it varies from K&R or H&S. The manual does not include a full language reference, although it does have pages for the C library routines. It also includes a condensed quick-reference listing of the Inside Macintosh calls. The ideal solution is to use three manuals that complement each other: H&S, The C Programmer's Handbook,{5} and the supplied Macintosh Programmer's Workshop C Reference.{6}

MPW Pascal

MPW Pascal is a descendant of Lisa Pascal and conforms closely to the ANSI standard for Pascal. Its enhancements to standard Pascal are major and significant and require a bit of explanation.

Silicon Valley Software (SVS) originally wrote Lisa Pascal for Apple in 1981, although Apple has maintained it for years now. It supported Units, a method of separate compilation that provides an Interface as well as an Implementation section for each module of code, thus providing similar facilities to Modula-2.{7}

An early version of object-oriented programming was supported as the language further evolved into a language called Clascal. Clascal began in 1983, when Larry Tesler (formerly of Xerox PARC) asked Chris Franklin to implement classes. It was later enhanced by Al Hoffman and then by Ira Ruben. Early in 1985, a team including Larry Tesler and Nikolaus Wirth created Object Pascal, a superset of Pascal and the successor to Clascal. Object Pascal also supports the concepts of objects, classes, and inheritance but in a simpler and clearer way than does Clascal. Ken Doyle finished things up by writing the Object Pascal extensions to the MPW Pascal compiler. MPW Pascal is thus a full Object Pascal compiler.

In addition to Units with their facility for separate compilation, MPW Pascal has also been extended to support conditional compilation and compile-time variables, bit operators, short-circuit Boolean operators, Leave and Cycle statements (similar to break and continue in C), type coercion, and many other concepts. MPW Pascal overcomes most of Brian Kernighan's objections to Pascal included in his famous memo "Why Pascal Is Not My Favorite Programming Language."{8}

New in the MPW 2.0 Pascal compiler was the facility to generate 68020 and 68881 code. Support for large arrays was also added by dynamically allocating them on the heap. These additions combine to make MPW Pascal a good choice for general scientific and numeric programming, as MPW Pascal fully supports SANE (Standard Apple Numerics Environment). MPW Pascal comes with its own language reference manual detailing all aspects of this extended language.{9}

MPW Linker Tools

MPW has been designed from the onset to provide a multilingual environment. It is possible to link the object code files that result from applications written in the three standard languages--assembly language, C, and Pascal. The MPW system itself is built using all three of these languages. Other languages are now becoming available for MPW, and their object code can also be linked in.{10}

The Link tool can automatically strip unused code but at a cost: Linking HyperCard on a Mac II, for example, takes about 42 seconds; the MPW shell takes 35 seconds.{11} One reason why the linker is so slow is simply that a large number of symbols are being pushed through it. Nevertheless, because MPW provides interlanguage linking support, solutions to performance problems in an application can be solved with Bill Atkinson's success formula: 95 percent Pascal and 5 percent assembly language.{12}

MPW Resource Tools

rez is a language that is similar in its syntax to C but is especially crafted for describing Macintosh resources, such as ALRTs, DLOGs, DITLs, and MENUs. These and many other resources can be described textually in the rez language. User-defined types are easily constructed and aid in making programs easily localizable to foreign languages. As an aid to using rez, MPW provides a companion resource decompiler called derez that can derive source from existing resources.

Other than the MPW shell itself, resedit--a familiar utility program to most Mac programmers, not to mention many power users--is the only other application in MPW. resedit is an interactive tool for creating, modifying, deleting, and moving resources. It was originally written by Steve Capps, who incidentally wrote many versions of the Finder. Rony Sebok wrote the template editor, and Gene Pope wrote most of the other pickers and editors. Using MPW Pascal, you can write custom editors and add them to the many editors already present in resedit. Sample code to extend resedit is included with MPW Pascal.

A common way to work with resources is to create resources with resedit, use derez to decompile them, and then maintain and tweak the rez sources.

Two other resource tools are also provided with MPW. resequal is a comparison tool, similar to diff in Unix. resequal, however, compares resources rather than text, showing all differences between two files. rezdet is a resource detective that verifies a resource fork and can also list the contents of a resource fork in several different formats.

Object-Oriented Programming

The MPW assembler with its object macros and the MPW Pascal compiler both support object-oriented programming. To a first approximation, the following equation defines object-orientedness:{13}

object-oriented = objects + classes + inheritance

Objects are the atomic entities of object-oriented programming. Objects consist of a data structure and its related methods (procedures) that can manipulate objects. Objects are specific instances of a class. Classes are arranged hierarchically, with descendant objects referred to as subclasses and ancestor objects referred to as superclasses. Objects of a subclass inherit properties from their ancestor objects. Objects can send, receive, and respond to messages sent by other objects.{14}

Data abstraction is an orthogonal language attribute from object-orientedness. An abstract data type as supported in Ada or C++ is a data structure and a set of associated operations that are the only way to access the private data structure. An object-oriented language such as Object Pascal, however, can access or modify any field of an object directly, as if the object were a record. C++ supports object-oriented programming by allowing members of an object to be public or private. Ada does not support inheritance, which means that Ada is not an object-oriented language.

MacApp

MacApp (Macintosh Application) is another part of MPW that originally developed out of the Lisa program from a project called the Lisa Toolkit. The Lisa Toolkit was developed by Larry Tesler, Larry Rosenstein, and Pete Young and was written using Clascal. MacApp was a completely new system designed by Larry Rosenstein, Larry Tesler, Scott Wallace, and Ken Doyle and implemented by Larry Rosenstein and Scott Wallace. Early versions ran in the Lisa Workshop, but the official 1.0 release and all subsequent releases have been for MPW.

MacApp is a separately sold product built upon Object Pascal, so use of MacApp requires MPW and MPW Pascal. Essentially, it is a huge library of routines consisting of some 29,000+ lines of Object Pascal and 1,600+ lines of object assembly language.

MacApp fully implements the standard Macintosh user interface in a generic Macintosh application that the programmer builds upon, thus greatly reducing the amount of code that needs to be written without reducing the ensuing quality. A programmer would, for example, need only to write routines to draw items in windows or to write files to the disk. The MacApp libraries support desk accessories, menus, multiple documents, error handling, the Clipboard, and printing as well as scrolling, moving, resizing, and zooming windows.

With the help of MacApp, you can build significant Macintosh applications in a few weeks rather than in several months. What is even more important is that they comply with the recommended guidelines for developing applications and therefore are more robust to changes in system software. Users also benefit from applications that are consistent with the Mac interface and hence are easy to use.

MacApp includes the full source code for the MacApp libraries as well as many sample programs illustrating object-oriented Macintosh programming. Also included is a cookbook of tips and routines useful in the creation of Macintosh applications.

A Sample MPW Shell Script

The sample script in Example 1, this page, canonizes the text files that ship with MPW to have the same font, font size, tab settings, and window size. It is an example of a script that automates an otherwise laborious process.

Example 1: A sample script to canonize text files

  # StdMPW Canonizes all MPW Textfiles
  # By Dan Allen 7/13/87 set today "'date -s -d' 12:00pm"
  directory "{mpw}"
  for i in : 'files -d'
     directory "{i}"
       for j in 'files -t TEXT'
               setfile -a 1 "{j}"
               target "{j}"
                         font Monaco 9 ; tab 4 ; find
                         movewindow 36 22 ; sizewindow 473 280
                         close

       end
       if "{i}" != ":"
               directory ::
       end
  end

The pound sign (#) serves as a comment token, with comments being valid until the next carriage return. The first line of the script creates and sets a local shell variable named today to hold the current date and time. Command substitution takes place by use of backquotes: the output of the date command is substituted for what is between the backquotes. Double quotes group the two resultant strings.

The second line of the script changes directory into the standard MPW directory, looking up that location in a shell variable of the same name. Braces are used for referring to the contents of shell variables and usually require quoting if the variable contains spaces or other special characters.

The third line of the script begins a for loop. for loops iterate through a provided list of items--in this case a list of directories found in the main MPW folder. This list is also dynamically generated by using backquotes and command substitution. The colon denotes the current directory.

The body of the loop changes directory into a folder and then uses another backquoted expression, this time to list the files of type TEXT that exist within the directory. If the file has been locked, it is unlocked using the setfile command and then opened as the target next-to-top window with the target command. The target window denotes not the topmost window but the next-to-topmost window. If commands do not specify a window, then the target window is the automatic default receiver of commands.

After the window has been opened as the target window, the font and tab commands are used to change these settings. Multiple commands are placed on the same line by using the semicolon as a separator. The find command then uses the bullet selection expression to specify placing the cursor at the start of the file. The movewindow command places the upper-left corner of the window at the coordinates (36,22) (pixels are measured from the bottom-left corner of the menu bar). The sizewindow command changes the windows size to 473 pixels wide by 280 pixels high. The window is then closed, with these settings automatically being saved. (If the contents of the file had been changed, then you would have been prompted with a dialog. It is possible to override the dialog by using an option to the close command, but the changes in this example are only of a cosmetic nature and are thus always saved to the resource fork of the file.)

The end of the script illustrates the conditional if statement and the shell's use of C-like expressions. If the current directory is not at the main MPW level, the colon-colon argument to the directory command simply pops back up a level in the HFS hierarchy.

Benchmarks

I tested MPW with a suite of five benchmarks--Sieve, Dhrystone, Sqrt, Hilbert, and Trig. The hardware platform was a Macintosh II (with its standard 16-MHz 68020 and 16-MHz 68881) with 5-Mbyte RAM and an Apple HD-80SC internal hard disk. MPW 2.0 ran in a 1,024K partition under MultiFinder 1.0.

Unless otherwise specified, MPW C used only the -g option to generate MacsBug symbols. MPW Pascal defaults to generating MacsBug symbols. I also used the -r option to suppress range checking. The hardware floating-point versions of the benchmarks for both MPW C and MPW Pascal also used the -mc68020, -mc68881, -elems881, and -x149 options for the greatest possible speed.

The build time was measured by bracketing the build using the built-in date command; its display precision is good only to a second. The actual execution time was timed using calls to the TickCount routine built into the Macintosh Toolbox. This function is good to 1/60th of a second. Object code size was determined in separate compilations of the code using the -p (progress) option found in the compilers. And finally, the executable code size was determined by the files command.

To test integer math, I used the ubiquitous Sieve benchmark (see Listing One, page 27) of Byte magazine fame. It generates the first 1,899 prime numbers by a method attributed to Eratosthenes. Table 4, below, gives the results.

Table 4: Sieve benchmark results

  Parameter                   MPW C        MPW Pascal
  ---------------------------------------------------

  Build time (sec)            00,009       00,010
  Time for 100 iter. (sec)    00,006.37    00,011.97
  Object code size (bytes)    00,244       00,406
  Exec. code size (bytes)     14,343       13,191

Version 1.1 of the Dhrystone benchmark represents the mix of instructions that the average C program contains. It is therefore 53 percent assignments, 32 percent control statements, and 15 percent procedure calls. This Usenet favorite (see Listing Two, page 27) has been run on almost every machine made. All the results are displayed in the traditional Dhrystones-per-second notation, but the tests were done with 50,000 iterations of the code. Table 5, below, gives the results.

Table 5: Dhrystone benchmark results

  Software SANE               MPW C        MPW Pascal
  ---------------------------------------------------

  Build time (sec)            00,015       00,011
  Dhrystones/sec              02,173       02,777
  Object code size (bytes)    01,440       01,832
  Exec. code size (bytes)     16,385       15,541

  Direct to 68881             MPW C        MPW Pascal
  ---------------------------------------------------

  Build time (sec)            00,016       00,011
  Dhrystones/sec              02,500       02,941
  Object code size (bytes)    01,420       01,832
  Exec. code size (bytes)     16,579       15,405

The Sqrt benchmark (see Listing Three, page 32) is similar to the Sieve for floating point: It is one loop that adds the square roots of the first 100,000 integers. Table 6, below, gives the results.

Table 6: Sqrt benchmark results

  Software SANE               MPW C        MPW Pascal
  ---------------------------------------------------

  Build time (sec)            00,010       00,009
  Execution time (sec)        00,043.65    00,040.18
  Object code size (bytes)    00,312       00,314
  Exec. code size (bytes)     14,461       2,815

  Direct to 68881             MPW C        MPW Pascal
  ---------------------------------------------------

  Build time (sec)            00,009       00,009
  Execution time (sec)        00,001.48    00,002.17
  Object code size (bytes)    00,164       00,290
  Exec. code size (bytes)     04,465       12,793

The Hilbert benchmark (see Listing Four, page 33) tests basic floating-point arithmetic, both in speed and accuracy. This benchmark, from Dr. Paul Finlayson of the Apple Numerics Group, generates a 10 x 10 Hilbert matrix whose determinant is on the order of 10-21. A related matrix equation is then solved by Gaussian elimination. The resulting solution vector has a result of all 1s if the arithmetic is exact. The total error is a measure of the vector's deviation from the exact value. Table 7, below, gives the results.

Table 7: Hilbert benchmark results

  Software SANE               MPW C        MPW Pascal
  ---------------------------------------------------

  Build time (sec)            00,014       00,011
  Time for 100 iter. (sec)    00,016.72    00,015.00
  Object code size (bytes)    01,760       01,670
  Exec. code size (bytes)     16,171       14,337
  Total error                 4.435 E-7    4.435 E-7

  Direct to 68881             MPW C        MPW Pascal
  ---------------------------------------------------

  Build time (sec)            00,013       00,010
  Time for 100 iter. (sec)    00,001.68    00,001.75
  Object code size (bytes)    01,192       01,392
  Exec. code size (bytes)     15,643       14,061
  Total error                 4.435 E-7    4.435 E-7

The Trig benchmark (see Listing Five, page 34) is another useful benchmark by Dr. Finlayson that tests the speed and accuracy of an implementation's trigonometric functions by calculating the Pythagorean identity every 0.01 radians from zero to three. The inner loop should therefore be executed 300 times. Note that in this case the trig error for the direct calls is an order of magnitude worse than for the software calls.{15} Table 8, below, gives the results.

Table 8: Trig benchmark results

  Software SANE               MPW C        MPW Pascal
  ---------------------------------------------------

  Build time (sec)            00,010       00,010
  Time for 100 iter. (sec)    00,180.28    00,173.57
  Object code size (bytes)    00,512       00,636
  Exec. code size (bytes)     14,821       13,179
  Trig error                  4.662 E18    4.662 E-18

  Direct to 68881             MPW C        MPW Pascal
  ---------------------------------------------------

  Build time (sec)            00,009       00,008
  Time for 100 iter. (sec)    00,003.27    00,003.70
  Object code size (bytes)    00,266       00,516
  Exec. code size (bytes)     14,683       13,019
  Trig error                  4.597 E17    4.597 E17

Documentation

Several levels of help are provided with MPW. An on-line Help command gives concise summaries of commands and their options, expression syntax and precedence, selections, and keyboard shortcuts. Any user of MPW can modify and extend the help system to include additional information.

An MPW tool called Commando is a second level of help, oriented toward building command lines. Commando (written by Tom Taylor in his spare time!) provides a Mac-like dialog interface to tools and was new with MPW 2.0. Any MPW tool can be made Commando compatible by adding a single cmdo resource to its resource fork. Typing a command name followed by the ellipsis character invokes a dialog that offers radio buttons, pop-up menus, check boxes, text fields, and on-line explanations of each option for that tool. The resulting command line is displayed dynamically in the dialog box and can then be copied or immediately executed. Commando is a great way to explore new options and to learn about tools. Every command in the MPW system has been Commando-ized for the 2.0 release, even the built-ins. Commando saves frequent forays into the manual pages.

A third level of help comes through MPW shell scripts that automate and guide you through building an application, desk accessory, or tool. These powerful scripts are collectively called build scripts. The build scripts install two additional menus in the menu bar, which allow you to change directories quickly and to generate and run make files automatically. These scripts were written by Rick Meyers to help beginning users with the otherwise potentially overwhelming system, but they are also useful to anyone who needs to crank out a tool quickly. Each language (Asm, C, or Pascal) includes three programs to build and play with using the build scripts: a sample Mac application, a sample desk accessory, and a sample integrated tool.

The main MPW reference manual fully describes the shell and its commands. It has two parts: the shell tutorial and the manual pages for the commands and tools.

Notes

    1. Note that the C and Pascal products are sold separately; Pascal includes the Pascal-specific tools. The items listed in Table 3 are MPW tools except for ResEdit, which is a stand-alone Mac application, and MacsBug, which is a debugger. This list is for MPW 2.0. In addition to this list are a few conversion tools useful to those bringing forward sources from the Lisa Workshop and MDS.

    2. Macintosh Programmer's Workshop Assembler Reference (Renton, Wash.: APDA, 1987).

More Details.

    3. This benchmark is derived from assembling the 68xxx disassembler in MacsBug, in which 8,033 lines of assembly-language code are assembled on a Mac II in 11.4 seconds, or at a rate of 42,279 lines per minute. A Mac Plus would be about one quarter as fast.

    4. Samuel P. Harbison and Guy L. Steele, Jr., C: A Reference Manual (Englewood Cliffs, N.J.: Prentice-Hall, 1987).

    5. AT&T Bell Labs and M. I. Bolsky, The C Programmer's Handbook (Englewood Cliffs, N.J.: Prentice-Hall, 1985).

    6. Macintosh Programmer's Workshop C Reference (Renton, Wash.: APDA, 1987).

    7. Units originated with UCSD Pascal. Other versions of Pascal for the Macintosh have since been enhanced with the addition of Units, including Turbo Pascal from Borland and LightSpeed Pascal from Think Technologies. Turbo Pascal 5.0 for the IBM PC now also has Units.

    8. Brian W. Kernighan, "Why Pascal Is Not My Favorite Programming Language," Bell Laboratories internal memo #81-11272-12 (April 2, 1981).

    9. Macintosh Programmer's Workshop Pascal Reference (Renton, Wash.:APDA, 1987).

    10. At least two versions of Modula-2 are currently available and at least two versions of FORTRAN are under development. There is a growing market for further languages and tools to be developed and marketed for MPW.

    11. Benchmarks performed on a Mac II with an Apple HD-80SC drive and MPW running in 1 Mbyte under MultiFinder.

    12. Bill Atkinson's HyperCard and MacPaint programs are about 95 percent Pascal object code and 5 percent assembly-language object code.

    13. This equation is from Peter Wegner's paper entitled "Dimensions of Object-Based Language Design," given at OOPSLA '87.

    14. For more information about data abstraction and object-oriented programming from a language-design point of view, see Programming Language Concepts, by Carlo Ghezzi and Mehdi Jazayeri (New York: Wiley, 1987).

    15. Most of the Motorola 68881 functions return identical results as the software versions, but the elementary functions are an exception. Motorola traded accuracy for speed. The -elems881 compiler switch allows users to decide which set of routines are called: the hardware or the software routines.

Availability

MPW and MacApp are available through the Apple Programmer's and Developer's Association (APDA). For more information contact: Apple Programmer's and Developer's Association (APDA) 290 S.W. 43rd St., Renton, WA 98055; 206-251-6548.

All software includes documentation and is shipped on 800K HFS disks. MPW 2.0.2 (five disks, 940-page manual) costs $200, MPW C 2.0.2 (one disk, 368-page manual) costs $150, MPW Pascal 2.0.2 (one disk, 402-page manual) costs $150, and MacApp 1.1.1 (two disks, 470-page manual) costs $100.

MPW 1.0 supported development on any Macintosh with 1-Mbyte RAM and at least 1.6 Mbytes of disk space and was shipped on 400K floppies. MPW 2.0 ships on 800K floppies and requires 128K ROM (or more) and a hard disk. MPW 2.0 does not support the Mac XL, but MPW 1.0 is still available through APDA for those with Mac XLs.

MPW Background, History, and Credits

Development on MPW began late in 1984, when Apple engineer Rick Meyers was assigned to bring about a development environment, to suit Apple's internal requirements.

The original team consisted of three people. Rick Meyers, Jeff Parrish, and Dan Smith. The project was originally known as MPS, for Macintosh Programming System (not Meyers, Parrish, and Smith). All three had worked on major Lisa software projects. Rick worked on C and Smalltalk, Jeff worked on MacWorks, and Dan wrote the Lisa Finder. Together these three engineers began work on the core application of MPW, the MPW shell. They began their effort by porting the MDS Edit program, which had been written for Apple in C by Bill Duvall of Censulair Corp. Much of the early work on the MPW shell was done in C on three Apollo workstations. As the Lisa Workshop's Green Hills C compiler was parted to run under MPW, so the development of the MPW shell moved to Macintosh.

As the design of the MPW shell progressed, a need for two different applications became apparent: a Unix-like command shell and a Mac-like mouse-based editor. Further, it became clear that these two applications needed to be tightly coupled. The solution was a combination shell/editor. Dan Smith wrote the shell and Jeff Parrish wrote the editor. Project leader Rick Meyers worked on the command interpreter.

By early 1985, others had joined the effort, most of them also key contributors to the previous Lisa Workshop. Ira Ruben wrote a completely new 68xxx assembler from scratch as well as many of the other tools for MPW. Fred Forsman wrote two major utilities: Make and Print. Ken Friedenbach brought the Lisa Linker forward, with major enhancements. Jim Thomas (head of the Development Systems group) and Clayton Lewis (of the Numerics group) made sure that the Standard Apple Numerics Environment (SANE) was implemented properly across all the languages. (For more information on SANE, set the Apple Numerics Manual, Addison-Wesley, 1986. The second edition, due this year, covers the 68881 details of SANE.)

Johan Standberg designed the rez line of resource tools, and Tom Taylor finished them. Gene Pope worked on resedit. Neal Johnson supervised the equates files and Steve Hartwell (formerly of Bell Labs) ported the standard C libraries. Mike Shannon took over dealing with the Green Hills C compiler from Rick Meyers, and Al Hoffman, Key Doyle, and Roger Lawrence brought Lisa Pascal forward. Russ Daniels began work on a symbolic debugger. When that became too ambitious for the schedule, Dan Allen joined the team and rewrote MacsBug, the Macintosh assembly level debugger. Russ contributed greatly as Chief Heap Dump Analyzer for the group.

Chris Brown and at least 13 other people worked on testing the system, as did many beta testers. Paul Zemlin was the product manager, Harry Yee built the system for Apple's Software Configuration Management (SCM) group, and Lisa Parr kept the whole group coordinated and running smoothly.

It took a year and a half to create MPW 1.0, which began distribution through the Apple Programmer's and Developer's Association (APDA) in September 1986. The team then grew substantially and released MPW 2.0 through APDA, in July 1987. Work on MPW 3.0 is currently underway with an even bigger team.--D.A.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.