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
ErrorPos()34 ErrorPos::ErrorPos()
35 :line(-1), level(NOTE)
36 {
37 }
38
ErrorPos(const ErrorPos & that)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
ErrorPos(const String8 & f,int l,const String8 & e,Level lev)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&
operator =(const ErrorPos & rhs)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
print(FILE * to) const66 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 // =============================================================================
SourcePos(const String8 & f,int l)94 SourcePos::SourcePos(const String8& f, int l)
95 : file(f), line(l)
96 {
97 }
98
SourcePos(const SourcePos & that)99 SourcePos::SourcePos(const SourcePos& that)
100 : file(that.file), line(that.line)
101 {
102 }
103
SourcePos()104 SourcePos::SourcePos()
105 : file("???", 0), line(-1)
106 {
107 }
108
~SourcePos()109 SourcePos::~SourcePos()
110 {
111 }
112
113 void
error(const char * fmt,...) const114 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
warning(const char * fmt,...) const124 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
printf(const char * fmt,...) const134 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
operator <(const SourcePos & rhs) const144 SourcePos::operator<(const SourcePos& rhs) const
145 {
146 return (file < rhs.file) || (line < rhs.line);
147 }
148
149 bool
hasErrors()150 SourcePos::hasErrors()
151 {
152 return g_errors.size() > 0;
153 }
154
155 void
printErrors(FILE * to)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