The History of Mac Office, Part I

We've all seen the scene. A group of people are having a discussion about something, and one older, and allegedly wiser, person has been sitting back just letting the discussion ramble on, until they meet some sort of impasse, at which point everyone turns to this older, and allegedly wiser, person for the answer to some obscure question. A pregnant pause ensues while this older, and allegedly wiser, person ponders the situation. The pondering thought is, more often than not, something along the lines of, "How the hell did I get myself into this?"

Well, in a sort-of, kind-of, almost way, we've enacted this little scene out in the bloggosphere. Erik Schwiebert wrote about some past changes to the tool sets we've used to build various versions of Office, and closes his post with:

I don’t know what tools were used on versions of Mac Office prior to Office 98 (Rick Schaut would know about Word 5.1 and Word 6). MPW? Maybe, but that would have been a really long time ago! [Emphasis not added.]

Thanks, Schwieb! You've given me another item I can add to my "You know you're getting old when..." list.

Enough self-flagellation. Someone with the nom de plume of "odysseus" left this crumb at the end of Schwieb's post:

You haven’t mentioned anything about the fact that Mac Office versions all the way through Office 2001 were written in a mid-level interpreted language called “pcode.” Was that a consequence of using MSVC4?

Earlier versions of Microsoft's applications were compiled to a mid-level interpreted language. They weren't written in that language. They were still written in C with some hand-coded assembly where speed was crucial.

The term "P-Code" is based on the UCSD P-System, where the "P" stands for "Pseudo". In many ways, it was a precursor to the Java run-time and the .NET CLR. Code was compiled to run on a pseudo-machine, and you implemented this pseudo, or virtual, machine on the various systems where you wanted to run your code. We were supposed to get easy portability that way, but that was back in the time when operating systems basically gave applications a way to talk to the file system and nothing else. Since then, massive API differences have accrued to each of the various systems such that the CPU is no longer the primary issue when porting code from one system to another.

At this point, I'm going to have to digress a bit for the non-programmers who are reading this. The most important tool in a programmer's toolset isn't the compiler. It's not even the editor, despite the constant religious battles between proponents of the various editors in existence. Rather, the most important tool in a programmer's tool set is the debugger. That tool is the one that allows us to monitor the execution of the code we write. It's how we find where the code is wrong so we can fix it.

Now, there are different kinds of debuggers, but we can generally break them down into two categories: source-level and low-level. A low-level debugger only shows you the machine code that your compiler generated. A source-level debugger shows you the source code you wrote for the code that's currently being run by the computer.

The rest of the tale isn't quite so much about compilers. It's about debuggers. One of those debuggers will be familiar to old Mac hats: MacsBug. It was a low-level debugger. The other debuggers are more closely tied to the compilers we used. So, back to our tale.

Before we started using MSVC, we were using another internal compiler that ran on DOS (we're talking before Windows here). Folks who were around before 1990 also remember that it was very difficult to get a PC to talk to a Mac, so we used to have to connect our PCs to our Macs using SCSI cables. The P-Code debugger, which was a source-level debugger, ran on DOS, and talked to the Mac over the SCSI cable.

This had some unfortunate consequences. For example, you couldn't use the P-Code debugger and MacsBug at the same time. The P-Code debugger used a polling mechanism to determine if the P-Code interpreter was still running on the target Mac. Imagine a phone conversation. When you dropped into MacsBug, it was like the P-Code interpreter had lost the signal on the cell phone. The P-Code debugger would hang on for a short while waiting for the signal to come back, but it wouldn't take very long before the P-Code debugger would hang up the phone.

If you're starting to see visions of bear skins and stone knives, then your understanding of the situation isn't very far off the mark. But, it gets worse. For Mac Word 5.x, we implemented some of the features as plug-in code resources. These features included all of the proofing tools and the drawing tool in Word 5.x (known then as "Subdraw"). We built these plug-ins using Think C.

Think C had its own debugger, but that debugger didn't have a clue about P-Code. So, now we're using two different compilers, and three different debuggers. And, one of those debuggers is completely useless. Yuk! Throw loadable code resources into the mix, and you have an absolute mess.

One of the features of a debugger is the ability to set a breakpoint. A breakpoint is a location in the code where the debugger will pause the program kind of like hitting the pause button on a VCR or a DVD player. Once your program is paused, you can then examine the program's execution in more detail.

But loadable code resources are a problem. One of the reasons for using a code resource is the fact that it doesn't always have to be in memory. On a Mac that has only half a MB of RAM, being able to kick some code out of memory is a very useful feature. This feature, however, makes debugging a plug-in exceedingly difficult. You can't set a breakpoint in a code resource until it's loaded into memory.

So, let's summarize the situation. We have pieces of code built by two different compilers, neither of which understand the other. The debugger with Think C is completely useless, because it hasn't a clue about the main program that's running, which means the only way we could debug, say, the grammar checker was using MacsBug. But, every time we dropped into MacsBug, the P-Code debugger would whig out.

Those of you who've seen me in person now know that the thinning hair on the top of my head is not entirely due to male pattern baldness. By comparison, MSVC was heaven.

One last little tidbit: Back when we were using MSVC, someone had written two little programs, called victory.exe and defeat.exe. Each of them played two octaves of the C-Major scale through the PC's speaker. Victory.exe played the notes in ascending order, and defeat.exe played the notes in descending order. When your builds succeeded, the build system would run victory.exe, and when your builds failed, it would run defeat.exe. The cool part about that is you didn't have to keep watching your computer to see if the build had finished.

When we moved from MSVC to CodeWarrior, we lost this ability to play some custom sound. But, XCode has this feature. If you have XCode installed, type "defaults read | egrep Sound" in your terminal window to see if these are set. This sent me down a rather amusing path.

Because we're porting quite a bit of code from Win Office so we can support the new file formats, we have our own Win Office build machine set up in our lab (where we connect to the machine using Remote Desktop Connection). And, feeling a bit nostalgic, I decided to rummage around in their build system to see if they still had those sounds. Well, they have a couple of .wav files, but they're not the same sounds. In particular, the sound for a build failure is about a 15 second montage of Homer Simpson uttering his famous "Doh!" with various inflections.

I played this, and laughed a bit. Then it occurred to me that, as I had been setting this Win Office build machine up, the first couple of times I tried to build Win Office, the builds failed. I hadn't gotten the setup quite right yet.

I wonder if anyone was in the lab when one of those builds failed...



Currently playing in iTunes: Life Before Insanity by Gov't Mule

Comments (13)
  1. Odysseus says:

    Ric, how do you *port* code from WinOffice to MacOffice? Is it done by hand?

  2. Rick Schaut says:


    We use source control and file merging tools to merge changes from the Win Office code base into the Mac Office code base, but the process is not at all automatic.  It’s been nearly eight years since our code bases have diverged, and we certainly don’t want all of the changes that they’ve made to their code.  That requires a selective merge, quite a bit of hand-holding, and spending a lot of time resolving compile and link errors that arise as a result of the merge.

    I might, some day, write up a more lengthy post on the subject, but porting code is rather involved.  You have API differences, compiler differences, overall build system differences, and a host of other differences with which you have to contend as you move code from one code base to another.


  3. pUnk says:

    MacsBug rocked.;)

    Ah progress, you know you can’t play sounds any more with VS2005?

  4. Rosyna says:

    FWIW, the preferences to set in Xcode can be found via Help->Show Expert Preferences. And they are..


    Path to a sound file to play when a build fails. There is no default setting.


    Path to a sound file to play when a build succeeds. There is no default setting.

  5. Gabe says:

    I once had a chance to speak with Doug Klunder (one of the original authors of Excel), and my recollections with regards to p-code are a bit different.

    The first Macs had only 128k RAM and nothing but 400k floppies for storage. All 68k machine code was stored in CODE resources that were limited to 32k. Fitting a whole program into 128k was impossible, so CODE resources you didn’t need could be discarded and new ones could be loaded from floppy — which would be really slow.

    The combination of 32k CODE limit and the need to avoid hitting the slow floppy meant that it was extremely important that code size be reduced. This was done with p-code. While being slower to execute than native code, it was smaller, thus faster to load.

    Anything that had to be fast was compiled to native machine code, while everything else was a candidate for p-code. That was the only way to fit Excel into the original Mac, though the reasons to use it in later versions may have varied.

    I recall that Microsoft’s DOS compiler had a p-code option, so I don’t know if it was a common thing at the time, or if MS created it for Excel, or if it predates both.

  6. Rick Schaut says:


    Machine limitations and disk speed trade-offs are why we continued to use p-code, but it wasn’t the initial impetus behind p-code.  The original impetus, however, was to provide some platform independence.

Comments are closed.

Skip to main content