• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "definition.h"
9 #include "textParser.h"
10 
11 #ifdef SK_BUILD_FOR_WIN
12 #include <Windows.h>
13 #endif
14 
TextParser(const Definition * definition)15 TextParser::TextParser(const Definition* definition) :
16     TextParser(definition->fFileName, definition->fContentStart, definition->fContentEnd,
17         definition->fLineCount) {
18 }
19 
ReportFilename(string file)20 string TextParser::ReportFilename(string file) {
21 	string fullName;
22 #ifdef SK_BUILD_FOR_WIN
23 	TCHAR pathChars[MAX_PATH];
24 	DWORD pathLen = GetCurrentDirectory(MAX_PATH, pathChars);
25 	for (DWORD index = 0; index < pathLen; ++index) {
26 		fullName += pathChars[index] == (char)pathChars[index] ? (char)pathChars[index] : '?';
27 	}
28 	fullName += '\\';
29 #endif
30 	fullName += file;
31     return fullName;
32 }
33 
reportError(const char * errorStr) const34 void TextParser::reportError(const char* errorStr) const {
35     this->reportWarning(errorStr);
36     SkDebugf("");  // convenient place to set a breakpoint
37 }
38 
reportWarning(const char * errorStr) const39 void TextParser::reportWarning(const char* errorStr) const {
40     const char* lineStart = fLine;
41     if (lineStart >= fEnd) {
42         lineStart = fChar;
43     }
44     SkASSERT(lineStart < fEnd);
45     TextParser err(fFileName, lineStart, fEnd, fLineCount);
46     size_t lineLen = this->lineLength();
47     ptrdiff_t spaces = fChar - lineStart;
48     while (spaces > 0 && (size_t) spaces > lineLen) {
49         ++err.fLineCount;
50         err.fLine += lineLen;
51         spaces -= lineLen;
52         lineLen = err.lineLength();
53     }
54 	string fullName = this->ReportFilename(fFileName);
55     SkDebugf("\n%s(%zd): error: %s\n", fullName.c_str(), err.fLineCount, errorStr);
56     if (0 == lineLen) {
57         SkDebugf("[blank line]\n");
58     } else {
59         while (lineLen > 0 && '\n' == err.fLine[lineLen - 1]) {
60             --lineLen;
61         }
62         SkDebugf("%.*s\n", (int) lineLen, err.fLine);
63         SkDebugf("%*s^\n", (int) spaces, "");
64     }
65 }
66 
setForErrorReporting(const Definition * definition,const char * str)67 void TextParser::setForErrorReporting(const Definition* definition, const char* str) {
68     fFileName = definition->fFileName;
69     fStart = definition->fContentStart;
70     fLine = str;
71     while (fLine > fStart && fLine[-1] != '\n') {
72         --fLine;
73     }
74     fChar = str;
75     fEnd = definition->fContentEnd;
76     fLineCount = definition->fLineCount;
77     const char* lineInc = fStart;
78     while (lineInc < str) {
79         fLineCount += '\n' == *lineInc++;
80     }
81 }
82 
typedefName()83 string TextParser::typedefName() {
84     // look for typedef as one of three forms:
85     // typedef return-type (*NAME)(params);
86     // typedef alias NAME;
87     // typedef std::function<alias> NAME;
88     string builder;
89     const char* end = this->doubleLF();
90     if (!end) {
91        end = fEnd;
92     }
93     const char* altEnd = this->strnstr("#Typedef ##", end);
94     if (altEnd) {
95         end = this->strnchr('\n', end);
96     }
97     if (!end) {
98         return this->reportError<string>("missing typedef std::function end bracket >");
99     }
100     bool stdFunction = this->startsWith("std::function");
101     if (stdFunction) {
102         if (!this->skipToEndBracket('>')) {
103             return this->reportError<string>("missing typedef std::function end bracket >");
104         }
105         this->next();
106         this->skipWhiteSpace();
107         builder += string(fChar, end - fChar);
108     } else {
109         const char* paren = this->strnchr('(', end);
110         if (!paren) {
111             const char* lastWord = nullptr;
112             do {
113                 this->skipToWhiteSpace();
114                 if (fChar < end && isspace(fChar[0])) {
115                     const char* whiteStart = fChar;
116                     this->skipWhiteSpace();
117                     // FIXME: test should be for fMC
118                     if ('#' == fChar[0]) {
119                         end = whiteStart;
120                         break;
121                     }
122                     lastWord = fChar;
123                 } else {
124                     break;
125                 }
126             } while (true);
127             if (!lastWord) {
128                 return this->reportError<string>("missing typedef name");
129             }
130             builder += string(lastWord, end - lastWord);
131         } else {
132             this->skipTo(paren);
133             this->next();
134             if ('*' != this->next()) {
135                 return this->reportError<string>("missing typedef function asterisk");
136             }
137             const char* nameStart = fChar;
138             if (!this->skipToEndBracket(')')) {
139                 return this->reportError<string>("missing typedef function )");
140             }
141             builder += string(nameStart, fChar - nameStart);
142             if (!this->skipToEndBracket('(')) {
143                 return this->reportError<string>("missing typedef params (");
144             }
145             if (! this->skipToEndBracket(')')) {
146                 return this->reportError<string>("missing typedef params )");
147             }
148             this->skipTo(end);
149         }
150     }
151     return builder;
152 }
153 
skipToMethodEnd(Resolvable resolvable)154 void MethodParser::skipToMethodEnd(Resolvable resolvable) {
155     if (this->eof()) {
156         return;
157     }
158     string name = fLocalName.length() ? fLocalName : fClassName;
159     if ('~' == this->peek()) {
160         this->next();
161         if (!this->startsWith(name.c_str())) {
162             --fChar;
163             return;
164         }
165     }
166     if (Resolvable::kSimple != resolvable
167             && Resolvable::kInclude != resolvable
168             && (this->startsWith(name.c_str()) || this->startsWith("operator"))) {
169         const char* ptr = this->anyOf("\n (");
170         if (ptr && '(' ==  *ptr && strncmp(ptr, "(...", 4)) {
171             this->skipToEndBracket(')');
172             SkAssertResult(')' == this->next());
173             Resolvable::kCode == resolvable && this->skipExact(" const");
174             return;
175         }
176     }
177     if (this->startsWith("Sk") && this->wordEndsWith(".h")) {  // allow include refs
178         this->skipToNonName();
179     } else {
180         this->skipFullName();
181         if (this->endsWith("operator")) {
182             const char* ptr = this->anyOf("\n (");
183             if (ptr && '(' ==  *ptr) {
184                 this->skipToEndBracket(')');
185                 SkAssertResult(')' == this->next());
186                 this->skipExact(" const");
187             }
188         }
189     }
190 }
191