Oh well, Zortech didn't return calls, either. When it first came out,
they sent me an offer to get it at a reduced price. I called with some
technical questions, and they promised to FAX me the answers or call
back, and they never did.
Maybe Symantec wants to support Zortech customers in the manner in which
they are accustomed? :-)
More detailed summary:
Zortech does not have (or is not willing to admit the results of) any
comparative benchmarks between MPW C++ and ZC++.
Slower than MPW C++ with load/dump
ZC++ does not work with MacApp 3.0, nor does in come with any class
library (e.g. TCL).
ZC++ is a partial implimentation of C++ 2.1. Some stuff in not implimented
(iostreams, for example). C++ 3.0 features such as templates & exceptions
are not implimented either.
ZC++ does not come with a debugger. SADE is the recommended debugger.
One person commented that ZC++ does not produce .SYM files, so that
would rule out using SourceBug (I thought that it would also kill
SADE as well! -- Maybe he was mistaken)
ZC++ does not include HandleObject support.
ZC++ Documentation is weak. Especially w.r.t Mac Interface.
ZC++ has trouble with non-sample applications (e.g. non-trivial code).
Symantec's tech support ain't all that up on the Mac version of the
compiler; one tech support group from all platforms. They also don't
And the final, most damning statement:
"I'm not convinced that it can be used for ANY machintosh native
Thanks to all who contributed.
Cory Kempf EnigamI, Inc.
Kempf is, unfortunately, all too right about the previous release.
It's really sad. I originally purchased Zortech C++ for the Mac
because I was pleased with their MS-DOS product and needed a compatible
compiler on the Mac. I was very disappointed. I had months of anguish,
submitted about five bug reports, and finally bought MPW C/C++.
The product had such promise. The global optimizer really does
the hard optimizations right. It's just the 680x0 code generator that's
broken. The MS-DOS product never could optimize as much as one would
like because the Intel CPUs just don't have enough registers. But on
the 68000, much more serious optimizing is possible. In theory, this
should be a really great compiler. It just needed serious testing
before shipment, which it didn't get.
Not only that, but since it's a hard compiler, rather than a
front end for C, an efficient implementation of exceptions is possible.
With some work, Symantec could leapfrog MPW and bring C++ up to the
level documented in Strostrup's latest definition of the language.
C++ with exceptions, and classes that use them properly to protect
themselves, could provide a much more reliable support structure for
Mac programs. This might provide a path out of the general flakeyness
of Mac programs.
But I'm not holding my breath.
> With some work, Symantec could leapfrog MPW and bring C++ up to the
> level documented in Strostrup's latest definition of the language.
> C++ with exceptions, and classes that use them properly to protect
> themselves, could provide a much more reliable support structure for
> Mac programs. This might provide a path out of the general flakeyness
> of Mac programs.
Much to my pleasant surprise, I discovered that it is not that
difficult to implement your own try/catch-like exception scheme for MPW
Just have every "try" initialize an "exception scope" when at the
beginning of the block, and clean it up at the end. Every catch also
cleans up the "scope", too.
Derive all of your objects (or all of your non-Handle-based objects, or
whatever subset of your objects you want this to work for) off of a
root class. This root class has code in it's constructor to interact
with your exception code that, specifically, instantiates a linked list
element that associates your new object with the current exception
scope. The destructor does the reverse, of course.
When you reach the end of a "try" block (success!) any items left on
the current scope's list get appended on to the list of the next scope
up, if any. Of course, if all the objects that were using this scheme
were stack based, then there won't be any items in the list when you
reach the end of the try block - all the stack based objects in that
block (and any called by it) already automagically had their
destructors called, and hence removed themselves from the list.
The case for the "catch" is pretty much the same (remaining objects
about to outlive their scope are handed off to the parent scope), but
some important work has occurred before the "catch" is ever reached.
When an error occurs, and a "throw" is called, the throw code walks the
list associated with the current exception scope and destroys all the
associated objects. (Note that this must happen before the longjmp
back to the "catch", otherwise any stackbased objects become invalid
and cannot safely be destroyed.)
That's all there is to it, as far as the basics go. There are some
things to note:
* The basic try/throw mechanism is based on setjmp/longjmp, which are
described in K&R C and also the MPW C documentation.
* I made no attempt to imitate the "typing" of catch statements
described in C++PL, 2nd edition. I didn't need this, and I don't think
it can be cleanly done without the compiler's support & TLC.
* Yes, this will exact a performance penalty. If you want to use
20,000 stack based objects in a try-scope, you'll eat up space and
time. My use of objects is not so extreme as to cause any noticeable
* I wanted to get let the programmer have some control, on an object by
object basis, how it interacted with the exception code; and I wanted
different types of objects to have different types of default behavior.
Stack based objects go onto the current scope by default, heap based
objects do not play the game by default. This means that the root
class constructor has to figure out if an object is on the stack. The
following macros have worked for me (and *please* let me know if they
* The code that deletes all the objects on a scope list during a
"throw" has to figure out whether it stack or heap based no matter
what, of course, so that it can properly delete it. If it's heap based
you "delete object;", but if it's stack based, you
"object->RootObject::~RootObject();". At least that's what you do with
MPW C++ 3.x. I've examined the intermediate code and verified that
these two methods of deletion generate exactly the same code, except
for a flag argument that tells the destructor whether or not to do a
"free" on the object's 'this' pointer. Note that the
"object->RootObject::~RootObject();" call still exercises virtual
destructors. This was not obvious to me at first, especially since the
same syntax with any member function other than a destructor will not
result in virtual member functions of child classes being honored.
Fortunately the destructor syntax works differently. (The syntax you
might think was most natural, "object->~RootObject();", is just plain
illegal for reasons I don't understand.)
* Use different keywords than "try" and "catch" - MPW C++ treats these
as key words reserved for future use. I used "ATTEMPT" and "RECOVER".
(I know, no imagination. I should have used "SOYBEAN" and "POWERTOOL",
or maybe "QUAYLE" and "BARBARA".)
* The best part about all of this is that you then control the
exception handling functionality. You can't easily add support for,
say, error alerts (or notifications if you are in the background at the
time) to the try/throw/catch mechanism that will eventually be supplied
with MPW C++ version 17.0, but you can throw the whole kitchen sink
into your own exception code, if you so desire.
I want to encourage people to try this sort of thing if they are
hurting (like I was) for a throw mechanism that cleans up orphaned
objects. It really didn't turn out to be as big a job as I thought.
You write a little code, you change all your favorite base class
declarations to hang off of RootObject, and your off!
These macros will work for all current & normal Mac environments, and
they will also work with the Threads package published in Develop #6.
One might imagine that some future threads package might place stacks
inside of your heap, in which case it would not be so easy to determine
if an object is heap based or stack based.
With luck, though, we'll have language support for try/throw/catch before
then, and it won't be an issue.
Good article, by the way.
===================== =========================== =====================
Greg Anderson Apple Computer, Inc. O Ponnuki O
Macintosh Bodhisattva Macintosh System Software O O is ideal O O
gre...@apple.com Finder Team O shape O
===================== =========================== =====================