1#include "SourcePos.h" 2 3#include <stdarg.h> 4#include <vector> 5 6using namespace std; 7 8 9// ErrorPos 10// ============================================================================= 11struct ErrorPos 12{ 13 enum Level { 14 NOTE, 15 WARNING, 16 ERROR 17 }; 18 19 String8 file; 20 int line; 21 String8 error; 22 Level level; 23 24 ErrorPos(); 25 ErrorPos(const ErrorPos& that); 26 ErrorPos(const String8& file, int line, const String8& error, Level level); 27 ErrorPos& operator=(const ErrorPos& rhs); 28 29 void print(FILE* to) const; 30}; 31 32static vector<ErrorPos> g_errors; 33 34ErrorPos::ErrorPos() 35 :line(-1), level(NOTE) 36{ 37} 38 39ErrorPos::ErrorPos(const ErrorPos& that) 40 :file(that.file), 41 line(that.line), 42 error(that.error), 43 level(that.level) 44{ 45} 46 47ErrorPos::ErrorPos(const String8& f, int l, const String8& e, Level lev) 48 :file(f), 49 line(l), 50 error(e), 51 level(lev) 52{ 53} 54 55ErrorPos& 56ErrorPos::operator=(const ErrorPos& rhs) 57{ 58 this->file = rhs.file; 59 this->line = rhs.line; 60 this->error = rhs.error; 61 this->level = rhs.level; 62 return *this; 63} 64 65void 66ErrorPos::print(FILE* to) const 67{ 68 const char* type = ""; 69 switch (level) { 70 case NOTE: 71 type = "note: "; 72 break; 73 case WARNING: 74 type = "warning: "; 75 break; 76 case ERROR: 77 type = "error: "; 78 break; 79 } 80 81 if (!this->file.isEmpty()) { 82 if (this->line >= 0) { 83 fprintf(to, "%s:%d: %s%s\n", this->file.string(), this->line, type, this->error.string()); 84 } else { 85 fprintf(to, "%s: %s%s\n", this->file.string(), type, this->error.string()); 86 } 87 } else { 88 fprintf(to, "%s%s\n", type, this->error.string()); 89 } 90} 91 92// SourcePos 93// ============================================================================= 94SourcePos::SourcePos(const String8& f, int l) 95 : file(f), line(l) 96{ 97} 98 99SourcePos::SourcePos(const SourcePos& that) 100 : file(that.file), line(that.line) 101{ 102} 103 104SourcePos::SourcePos() 105 : file("???", 0), line(-1) 106{ 107} 108 109SourcePos::~SourcePos() 110{ 111} 112 113void 114SourcePos::error(const char* fmt, ...) const 115{ 116 va_list ap; 117 va_start(ap, fmt); 118 String8 msg = String8::formatV(fmt, ap); 119 va_end(ap); 120 g_errors.push_back(ErrorPos(this->file, this->line, msg, ErrorPos::ERROR)); 121} 122 123void 124SourcePos::warning(const char* fmt, ...) const 125{ 126 va_list ap; 127 va_start(ap, fmt); 128 String8 msg = String8::formatV(fmt, ap); 129 va_end(ap); 130 ErrorPos(this->file, this->line, msg, ErrorPos::WARNING).print(stderr); 131} 132 133void 134SourcePos::printf(const char* fmt, ...) const 135{ 136 va_list ap; 137 va_start(ap, fmt); 138 String8 msg = String8::formatV(fmt, ap); 139 va_end(ap); 140 ErrorPos(this->file, this->line, msg, ErrorPos::NOTE).print(stderr); 141} 142 143bool 144SourcePos::operator<(const SourcePos& rhs) const 145{ 146 return (file < rhs.file) || (line < rhs.line); 147} 148 149bool 150SourcePos::hasErrors() 151{ 152 return g_errors.size() > 0; 153} 154 155void 156SourcePos::printErrors(FILE* to) 157{ 158 vector<ErrorPos>::const_iterator it; 159 for (it=g_errors.begin(); it!=g_errors.end(); it++) { 160 it->print(to); 161 } 162} 163 164 165 166