Hi all, I'm a terrible lurker, so apologies for my first post being a bug report. I should say up front that I'm very grateful that you folks have made mspgcc, it's made our project much more pleasant than it would have been if we were stuck on Windows with some proprietary tools. BTW we're using the USB FET under Linux, and working well apart from lack of working backtrace. Anyway here goes:
The printf functions all call vuprintf. If you use the %s format with an argument string longer than 128 chars, it's truncated. It comes down to this line in vuprintf: signed char size = 0; /* size of converted field or string */ So this works as expected: snprintf(buf, sizeof(buf), "%s", "Hello world"); and this fails: snprintf(buf, sizeof(buf), "%s", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // 50 chars "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // 50 chars "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" // 50 chars ); because 50 + 50 + 50 = 150 > 128. Ok, not exactly front page news, but I thought I'd report it in case this saves someone 10 mins of headscratching. The patch attached might be a bit heavy-handed, I just changed the relevant-looking 'signed char's to 'signed int'. Works for me, but someone who knows more should check and test before a fix is committed. Cheers, - Ben.
Index: vuprintf.c =================================================================== RCS file: /home/cvs/Projects/neuro/software/source/framework/vuprintf.c,v retrieving revision 1.1 diff -u -r1.1 vuprintf.c --- vuprintf.c 26 Sep 2006 05:16:59 -0000 1.1 +++ vuprintf.c 26 Sep 2006 05:33:37 -0000 @@ -119,7 +119,7 @@ #define PAD_SP(x) __write_pad(' ',x) #define PAD_0(x) __write_pad('0',x) -static int __write_pad(char c, signed char howmany) +static int __write_pad(char c, signed int howmany) { for(;howmany>0;howmany--) { @@ -165,21 +165,21 @@ register char *cp; /* handy char pointer (short term usage) */ const char *fmark; /* for remembering a place in fmt */ register unsigned char flags; /* flags as above */ - signed char width; /* width from format (%8d), or 0 */ - signed char prec; /* precision from format (%.3d), or -1 */ + signed int width; /* width from format (%8d), or 0 */ + signed int prec; /* precision from format (%.3d), or -1 */ char sign; /* sign prefix (' ', '+', '-', or \0) */ unsigned long _ulong=0; /* integer arguments %[diouxX] */ #define OCT 8 #define DEC 10 #define HEX 16 unsigned char base; /* base for [diouxX] conversion */ - signed char dprec; /* a copy of prec if [diouxX], 0 otherwise */ - signed char dpad; /* extra 0 padding needed for integers */ - signed char fieldsz; /* field size expanded by sign, dpad etc */ + signed int dprec; /* a copy of prec if [diouxX], 0 otherwise */ + signed int dpad; /* extra 0 padding needed for integers */ + signed int fieldsz; /* field size expanded by sign, dpad etc */ /* The initialization of 'size' is to suppress a warning that 'size' might be used unitialized. It seems gcc can't quite grok this spaghetti code ... */ - signed char size = 0; /* size of converted field or string */ + signed int size = 0; /* size of converted field or string */ char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ char ox[2]; /* space for 0x hex-prefix */