Hi Martin
I think that there was one pointer decrement too many at one position, this is the code that i successfully tested in the simulator.
static char cDisplayStr[40]; // not sure if this needs to be static or if pointer passed ??
unsigned int uiDecNumber = 123;
unsigned int uiHexNumber = 0xa5;
char *cPtr;
cPtr = uStrcpy(cDisplayStr, "Part1");
cPtr = uStrcpy(--cPtr, "Part2"); // decrement cPtr to loose null at end of string
cPtr--; // Loose Null from end of string
*cPtr++ = ' '; // Add space character to string
cPtr = fnDebugDec(uiDecNumber, 0, cPtr); // Add a number in DECIMAL format to string
*cPtr++ = '*'; // Add * character to string
cPtr = fnBufferHex(uiHexNumber, (2 | WITH_LEADIN | NO_TERMINATOR), cPtr); // Add a number in HEX format to string, precede with 0x and display 4 hex digits
*cPtr++ = ':'; // Terminate String with : character
cDisplayStr[] doesn't generally need to be static.
This does however look rather complicated, and the first part is indeed so since it concatenates two known strings and adds a space, which can of course be performed more like in the sprintf reference.
The following is the same but looks a bit better:
static char cDisplayStr[40]; // not sure if this needs to be static or if pointer passed ??
unsigned int uiDecNumber = 123;
unsigned int uiHexNumber = 0xa5;
char *cPtr;
cPtr = uStrcpy(cDisplayStr, "Part1Part2 ");
cPtr = fnDebugDec(uiDecNumber, NO_TERMINATOR, --cPtr); // Add a number in DECIMAL format to string
*cPtr++ = '*'; // Add * character to string
cPtr = fnBufferHex(uiHexNumber, (2 | WITH_LEADIN | NO_TERMINATOR), cPtr); // Add a number in HEX format to string, precede with 0x and display 4 hex digits
*cPtr++ = ':'; // Terminate String with : character
Essentially this is the way to do it but I have the following notes:
1) It is true that fnDebugDec() is not consistent with the pointer return. When it adds a terminator it will return a pointer to it rather than after it, as the others do.
2) I an not that happy with the fact that the pointer is generally one past the null termination (when added) because it means that a decrement is necessary to concatenate strings. I think that I will add a project option to change this behavior (so that it doesn't generally disturb existing use, if not activated).
3) What I miss is a flag to set CR+LF, which I would also like to add.
Since I have been unhappy with the situation for a time I just improved it. There were only two small changes required and the following is the code to produce the output as you want it:
static char cDisplayStr[40]; // not sure if this needs to be static or if pointer passed ??
unsigned int uiDecNumber = 123;
unsigned int uiHexNumber = 0xa5;
char *cPtr;
cPtr = fnDebugDec(uiDecNumber, NO_TERMINATOR, uStrcpy(cDisplayStr, "Part1Part2 ")); // Add a number in DECIMAL format to string
*cPtr++ = '*'; // Add * character to string
cPtr = fnBufferHex(uiHexNumber, (2 | WITH_LEADIN | NO_TERMINATOR), cPtr); // Add a number in HEX format to string, precede with 0x and display 4 hex digits
*cPtr++ = ':'; // Terminate String with : character
It is a bit compressed due to the call of uStrcpy() within the fnDebugDec() but there are no more pointer decrements required. Using NO_TERMINATOR or WITH_TERMINATOR doesn't in fact change the result in any way since the terminators are no longer counted as pointer increments in any subroutines and they are overwritten anyway in your example.
In driver.c I have the following two changes:
1) at the end of uStrcpy()
#ifdef STRING_OPTIMISATION // {9}
return (ptrTo - 1); // return pointer to null termination to simplify concatination
#else
return ptrTo; // return the pointer to the address which would have been written to next
#endif
2) at the end of fnBufferHex()
if (iTerminate) {
#ifdef STRING_OPTIMISATION // {9}
*pBuf = 0; // return pointer to null termination to simplify concatination
#else
*pBuf++ = 0;
#endif
}
I decided to put the optional define STRING_OPTIMISATION in types.h rather than in config.h since it is so fundamental.
There are various uses of these functions in the demo project which mean that there will be a number of application level changes before all is tuned but the option is now ready to bring some improvements if required.
Finally, I added a new flag called WITH_CR_LF which adds optionally adds CR + LF to the end of a string. This won't need a configuration define since it is compatible but helps the following type of (for me very often used) construction:
fnDebugMsg("Result =");
fnDebugHex(ulValue, (WITH_LEADIN | CODE_CAPITALS | WITH_SPACE | sizeof(ulValue)));
fnDebugMsg("\r\n");
This now can be achieved with
fnDebugMsg("Result =");
fnDebugHex(ulValue, (WITH_LEADIN | CODE_CAPITALS | WITH_SPACE | WITH_CR_LF | sizeof(ulValue)));
This will be in the next SPs...
Finally I do like the fact that pointers are returned (which is not the case with a standard strcpy()) because it allows the complete of strings to be calculated by (cPtr - cDisplayStr) rather than having to call an additional strlen() to find it.
So finally I cleaned up a little. I hope that you nevertheless find the functions useful. They may not be as convenient as printf() types but avoid any library use and so avoid code bloat which often takes place when linking in these library routines. Thanks for keeping with the spirit of the uTasker!!;-)
Regards
Mark