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