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