Commit 4e4facd4 by alokp@chromium.org

Refactored InfoSink. I have replaced most instances of sprintf with…

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
parent e37888d1
......@@ -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 @@ typedef int TSourceLoc;
// 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 @@ inline TString* NewPoolTString(const char* s)
}
//
// 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 @@ public:
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_
......@@ -7,6 +7,7 @@
#ifndef _CONSTANT_UNION_INCLUDED_
#define _CONSTANT_UNION_INCLUDED_
#include <assert.h>
class ConstantUnion {
public:
......
......@@ -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);
}
if (outputStream & EStdOut)
fprintf(stdout, "%c", c);
}
void TInfoSinkBase::location(TSourceLoc loc) {
int string = loc >> SourceLocStringShift;
int line = loc & SourceLocLineMask;
void TInfoSinkBase::append(const TPersistString& t)
{
if (outputStream & EString) {
checkMem(t.size());
sink.append(t);
}
TPersistStringStream stream;
if (line)
stream << string << ":" << line;
else
stream << string << ":? ";
stream << ": ";
if (outputStream & EStdOut)
fprintf(stdout, "%s", t.c_str());
sink.append(stream.str());
}
void TInfoSinkBase::append(const TString& t)
{
if (outputStream & EString) {
checkMem(t.size());
sink.append(t.c_str());
}
void TInfoSinkBase::message(TPrefixType message, const char* s) {
prefix(message);
sink.append(s);
sink.append("\n");
}
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");
}
......@@ -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 @@ enum TPrefixType {
EPrefixNote
};
enum TOutputStream {
ENull = 0,
EStdOut = 0x01,
EString = 0x02,
};
//
// Encapsulate info logs for all objects that have them.
//
......@@ -43,72 +37,68 @@ enum TOutputStream {
//
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;
}
void location(TSourceLoc loc) {
append(FormatSourceLoc(loc).c_str());
append(": ");
TInfoSinkBase& operator<<(const char* str) {
sink.append(str);
return *this;
}
void message(TPrefixType message, const char* s) {
prefix(message);
append(s);
append("\n");
TInfoSinkBase& operator<<(const TPersistString& str) {
sink.append(str);
return *this;
}
void message(TPrefixType message, const char* s, TSourceLoc loc) {
prefix(message);
location(loc);
append(s);
append("\n");
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 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(); }
const TPersistString& str() const { return sink; }
const char* c_str() const { return sink.c_str(); }
void append(int count, char c);
void append(const TPersistString& t);
void append(const TString& t);
void prefix(TPrefixType message);
void location(TSourceLoc loc);
void message(TPrefixType message, const char* s);
void message(TPrefixType message, const char* s, TSourceLoc loc);
void checkMem(size_t growth) { if (sink.capacity() < sink.size() + growth + 2)
sink.reserve(sink.capacity() + sink.capacity() / 2); }
void appendToStream(const char* s);
private:
TPersistString sink;
int outputStream;
};
class TInfoSink {
......
......@@ -477,37 +477,21 @@ void TBuiltIns::initialize()
void TBuiltIns::initialize(const TBuiltInResource &resources)
{
TString builtIns;
TStringStream builtIns;
// Implementation dependent constants
char builtInConstant[80];
sprintf(builtInConstant, "const int gl_MaxVertexAttribs = %d;", resources.maxVertexAttribs);
builtIns.append(TString(builtInConstant));
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);
builtIns << "const int gl_MaxVertexAttribs = " << resources.maxVertexAttribs << ";";
builtIns << "const int gl_MaxVertexUniformVectors = " << resources.maxVertexUniformVectors << ";";
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 << ";";
builtInStrings[EShLangFragment].push_back(builtIns.str());
builtInStrings[EShLangVertex].push_back(builtIns.str());
}
void IdentifyBuiltIns(EShLanguage language, TSymbolTable& symbolTable)
......
......@@ -183,12 +183,7 @@ const ConstantUnion* TOutputGLSL::writeConstantUnion(const TType& type,
{
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 << ", ";
......
......@@ -2085,16 +2085,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
{
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();
}
......
......@@ -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"
......
......@@ -7,6 +7,7 @@
#ifndef _TYPES_INCLUDED
#define _TYPES_INCLUDED
#include <assert.h>
#include "compiler/Common.h"
#include "compiler/BaseTypes.h"
......
......@@ -37,22 +37,20 @@ protected:
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 @@ void OutputTreeText(TInfoSink& infoSink, TIntermNode* node, const int depth)
{
int i;
infoSink.debug << FormatSourceLoc(node->getLine());
infoSink.debug.location(node->getLine());
for (i = 0; i < depth; ++i)
infoSink.debug << " ";
......@@ -81,12 +79,8 @@ void TOutputTraverser::visitSymbol(TIntermSymbol* node)
{
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 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
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 @@ void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node)
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());
......
......@@ -63,9 +63,10 @@ bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node)
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::visitBinary(Visit visit, TIntermBinary* node)
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::visitUnary(Visit visit, TIntermUnary* node)
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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment