Refactored InfoSink. I have replaced most instances of sprintf with std::ostringstream to make it safer. I have made sure that everything still compiles and passes conformance tests.
Review URL: http://codereview.appspot.com/1391041
git-svn-id: https://angleproject.googlecode.com/svn/trunk@322 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/Common.h b/src/compiler/Common.h
index 79c5871..1c1e5c6 100644
--- a/src/compiler/Common.h
+++ b/src/compiler/Common.h
@@ -7,16 +7,16 @@
#ifndef _COMMON_INCLUDED_
#define _COMMON_INCLUDED_
-#include <assert.h>
-#include <stdio.h>
-
#include <map>
+#include <sstream>
#include <string>
#include <vector>
#include "compiler/PoolAlloc.h"
typedef int TSourceLoc;
+const unsigned int SourceLocLineMask = 0xffff;
+const unsigned int SourceLocStringShift = 16;
//
// Put POOL_ALLOCATOR_NEW_DELETE in base classes to make them use this scheme.
@@ -35,7 +35,8 @@
// Pool version of string.
//
typedef pool_allocator<char> TStringAllocator;
-typedef std::basic_string <char, std::char_traits<char>, TStringAllocator > TString;
+typedef std::basic_string <char, std::char_traits<char>, TStringAllocator> TString;
+typedef std::basic_ostringstream<char, std::char_traits<char>, TStringAllocator> TStringStream;
inline TString* NewPoolTString(const char* s)
{
void* memory = GlobalPoolAllocator.allocate(sizeof(TString));
@@ -43,6 +44,13 @@
}
//
+// Persistent string memory. Should only be used for strings that survive
+// across compiles/links.
+//
+#define TPersistString std::string
+#define TPersistStringStream std::ostringstream
+
+//
// Pool allocator versions of vectors, lists, and maps
//
template <class T> class TVector : public std::vector<T, pool_allocator<T> > {
@@ -63,49 +71,6 @@
TMap(const tAllocator& a) : std::map<K, D, CMP, tAllocator>(std::map<K, D, CMP, tAllocator>::key_compare(), a) {}
};
-//
-// Persistent string memory. Should only be used for strings that survive
-// across compiles/links.
-//
-typedef std::basic_string<char> TPersistString;
-
-//
-// Create a TString object from an integer.
-//
-inline const TString String(const int i, const int base = 10)
-{
- char text[16]; // 32 bit ints are at most 10 digits in base 10
-
- #ifdef _WIN32
- _itoa(i, text, base);
- #else
- // we assume base 10 for all cases
- sprintf(text, "%d", i);
- #endif
-
- return text;
-}
-
-const unsigned int SourceLocLineMask = 0xffff;
-const unsigned int SourceLocStringShift = 16;
-
-__inline TPersistString FormatSourceLoc(const TSourceLoc loc)
-{
- char locText[64];
-
- int string = loc >> SourceLocStringShift;
- int line = loc & SourceLocLineMask;
-
- if (line)
- sprintf(locText, "%d:%d", string, line);
- else
- sprintf(locText, "%d:? ", string);
-
- return TPersistString(locText);
-}
-
-
typedef TMap<TString, TString> TPragmaTable;
-typedef TMap<TString, TString>::tAllocator TPragmaTableAllocator;
#endif // _COMMON_INCLUDED_
diff --git a/src/compiler/ConstantUnion.h b/src/compiler/ConstantUnion.h
index 1fdb61d..cf531ea 100644
--- a/src/compiler/ConstantUnion.h
+++ b/src/compiler/ConstantUnion.h
@@ -7,6 +7,7 @@
#ifndef _CONSTANT_UNION_INCLUDED_
#define _CONSTANT_UNION_INCLUDED_
+#include <assert.h>
class ConstantUnion {
public:
diff --git a/src/compiler/InfoSink.cpp b/src/compiler/InfoSink.cpp
index 6690d88..317a88f 100644
--- a/src/compiler/InfoSink.cpp
+++ b/src/compiler/InfoSink.cpp
@@ -6,50 +6,54 @@
#include "compiler/InfoSink.h"
-#ifdef _WIN32
- #include <windows.h>
-#endif
-
-void TInfoSinkBase::append(const char *s)
-{
- if (outputStream & EString) {
- checkMem(strlen(s));
- sink.append(s);
+void TInfoSinkBase::prefix(TPrefixType message) {
+ switch(message) {
+ case EPrefixNone:
+ break;
+ case EPrefixWarning:
+ sink.append("WARNING: ");
+ break;
+ case EPrefixError:
+ sink.append("ERROR: ");
+ break;
+ case EPrefixInternalError:
+ sink.append("INTERNAL ERROR: ");
+ break;
+ case EPrefixUnimplemented:
+ sink.append("UNIMPLEMENTED: ");
+ break;
+ case EPrefixNote:
+ sink.append("NOTE: ");
+ break;
+ default:
+ sink.append("UNKOWN ERROR: ");
+ break;
}
-
- if (outputStream & EStdOut)
- fprintf(stdout, "%s", s);
}
-void TInfoSinkBase::append(int count, char c)
-{
- if (outputStream & EString) {
- checkMem(count);
- sink.append(count, c);
- }
+void TInfoSinkBase::location(TSourceLoc loc) {
+ int string = loc >> SourceLocStringShift;
+ int line = loc & SourceLocLineMask;
- if (outputStream & EStdOut)
- fprintf(stdout, "%c", c);
+ TPersistStringStream stream;
+ if (line)
+ stream << string << ":" << line;
+ else
+ stream << string << ":? ";
+ stream << ": ";
+
+ sink.append(stream.str());
}
-void TInfoSinkBase::append(const TPersistString& t)
-{
- if (outputStream & EString) {
- checkMem(t.size());
- sink.append(t);
- }
-
- if (outputStream & EStdOut)
- fprintf(stdout, "%s", t.c_str());
+void TInfoSinkBase::message(TPrefixType message, const char* s) {
+ prefix(message);
+ sink.append(s);
+ sink.append("\n");
}
-void TInfoSinkBase::append(const TString& t)
-{
- if (outputStream & EString) {
- checkMem(t.size());
- sink.append(t.c_str());
- }
-
- if (outputStream & EStdOut)
- fprintf(stdout, "%s", t.c_str());
+void TInfoSinkBase::message(TPrefixType message, const char* s, TSourceLoc loc) {
+ prefix(message);
+ location(loc);
+ sink.append(s);
+ sink.append("\n");
}
diff --git a/src/compiler/InfoSink.h b/src/compiler/InfoSink.h
index 6ddf6b0..5c25c03 100644
--- a/src/compiler/InfoSink.h
+++ b/src/compiler/InfoSink.h
@@ -8,7 +8,6 @@
#define _INFOSINK_INCLUDED_
#include <math.h>
-
#include "compiler/Common.h"
// Returns the fractional part of the given floating-point number.
@@ -30,11 +29,6 @@
EPrefixNote
};
-enum TOutputStream {
- ENull = 0,
- EStdOut = 0x01,
- EString = 0x02,
-};
//
// Encapsulate info logs for all objects that have them.
//
@@ -43,72 +37,68 @@
//
class TInfoSinkBase {
public:
- TInfoSinkBase() : outputStream(EString) {}
- void erase() { sink.erase(); }
- TInfoSinkBase& operator<<(const TPersistString& t) { append(t); return *this; }
- TInfoSinkBase& operator<<(char c) { append(1, c); return *this; }
- TInfoSinkBase& operator<<(const char* s) { append(s); return *this; }
- TInfoSinkBase& operator<<(int n) { append(String(n)); return *this; }
- TInfoSinkBase& operator<<(const unsigned int n) { append(String(n)); return *this; }
- TInfoSinkBase& operator<<(float n) {
- char buf[40];
- // Make sure that at least one decimal point is written. If a number
- // does not have a fractional part, %g does not written the decimal
- // portion which gets interpreted as integer by the compiler.
- const char* format = fractionalPart(n) == 0.0f ? "%.1f" : "%.8g";
- sprintf(buf, format, n);
- append(buf);
+ TInfoSinkBase() {}
+
+ template <typename T>
+ TInfoSinkBase& operator<<(const T& t) {
+ TPersistStringStream stream;
+ stream << t;
+ sink.append(stream.str());
return *this;
}
- TInfoSinkBase& operator+(const TPersistString& t) { append(t); return *this; }
- TInfoSinkBase& operator+(const TString& t) { append(t); return *this; }
- TInfoSinkBase& operator<<(const TString& t) { append(t); return *this; }
- TInfoSinkBase& operator+(const char* s) { append(s); return *this; }
- const char* c_str() const { return sink.c_str(); }
- void prefix(TPrefixType message) {
- switch(message) {
- case EPrefixNone: break;
- case EPrefixWarning: append("WARNING: "); break;
- case EPrefixError: append("ERROR: "); break;
- case EPrefixInternalError: append("INTERNAL ERROR: "); break;
- case EPrefixUnimplemented: append("UNIMPLEMENTED: "); break;
- case EPrefixNote: append("NOTE: "); break;
- default: append("UNKOWN ERROR: "); break;
+ // Override << operator for specific types. It is faster to append strings
+ // and characters directly to the sink.
+ TInfoSinkBase& operator<<(char c) {
+ sink.append(1, c);
+ return *this;
+ }
+ TInfoSinkBase& operator<<(const char* str) {
+ sink.append(str);
+ return *this;
+ }
+ TInfoSinkBase& operator<<(const TPersistString& str) {
+ sink.append(str);
+ return *this;
+ }
+ TInfoSinkBase& operator<<(const TString& str) {
+ sink.append(str.c_str());
+ return *this;
+ }
+ // Make sure floats are written with correct precision.
+ TInfoSinkBase& operator<<(float f) {
+ // Make sure that at least one decimal point is written. If a number
+ // does not have a fractional part, the default precision format does
+ // not write the decimal portion which gets interpreted as integer by
+ // the compiler.
+ TPersistStringStream stream;
+ if (fractionalPart(f) == 0.0f) {
+ stream.precision(2);
+ stream << std::showpoint << f;
+ } else {
+ stream << f;
}
+ sink.append(stream.str());
+ return *this;
}
- void location(TSourceLoc loc) {
- append(FormatSourceLoc(loc).c_str());
- append(": ");
- }
- void message(TPrefixType message, const char* s) {
- prefix(message);
- append(s);
- append("\n");
- }
- void message(TPrefixType message, const char* s, TSourceLoc loc) {
- prefix(message);
- location(loc);
- append(s);
- append("\n");
- }
-
- void setOutputStream(int output = 4)
- {
- outputStream = output;
+ // Write boolean values as their names instead of integral value.
+ TInfoSinkBase& operator<<(bool b) {
+ const char* str = b ? "true" : "false";
+ sink.append(str);
+ return *this;
}
-protected:
- void append(const char *s);
+ void erase() { sink.clear(); }
- void append(int count, char c);
- void append(const TPersistString& t);
- void append(const TString& t);
+ const TPersistString& str() const { return sink; }
+ const char* c_str() const { return sink.c_str(); }
- void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2)
- sink.reserve(sink.capacity() + sink.capacity() / 2); }
- void appendToStream(const char* s);
+ void prefix(TPrefixType message);
+ void location(TSourceLoc loc);
+ void message(TPrefixType message, const char* s);
+ void message(TPrefixType message, const char* s, TSourceLoc loc);
+
+private:
TPersistString sink;
- int outputStream;
};
class TInfoSink {
diff --git a/src/compiler/Initialize.cpp b/src/compiler/Initialize.cpp
index ab61528..ebd23fb 100644
--- a/src/compiler/Initialize.cpp
+++ b/src/compiler/Initialize.cpp
@@ -477,37 +477,21 @@
void TBuiltIns::initialize(const TBuiltInResource &resources)
{
- TString builtIns;
+ TStringStream builtIns;
// Implementation dependent constants
- char builtInConstant[80];
+ builtIns << "const int gl_MaxVertexAttribs = " << resources.maxVertexAttribs << ";";
+ builtIns << "const int gl_MaxVertexUniformVectors = " << resources.maxVertexUniformVectors << ";";
- sprintf(builtInConstant, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
- builtIns.append(TString(builtInConstant));
+ builtIns << "const int gl_MaxVaryingVectors = " << resources.maxVaryingVectors << ";";
+ builtIns << "const int gl_MaxVertexTextureImageUnits = " << resources.maxVertexTextureImageUnits << ";";
+ builtIns << "const int gl_MaxCombinedTextureImageUnits = " << resources.maxCombinedTextureImageUnits << ";";
+ builtIns << "const int gl_MaxTextureImageUnits = " << resources.maxTextureImageUnits << ";";
+ builtIns << "const int gl_MaxFragmentUniformVectors = " << resources.maxFragmentUniformVectors << ";";
+ builtIns << "const int gl_MaxDrawBuffers = " << resources.maxDrawBuffers << ";";
- sprintf(builtInConstant, "const int gl_MaxVertexUniformVectors = %d;", resources.maxVertexUniformVectors);
- builtIns.append(TString(builtInConstant));
-
- sprintf(builtInConstant, "const int gl_MaxVaryingVectors = %d;", resources.maxVaryingVectors);
- builtIns.append(TString(builtInConstant));
-
- sprintf(builtInConstant, "const int gl_MaxVertexTextureImageUnits = %d;", resources.maxVertexTextureImageUnits);
- builtIns.append(TString(builtInConstant));
-
- sprintf(builtInConstant, "const int gl_MaxCombinedTextureImageUnits = %d;", resources.maxCombinedTextureImageUnits);
- builtIns.append(TString(builtInConstant));
-
- sprintf(builtInConstant, "const int gl_MaxTextureImageUnits = %d;", resources.maxTextureImageUnits);
- builtIns.append(TString(builtInConstant));
-
- sprintf(builtInConstant, "const int gl_MaxFragmentUniformVectors = %d;", resources.maxFragmentUniformVectors);
- builtIns.append(TString(builtInConstant));
-
- sprintf(builtInConstant, "const int gl_MaxDrawBuffers = %d;", resources.maxDrawBuffers);
- builtIns.append(TString(builtInConstant));
-
- builtInStrings[EShLangFragment].push_back(builtIns);
- builtInStrings[EShLangVertex].push_back(builtIns);
+ builtInStrings[EShLangFragment].push_back(builtIns.str());
+ builtInStrings[EShLangVertex].push_back(builtIns.str());
}
void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable)
diff --git a/src/compiler/OutputGLSL.cpp b/src/compiler/OutputGLSL.cpp
index 66ff473..4209b40 100644
--- a/src/compiler/OutputGLSL.cpp
+++ b/src/compiler/OutputGLSL.cpp
@@ -183,12 +183,7 @@
{
case EbtFloat: out << pConstUnion->getFConst(); break;
case EbtInt: out << pConstUnion->getIConst(); break;
- case EbtBool:
- if (pConstUnion->getBConst())
- out << "true";
- else
- out << "false";
- break;
+ case EbtBool: out << pConstUnion->getBConst(); break;
default: UNREACHABLE();
}
if (i != size - 1) out << ", ";
diff --git a/src/compiler/OutputHLSL.cpp b/src/compiler/OutputHLSL.cpp
index 66d0e83..774d596 100644
--- a/src/compiler/OutputHLSL.cpp
+++ b/src/compiler/OutputHLSL.cpp
@@ -2085,16 +2085,7 @@
{
case EbtFloat: out << constUnion->getFConst(); break;
case EbtInt: out << constUnion->getIConst(); break;
- case EbtBool:
- if (constUnion->getBConst())
- {
- out << "true";
- }
- else
- {
- out << "false";
- }
- break;
+ case EbtBool: out << constUnion->getBConst(); break;
default: UNREACHABLE();
}
diff --git a/src/compiler/SymbolTable.h b/src/compiler/SymbolTable.h
index fa6e64d..87c6e8a 100644
--- a/src/compiler/SymbolTable.h
+++ b/src/compiler/SymbolTable.h
@@ -30,6 +30,7 @@
// are tracked in the intermediate representation, not the symbol table.
//
+#include <assert.h>
#include "compiler/Common.h"
#include "compiler/intermediate.h"
#include "compiler/InfoSink.h"
diff --git a/src/compiler/Types.h b/src/compiler/Types.h
index fca0ac1..813250a 100644
--- a/src/compiler/Types.h
+++ b/src/compiler/Types.h
@@ -7,6 +7,7 @@
#ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED
+#include <assert.h>
#include "compiler/Common.h"
#include "compiler/BaseTypes.h"
diff --git a/src/compiler/intermOut.cpp b/src/compiler/intermOut.cpp
index 70ead52..db042dd 100644
--- a/src/compiler/intermOut.cpp
+++ b/src/compiler/intermOut.cpp
@@ -37,22 +37,20 @@
TString TType::getCompleteString() const
{
- char buf[100];
- char *p = &buf[0];
+ TStringStream stream;
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
- p += sprintf(p, "%s %s ", getQualifierString(), getPrecisionString());
+ stream << getQualifierString() << " " << getPrecisionString() << " ";
if (array)
- p += sprintf(p, "array of ");
+ stream << "array of ";
if (matrix)
- p += sprintf(p, "%dX%d matrix of ", size, size);
+ stream << size << "X" << size << " matrix of ";
else if (size > 1)
- p += sprintf(p, "%d-component vector of ", size);
+ stream << size << "-component vector of ";
- sprintf(p, "%s", getBasicString());
-
- return TString(buf);
-}
+ stream << getBasicString();
+ return stream.str();
+}
//
// Helper functions for printing, not part of traversing.
@@ -62,7 +60,7 @@
{
int i;
- infoSink.debug << FormatSourceLoc(node->getLine());
+ infoSink.debug.location(node->getLine());
for (i = 0; i < depth; ++i)
infoSink.debug << " ";
@@ -81,12 +79,8 @@
{
OutputTreeText(infoSink, node, depth);
- char buf[100];
- sprintf(buf, "'%s' (%s)\n",
- node->getSymbol().c_str(),
- node->getCompleteString().c_str());
-
- infoSink.debug << buf;
+ infoSink.debug << "'" << node->getSymbol() << "' ";
+ infoSink.debug << "(" << node->getCompleteString() << ")\n";
}
bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node)
@@ -317,7 +311,6 @@
int size = node->getType().getObjectSize();
- char buf[300];
for (int i = 0; i < size; i++) {
OutputTreeText(out, node, depth);
switch (node->getUnionArrayPointer()[i].getType()) {
@@ -331,12 +324,12 @@
out.debug << "\n";
break;
case EbtFloat:
- sprintf(buf, "%f (%s)", node->getUnionArrayPointer()[i].getFConst(), "const float");
- out.debug << buf << "\n";
+ out.debug << node->getUnionArrayPointer()[i].getFConst();
+ out.debug << " (const float)\n";
break;
case EbtInt:
- sprintf(buf, "%d (%s)", node->getUnionArrayPointer()[i].getIConst(), "const int");
- out.debug << buf << "\n";
+ out.debug << node->getUnionArrayPointer()[i].getIConst();
+ out.debug << " (const int)\n";
break;
default:
out.info.message(EPrefixInternalError, "Unknown constant", node->getLine());
diff --git a/src/compiler/parseConst.cpp b/src/compiler/parseConst.cpp
index 4b130e9..833d429 100644
--- a/src/compiler/parseConst.cpp
+++ b/src/compiler/parseConst.cpp
@@ -63,9 +63,10 @@
TQualifier qualifier = node->getType().getQualifier();
if (qualifier != EvqConst) {
- char buf[200];
- sprintf(buf, "'constructor' : assigning non-constant to %s", type.getCompleteString().c_str());
- infoSink.info.message(EPrefixError, buf, node->getLine());
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
error = true;
return false;
}
@@ -77,9 +78,10 @@
bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node)
{
- char buf[200];
- sprintf(buf, "'constructor' : assigning non-constant to '%s'", type.getCompleteString().c_str());
- infoSink.info.message(EPrefixError, buf, node->getLine());
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
error = true;
return false;
}
@@ -87,9 +89,10 @@
bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node)
{
if (!node->isConstructor() && node->getOp() != EOpComma) {
- char buf[200];
- sprintf(buf, "'constructor' : assigning non-constant to '%s'", type.getCompleteString().c_str());
- infoSink.info.message(EPrefixError, buf, node->getLine());
+ TString buf;
+ buf.append("'constructor' : assigning non-constant to ");
+ buf.append(type.getCompleteString());
+ infoSink.info.message(EPrefixError, buf.c_str(), node->getLine());
error = true;
return false;
}