|
|
//+----------------------------------------------------------------------------
//
// Copyright (c) 1996 Microsoft Corporation
//
// File: ctprintf.cxx
//
// Synopsis: ct versions of the printf family
//
// History: 30-May-96 MikeW Created
//
// Notes: The ct version of the printf family adds two new format
// specifiers: %os and %oc. These specifiers mean ole-string
// and ole-character respectively.
//
// In the ANSI-version of this family these specifiers mean
// "an octal digit followed by the letter s (or c)". Code that
// uses octal should be careful when using these functions.
//
//-----------------------------------------------------------------------------
#include <ctolerpc.h>
#pragma hdrstop
//
// MAX_FORMAT_SPECIFIER_BUFFER is the maximum length of a (munged) format
// specifier
//
const MAX_FORMAT_SPECIFIER_BUFFER = 1024;
//
// MAKE_UNICODE unconditionally makes a string or char constant Unicode
//
#define _MAKE_UNICODE(x) L##x
#define MAKE_UNICODE(x) _MAKE_UNICODE(x)
#ifndef UNICODE_ONLY
//+----------------------------------------------------------------------------
//
// Function: MungeFormatSpecifiersA
//
// Synopsis: Convert the 'os' and 'oc' printf-format specifier to the right
// thing to handle Ole strings and Ole chars.
//
// Parameters: [format] -- The format string to convert
// [munged_format] -- Where to put the munged format
//
// Returns: void
//
// History: 30-May-96 MikeW Created
//
// Notes: In the regular printf family "%os" and "%oc" evaluate to
// an octal number followed by a 's' or a 'c'. To get these
// cases to work always put some character (such as a space)
// after a %o specifier.
//
//-----------------------------------------------------------------------------
void MungeFormatSpecifiersA(const char *format, char *munged_format) { const char *start_of_uncopied_data; *munged_format = '\0';
start_of_uncopied_data = format; format = strchr(format, '%');
while (NULL != format) { //
// Find the type of the format specifier.
// Watch out for "%%" and "%<null terminator>".
//
do { ++format; } while ('%' != *format && '\0' != *format && !isalpha(*format));
strncat( munged_format, start_of_uncopied_data, format - start_of_uncopied_data);
start_of_uncopied_data = format; //
// Munge it to the right thing for %os or %oc
//
if ('o' == *format && 's' == *(format + 1)) { strcat(munged_format, OLE_STRING_SPECIFIER); format += 1; start_of_uncopied_data += 2; } else if ('o' == *format && 'c' == *(format + 1)) { strcat(munged_format, OLE_CHAR_SPECIFIER); format += 1; start_of_uncopied_data += 2; }
format = strchr(format + 1, '%'); }
strcat(munged_format, start_of_uncopied_data); }
//+----------------------------------------------------------------------------
//
// Functions: ctprintfA, ctsprintfA, ctsnprintfA, ctfprintfA
// ctvprintfA, ctvsprintfA, ctvsnprintfA, ctvfprintfA
//
// Synopsis: ct versions of standard ANSI printf family
//
// History: 30-May-96 MikeW Created
//
//-----------------------------------------------------------------------------
int ctprintfA(const char *format, ...) { va_list varargs; va_start(varargs, format); return ctvprintfA(format, varargs); }
int ctsprintfA(char *buffer, const char *format, ...) { va_list varargs; va_start(varargs, format); return ctvsprintfA(buffer, format, varargs); }
int ctsnprintfA(char *buffer, size_t count, const char *format, ...) { va_list varargs; va_start(varargs, format); return ctvsnprintfA(buffer, count, format, varargs); }
int ctfprintfA(FILE *stream, const char *format, ...) { va_list varargs; va_start(varargs, format); return ctvfprintfA(stream, format, varargs); }
int ctvprintfA(const char *format, va_list varargs) { char munged_format[MAX_FORMAT_SPECIFIER_BUFFER]; MungeFormatSpecifiersA(format, munged_format); return vprintf(munged_format, varargs); }
int ctvsprintfA(char *buffer, const char *format, va_list varargs) { char munged_format[MAX_FORMAT_SPECIFIER_BUFFER]; MungeFormatSpecifiersA(format, munged_format); return vsprintf(buffer, munged_format, varargs); }
int ctvsnprintfA( char *buffer, size_t count, const char *format, va_list varargs) { char munged_format[MAX_FORMAT_SPECIFIER_BUFFER]; MungeFormatSpecifiersA(format, munged_format); return _vsnprintf(buffer, count, munged_format, varargs); }
int ctvfprintfA(FILE *stream, const char *format, va_list varargs) { char munged_format[MAX_FORMAT_SPECIFIER_BUFFER]; MungeFormatSpecifiersA(format, munged_format); return vfprintf(stream, munged_format, varargs); }
#endif // !UNICODE_ONLY
#ifndef ANSI_ONLY
//+----------------------------------------------------------------------------
//
// Function: MungeFormatSpecifiersW
//
// Synopsis: Convert the 'os' and 'oc' printf-format specifier to the right
// thing to handle Ole strings and Ole chars.
//
// Parameters: [format] -- The format string to convert
// [munged_format] -- Where to put the munged format
//
// Returns: void
//
// History: 30-May-96 MikeW Created
//
// Notes: In the regular printf family "%os" and "%oc" evaluate to
// an octal number followed by a 's' or a 'c'. To get these
// cases to work always put some character (such as a space)
// after a %o specifier.
//
//-----------------------------------------------------------------------------
void MungeFormatSpecifiersW(const wchar_t *format, wchar_t *munged_format) { const wchar_t *start_of_uncopied_data; *munged_format = L'\0';
start_of_uncopied_data = format; format = wcschr(format, L'%');
while (NULL != format) { //
// Find the type of the format specifier.
// Watch out for "%%" and "%<null terminator>".
//
do { ++format; } while (L'%' != *format && L'\0' != *format && !iswalpha(*format));
wcsncat( munged_format, start_of_uncopied_data, format - start_of_uncopied_data);
start_of_uncopied_data = format; //
// Munge it to the right thing for %os or %oc
//
if (L'o' == *format && L's' == *(format + 1)) { wcscat(munged_format, MAKE_UNICODE(OLE_STRING_SPECIFIER)); format += 1; start_of_uncopied_data += 2; } else if (L'o' == *format && L'c' == *(format + 1)) { wcscat(munged_format, MAKE_UNICODE(OLE_CHAR_SPECIFIER)); format += 1; start_of_uncopied_data += 2; }
format = wcschr(format + 1, '%'); }
wcscat(munged_format, start_of_uncopied_data); }
//+----------------------------------------------------------------------------
//
// Functions: ctprintfW, ctsprintfW, ctsnprintfW, ctfprintfW
// ctvprintfW, ctvsprintfW, ctvsnprintfW, ctvfprintfW
//
// Synopsis: ct versions of standard Unicode printf family
//
// History: 30-May-96 MikeW Created
//
//-----------------------------------------------------------------------------
int ctprintfW(const wchar_t *format, ...) { va_list varargs; va_start(varargs, format); return ctvprintfW(format, varargs); }
int ctsprintfW(wchar_t *buffer, const wchar_t *format, ...) { va_list varargs; va_start(varargs, format); return ctvsprintfW(buffer, format, varargs); }
int ctsnprintfW(wchar_t *buffer, size_t count, const wchar_t *format, ...) { va_list varargs; va_start(varargs, format); return ctvsnprintfW(buffer, count, format, varargs); }
int ctfprintfW(FILE *stream, const wchar_t *format, ...) { va_list varargs; va_start(varargs, format); return ctvfprintfW(stream, format, varargs); }
int ctvprintfW(const wchar_t *format, va_list varargs) { wchar_t munged_format[MAX_FORMAT_SPECIFIER_BUFFER]; MungeFormatSpecifiersW(format, munged_format); return vwprintf(munged_format, varargs); }
int ctvsprintfW(wchar_t *buffer, const wchar_t *format, va_list varargs) { wchar_t munged_format[MAX_FORMAT_SPECIFIER_BUFFER]; MungeFormatSpecifiersW(format, munged_format); return vswprintf(buffer, munged_format, varargs); }
int ctvsnprintfW( wchar_t *buffer, size_t count, const wchar_t *format, va_list varargs) { wchar_t munged_format[MAX_FORMAT_SPECIFIER_BUFFER]; MungeFormatSpecifiersW(format, munged_format); return _vsnwprintf(buffer, count, munged_format, varargs); }
int ctvfprintfW(FILE *stream, const wchar_t *format, va_list varargs) { wchar_t munged_format[MAX_FORMAT_SPECIFIER_BUFFER]; MungeFormatSpecifiersW(format, munged_format); return vfwprintf(stream, munged_format, varargs); }
#endif // !ANSI_ONLY
|