/* internal do-anything v[s][n]printf() formatting system with output to strings or FILE * */ int StdioBasePrintf(struct ParseState *Parser, FILE *Stream, char *StrOut, int StrOutLen, char *Format, struct StdVararg *Args) { struct Value *ThisArg = Args->Param[0]; int ArgCount = 0; char *FPos = Format; char OneFormatBuf[MAX_FORMAT+1]; int OneFormatCount; struct ValueType *ShowType; StdOutStream SOStream; SOStream.FilePtr = Stream; SOStream.StrOutPtr = StrOut; SOStream.StrOutLen = StrOutLen; SOStream.CharCount = 0; while (*FPos != '\0') { if (*FPos == '%') { /* work out what type we're printing */ FPos++; ShowType = NULL; OneFormatBuf[0] = '%'; OneFormatCount = 1; do { switch (*FPos) { case 'd': case 'i': ShowType = &IntType; break; /* integer decimal */ case 'o': case 'u': case 'x': case 'X': ShowType = &IntType; break; /* integer base conversions */ #ifndef NO_FP case 'e': case 'E': ShowType = &FPType; break; /* double, exponent form */ case 'f': case 'F': ShowType = &FPType; break; /* double, fixed-point */ case 'g': case 'G': ShowType = &FPType; break; /* double, flexible format */ #endif case 'a': case 'A': ShowType = &IntType; break; /* hexadecimal, 0x- format */ case 'c': ShowType = &IntType; break; /* character */ case 's': ShowType = CharPtrType; break; /* string */ case 'p': ShowType = VoidPtrType; break; /* pointer */ case 'n': ShowType = &VoidType; break; /* number of characters written */ case 'm': ShowType = &VoidType; break; /* strerror(errno) */ case '%': ShowType = &VoidType; break; /* just a '%' character */ case '\0': ShowType = &VoidType; break; /* end of format string */ } /* copy one character of format across to the OneFormatBuf */ OneFormatBuf[OneFormatCount] = *FPos; OneFormatCount++; /* do special actions depending on the conversion type */ if (ShowType == &VoidType) { switch (*FPos) { case 'm': StdioOutPuts(strerror(errno), &SOStream); break; case '%': StdioOutPutc(*FPos, &SOStream); break; case '\0': OneFormatBuf[OneFormatCount] = '\0'; StdioOutPutc(*FPos, &SOStream); break; case 'n': ThisArg = (struct Value *)((char *)ThisArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(ThisArg))); if (ThisArg->Typ->Base == TypeArray && ThisArg->Typ->FromType->Base == TypeInt) *(int *)ThisArg->Val->Pointer = SOStream.CharCount; break; } } FPos++; } while (ShowType == NULL && OneFormatCount < MAX_FORMAT); if (ShowType != &VoidType) { if (ArgCount >= Args->NumArgs) StdioOutPuts("XXX", &SOStream); else { /* null-terminate the buffer */ OneFormatBuf[OneFormatCount] = '\0'; /* print this argument */ ThisArg = (struct Value *)((char *)ThisArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(ThisArg))); if (ShowType == &IntType) { /* show a signed integer */ if (IS_NUMERIC_COERCIBLE(ThisArg)) StdioFprintfWord(&SOStream, OneFormatBuf, ExpressionCoerceUnsignedInteger(ThisArg)); else StdioOutPuts("XXX", &SOStream); } #ifndef NO_FP else if (ShowType == &FPType) { /* show a floating point number */ if (IS_NUMERIC_COERCIBLE(ThisArg)) StdioFprintfFP(&SOStream, OneFormatBuf, ExpressionCoerceFP(ThisArg)); else StdioOutPuts("XXX", &SOStream); } #endif else if (ShowType == CharPtrType) { if (ThisArg->Typ->Base == TypePointer) StdioFprintfPointer(&SOStream, OneFormatBuf, ThisArg->Val->Pointer); else if (ThisArg->Typ->Base == TypeArray && ThisArg->Typ->FromType->Base == TypeChar) StdioFprintfPointer(&SOStream, OneFormatBuf, &ThisArg->Val->ArrayMem[0]); else StdioOutPuts("XXX", &SOStream); } else if (ShowType == VoidPtrType) { if (ThisArg->Typ->Base == TypePointer) StdioFprintfPointer(&SOStream, OneFormatBuf, ThisArg->Val->Pointer); else if (ThisArg->Typ->Base == TypeArray) StdioFprintfPointer(&SOStream, OneFormatBuf, &ThisArg->Val->ArrayMem[0]); else StdioOutPuts("XXX", &SOStream); } ArgCount++; } } } else { /* just output a normal character */ StdioOutPutc(*FPos, &SOStream); FPos++; } } /* null-terminate */ if (SOStream.StrOutPtr != NULL && SOStream.StrOutLen > 0) *SOStream.StrOutPtr = '\0'; return SOStream.CharCount; }
/* intrinsic functions made available to the language */ void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs, struct OutputStream *Stream) { char *FPos; struct Value *NextArg = Param[0]; struct ValueType *FormatType; int ArgCount = 1; int LeftJustify = FALSE; int ZeroPad = FALSE; int FieldWidth = 0; char *Format = Param[0]->Val->Pointer; for (FPos = Format; *FPos != '\0'; FPos++) { if (*FPos == '%') { FPos++; if (*FPos == '-') { /* a leading '-' means left justify */ LeftJustify = TRUE; FPos++; } if (*FPos == '0') { /* a leading zero means zero pad a decimal number */ ZeroPad = TRUE; FPos++; } /* get any field width in the format */ while (isdigit((int)*FPos)) FieldWidth = FieldWidth * 10 + (*FPos++ - '0'); /* now check the format type */ switch (*FPos) { case 's': FormatType = CharPtrType; break; case 'd': case 'u': case 'x': case 'b': case 'c': FormatType = &IntType; break; #ifndef NO_FP case 'f': FormatType = &FPType; break; #endif case '%': PrintCh('%', Stream); FormatType = NULL; break; case '\0': FPos--; FormatType = NULL; break; default: PrintCh(*FPos, Stream); FormatType = NULL; break; } if (FormatType != NULL) { /* we have to format something */ if (ArgCount >= NumArgs) PrintStr("XXX", Stream); /* not enough parameters for format */ else { NextArg = (struct Value *)((char *)NextArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(NextArg))); if (NextArg->Typ != FormatType && !((FormatType == &IntType || *FPos == 'f') && IS_NUMERIC_COERCIBLE(NextArg)) && !(FormatType == CharPtrType && (NextArg->Typ->Base == TypePointer || (NextArg->Typ->Base == TypeArray && NextArg->Typ->FromType->Base == TypeChar) ) ) ) PrintStr("XXX", Stream); /* bad type for format */ else { switch (*FPos) { case 's': { char *Str; if (NextArg->Typ->Base == TypePointer) Str = NextArg->Val->Pointer; else Str = &NextArg->Val->ArrayMem[0]; if (Str == NULL) PrintStr("NULL", Stream); else PrintStr(Str, Stream); break; } case 'd': PrintInt(ExpressionCoerceInteger(NextArg), FieldWidth, ZeroPad, LeftJustify, Stream); break; case 'u': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 10, FieldWidth, ZeroPad, LeftJustify, Stream); break; case 'x': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 16, FieldWidth, ZeroPad, LeftJustify, Stream); break; case 'b': PrintUnsigned(ExpressionCoerceUnsignedInteger(NextArg), 2, FieldWidth, ZeroPad, LeftJustify, Stream); break; case 'c': PrintCh(ExpressionCoerceUnsignedInteger(NextArg), Stream); break; #ifndef NO_FP case 'f': PrintFP(ExpressionCoerceFP(NextArg), Stream); break; #endif } } } ArgCount++; } } else PrintCh(*FPos, Stream); } }
void GenericPrintf(struct ParseState *Parser, struct Value *ReturnValue, struct Value **Param, int NumArgs, char * str) { const char *FPos; struct Value *NextArg = Param[0]; struct ValueType *FormatType; int ArgCount = 1; int LeftJustify = FALSE; int ZeroPad = FALSE; int FieldWidth = 0; const char *Format = Param[0]->Val->Pointer; int l; for (FPos = Format; *FPos != '\0'; FPos++) { if (*FPos == '%') { FPos++; if (*FPos == '-') { /* a leading '-' means left justify */ LeftJustify = TRUE; FPos++; } if (*FPos == '0') { /* a leading zero means zero pad a decimal number */ ZeroPad = TRUE; FPos++; } /* get any field width in the format */ while (isdigit((int)*FPos)) FieldWidth = FieldWidth * 10 + (*FPos++ - '0'); /* now check the format type */ switch (*FPos) { case 's': FormatType = CharPtrType; break; case 'd': case 'u': case 'x': case 'b': case 'c': FormatType = &IntType; break; case 'f': FormatType = &FPType; break; case '%': StrPutChar(str,'%');++str;FormatType = NULL; break; case '\0': FPos--; FormatType = NULL; break; default: StrPutChar(str,*FPos);++str; FormatType = NULL; break; } if (FormatType != NULL) { /* we have to format something */ if (ArgCount >= NumArgs) { l = StrPutStr(str,"XXX");str+=l; } else { // It won't compile if I don't add this. If you have an idea why, please tell me... actually this is defined in platform.h #define ALIGN_TYPE void * NextArg = (struct Value *)((char *)NextArg + MEM_ALIGN(sizeof(struct Value) + TypeStackSizeValue(NextArg))); if (NextArg->Typ != FormatType && !((FormatType == &IntType || *FPos == 'f') && IS_NUMERIC_COERCIBLE(NextArg)) && !(FormatType == CharPtrType && (NextArg->Typ->Base == TypePointer || (NextArg->Typ->Base == TypeArray && NextArg->Typ->FromType->Base == TypeChar) ) ) ) { l = StrPutStr(str,"XXX");str+=l; } else { switch (*FPos) { case 's': { char *Str; if (NextArg->Typ->Base == TypePointer) Str = NextArg->Val->Pointer; else Str = &NextArg->Val->ArrayMem[0]; if (Str == NULL) { l = StrPutStr(str,"NULL");str+=l; } else { l = StrPutStr(str,Str);str+=l; } break; } case 'd': l = sprintf(str,"%d",ExpressionCoerceInteger(NextArg));str+=l; break; case 'u': l = sprintf(str,"%u",ExpressionCoerceUnsignedInteger(NextArg));str+=l; break; case 'x': l = sprintf(str,"%x",ExpressionCoerceUnsignedInteger(NextArg));str+=l; break; case 'b': l = sprintf(str,"%b",ExpressionCoerceUnsignedInteger(NextArg));str+=l; break; case 'c': l = sprintf(str,"%c",ExpressionCoerceUnsignedInteger(NextArg));str+=l; break; case 'f': l = sprintf(str,"%f",ExpressionCoerceFP(NextArg));str+=l; break; } } } ArgCount++; } } else { StrPutChar(str,*FPos);++str; } } }