We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I have some legacy code that was originally compiled with Franklin and it also compiles with my Keil compiler. The problem is that the source code does some things that make no sense and I cannot find any documentation in my Keil manuals or on the website about this topic. I want to ensure that 1) the code still operates the same using Keil vs Franklin compiler 2) I understand how it works. The manuals reference va_start,va_end macros. Can the code below be written to use those macros? How? If so, would this be a better option? Looking at the ouput src file, it appears that keil makes a undocumented library call. I look forward to your inputs. Thanks, Paul Calvert 256-704-4134 Here is the code snipet: int sscanf(char *inBfrPtr, char *fmtPtr, ...) { Byte scanResult = 0; void *argPtr = &ellipsis_40; //THIS IS THE STATEMENT THAT I CAN FIND NO REFERNCE TO: ELLIPSIS_40. THERE ARE NO MACROS OR OTHER DECLARATIONS ANYWHERE IN MY CODE REFERENCING "ELLIPSIS_" register char tmpDigit; while(1){ if(*fmtPtr == '\0') break; else if(*fmtPtr == '%'){ fmtPtr++; if(*fmtPtr == 'c'){ **(char **)argPtr = *inBfrPtr; argPtr += 3; fmtPtr++; inBfrPtr++; scanResult += 1; continue; } else if(*fmtPtr == 'd'){ if(inBfrPtr[0] == '+' || inBfrPtr[0] == '-') tmpDigit = inBfrPtr[1]; else tmpDigit = inBfrPtr[0]; if(tmpDigit >= '0' && tmpDigit <= '9'){ **(int **)argPtr = atoi(inBfrPtr); while(1){ inBfrPtr++; if(inBfrPtr[0] < '0' || inBfrPtr[0] > '9') break; } fmtPtr++; argPtr += 3; scanResult += 1; continue; } else break; } else if(*fmtPtr == '%'){ /* fall through to continue string comparison */ } else{ /* unknown format specifier */ break; } } if(*fmtPtr++ != *inBfrPtr++) break; } return(scanResult); }
you might want to set up an XDATA reentrant stack and then define all your variadatic functions (only them) as reentrant, I did it like this:
void variable(U8 *inBfrPtr, U8 *pFormat, ...) large reentrant { }
I *really* appreciate your feedback. Please excuse my ignorance, but I am not following you too well. I modified the original posted code to the following and it does compile. Does it look right? I am unsure about where to put va_end/start. <pre > int sscanf(char *inBfrPtr, char *fmtPtr, ...) { Byte scanResult = 0; // void *argPtr = &ellipsis_40; void *argPtr; register char tmpDigit; va_list vargList; Byte argList[40]; va_start(vargList, fmtPtr); argList[0] = va_arg(vargList, Byte); argPtr = &argList[0]; while(1){ if(*fmtPtr == '\0') break; else if(*fmtPtr == '%'){ fmtPtr++; if(*fmtPtr == 'c'){ **(char **)argPtr = *inBfrPtr; argPtr += 3; fmtPtr++; inBfrPtr++; scanResult += 1; continue; } else if(*fmtPtr == 'd'){ if(inBfrPtr[0] == '+' || inBfrPtr[0] == '-') tmpDigit = inBfrPtr[1]; else tmpDigit = inBfrPtr[0]; if(tmpDigit >= '0' && tmpDigit <= '9'){ **(int **)argPtr = atoi(inBfrPtr); while(1){ inBfrPtr++; if(inBfrPtr[0] < '0' || inBfrPtr[0] > '9') break; } fmtPtr++; argPtr += 3; scanResult += 1; continue; } else break; } else if(*fmtPtr == '%'){ /* fall through to continue string comparison */ } else{ /* unknown format specifier */ break; } } if(*fmtPtr++ != *inBfrPtr++) break; } return(scanResult); va_end(vargList); } </pre >
Okay, we will get this pre tag to work. It's < pre > but *no* spaces after the < or before the >. I can't show it literally here of course. Hit the preview tab as you reply to see that you are getting blue highlighted, fixed pitch code blocks. Of course < /pre > is the < pre > terminator. Again, *no spaces* are allowed. It's really hard to read proportionally spaced code without indentation. Now on to the problem. You missed my point that I made poorly. You pop things off the variadatic stack which is made known to the compiler via the va_start() macro. You pop things off using the type you expect by using the va_arg() macro. Then you terminate your variadatic stack usage with the va_end() macro. Here's a printf() example (watch my < pre >):
int printf(char *pFmt, ...) reentrant large { long fourByte; short twoByte; char byte; int count; va_list vargList; va_start(vargList, pFmt); while (*pFmt) { if (!strcmp(pFmt, "%c")) { byte = va_arg(vargList, char); ++count; } else if ((!strcmp(pFmt, "%d"))) { twoByte = va_arg(vargList, short); count += sizeof (short) } else if ((!strcmp(pFmt, "%ld"))) { fourByte = va_arg(vargList, long); count += sizeof (long); } // Important, move along through the variadatic stack. ++pFmt; } // All done va_end(vargList); return count; }
"I can't show it literally here of course." If you type "&lt" and "&gt" in the 'post' window, they will display as '<' and '>' Thus you can show the <pre> and </pre> literally in your post! The ampersand, '&', is the standard HTML escape; of course, to show it here, I had to use the escape sequence for ampersand, which is "&amp". You should be able to see how it all works with your Browser's 'View Source' button, or equivalent. To check how your post will look, use the 'Preview' button below the 'Post' window (and then your Browser's 'Back' button if you need further editing).
Hmm... <pre> hey neat. Now why couldn't they just use the \ for escape? That seems so much better to me, of course I'm a C programmer too. Thanks Andrew. - Mark