#SAS 6 Problem?
11 messages in this thread
I recently had a problem with a program when changing from the
standard C library functions to the Amiga internal equivalents.
The function was fputc which in the standard C format is declared as:
int fputc(int c, FILE *fp)
however the Amiga equivalent is declared as:
int FPutC(FILE *fp, int c)
Unfortunately I didnt bother to check and used the standard format. This call
will actually work a couple of times before crashing the machine. It took me
days to find this bug simply because I assumed the function was okay. My
question is this. Surely the compiler should have noticed that the function
declaration and the function call were not compattible. I would expect an error
of the form: found int expected FILE *. Has anyone else had the same problem ?
Nev.
Sounds like you didn't include the correct prototypes for the function args to
be recognized…
Hi Nevil,
The compiler certainly would have complained, if it knew the
actual prototype. I suspect you're using an incorrect prototype
or not including the correct prototype.
Be careful NEVER to include <stdio.h> if you are going to be
using the AmigaDOS replacements. Those prototypes are designed
to work with the SAS/C supplied library, and may mislead the
compiler if used with the amiga.lib routines.
–Doug
I checked my includes and they were as follows: dos.h exec/types.h
exec/memory.h dos/dosextens.h proto/dos.h proto/exec.h string.h
and dos/rdargs.h would any of these have caused a problem ?
I also checked the linker options from the scopts window this had the
StdIO set on would this be the same as #include <stdio.h> ?
Nev
The prototype for FPutC (as found in "clib/dos_protos.h", which is
included by "proto/dos.h") is:
LONG FPutC(BPTR fh, unsigned long ch);
Now, according to "dos/dos.h", which is included by "libraries/dos.h",
which is included by "dos.h", we have:
typedef long BPTR;
So, the net effect is that FPutC takes two long values and can't
distinguish very well which is supposed to be your pointer and which
isn't.
Personally, I'm a little bit surprised that BPTR was defined as long
instead of VOID * (like APTR), but that's the way things are.
–>Steve Bennett
If you need more prototype protection, you could always write some wrapper
functions…
Could you explain wrapper functions please ?
Nev.
I mean make a new function called myFWrite(), for example, and declare it to
have the type of parameters you believe to be more correct – for example, if a
system function was defined to take a 'UBYTE *' and you wanted it to check
against 'char *' instead, one approach is to write a new function that takes
'char *' and inside calls the real system function. For example, if I knew I
was writing a lot of USHORTs with the Write() call, I might make a new
function:
LONG myWrite( BPTR file, USHORT *buffer, long length )
{
return Write( file, (APTR) buffer, length );
}
which would have a prototype that expects you to pass it only USHORT pointers
and not 'char *' or whatever. This gets you the type checking you want.
That looks a good idea. Thanks.
Nev.
Steve,
Actually, it would be better to typedef BPTR as follows:
typedef struct BPTR *BPTR;
The definition for struct BPTR would never be found, but that
wouldn't keep any code from working. Then if you misused it you'd
get a compiler warning like
x.c 7 Warning 88: argument type incorrect
Expecting "BPTR", found "long"
which would be much more helpful than "Expecting void *, found long",
in my opinion. I don't know why this technique isn't used more
often, I find it very useful.
–Doug
I see the problem. Many thanks.
Nev.