If you set a breakpoint, you'll see thatwhy does it get past the > 0 conditional?
why doesn't it detect information in the buffer?
nbBytes is not zero.printf statement.%d is always for int but nbBytes must be a 32-bit long according to the documentation for SerGetBuf.printf might push different number of bytes for int and long. In this case, it may push 4 bytes but %d only looks at 2 bytes. Since 68K is big endian, the two bytes it will access are the two most significant bytes which are probably zero (unless you're expecting more than 64K bytes of data which is unlikely).%d might work for long in some other C compilers or architectures. Different headers for different build environments may define macros for printf format specifications. These are typically in a header named inttypes.h for C and cinttypes for C++. Does Think C have either of those files? Probably not since it was added for C99. Search for PRId32 in all the header files to find out. If it did, then you could do this:printf("\n%" PRId32 " bytes waiting", nbBytes);
nbBytes is 32-bits. The PRId32 macro will be defined correctly for your environment to indicate a 32-bit quantity. In modern macOS, it would be defined as d but for your Think C, it should be ld unless Think C has a 32-bit ints option like Metrowerks?[ @Mu0n ] THINK C 5 has <stdarg.h> for handling variable arguments. The example on page 268 of the User Manual (which I have a paper copy of):<snip> These are typically in a header namedinttypes.hfor C andcinttypesfor C++. Does Think C have either of those files? Probably not since it was added for C99.
#include <stdarg.h>
int minimum(int count, ...)
{
va_list xp; // Declare arg pointer.
int x,min;
va_start(xp, count); // init the pointer.
min=va_arg(xp,int); // Get the first arg.
while(--count) {
x=va_arg(xp,int); // Get the next arg.
if(x<min) min=x;
}
va_end(xp);
return (min)
}
THINK C doesn't haveSearch forPRId32in all the header files to find out. If it did, then you could do this:
since we know thatCode:printf("\n%" PRId32 " bytes waiting", nbBytes);nbBytesis 32-bits. ThePRId32macro will be defined correctly for your environment to indicate a 32-bit quantity. In modern macOS, it would be defined asdbut for your Think C
inttypes.h . However, format specifications are handled by the int vfprintf(FILE *fp, const char *fmt, va_list arg); function in the THINK C 5.0 Folder:C Libraries:sources folder.It does have a 32-bit int option. Edit:Options...:Compiler Settings:4-byte ints checkbox.it should beldunless Think C has a 32-bit ints option like Metrowerks?
case 'd':
case 'i':
if(F.lSize)
n=va_arg(arg,long);
else
n=va_arg(arg,int);
if(F.hSize)
n=(short)n;
// etc.
typedef char int8_t; // char is always signed in THINK C
typedef unsigned char uint8_t;
typedef short int16_t; // short is always 16-bits in THINK C
typedef unsigned short uint16_t;
typedef long int32_t; // long is always 32-bits in THINK C
typedef unsigned long uint32_t;
// long long isn't supported.
@Mu0n , @joevt . I did a bit more looking for how sprintf is handled. In <stdio.c> we have:<snip> format specifications are handled by theint vfprintf(FILE *fp, const char *fmt, va_list arg);function in theTHINK C 5.0 Folder:C Libraries:sourcesfolder.
int sprintf(char *s, const char *fmt, ...)
{
return(vsprintf(s, fmt, __va(fmt)));
}
int vsprintf(char *s, const char *fmt, void *p)
{
FILE f;
int n;
if((n=vfprintf(__strout(&f,s),fmt,p))>=0)
s[n]=0;
return(n);
}
The '*' modifier for the field width usually refers to the width of the text in characters, rather than the byte width of the parameter?THINK C supports the '*' modifier which takes the field width from the next va_arg argument and the 'h' modifier (but not 'hh') for enforcing short arguments (which are always 16-bits). This means you can ensure correct 32-bit and 16-bit processing by using %l or %h regardless of the int setting.
hh is for char, but single byte quantities in 68K are always two bytes on the stack so it's not necessary?%l and %h - you mean these: o An optional length modifier, that specifies the size of the argument.
The following length modifiers are valid for the d, i, n, o, u, x, or X
conversion:
Modifier d, i o, u, x, X n
hh signed char unsigned char signed char *
h short unsigned short short *
l (ell) long unsigned long long *
ll (ell ell) long long unsigned long long long long *
j intmax_t uintmax_t intmax_t *
t ptrdiff_t (see note) ptrdiff_t *
z (see note) size_t (see note)
q (deprecated) quad_t u_quad_t quad_t *
%ld will always refer to a long regardless of the size of long%hd will always refer to a short regardless of the size of short%d will always refer to a int regardless of the size of intprintf has the some compile options as the code you are calling printf from.nbBytes is not an int so %d should not be used.nbBytes might not be a long either so you can't always use %ld. The solution then is to explicitly type cast the parameter like this:(long)nbBytes to ensure that %ld is always correct.Yes, that's what the code does. I can see it substitutes the next va_arg for the literal field width you'd otherwise expect.The '*' modifier for the field width usually refers to the width of the text in characters, rather than the byte width of the parameter?
That's a good point. You can't push a char on the 68K.hhis forchar, but single byte quantities in 68K are always two bytes on the stack so it's not necessary?
I can see it doesn't support all of the combinations, but I was only checking for 'l' and 'd'. There's no 'q' support, so it was already pre-deprecated ;-) !%land%h- you mean these:
Code:o An optional length modifier, that specifies the size of the argument. The following length modifiers are valid for the d, i, n, o, u, x, or X conversion: Modifier d, i o, u, x, X n hh signed char unsigned char signed char * h short unsigned short short * l (ell) long unsigned long long * ll (ell ell) long long unsigned long long long long * j intmax_t uintmax_t intmax_t * t ptrdiff_t (see note) ptrdiff_t * z (see note) size_t (see note) q (deprecated) quad_t u_quad_t quad_t *
There's only one ANSI library.Right. I believe
%ldwill always refer to alongregardless of the size oflong
%hdwill always refer to ashortregardless of the size ofshort
%dwill always refer to aintregardless of the size ofint
as long as the C standard library that does theprintfhas the some compile options as the code you are callingprintffrom.
printf("%d %d", 1234, 5678); displays 1234, 5678.printf("%ld", 1234, 5678); displays 80877102.printf("%d %d", 1234, 5678); displays 0, 1234.It would then work in 2-byte int and 4-byte int mode. The combination ofThe problem in this case was thatnbBytesis not anintso%dshould not be used.
ButnbBytesmight not be alongeither so you can't always use%ld. The solution then is to explicitly type cast the parameter like this:
(long)nbBytesto ensure that%ldis always correct.
nbBytes and %ld would also work in 4-byte int mode, but your solution is probably best.Metrowerks CodeWarrior has different C standard library binaries for different compile options. "Build MSL Libraries.app" lets you choose which libraries to build. (This shows the ANSI library doesn't handle 4-byte ints automatically and there isn't a version for 4-byte ints. What you'd have to do is roll-your-own 4-byte int ANSI library and Source:Add... it to your project in place of the default one. I think that's possible, because the source code is included, as I've been browsing through it to find out this stuff. Of course, there could be other bugs in the library which prevent the expected behaviour from 4-byte ints.
4i means 4 byte ints). If you discover a bug in the source and make a fix, then you can recompile all the libraries.MSL C.68K (2i_8d).A4.Lib
MSL C.68K (2i_8d).Lib
MSL C.68K (2i_F_8d).A4.Lib
MSL C.68K (2i_F_8d).Lib
MSL C.68K (2i_F).A4.Lib
MSL C.68K (2i_F).Lib
MSL C.68K (2i).A4.Lib
MSL C.68K (2i).Lib
MSL C.68K (4i_8d).A4.Lib
MSL C.68K (4i_8d).Lib
MSL C.68K (4i_F_8d).A4.Lib
MSL C.68K (4i_F_8d).Lib
MSL C.68K (4i_F).A4.Lib
MSL C.68K (4i_F).Lib
MSL C.68K (4i).A4.Lib
MSL C.68K (4i).Lib
MSL C.68K (NL_2i_8d).A4.Lib
MSL C.68K (NL_2i_8d).Lib
MSL C.68K (NL_2i_F_8d).A4.Lib
MSL C.68K (NL_2i_F_8d).Lib
MSL C.68K (NL_2i_F).A4.Lib
MSL C.68K (NL_2i_F).Lib
MSL C.68K (NL_2i).A4.Lib
MSL C.68K (NL_2i).Lib
MSL C.68K (NL_4i_8d).A4.Lib
MSL C.68K (NL_4i_8d).Lib
MSL C.68K (NL_4i_F_8d).A4.Lib
MSL C.68K (NL_4i_F_8d).Lib
MSL C.68K (NL_4i_F).A4.Lib
MSL C.68K (NL_4i_F).Lib
MSL C.68K (NL_4i).A4.Lib
MSL C.68K (NL_4i).Lib
MSL C.68K Fa(2i_8d).A4.Lib
MSL C.68K Fa(2i_8d).Lib
MSL C.68K Fa(2i_F_8d).A4.Lib
MSL C.68K Fa(2i_F_8d).Lib
MSL C.68K Fa(2i_F).A4.Lib
MSL C.68K Fa(2i_F).Lib
MSL C.68K Fa(2i).A4.Lib
MSL C.68K Fa(2i).Lib
MSL C.68K Fa(4i_8d).A4.Lib
MSL C.68K Fa(4i_8d).Lib
MSL C.68K Fa(4i_F_8d).A4.Lib
MSL C.68K Fa(4i_F_8d).Lib
MSL C.68K Fa(4i_F).A4.Lib
MSL C.68K Fa(4i_F).Lib
MSL C.68K Fa(4i).A4.Lib
MSL C.68K Fa(4i).Lib
MSL C.68K Fa(NL_2i_8d).A4.Lib
MSL C.68K Fa(NL_2i_8d).Lib
MSL C.68K Fa(NL_2i_F_8d).A4.Lib
MSL C.68K Fa(NL_2i_F_8d).Lib
MSL C.68K Fa(NL_2i_F).A4.Lib
MSL C.68K Fa(NL_2i_F).Lib
MSL C.68K Fa(NL_2i).A4.Lib
MSL C.68K Fa(NL_2i).Lib
MSL C.68K Fa(NL_4i_8d).A4.Lib
MSL C.68K Fa(NL_4i_8d).Lib
MSL C.68K Fa(NL_4i_F_8d).A4.Lib
MSL C.68K Fa(NL_4i_F_8d).Lib
MSL C.68K Fa(NL_4i_F).A4.Lib
MSL C.68K Fa(NL_4i_F).Lib
MSL C.68K Fa(NL_4i).A4.Lib
MSL C.68K Fa(NL_4i).Lib
MSL C.68K MPW.mcp
MSL C.68K MPW(NL_4i_8d).Lib
MSL C.68K MPW(NL_4i_F_8d).Lib
MSL C.68K MPW(NL_4i_F).Lib
MSL C.68K MPW(NL_4i).Lib