comp.sys.mac.programmer.codewarrior
FAQ
Written and maintained by Michael Hudson
HTML formatting by Matt Keith
Last updated 11/01/97 (a UK date)
NB This is only a draft version!
First a disclaimer:
Further/Parallel reading:
"I get an error message during linking that 'some_function' referenced from 'some_other_function' is undefined, but I've included every header I can think of. What can I do?"
Assuming it is a library, there is a feature provided by MW to help you find the right one. Quoting from the 'Find Library Notes':
"I've found I need to include the ANSI C library in my project, but when I look for the library I find loads of different ones. Which do I want?"
There is, however, hope to be had. The most convoluted name I could find was:
ANSI | this means (wow!) that it is an ANSI library. |
Fa | this is for use with the 'Far Method Tables' switch in the 68K Codegen panel. If this switch is on, you want a lib with Fa in its name. If it aint, you don't. |
N | his is for use with the 'MPW Newlines' switch in the C/C++ Language panel. If this switch is on, you want a lib with N in its name (The 'N' in ANSI doesn't count!). If it aint, you don't. |
4i | this is for use with the '4-byte ints' switch in the 68K Codegen panel. If this switch is on, you want a lib with 4i in its name. If it aint, you want one with 2i instead. |
F | this is for use with the '68020 Codegen' switch in the 68K Codegen panel. If this switch is on, you want a lib with F in its name. If it aint, you don't. |
8d | this is for use with the '8-byte doubles' switch in the 68K Codegen panel. If this switch is on, you want a lib with F in its name. If it aint, you don't. |
C | this means its the standard C library, rather than the C++ library. |
A4 | this is for use in a code resource, rather than an app. |
68K | this is for use in a 68K app, rather than PPC. |
Lib | Guess! |
I most commonly use the ANSI(2i)C.68K.Lib, and in fact have trashed nearly all the others to save disk space.
Many of these options only apply to 68K. There is also CFM68K to worry about, but I'll assume you know what you're doing with that.
Make sure you match library to preference options, or risk crashes. It's only 'risk crashes' because some libraries might not use doubles (for instance) and so whether they were compiled with the '8-byte doubles' switch on or not is irrelevant.
"When I step through my code in the debugger, some variables seem to change at random. What's going on?"
For an example, try this in a new CW project:
01> #include "stdio.h" 02> 03> void main(void) 04> { 05> int i,j,k; 06> 07> i = 8; 08> j = i + 10; 09> k = i - 5; 10> 11> printf("k is %d",k); 12> }Hit debug and step through the code, seeing what changes. (On PPC, make sure that optimization level 1 is ON).
As you step through, at line 5 all the values are junk. Notice that j & k are the same. When you get to line 8, both j AND k become 18. Then at line 9, both j & k become 3. This is a bit scary for the newcomer, but if you think about it, its safe because j is never referenced again.
If line 11 became:
11> printf("j is %d, k is %d",j,k);
If you don't want this to happen, line 5 could be rewritten:
05> volatile int i,j,k;
On PPC, optimization level 1 is register coloring. You might want to turn it off for debugging, but it will do scary things to the size and speed of your executable. For 68K it is always on.
"When I try to link my project I get these error messages:
Link Error : Error while saving resources.
Link Error : Error while creating new file.
Is it English? Is it even American? What does it mean?"
The read/write permission of only one access path to a file can allow writing
Saving spool file / Entry not in queue
What the problem usually is is that the name of the application you're trying to build (set in the '68K Project' or 'PPC Project' preferences panel) is the same as the name of the project.
A class one way of getting this problem is to fail to add a mu (option-m) to the project name when creating the project.
To get rid of the message either:
And no, it's not English.
NB The slightly less unhelpful messages
Link Error : Error while saving resources.
Saving spool file / Entry not in queue
"How do I concatenate two pascal strings in C/C++?"
Route one: use someone else's sweat. For example you can use the functions declared in PLStringFuncs.h (specifically PLstrcat). If you do C++ I recommend LString from PowerPlant, even if you don't normally use PP.
If you do use PLstrcat, make sure you add PLStringFuncs.glue.lib to your project. This can be found at 'MacOS Support:Libraries:MacOS 68K:MacOS Files:PLStringFuncs.glue.lib'.
Route two: Roll your own, something like:
StringPtr concat(StringPtr inLeft, ConstStringPtr inRight) { short charsToCopy = inRight[0]; if (charsToCopy + inLeft[0] > 255) { charsToCopy = 255 - inLeft[0]; } BlockMoveData(&inRight[1],&inLeft[inLeft[0]],charsToCopy); inLeft[0] += charsToCopy; return inLeft; }This assumes that inLeft points to a Str255.
"I'm new to the newsgroup. How do I know what's being discussed at the moment? What should I do if I need a question answering?"
Common discussion topics are what's coming in the next release of CodeWarrior, what people would like to see in the next release of CodeWarrior, when CodeWarrior will catch up with the C++ standard and various things about Java which I don't understand.
Occasionally stuff gets massively cross-posted saying things like "PCs rul, Macz suck," but decent people ignore them. This hasn't happened for a while.
To answer the second point, post it! Generally people are helpful and polite, but to make this more likely, think about the following:
Having said all that, don't be shy. This is a civilised and helpful newsgroup.
"When I try to debug a project, I hit MacsBug almost instantly. I have a 68K Mac. Help!?"
"How do I access the QuickDraw globals from my XCMD/MDEF/CDEF/code resource?"
"Metrowerks C++ gives me this warning:
Warning : 'derived::aFunc(int)' hides inherited virtual function 'base::aFunc()'
hmm.h line 7 };
What's it barking on about?"
Take this example (which was used to generate the above warning):
01> struct base { 02> virtual void aFunc() {} 03> }; 04> 05> struct derived : public base { 06> virtual void aFunc(int) {} 07> }; 08> 09> 10> void main(void) 11> { 12> base base_object; 13> derived derived_object; 14> 15> base_object.aFunc(); // OK so far I hope... 16> // This calls derived::aFunc() 17> derived_object.aFunc(1); // Still following? 18> // This calls derived::aFunc(int) 19> derived_object.aFunc(); // Error! 20> // "function call does not match prototype" 21> }This strikes most new C++ programmers as completely loopy (it certainly did me). The reason becomes apparent when you have a really big class heirachy and then you might end up calling the wrong function by mistake and not have any clue from the compiler.
To preserve aFunc(void) in derived, insert a line in its declaration like:
If you need this explained properly read Scott Meyers' Effective C++, a very good book.
It's dead handy that CodeWarrior produces this warning because nine times out of ten you actually wanted to override the function you're in fact hiding and you've made a typo.
"Is there any way to define macro symbols globally? I miss the -d switch from MPW."
In the C/C++ Language preference panel there is a text field for a prefix file. This file will be implicitly #included in every file in your project. If you haven't changed this field it will most likely read MacHeaders.h. This file just #includes the most appropriate precompiled version of the Universal Headers. What you want to do is create a file in the project folder (or wherever you keep project specific headers) and in this file type:
#includeNow go to the C/C++ Language preferences panel and type this file's name into the prefix field.#define a_very_interesting_symbol 1 ... #define whatever you need. this is also a good place for miscellaneous constants ...
You'll need to completely recompile your entire project whenever you change this file.
"I'm porting an application from 68K to PPC and have found that CountAppFiles, GetAppFiles,ClrAppFiles, and GetAppParms have vanished! Where've they gone?"
You can use a framework such as DropShell URL? to ease the burden of transition.
"I'm porting an application from 68K to PPC and get error messages like:
Error : Can't convert unsigned char (*)(struct WindowRecord *,
struct EventRecord *, short *) to struct RoutineDescriptor *
file.c line 87 ModalDialog(MyModalFilter, &itemHit);"
Some unecessary background:
The PowerMacintoshes are very different from all that has gone before (you knew this, right?), as they have a different sort of chip in. However due to some extremely clever programming at Apple, software compiled for old (68K) Macs still works.
Now consider calling a function such as ModalDialog. If Apple have gotten around to implementing this trap in native PowerPC code, but you call it from 68K code you will have passed it a function pointer that POINTS TO 68K CODE, but is being handled by native code. The converse is worth considering, ie if ModalDialog is still emulated, but native code calls it with a PowerPC function pointer. The problem is that the toolbox needs to be able to tell what sort of function the pointer points at. To this end, Apple devised the universal procedure pointer, or UPP.
A UPP actually points to a struct of type RoutineDescriptor. The first two bytes of a RoutineDescriptor contain the constant _MixedModeMagic. So the toolbox takes the function pointer, dereferences it and checks what it finds against _MixedModeMagic. The toolbox knows that if they match the function is PowerPC code and if they don't its good old 68K (_MixedModeMagic is not a valid 68K instruction so an old program will not unfortunately pass a function that looks like PowerPC code - although read on).
But what, I hear you ask, about that other scenario you mentioned, where native code calls an emulated ModalDialog with a PowerPC function pointer? Well, if a RoutineDescriptor gets executed the first instruction is _MixedModeMagic. It just so happens that _MixedModeMagic is an A-trap, so the mixed mode manager gets control from the trap dispatcher and handles the function call properly.
It's not all sweetness and light because switching from executing PPC to emulating 68K takes quite a while in processor terms (like a thousandth { is that right? } of a second or so) so if native code calls an emulated toolbox trap which calls a native callback function there will be four mode switches, a significant overhead. Of course the opposite is true, ie if 68K code calls a PowerPC native toolbox trap which calls a 68K native callback there will be the same overhead.
I have no idea if ModalDialog is implemented natively yet.
Enough of that. What you need to do is take your function pointer and make a UPP of it. There is a call NewRoutineDescriptor that does just this, but the mixed mode manager needs some more information if it is to do its job, so Apple provide macros to call it properly. In the case of ModalDialog it's NewModalFilterProc. You might be tempted to use it thus:
01> ModalDialog(NewModalFilterProc(MyModalFilter), &itemHit);
There are two strategies. If the UPP is likely to be called often, just create it once:
01> static ModalFilterUPP myModalFilterUPP = NewModalFilterProc(MyModalFilter); 02...n> ... 0n+1> ModalDialog(myModalFilterUPP, &itemHit);If the UPP is not going to be used often then it is probably best to create and destroy it as you need it.
01> ModalFilterUPP theModalFilterUPP = NewModalFilterProc(MyModalFilter); 02> 03> ModalDialog(theModalFilterUPP, &itemHit); 04> 05> DisposeRoutineDescriptor(theModalFilterUPP);A good thing: When compiling for 68K NewModalFilterProc (and relatives) and DisposeRoutineDescriptor are macros that disappear leaving you with code that is mighty similar to what you've always done, and no larger. They're called the Universal Headers for good reason.
"Can anyone send me their old copy of CW9 now that they've got CW10?"
"What's the difference between CW Academic Pro & CW Gold?"
CW Academic includes the frontends for C, C++, Pascal, Object Pascal and Java, and backends and debuggers for Win32/x86, Magic Cap, Be and MIPS, just like CW Gold. You still get 2 'free' updates. The only difference is you are not licensed to develop commercial software with the Academic version. Share and freeware are OK. Academic Pro is a fantastic deal for the beginner, but if you don't qualify Discover Programming For Macintosh is pretty cool, and Metrowerks will deduct its price from that of CW Gold should you decide to upgrade.
"What's this I hear about a major bug in the 68K CFM Enabler?"
This is because some of the glue involved trashes A5, thus making sure the interrupt code has no way of resetting it, which causes major strife for your computer and crashes. If your CFM68K code doesn't execute at interrupt time, don't worry. If it does, you have problems. I'd contact Apple Developer Technical Support for help. { Is there some technote which explains this properly? }
"I have a ............ with ... megs of RAM and ... megs of hard disk space. Will CodeWarrior run on my system?"
On the PowerMac, more memory is required {?} being a realistic minimum.
I this were my job, I'd want a PowerPC with as much RAM as I could gouge out of my employers (at least 20MB) and a gigabyte or so of hard disk. A 14 inch screen can get cramped very easily. The bigger the better.