/*** *printf.h - print formatted * * Copyright (c) 1985-1991, Microsoft Corporation. All rights reserved. * *Purpose: * defines w4*printf() - print formatted data * defines w4v*printf() - print formatted output, get data from an * argument ptr instead of explicit args. * *Revision History: * 09-02-83 RN original sprintf * 06-17-85 TC rewrote to use new varargs macros, and to be vsprintf * 04-13-87 JCR added const to declaration * 11-07-87 JCR Multi-thread support * 12-11-87 JCR Added "_LOAD_DS" to declaration * 05-27-88 PHG Merged DLL and normal versions * 06-13-88 JCR Fake _iob entry is now static so that other routines * can assume _iob entries are in DGROUP. * 08-25-88 GJF Define MAXSTR to be INT_MAX (from LIMITS.H). * 06-06-89 JCR 386 mthread support * 08-18-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat * model). Also fixed copyright and indents. * 02-16-90 GJF Fixed copyright * *******************************************************************************/ #include #include #include #include "w4io.h" #if defined(_W4PRINTF_) static long fh; // extern long GetStdHandle(long); // extern void WriteFile(long fh, char FAR *s, long cch, long FAR * pcchret, long); # define _PRINTF_ #elif defined(_W4DPRINTF_) # define _pwritechar _dwritechar # define _pflushbuf _dflushbuf # define w4printf w4dprintf # define w4vprintf w4vdprintf # define _PRINTF_ #elif defined(_W4SPRINTF_) # define _pwritechar _swritechar # define w4printf w4sprintf # define w4vprintf w4vsprintf #elif defined(_W4WCSPRINTF_) # define _TCHAR_ wchar_t # define _PBUF_ pwcbuf # define _PSTART_ pwcstart # define w4printf w4wcsprintf # define w4vprintf w4vwcsprintf # define _pwritechar _wwritechar #else # error configuration problem #endif #ifndef _TCHAR_ # define _TCHAR_ char # define _PBUF_ pchbuf # define _PSTART_ pchstart #endif #ifdef _PRINTF_ # ifndef FLAT # define OutputDebugStringA OutputDebugString # endif int _cdecl _pflushbuf(struct w4io FAR *f); # define SPR(a) # define MAXSTR 128 #else # define SPR(a) a, # define MAXSTR INT_MAX #endif void _cdecl _pwritechar(int ch, int num, struct w4io FAR *f, int FAR *pcchwritten); int _cdecl w4vprintf(SPR(_TCHAR_ FAR *string) const char FAR *format, va_list arglist); #ifdef __cplusplus extern "C" { #endif DWORD FAR PASCAL CallProc32W(DWORD dw1, DWORD dw2, DWORD dw3, LPVOID pfn32, DWORD dwPtrTranslate, DWORD dwArgCount); #ifdef __cplusplus } #endif LPVOID lpThkCallOutputFunctionsProc; /*** *int w4printf(format, ...) - print formatted data * *Purpose: * Prints formatted data using the format string to * format data and getting as many arguments as called for * Sets up a w4io so file i/o operations can be used. * w4iooutput does the real work here * *Entry: * char *format - format string to control data format/number * of arguments followed by list of arguments, number and type * controlled by format string * *Exit: * returns number of characters written * *Exceptions: * *******************************************************************************/ int _cdecl w4printf(SPR(_TCHAR_ FAR *string) const char FAR *format, ...) /* * 'PRINT', 'F'ormatted */ { va_list arglist; va_start(arglist, format); return(w4vprintf(SPR(string) format, arglist)); } /*** *int w4vprintf(format, arglist) - print formatted data from arg ptr * *Purpose: * Prints formatted data, but gets data from an argument pointer. * Sets up a w4io so file i/o operations can be used, make string look * like a huge buffer to it, but _flsbuf will refuse to flush it if it * fills up. Appends '\0' to make it a true string. * * Multi-thread: (1) Since there is no stream, this routine must never try * to get the stream lock (i.e., there is no stream lock either). (2) * Also, since there is only one staticly allocated 'fake' iob, we must * lock/unlock to prevent collisions. * *Entry: * char *format - format string, describes format of data * va_list arglist - varargs argument pointer * *Exit: * returns number of characters written * *Exceptions: * *******************************************************************************/ int _cdecl w4vprintf(SPR(_TCHAR_ FAR *string) const char FAR *format, va_list arglist) /* * 'V'ariable argument 'PRINT', 'F'ormatted */ { struct w4io outfile; register int retval; #ifdef _PRINTF_ char string[MAXSTR + 1]; // leave room for null termination #else int dummy; #endif #ifdef _W4PRINTF_ long ldummy; if (fh == 0 || fh == -1) { ldummy = -11; // C7 bug workaround if ((fh = (long)GetStdHandle(ldummy)) == 0 || fh == -1) { OutputDebugStringA("GetStdHandle in " __FILE__ " failed\n"); return(-1); } } #endif outfile._PBUF_ = outfile._PSTART_ = string; outfile.cchleft = MAXSTR; outfile.writechar = _pwritechar; retval = w4iooutput(&outfile, format, arglist); #ifdef _PRINTF_ if (_pflushbuf(&outfile) == -1) { return(-1); } #else _pwritechar('\0', 1, &outfile, &dummy); #endif return(retval); } void _cdecl _pwritechar(int ch, int num, struct w4io FAR *f, int FAR *pcchwritten) { //printf(" char: ch=%c, cnt=%d, cch=%d\n", ch, num, *pcchwritten); while (num-- > 0) { #ifdef _PRINTF_ if (f->cchleft < 2 && _pflushbuf(f) == -1) { *pcchwritten = -1; return; } #endif #ifdef _W4DPRINTF_ # ifndef FLAT if (ch == '\n') { *f->_PBUF_++ = '\r'; f->cchleft--; (*pcchwritten)++; } # endif #endif *f->_PBUF_++ = (char) ch; f->cchleft--; (*pcchwritten)++; } } #ifdef _PRINTF_ int _cdecl _pflushbuf(struct w4io FAR *f) { int cch; if (cch = (int) (f->pchbuf - f->pchstart)) { #ifdef _W4DPRINTF_ *f->pchbuf = '\0'; // null terminate if (lpThkCallOutputFunctionsProc == NULL) { OutputDebugStringA(f->pchstart); } else { // note casting and dummy arguments to match other uses of it (see interop.hxx) CallProc32W((DWORD) f->pchstart, 0, 0, lpThkCallOutputFunctionsProc, 0x00000004, 3); // thunk it to olethk32.dll } #else long cchret; //*f->pchbuf = '\0'; // null terminate //printf("%d chars: \"%s\"\n", cch, f->pchstart); WriteFile((HANDLE)fh, f->pchstart, cch, &cchret, 0); if (cch != cchret) { OutputDebugString("WriteFile in " __FILE__ " failed\n"); return(-1); } #endif f->pchbuf -= cch; // reset pointer f->cchleft += cch; // reset count } return(0); } #endif // _PRINTF_