From 5de6577d1f0b379960345bcbd91c9b62b401350e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Sat, 19 Feb 2005 23:05:09 +0000 Subject: [PATCH] Don't use svn command line tool to get revision number XML code stolen from the xmlbuildsystem branch, we need to merge this when merging the xmlbuildsystem back into trunk svn path=/trunk/; revision=13656 --- reactos/tools/Makefile | 16 +- reactos/tools/buildno/Makefile | 42 + reactos/tools/buildno/XML.cpp | 727 +++++++ reactos/tools/buildno/XML.h | 96 + .../tools/{buildno.c => buildno/buildno.cpp} | 89 +- reactos/tools/buildno/exception.cpp | 178 ++ reactos/tools/buildno/exception.h | 125 ++ reactos/tools/buildno/pch.h | 44 + reactos/tools/buildno/ssprintf.cpp | 1920 +++++++++++++++++ reactos/tools/buildno/ssprintf.h | 23 + 10 files changed, 3222 insertions(+), 38 deletions(-) create mode 100644 reactos/tools/buildno/Makefile create mode 100644 reactos/tools/buildno/XML.cpp create mode 100644 reactos/tools/buildno/XML.h rename reactos/tools/{buildno.c => buildno/buildno.cpp} (77%) create mode 100644 reactos/tools/buildno/exception.cpp create mode 100644 reactos/tools/buildno/exception.h create mode 100644 reactos/tools/buildno/pch.h create mode 100644 reactos/tools/buildno/ssprintf.cpp create mode 100644 reactos/tools/buildno/ssprintf.h diff --git a/reactos/tools/Makefile b/reactos/tools/Makefile index 40084444a4d..9a53c9af24e 100644 --- a/reactos/tools/Makefile +++ b/reactos/tools/Makefile @@ -5,7 +5,6 @@ include $(PATH_TO_TOP)/rules.mak CFLAGS += -Wall -Werror TOOLS = \ - buildno$(EXE_POSTFIX) \ regtests$(EXE_POSTFIX) \ rcopy$(EXE_POSTFIX) \ rdel$(EXE_POSTFIX) \ @@ -20,11 +19,7 @@ TOOLS = \ CLEAN_FILES = $(TOOLS) all: $(TOOLS) zlib_target wmc_target cabman_target cdmake_target mkhive_target rgenstat_target \ - wine2ros_target pipetools_target winebuild_target bin2res_target wrc_target - -buildno$(EXE_POSTFIX): buildno.c ../include/reactos/version.h - @$(HOST_CC) $(CFLAGS) -o buildno$(EXE_POSTFIX) buildno.c - @$(EXE_PREFIX)buildno$(EXE_POSTFIX) + wine2ros_target pipetools_target winebuild_target bin2res_target wrc_target buildno_target regtests$(EXE_POSTFIX): regtests.c @$(HOST_CC) $(CFLAGS) -o regtests$(EXE_POSTFIX) regtests.c @@ -133,11 +128,15 @@ bin2res_target: wrc_target: $(MAKE) --silent -C wrc wrc$(EXE_POSTFIX) -.PHONY: wmc_target cdmake_target mkhive_target rgenstat_target pipetools_target wrc_target +buildno_target: + $(MAKE) --silent -C buildno buildno$(EXE_POSTFIX) + +.PHONY: wmc_target cdmake_target mkhive_target rgenstat_target pipetools_target wrc_target buildno_target ifeq ($(HOST),mingw32-linux) clean: + $(MAKE) --silent -C buildno clean $(MAKE) --silent -C wrc clean $(MAKE) --silent -C cabman clean $(MAKE) --silent -C cdmake clean @@ -148,12 +147,12 @@ clean: $(MAKE) --silent -C winebuild clean $(MAKE) --silent -C bin2res clean $(MAKE) --silent -C ../lib/zlib -f Makefile.host clean - @rm ../include/reactos/buildno.h @rm mkconfig @rm $(TOOLS) endif ifeq ($(HOST),mingw32-windows) clean: + $(MAKE) --silent -C buildno clean $(MAKE) --silent -C wrc clean $(MAKE) --silent -C cabman clean $(MAKE) --silent -C cdmake clean @@ -165,7 +164,6 @@ clean: $(MAKE) --silent -C winebuild clean $(MAKE) --silent -C bin2res clean $(MAKE) --silent -C ../lib/zlib -f Makefile.host clean - -@del ..\include\reactos\buildno.h -@del *$(EXE_POSTFIX) endif diff --git a/reactos/tools/buildno/Makefile b/reactos/tools/buildno/Makefile new file mode 100644 index 00000000000..a5e3cd7493e --- /dev/null +++ b/reactos/tools/buildno/Makefile @@ -0,0 +1,42 @@ +PATH_TO_TOP = ../.. + +TARGET = buildno$(EXE_POSTFIX) + +all: $(TARGET) + +OBJECTS = buildno.o XML.o exception.o ssprintf.o + +CLEAN_FILES = *.o buildno$(EXE_POSTFIX) + +HOST_CXXFLAGS = -I$(PATH_TO_TOP)/include/reactos -g -Wall -Werror + +buildno.o: buildno.cpp $(PATH_TO_TOP)/include/reactos/version.h + $(HOST_CXX) $(HOST_CXXFLAGS) -o buildno.o -c buildno.cpp + +XML.o: XML.cpp + $(HOST_CXX) $(HOST_CXXFLAGS) -o XML.o -c XML.cpp + +exception.o: exception.cpp + $(HOST_CXX) $(HOST_CXXFLAGS) -o exception.o -c exception.cpp + +ssprintf.o: ssprintf.cpp + $(HOST_CXX) $(HOST_CXXFLAGS) -o ssprintf.o -c ssprintf.cpp + +buildno$(EXE_POSTFIX): $(OBJECTS) + $(HOST_CXX) -g $(OBJECTS) -o $(TARGET) + @$(EXE_PREFIX)buildno$(EXE_POSTFIX) + +ifeq ($(HOST),mingw32-linux) +clean: + -rm -f *.o $(TARGET) + -rm $(PATH_TO_TOP)/include/reactos/buildno.h +endif +ifneq ($(HOST),mingw32-linux) +clean: + -del *.o $(TARGET) + -del ..\..\include\reactos\buildno.h +endif + +.PHONY: clean + +include $(PATH_TO_TOP)/rules.mak diff --git a/reactos/tools/buildno/XML.cpp b/reactos/tools/buildno/XML.cpp new file mode 100644 index 00000000000..741c41b566e --- /dev/null +++ b/reactos/tools/buildno/XML.cpp @@ -0,0 +1,727 @@ +// XML.cpp + +#include "pch.h" + +#ifdef _MSC_VER +#define MAX_PATH _MAX_PATH +#endif + +#ifdef WIN32 +# include +# include +#else +# include +# define MAX_PATH PATH_MAX +#endif +#include + +#include "XML.h" +#include "exception.h" +#include "ssprintf.h" + +using std::string; +using std::vector; + +#ifdef WIN32 +#define getcwd _getcwd +#endif//WIN32 + +static const char* WS = " \t\r\n"; +static const char* WSEQ = " =\t\r\n"; + +string working_directory; + +class XMLInclude +{ +public: + XMLElement *e; + Path path; + + XMLInclude ( XMLElement* e_, const Path& path_ ) + : e(e_), path(path_) + { + } +}; + +class XMLIncludes : public vector +{ +public: + ~XMLIncludes() + { + for ( size_t i = 0; i < this->size(); i++ ) + delete (*this)[i]; + } +}; + +void +InitWorkingDirectory() +{ + // store the current directory for path calculations + working_directory.resize ( _MAX_PATH ); + working_directory[0] = 0; + getcwd ( &working_directory[0], working_directory.size() ); + working_directory.resize ( strlen ( working_directory.c_str() ) ); +} + +#ifdef _MSC_VER +unsigned __int64 +#else +unsigned long long +#endif +filelen ( FILE* f ) +{ +#ifdef WIN32 + return _filelengthi64 ( _fileno(f) ); +#else + struct stat64 file_stat; + if ( fstat64(fileno(f), &file_stat) != 0 ) + return 0; + return file_stat.st_size; +#endif +} + +Path::Path() +{ + if ( !working_directory.size() ) + InitWorkingDirectory(); + string s ( working_directory ); + const char* p = strtok ( &s[0], "/\\" ); + while ( p ) + { + if ( *p ) + path.push_back ( p ); + p = strtok ( NULL, "/\\" ); + } +} + +Path::Path ( const Path& cwd, const string& file ) +{ + string s ( cwd.Fixup ( file, false ) ); + const char* p = strtok ( &s[0], "/\\" ); + while ( p ) + { + if ( *p ) + path.push_back ( p ); + p = strtok ( NULL, "/\\" ); + } +} + +string +Path::Fixup ( const string& file, bool include_filename ) const +{ + if ( strchr ( "/\\", file[0] ) +#ifdef WIN32 + // this squirreliness is b/c win32 has drive letters and *nix doesn't... + || file[1] == ':' +#endif//WIN32 + ) + { + return file; + } + vector pathtmp ( path ); + string tmp ( file ); + const char* prev = strtok ( &tmp[0], "/\\" ); + const char* p = strtok ( NULL, "/\\" ); + while ( p ) + { + if ( !strcmp ( prev, "." ) ) + ; // do nothing + else if ( !strcmp ( prev, ".." ) ) + { + // this squirreliness is b/c win32 has drive letters and *nix doesn't... +#ifdef WIN32 + if ( pathtmp.size() > 1 ) +#else + if ( pathtmp.size() ) +#endif + pathtmp.resize ( pathtmp.size() - 1 ); + } + else + pathtmp.push_back ( prev ); + prev = p; + p = strtok ( NULL, "/\\" ); + } + if ( include_filename ) + pathtmp.push_back ( prev ); + + // reuse tmp variable to return recombined path + tmp.resize(0); + for ( size_t i = 0; i < pathtmp.size(); i++ ) + { + // this squirreliness is b/c win32 has drive letters and *nix doesn't... +#ifdef WIN32 + if ( i ) tmp += "/"; +#else + tmp += "/"; +#endif + tmp += pathtmp[i]; + } + return tmp; +} + +/*static*/ string +Path::RelativeFromWorkingDirectory ( const string& path ) +{ + vector vwork, vpath, vout; + Path::Split ( vwork, working_directory, true ); + Path::Split ( vpath, path, true ); +#ifdef WIN32 + // this squirreliness is b/c win32 has drive letters and *nix doesn't... + // not possible to do relative across different drive letters + if ( vwork[0] != vpath[0] ) + return path; +#endif + size_t i = 0; + while ( i < vwork.size() && i < vpath.size() && vwork[i] == vpath[i] ) + ++i; + if ( i < vwork.size() ) + { + // path goes above our working directory, we will need some ..'s + for ( size_t j = 0; j < i; j++ ) + vout.push_back ( ".." ); + } + while ( i < vpath.size() ) + vout.push_back ( vpath[i++] ); + + // now merge vout into a string again + string out = "."; + for ( i = 0; i < vout.size(); i++ ) + { + out += "/" + vout[i]; + } + return out; +} + +/*static*/ void +Path::Split ( vector& out, + const string& path, + bool include_last ) +{ + string s ( path ); + const char* prev = strtok ( &s[0], "/\\" ); + const char* p = strtok ( NULL, "/\\" ); + out.resize ( 0 ); + while ( p ) + { + out.push_back ( prev ); + prev = p; + p = strtok ( NULL, "/\\" ); + } + if ( include_last ) + out.push_back ( prev ); +} + +XMLFile::XMLFile() +{ +} + +void +XMLFile::close() +{ + _buf.resize(0); + _p = _end = NULL; +} + +bool +XMLFile::open(const string& filename_) +{ + close(); + FILE* f = fopen ( filename_.c_str(), "rb" ); + if ( !f ) + return false; + unsigned long len = (unsigned long)filelen(f); + _buf.resize ( len ); + fread ( &_buf[0], 1, len, f ); + fclose ( f ); + _p = _buf.c_str(); + _end = _p + len; + _filename = filename_; + next_token(); + return true; +} + +// next_token() moves the pointer to next token, which may be +// an xml element or a text element, basically it's a glorified +// skipspace, normally the user of this class won't need to call +// this function +void +XMLFile::next_token() +{ + _p += strspn ( _p, WS ); +} + +bool +XMLFile::next_is_text() +{ + return *_p != '<'; +} + +bool +XMLFile::more_tokens() +{ + return _p != _end; +} + +// get_token() is used to return a token, and move the pointer +// past the token +bool +XMLFile::get_token(string& token) +{ + const char* tokend; + if ( !strncmp ( _p, "" ); + if ( !tokend ) + tokend = _end; + else + tokend += 3; + } + else if ( !strncmp ( _p, "" ); + if ( !tokend ) + tokend = _end; + else + tokend += 2; + } + else if ( *_p == '<' ) + { + tokend = strchr ( _p, '>' ); + if ( !tokend ) + tokend = _end; + else + ++tokend; + } + else + { + tokend = strchr ( _p, '<' ); + if ( !tokend ) + tokend = _end; + while ( tokend > _p && isspace(tokend[-1]) ) + --tokend; + } + if ( tokend == _p ) + return false; + token = string ( _p, tokend-_p ); + _p = tokend; + next_token(); + return true; +} + +string +XMLFile::Location() const +{ + int line = 1; + const char* p = strchr ( _buf.c_str(), '\n' ); + while ( p && p < _p ) + { + ++line; + p = strchr ( p+1, '\n' ); + } + return ssprintf ( "%s(%i)",_filename.c_str(), line ); +} + +XMLAttribute::XMLAttribute() +{ +} + +XMLAttribute::XMLAttribute(const string& name_, + const string& value_) + : name(name_), value(value_) +{ +} + +XMLAttribute::XMLAttribute ( const XMLAttribute& src ) + : name(src.name), value(src.value) +{ + +} + +XMLAttribute& XMLAttribute::operator = ( const XMLAttribute& src ) +{ + name = src.name; + value = src.value; + return *this; +} + +XMLElement::XMLElement ( const string& location_ ) + : location(location_), + parentElement(NULL) +{ +} + +XMLElement::~XMLElement() +{ + size_t i; + for ( i = 0; i < attributes.size(); i++ ) + delete attributes[i]; + for ( i = 0; i < subElements.size(); i++ ) + delete subElements[i]; +} + +void +XMLElement::AddSubElement ( XMLElement* e ) +{ + subElements.push_back ( e ); + e->parentElement = this; +} + +// Parse() +// This function takes a single xml tag ( i.e. beginning with '<' and +// ending with '>', and parses out it's tag name and constituent +// attributes. +// Return Value: returns true if you need to look for a for +// the one it just parsed... +bool +XMLElement::Parse(const string& token, + bool& end_tag) +{ + const char* p = token.c_str(); + assert ( *p == '<' ); + ++p; + p += strspn ( p, WS ); + + // check if this is a comment + if ( !strncmp ( p, "!--", 3 ) ) + { + name = "!--"; + end_tag = false; + return false; // never look for end tag to a comment + } + + end_tag = ( *p == '/' ); + if ( end_tag ) + { + ++p; + p += strspn ( p, WS ); + } + const char* end = strpbrk ( p, WS ); + if ( !end ) + { + end = strpbrk ( p, "/>" ); + assert ( end ); + } + name = string ( p, end-p ); + p = end; + p += strspn ( p, WS ); + while ( *p != '>' && *p != '/' ) + { + end = strpbrk ( p, WSEQ ); + if ( !end ) + { + end = strpbrk ( p, "/>" ); + assert ( end ); + } + string attribute ( p, end-p ), value; + p = end; + p += strspn ( p, WS ); + if ( *p == '=' ) + { + ++p; + p += strspn ( p, WS ); + char quote = 0; + if ( strchr ( "\"'", *p ) ) + { + quote = *p++; + end = strchr ( p, quote ); + } + else + { + end = strpbrk ( p, WS ); + } + if ( !end ) + { + end = strchr ( p, '>' ); + assert(end); + if ( end[-1] == '/' ) + end--; + } + value = string ( p, end-p ); + p = end; + if ( quote && *p == quote ) + p++; + p += strspn ( p, WS ); + } + else if ( name[0] != '!' ) + { + throw XMLSyntaxErrorException ( location, + "attributes must have values" ); + } + attributes.push_back ( new XMLAttribute ( attribute, value ) ); + } + return !( *p == '/' ) && !end_tag; +} + +XMLAttribute* +XMLElement::GetAttribute ( const string& attribute, + bool required ) +{ + // this would be faster with a tree-based container, but our attribute + // lists are likely to stay so short as to not be an issue. + for ( size_t i = 0; i < attributes.size(); i++ ) + { + if ( attribute == attributes[i]->name ) + return attributes[i]; + } + if ( required ) + { + throw RequiredAttributeNotFoundException ( location, + attribute, + name ); + } + return NULL; +} + +const XMLAttribute* +XMLElement::GetAttribute ( const string& attribute, + bool required ) const +{ + // this would be faster with a tree-based container, but our attribute + // lists are likely to stay so short as to not be an issue. + for ( size_t i = 0; i < attributes.size(); i++ ) + { + if ( attribute == attributes[i]->name ) + return attributes[i]; + } + if ( required ) + { + throw RequiredAttributeNotFoundException ( location, + attribute, + name ); + } + return NULL; +} + +// XMLParse() +// This function reads a "token" from the file loaded in XMLFile +// if it finds a tag that is non-singular, it parses sub-elements and/or +// inner text into the XMLElement that it is building to return. +// Return Value: an XMLElement allocated via the new operator that contains +// it's parsed data. Keep calling this function until it returns NULL +// (no more data) +XMLElement* +XMLParse(XMLFile& f, + XMLIncludes* includes, + const Path& path, + bool* pend_tag = NULL ) +{ + string token; + if ( !f.get_token(token) ) + return NULL; + bool end_tag, is_include = false; + + while ( token[0] != '<' + || !strncmp ( token.c_str(), "0) + f += ' '; + if (sign) + f += sign; + if (type & SPECIAL) + { + if (base==8) + f += '0'; + else if (base==16) + { + f += '0'; + f += digits[33]; + } + } + if (!(type & LEFT)) + { + while (size-- > 0) + f += c; + } + while (i < precision--) + { + f += '0'; + } + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += ' '; + } + return true; +} + +static bool +wnumber(std::wstring& f, LONGLONG num, int base, int size, int precision ,int type) +{ + wchar_t c,sign,tmp[66]; + const wchar_t *digits = L"0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = L"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = L'-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = L'+'; + size--; + } else if (type & SPACE) { + sign = L' '; + + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]=L'0'; + else while (num != 0) + tmp[i++] = digits[do_div(&num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + f += L' '; + if (sign) + f += sign; + if (type & SPECIAL) + { + if (base==8) + f += L'0'; + else if (base==16) + { + f += L'0'; + f += digits[33]; + } + } + if (!(type & LEFT)) + { + while (size-- > 0) + f += c; + } + while (i < precision--) + { + f += L'0'; + } + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += L' '; + } + return true; +} + + +static bool +numberf(std::string& f, double __n, char exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + double frac, intr; + double p; + char sign; + char c; + char ro = 0; + int result; + + union + { + double* __n; + ieee_double_t* n; + } n; + + n.__n = &__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n.n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = numberf(f,__n/pow(10.0L,e),'f',size-4, precision, type); + if (result < 0) + return false; + f += exp_sign; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = number(f,ie, 10,2, 2,type ); + if (result < 0) + return false; + return true; + } + + if ( exp_sign == 'f' ) { + buf = (char*)alloca(4096); + if (type & LEFT) { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (__n < 0) { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = '0'; + size--; + } + else { + while ( intr > 0.0 ) { + p = intr; + intr/=10.0L; + modf(intr, &intr); + + p -= 10.0*intr; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += ' '; + } + if (sign) + { + f += sign; + } + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + f += ' '; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + f += c; + } + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) + { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) + { + tmp++; + i--; + } + } +// else +// while (i < precision--) +// putc('0', f); + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += ' '; + } + } + return true; +} + +static bool +wnumberf(std::wstring& f, double __n, wchar_t exp_sign, int size, int precision, int type) +{ + double exponent = 0.0; + double e; + long ie; + + int i = 0; + int j = 0; + + double frac, intr; + double p; + wchar_t *buf, *tmp, sign, c, ro = 0; + int result; + + union + { + double* __n; + ieee_double_t* n; + } n; + + n.__n = &__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n.n->exponent - (unsigned int)0x3ff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) + { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == L'e' || exp_sign == L'E' ) + { + frac = modf(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = wnumberf(f,__n/pow(10.0L,e),L'f',size-4, precision, type); + if (result < 0) + return false; + f += exp_sign; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = wnumber(f,ie, 10,2, 2,type ); + if (result < 0) + return false; + return true; + } + + if ( exp_sign == L'f' ) + { + buf = (wchar_t*)alloca(4096*sizeof(wchar_t)); + if (type & LEFT) + type &= ~ZEROPAD; + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) + { + if (__n < 0) + { + sign = L'-'; + __n = fabs(__n); + size--; + } + else if (type & PLUS) + { + sign = L'+'; + size--; + } + else if (type & SPACE) + { + sign = L' '; + size--; + } + } + + frac = modf(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + + if ( precision > 0 ) { + //frac = modfl(__n,&intr); + i = precision-1; + while ( i >= 0 ) { + frac*=10.0L; + frac = modf(frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) { + buf[i++] = L'.'; + size--; + } + } + + if ( intr == 0.0 ) { + buf[i++] = L'0'; + size--; + } + else { + while ( intr > 0.0 ) { + p = intr; + intr/=10.0L; + modf(intr, &intr); + + p -= 10.0*intr; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += L' '; + } + if (sign) + { + f += sign; + } + + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + { + f += L' '; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + f += c; + } + + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) + { + j = 0; + while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) + { + tmp++; + i--; + } + } + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += L' '; + } + } + return true; +} + +static bool +numberfl(std::string& f, long double __n, char exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + //int x; + char *buf, *tmp; + int i = 0; + int j = 0; + //int k = 0; + + long double frac, intr; + long double p; + char sign; + char c; + char ro = 0; + + int result; + + union + { + long double* __n; + ieee_long_double_t* n; + } n; + + n.__n = &__n; + + if ( exp_sign == 'g' || exp_sign == 'G' || exp_sign == 'e' || exp_sign == 'E' ) { + ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == 'g' || exp_sign == 'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + if ( exp_sign == 'e' || exp_sign == 'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = numberf(f,__n/powl(10.0L,e),'f',size-4, precision, type); + if (result < 0) + return false; + f += exp_sign; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = number(f,ie, 10,2, 2,type ); + if (result < 0) + return false; + return true; + + } + + if ( exp_sign == 'f' ) + { + + buf = (char*)alloca(4096); + if (type & LEFT) + { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) + { + if (__n < 0) + { + sign = '-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) + { + sign = '+'; + size--; + } else if (type & SPACE) + { + sign = ' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) + { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) + { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + '0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) + { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) + { + buf[i++] = '.'; + size--; + } + } + + if ( intr == 0.0 ) + { + buf[i++] = '0'; + size--; + } + else + { + while ( intr > 0.0 ) + { + p=intr; + intr/=10.0L; + modfl(intr, &intr); + + p -= 10.0L*intr; + + buf[i++] = (int)p + '0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= '0' && buf[j] <= '8' ) + { + buf[j]++; + ro = 0; + } + else if ( buf[j] == '9' ) + { + buf[j] = '0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = '1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += ' '; + } + if (sign) + { + f += sign; + } + + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += ' '; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + f += c; + } + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) + { + j = 0; + while ( j < i && ( *tmp == '0' || *tmp == '.' )) + { + tmp++; + i--; + } + } + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += ' '; + } + } + return true; +} + +static bool +wnumberfl(std::wstring& f, long double __n, wchar_t exp_sign, int size, int precision, int type) +{ + long double exponent = 0.0; + long double e; + long ie; + + wchar_t *buf, *tmp, sign, c, ro = 0; + int i = 0; + int j = 0; + + long double frac, intr; + long double p; + + int result; + + union + { + long double* __n; + ieee_long_double_t* n; + } n; + + n.__n = &__n; + + if ( exp_sign == L'g' || exp_sign == L'G' || exp_sign == L'e' || exp_sign == L'E' ) { + ie = ((unsigned int)n.n->exponent - (unsigned int)0x3fff); + exponent = ie/3.321928; + } + + if ( exp_sign == L'g' || exp_sign == L'G' ) { + type |= ZEROTRUNC; + if ( exponent < -4 || fabs(exponent) >= precision ) + exp_sign -= 2; // g -> e and G -> E + } + + + if ( exp_sign == L'e' || exp_sign == L'E' ) { + frac = modfl(exponent,&e); + if ( frac > 0.5 ) + e++; + else if ( frac < -0.5 ) + e--; + + result = wnumberf(f,__n/powl(10.0L,e),L'f',size-4, precision, type); + if (result < 0) + return false; + f += exp_sign; + size--; + ie = (long)e; + type = LEFT | PLUS; + if ( ie < 0 ) + type |= SIGN; + + result = wnumber(f,ie, 10,2, 2,type ); + if (result < 0) + return false; + return true; + } + + if ( exp_sign == L'f' ) + { + + buf = (wchar_t*)alloca(4096*sizeof(wchar_t)); + if (type & LEFT) + { + type &= ~ZEROPAD; + } + + c = (type & ZEROPAD) ? L'0' : L' '; + sign = 0; + if (type & SIGN) + { + if (__n < 0) + { + sign = L'-'; + __n = fabs(__n); + size--; + } else if (type & PLUS) + { + sign = L'+'; + size--; + } else if (type & SPACE) + { + sign = L' '; + size--; + } + } + + frac = modfl(__n,&intr); + + // # flags forces a . and prevents trucation of trailing zero's + if ( precision > 0 ) + { + //frac = modfl(__n,&intr); + + i = precision-1; + while ( i >= 0 ) + { + frac*=10.0L; + frac = modfl((long double)frac, &p); + buf[i] = (int)p + L'0'; + i--; + } + i = precision; + size -= precision; + + ro = 0; + if ( frac > 0.5 ) + { + ro = 1; + } + + if ( precision >= 1 || type & SPECIAL) + { + buf[i++] = L'.'; + size--; + } + } + + if ( intr == 0.0 ) + { + buf[i++] = L'0'; + size--; + } + else + { + while ( intr > 0.0 ) + { + p=intr; + intr/=10.0L; + modfl(intr, &intr); + + p -= 10.0L*intr; + + buf[i++] = (int)p + L'0'; + size--; + } + } + + j = 0; + while ( j < i && ro == 1) { + if ( buf[j] >= L'0' && buf[j] <= L'8' ) + { + buf[j]++; + ro = 0; + } + else if ( buf[j] == L'9' ) + { + buf[j] = L'0'; + } + j++; + } + if ( ro == 1 ) + buf[i++] = L'1'; + + buf[i] = 0; + + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += L' '; + } + if (sign) + { + f += sign; + } + + if (!(type&(ZEROPAD+LEFT))) + { + while(size-->0) + f += L' '; + } + if (type & SPECIAL) { + } + + if (!(type & LEFT)) + while (size-- > 0) + { + f += c; + } + tmp = buf; + if ( type & ZEROTRUNC && ((type & SPECIAL) != SPECIAL) ) + { + j = 0; + while ( j < i && ( *tmp == L'0' || *tmp == L'.' )) + { + tmp++; + i--; + } + } + while (i-- > 0) + { + f += tmp[i]; + } + while (size-- > 0) + { + f += L' '; + } + } + return true; +} + +static int +do_string(std::string& f, const char* s, int len, int field_width, int precision, int flags) +{ + int i, done = 0; + if (s == NULL) + { + s = ""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while ((unsigned int)len < (unsigned int)precision && s[len]) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + f += ' '; + done++; + } + for (i = 0; i < len; ++i) + { + f += *s++; + done++; + } + while (len < field_width--) + { + f += ' '; + done++; + } + return done; +} + +static int +do_wstring(std::wstring& f, const wchar_t* s, int len, int field_width, int precision, int flags) +{ + int i, done = 0; + if (s == NULL) + { + s = L""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while ((unsigned int)len < (unsigned int)precision && s[len]) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + f += L' '; + done++; + } + for (i = 0; i < len; ++i) + { + f += *s++; + done++; + } + while (len < field_width--) + { + f += L' '; + done++; + } + return done; +} + +static int +stringw(std::string& f, const wchar_t* sw, int len, int field_width, int precision, int flags) +{ + int i, done = 0; + if (sw == NULL) + { + sw = L""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while ((unsigned int)len < (unsigned int)precision && sw[len]) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + f += ' '; + done++; + } + for (i = 0; i < len; ++i) + { +#define MY_MB_CUR_MAX 1 + char mb[MY_MB_CUR_MAX]; + int mbcount, j; + mbcount = wctomb(mb, *sw++); + if (mbcount <= 0) + { + break; + } + for (j = 0; j < mbcount; j++) + { + f += mb[j]; + done++; + } + } + while (len < field_width--) + { + f += ' '; + done++; + } + return done; +} + +static int +wstringa(std::wstring& f, const char* sa, int len, int field_width, int precision, int flags) +{ + int i, done = 0; + if (sa == NULL) + { + sa = ""; + len = 6; + } + else + { + if (len == -1) + { + len = 0; + while ((unsigned int)len < (unsigned int)precision && sa[len]) + len++; + } + else + { + if ((unsigned int)len > (unsigned int)precision) + len = precision; + } + } + if (!(flags & LEFT)) + while (len < field_width--) + { + f += L' '; + done++; + } + for (i = 0; i < len;) + { + wchar_t w; + int mbcount; + mbcount = mbtowc(&w, sa, len-i); + if (mbcount <= 0) + break; + f += w; + done++; + i += mbcount; + } + while (len < field_width--) + { + f += L' '; + done++; + } + return done; +} + +#define _isnanl _isnan +#define _finitel _finite + +std::string +ssvprintf ( const char *fmt, va_list args ) +{ + ULONGLONG num; + int base; + long double _ldouble; + double _double; + const char *s; + const wchar_t* sw; + int result; + std::string f; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */ + + for (; *fmt ; ++fmt) + { + if (*fmt != '%') + { + f += *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (isdigit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = 0; + // %Z can be just stand alone or as size_t qualifier + if ( *fmt == 'Z' ) { + qualifier = *fmt; + switch ( *(fmt+1)) { + case 'o': + case 'b': + case 'X': + case 'x': + case 'd': + case 'i': + case 'u': + ++fmt; + break; + default: + break; + } + } else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == 'I' && *(fmt+1) == '6' && *(fmt+2) == '4') { + qualifier = *fmt; + fmt += 3; + } + + // go fine with ll instead of L + if ( *fmt == 'l' ) { + ++fmt; + qualifier = 'L'; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + { + f += ' '; + } + if (qualifier == 'l' || qualifier == 'w') + { + f += (char)(unsigned char)(wchar_t) va_arg(args,int); + } + else + { + f += (char)(unsigned char) va_arg(args,int); + } + while (--field_width > 0) + { + f += ' '; + } + continue; + + case 'C': + if (!(flags & LEFT)) + while (--field_width > 0) + { + f += ' '; + } + if (qualifier == 'h') + { + f += (char)(unsigned char) va_arg(args,int); + } + else + { + f += (char)(unsigned char)(wchar_t) va_arg(args,int); + } + while (--field_width > 0) + { + f += ' '; + } + continue; + + case 's': + if (qualifier == 'l' || qualifier == 'w') { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + result = stringw(f, sw, -1, field_width, precision, flags); + } else { + /* print ascii string */ + s = va_arg(args, char *); + result = do_string(f, s, -1, field_width, precision, flags); + } + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + continue; + + case 'S': + if (qualifier == 'h') { + /* print ascii string */ + s = va_arg(args, char *); + result = do_string(f, s, -1, field_width, precision, flags); + } else { + /* print unicode string */ + sw = va_arg(args, wchar_t *); + result = stringw(f, sw, -1, field_width, precision, flags); + } + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + continue; + + /*case 'Z': + if (qualifier == 'w') { + // print counted unicode string + PUNICODE_STRING pus = va_arg(args, PUNICODE_STRING); + if ((pus == NULL) || (pus->Buffer == NULL)) { + sw = NULL; + len = -1; + } else { + sw = pus->Buffer; + len = pus->Length / sizeof(WCHAR); + } + result = stringw(f, sw, len, field_width, precision, flags); + } else { + // print counted ascii string + PANSI_STRING pas = va_arg(args, PANSI_STRING); + if ((pas == NULL) || (pas->Buffer == NULL)) { + s = NULL; + len = -1; + } else { + s = pas->Buffer; + len = pas->Length; + } + result = string(f, s, -1, field_width, precision, flags); + } + if (result < 0) + return -1; + continue;*/ + + case 'e': + case 'E': + case 'f': + case 'g': + case 'G': + if (qualifier == 'l' || qualifier == 'L' ) { + _ldouble = va_arg(args, long double); + + if ( _isnanl(_ldouble) ) + { + f += "Nan"; + } + else if ( !_finitel(_ldouble) ) + { + if ( _ldouble < 0 ) + f += "-Inf"; + else + f += "+Inf"; + } else { + if ( precision == -1 ) + precision = 6; + result = numberfl(f,_ldouble,*fmt,field_width,precision,flags); + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + } + } else { + _double = (double)va_arg(args, double); + + if ( _isnan(_double) ) + { + f += "Nan"; + } + else if ( !_finite(_double) ) + { + if ( _double < 0 ) + f += "-Inf"; + else + f += "+Inf"; + } + else + { + if ( precision == -1 ) + precision = 6; + result = numberf(f,_double,*fmt,field_width,precision,flags); + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + } + } + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + result = number(f, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + continue; + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = 0; + } else { + int * ip = va_arg(args, int *); + *ip = 0; + } + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'b': + base = 2; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + if (*fmt != '%') + { + f += '%'; + } + if (*fmt) + { + f += *fmt; + } + else + --fmt; + continue; + } + + if (qualifier == 'I') + num = va_arg(args, ULONGLONG); + else if (qualifier == 'l') { + if (flags & SIGN) + num = va_arg(args, long); + else + num = va_arg(args, unsigned long); + } + else if (qualifier == 'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + result = number(f, num, base, field_width, precision, flags); + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + } + //putc('\0',f); + return f; +} + +std::wstring +sswvprintf ( const wchar_t* fmt, va_list args ) +{ + ULONGLONG num; + int base; + long double _ldouble; + double _double; + const wchar_t* s; + const char* sa; + int result; + std::wstring f; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier = 0; /* 'h', 'l', 'L' or 'I64' for integer fields */ + + for (; *fmt ; ++fmt) + { + if (*fmt != L'%') + { + f += *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case L'-': flags |= LEFT; goto repeat; + case L'+': flags |= PLUS; goto repeat; + case L' ': flags |= SPACE; goto repeat; + case L'#': flags |= SPECIAL; goto repeat; + case L'0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (isdigit(*fmt)) + field_width = skip_wtoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == L'.') { + ++fmt; + if (iswdigit(*fmt)) + precision = skip_wtoi(&fmt); + else if (*fmt == L'*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = 0; + // %Z can be just stand alone or as size_t qualifier + if ( *fmt == L'Z' ) { + qualifier = *fmt; + switch ( *(fmt+1)) { + case L'o': + case L'b': + case L'X': + case L'x': + case L'd': + case L'i': + case L'u': + ++fmt; + break; + default: + break; + } + } else if (*fmt == L'h' || *fmt == L'l' || *fmt == L'L' || *fmt == L'w') { + qualifier = *fmt; + ++fmt; + } else if (*fmt == L'I' && *(fmt+1) == L'6' && *(fmt+2) == L'4') { + qualifier = *fmt; + fmt += 3; + } + + // go fine with ll instead of L + if ( *fmt == L'l' ) { + ++fmt; + qualifier = L'L'; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case L'c': + if (!(flags & LEFT)) + while (--field_width > 0) + { + f += L' '; + } + if ( qualifier == L'h' ) + { + f += (wchar_t)(char)(unsigned char) va_arg(args,int); + } + else + { + f += (wchar_t) va_arg(args,int); + } + while (--field_width > 0) + { + f += ' '; + } + continue; + + case 'C': + if (!(flags & LEFT)) + while (--field_width > 0) + { + f += L' '; + } + if (qualifier == L'l' || qualifier == L'w') + { + f += (wchar_t) va_arg(args,int); + } + else + { + f += (wchar_t)(char)(unsigned char) va_arg(args,int); + } + while (--field_width > 0) + { + f += L' '; + } + continue; + + case 's': + if (qualifier == L'h') { + /* print ascii string */ + sa = va_arg(args, char *); + result = wstringa(f, sa, -1, field_width, precision, flags); + } else { + /* print unicode string */ + s = va_arg(args, wchar_t *); + result = do_wstring(f, s, -1, field_width, precision, flags); + } + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + continue; + + case 'S': + if (qualifier == L'l' || qualifier == L'w') { + /* print unicode string */ + s = va_arg(args, wchar_t *); + result = do_wstring(f, s, -1, field_width, precision, flags); + } else { + /* print ascii string */ + sa = va_arg(args, char *); + result = wstringa(f, sa, -1, field_width, precision, flags); + } + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + continue; + + case L'e': + case L'E': + case L'f': + case L'g': + case L'G': + if (qualifier == L'l' || qualifier == L'L' ) + { + _ldouble = va_arg(args, long double); + + if ( _isnanl(_ldouble) ) + { + f += L"Nan"; + } + else if ( !_finitel(_ldouble) ) + { + if ( _ldouble < 0 ) + f += L"-Inf"; + else + f += L"+Inf"; + } else { + if ( precision == -1 ) + precision = 6; + result = wnumberfl(f,_ldouble,*fmt,field_width,precision,flags); + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + } + } else { + _double = (double)va_arg(args, double); + + if ( _isnan(_double) ) + { + f += L"Nan"; + } + else if ( !_finite(_double) ) + { + if ( _double < 0 ) + f += L"-Inf"; + else + f += L"+Inf"; + } + else + { + if ( precision == -1 ) + precision = 6; + result = wnumberf(f,_double,*fmt,field_width,precision,flags); + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + } + } + continue; + + case L'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + result = wnumber(f, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + continue; + + case L'n': + if (qualifier == L'l') { + long * ip = va_arg(args, long *); + *ip = 0; + } else { + int * ip = va_arg(args, int *); + *ip = 0; + } + continue; + + /* integer number formats - set up the flags and "break" */ + case L'o': + base = 8; + break; + + case L'b': + base = 2; + break; + + case L'X': + flags |= LARGE; + case L'x': + base = 16; + break; + + case L'd': + case L'i': + flags |= SIGN; + case L'u': + break; + + default: + if (*fmt != L'%') + { + f += L'%'; + } + if (*fmt) + { + f += *fmt; + } + else + --fmt; + continue; + } + + if (qualifier == L'I') + num = va_arg(args, ULONGLONG); + else if (qualifier == L'l') { + if (flags & SIGN) + num = va_arg(args, long); + else + num = va_arg(args, unsigned long); + } + else if (qualifier == L'h') { + if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + } + else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + result = wnumber(f, num, base, field_width, precision, flags); + if (result < 0) + { + assert(!"TODO FIXME handle error better"); + return f; + } + } + //putc('\0',f); + return f; +} diff --git a/reactos/tools/buildno/ssprintf.h b/reactos/tools/buildno/ssprintf.h new file mode 100644 index 00000000000..c7a6d2d2595 --- /dev/null +++ b/reactos/tools/buildno/ssprintf.h @@ -0,0 +1,23 @@ +// ssprintf.h + +#ifndef SSPRINTF_H +#define SSPRINTF_H + +#include +#include + +std::string ssprintf ( const char* fmt, ... ); +std::string ssvprintf ( const char* fmt, va_list args ); + +std::wstring sswprintf ( const wchar_t* fmt, ... ); +std::wstring sswvprintf ( const wchar_t* fmt, va_list args ); + +#ifdef _UNICODE +#define sstprintf sswprintf +#define sstvprintf sswvprintf +#else +#define sstprintf ssprintf +#define sstvprintf ssvprintf +#endif + +#endif//SSPRINTF_H