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
ErrorPos()33 ErrorPos::ErrorPos()
34 {
35 }
36
ErrorPos(const ErrorPos & that)37 ErrorPos::ErrorPos(const ErrorPos& that)
38 :file(that.file),
39 line(that.line),
40 error(that.error)
41 {
42 }
43
ErrorPos(const string & f,int l,const string & e)44 ErrorPos::ErrorPos(const string& f, int l, const string& e)
45 :file(f),
46 line(l),
47 error(e)
48 {
49 }
50
~ErrorPos()51 ErrorPos::~ErrorPos()
52 {
53 }
54
55 bool
operator <(const ErrorPos & rhs) const56 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
operator ==(const ErrorPos & rhs) const69 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&
operator =(const ErrorPos & rhs)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
Print(FILE * to) const86 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 // =============================================================================
SourcePos(const string & f,int l)97 SourcePos::SourcePos(const string& f, int l)
98 : file(f), line(l)
99 {
100 }
101
SourcePos(const SourcePos & that)102 SourcePos::SourcePos(const SourcePos& that)
103 : file(that.file), line(that.line)
104 {
105 }
106
SourcePos()107 SourcePos::SourcePos()
108 : file("???", 0)
109 {
110 }
111
~SourcePos()112 SourcePos::~SourcePos()
113 {
114 }
115
116 string
ToString() const117 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
Error(const char * fmt,...) const130 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
HasErrors()152 SourcePos::HasErrors()
153 {
154 return g_errors.size() > 0;
155 }
156
157 void
PrintErrors(FILE * to)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