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