blob: 184bfe0a649efec85d743bd2f67be2b9ca780db2 [file] [log] [blame]
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07001#include "SourcePos.h"
2
3#include <stdarg.h>
Jack Palevichbdb087c2009-06-24 19:01:27 -07004#include <cstdio>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07005#include <set>
Scott Tsai8a2b9082009-03-21 08:08:36 +08006#include <cstdio>
The Android Open Source Project54b6cfa2008-10-21 07:00:00 -07007
8using namespace std;
9
10const SourcePos GENERATED_POS("<generated>", -1);
11
12// ErrorPos
13// =============================================================================
14struct 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
31static set<ErrorPos> g_errors;
32
33ErrorPos::ErrorPos()
34{
35}
36
37ErrorPos::ErrorPos(const ErrorPos& that)
38 :file(that.file),
39 line(that.line),
40 error(that.error)
41{
42}
43
44ErrorPos::ErrorPos(const string& f, int l, const string& e)
45 :file(f),
46 line(l),
47 error(e)
48{
49}
50
51ErrorPos::~ErrorPos()
52{
53}
54
55bool
56ErrorPos::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
68bool
69ErrorPos::operator==(const ErrorPos& rhs) const
70{
71 return this->file == rhs.file
72 && this->line == rhs.line
73 && this->error == rhs.error;
74}
75
76ErrorPos&
77ErrorPos::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
85void
86ErrorPos::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// =============================================================================
97SourcePos::SourcePos(const string& f, int l)
98 : file(f), line(l)
99{
100}
101
102SourcePos::SourcePos(const SourcePos& that)
103 : file(that.file), line(that.line)
104{
105}
106
107SourcePos::SourcePos()
108 : file("???", 0)
109{
110}
111
112SourcePos::~SourcePos()
113{
114}
115
116string
117SourcePos::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
129int
130SourcePos::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
151bool
152SourcePos::HasErrors()
153{
154 return g_errors.size() > 0;
155}
156
157void
158SourcePos::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