1 #include "SourcePos.h" 2 3 #include <stdarg.h> 4 #include <vector> 5 6 using namespace std; 7 8 9 // ErrorPos 10 // ============================================================================= 11 struct 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 32 static vector<ErrorPos> g_errors; 33 34 ErrorPos::ErrorPos() 35 :line(-1), level(NOTE) 36 { 37 } 38 39 ErrorPos::ErrorPos(const ErrorPos& that) 40 :file(that.file), 41 line(that.line), 42 error(that.error), 43 level(that.level) 44 { 45 } 46 47 ErrorPos::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 55 ErrorPos& 56 ErrorPos::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 65 void 66 ErrorPos::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 // ============================================================================= 94 SourcePos::SourcePos(const String8& f, int l) 95 : file(f), line(l) 96 { 97 } 98 99 SourcePos::SourcePos(const SourcePos& that) 100 : file(that.file), line(that.line) 101 { 102 } 103 104 SourcePos::SourcePos() 105 : file("???", 0), line(-1) 106 { 107 } 108 109 SourcePos::~SourcePos() 110 { 111 } 112 113 void 114 SourcePos::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 123 void 124 SourcePos::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 133 void 134 SourcePos::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 143 bool 144 SourcePos::operator<(const SourcePos& rhs) const 145 { 146 return (file < rhs.file) || (line < rhs.line); 147 } 148 149 bool 150 SourcePos::hasErrors() 151 { 152 return g_errors.size() > 0; 153 } 154 155 void 156 SourcePos::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