xref: /aosp_15_r20/frameworks/rs/script_api/Scanner.cpp (revision e1eccf28f96817838ad6867f7f39d2351ec11f56)
1*e1eccf28SAndroid Build Coastguard Worker /*
2*e1eccf28SAndroid Build Coastguard Worker  * Copyright (C) 2015 The Android Open Source Project
3*e1eccf28SAndroid Build Coastguard Worker  *
4*e1eccf28SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*e1eccf28SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*e1eccf28SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*e1eccf28SAndroid Build Coastguard Worker  *
8*e1eccf28SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*e1eccf28SAndroid Build Coastguard Worker  *
10*e1eccf28SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*e1eccf28SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*e1eccf28SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*e1eccf28SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*e1eccf28SAndroid Build Coastguard Worker  * limitations under the License.
15*e1eccf28SAndroid Build Coastguard Worker  */
16*e1eccf28SAndroid Build Coastguard Worker 
17*e1eccf28SAndroid Build Coastguard Worker #include <iostream>
18*e1eccf28SAndroid Build Coastguard Worker #include <sstream>
19*e1eccf28SAndroid Build Coastguard Worker 
20*e1eccf28SAndroid Build Coastguard Worker #include "Scanner.h"
21*e1eccf28SAndroid Build Coastguard Worker #include "Specification.h"
22*e1eccf28SAndroid Build Coastguard Worker #include "Utilities.h"
23*e1eccf28SAndroid Build Coastguard Worker 
24*e1eccf28SAndroid Build Coastguard Worker using namespace std;
25*e1eccf28SAndroid Build Coastguard Worker 
26*e1eccf28SAndroid Build Coastguard Worker // Maximum of errors we'll report before bailing out.
27*e1eccf28SAndroid Build Coastguard Worker const int MAX_ERRORS = 10;
28*e1eccf28SAndroid Build Coastguard Worker 
Scanner(const string & fileName,FILE * file)29*e1eccf28SAndroid Build Coastguard Worker Scanner::Scanner(const string& fileName, FILE* file)
30*e1eccf28SAndroid Build Coastguard Worker     : mFileName(fileName), mFile(file), mLineNumber(0), mTagConsumed(true), mErrorCount(0) {
31*e1eccf28SAndroid Build Coastguard Worker }
32*e1eccf28SAndroid Build Coastguard Worker 
atEnd()33*e1eccf28SAndroid Build Coastguard Worker bool Scanner::atEnd() {
34*e1eccf28SAndroid Build Coastguard Worker     return (mTagConsumed && feof(mFile)) || mErrorCount > MAX_ERRORS;
35*e1eccf28SAndroid Build Coastguard Worker }
36*e1eccf28SAndroid Build Coastguard Worker 
getChar()37*e1eccf28SAndroid Build Coastguard Worker int Scanner::getChar() {
38*e1eccf28SAndroid Build Coastguard Worker     int c = fgetc(mFile);
39*e1eccf28SAndroid Build Coastguard Worker     if (c == '\n') {
40*e1eccf28SAndroid Build Coastguard Worker         mLineNumber++;
41*e1eccf28SAndroid Build Coastguard Worker     }
42*e1eccf28SAndroid Build Coastguard Worker     return c;
43*e1eccf28SAndroid Build Coastguard Worker }
44*e1eccf28SAndroid Build Coastguard Worker 
readUpTo(char delimiter,string * segment)45*e1eccf28SAndroid Build Coastguard Worker void Scanner::readUpTo(char delimiter, string* segment) {
46*e1eccf28SAndroid Build Coastguard Worker     for (;;) {
47*e1eccf28SAndroid Build Coastguard Worker         int c = getChar();
48*e1eccf28SAndroid Build Coastguard Worker         if (c == EOF || c == '\n') {
49*e1eccf28SAndroid Build Coastguard Worker             break;
50*e1eccf28SAndroid Build Coastguard Worker         }
51*e1eccf28SAndroid Build Coastguard Worker         segment->push_back((char)c);
52*e1eccf28SAndroid Build Coastguard Worker         if (c == delimiter) {
53*e1eccf28SAndroid Build Coastguard Worker             break;
54*e1eccf28SAndroid Build Coastguard Worker         }
55*e1eccf28SAndroid Build Coastguard Worker     }
56*e1eccf28SAndroid Build Coastguard Worker }
57*e1eccf28SAndroid Build Coastguard Worker 
readRestOfLine(string * segment)58*e1eccf28SAndroid Build Coastguard Worker void Scanner::readRestOfLine(string* segment) {
59*e1eccf28SAndroid Build Coastguard Worker     for (;;) {
60*e1eccf28SAndroid Build Coastguard Worker         int c = getChar();
61*e1eccf28SAndroid Build Coastguard Worker         if (c == EOF || c == '\n') {
62*e1eccf28SAndroid Build Coastguard Worker             return;
63*e1eccf28SAndroid Build Coastguard Worker         }
64*e1eccf28SAndroid Build Coastguard Worker         segment->push_back((char)c);
65*e1eccf28SAndroid Build Coastguard Worker     }
66*e1eccf28SAndroid Build Coastguard Worker }
67*e1eccf28SAndroid Build Coastguard Worker 
getNextEntry()68*e1eccf28SAndroid Build Coastguard Worker bool Scanner::getNextEntry() {
69*e1eccf28SAndroid Build Coastguard Worker     mTag.clear();
70*e1eccf28SAndroid Build Coastguard Worker     mValue.clear();
71*e1eccf28SAndroid Build Coastguard Worker     for (;;) {
72*e1eccf28SAndroid Build Coastguard Worker         int c = getChar();
73*e1eccf28SAndroid Build Coastguard Worker         if (c == EOF) {
74*e1eccf28SAndroid Build Coastguard Worker             return false;
75*e1eccf28SAndroid Build Coastguard Worker         }
76*e1eccf28SAndroid Build Coastguard Worker         if (c == '#') {
77*e1eccf28SAndroid Build Coastguard Worker             // Skip the comment
78*e1eccf28SAndroid Build Coastguard Worker             string comment;
79*e1eccf28SAndroid Build Coastguard Worker             readRestOfLine(&comment);
80*e1eccf28SAndroid Build Coastguard Worker             continue;
81*e1eccf28SAndroid Build Coastguard Worker         }
82*e1eccf28SAndroid Build Coastguard Worker         if (c == ' ') {
83*e1eccf28SAndroid Build Coastguard Worker             readRestOfLine(&mValue);
84*e1eccf28SAndroid Build Coastguard Worker             break;
85*e1eccf28SAndroid Build Coastguard Worker         } else if (c == '\n') {
86*e1eccf28SAndroid Build Coastguard Worker             break;
87*e1eccf28SAndroid Build Coastguard Worker         } else {
88*e1eccf28SAndroid Build Coastguard Worker             mTag = c;
89*e1eccf28SAndroid Build Coastguard Worker             readUpTo(':', &mTag);
90*e1eccf28SAndroid Build Coastguard Worker             readRestOfLine(&mValue);
91*e1eccf28SAndroid Build Coastguard Worker             trimSpaces(&mValue);
92*e1eccf28SAndroid Build Coastguard Worker             break;
93*e1eccf28SAndroid Build Coastguard Worker         }
94*e1eccf28SAndroid Build Coastguard Worker     }
95*e1eccf28SAndroid Build Coastguard Worker     return true;
96*e1eccf28SAndroid Build Coastguard Worker }
97*e1eccf28SAndroid Build Coastguard Worker 
error()98*e1eccf28SAndroid Build Coastguard Worker ostream& Scanner::error() {
99*e1eccf28SAndroid Build Coastguard Worker     return error(mLineNumber);
100*e1eccf28SAndroid Build Coastguard Worker }
101*e1eccf28SAndroid Build Coastguard Worker 
error(int lineNumber)102*e1eccf28SAndroid Build Coastguard Worker ostream& Scanner::error(int lineNumber) {
103*e1eccf28SAndroid Build Coastguard Worker     if (++mErrorCount <= MAX_ERRORS) {
104*e1eccf28SAndroid Build Coastguard Worker         cerr << mFileName << ":" << lineNumber << ": error: ";
105*e1eccf28SAndroid Build Coastguard Worker     }
106*e1eccf28SAndroid Build Coastguard Worker     return cerr;
107*e1eccf28SAndroid Build Coastguard Worker }
108*e1eccf28SAndroid Build Coastguard Worker 
skipBlankEntries()109*e1eccf28SAndroid Build Coastguard Worker void Scanner::skipBlankEntries() {
110*e1eccf28SAndroid Build Coastguard Worker     while (findOptionalTag("")) {
111*e1eccf28SAndroid Build Coastguard Worker         if (!mValue.empty()) {
112*e1eccf28SAndroid Build Coastguard Worker             error() << "Unexpected: \" " << mValue << "\".\n";
113*e1eccf28SAndroid Build Coastguard Worker         }
114*e1eccf28SAndroid Build Coastguard Worker     }
115*e1eccf28SAndroid Build Coastguard Worker }
116*e1eccf28SAndroid Build Coastguard Worker 
findTag(const char * tag)117*e1eccf28SAndroid Build Coastguard Worker bool Scanner::findTag(const char* tag) {
118*e1eccf28SAndroid Build Coastguard Worker     bool found = findOptionalTag(tag);
119*e1eccf28SAndroid Build Coastguard Worker     if (!found) {
120*e1eccf28SAndroid Build Coastguard Worker         error() << "Found \"" << mTag << "\" while looking for \"" << tag << "\".\n";
121*e1eccf28SAndroid Build Coastguard Worker     }
122*e1eccf28SAndroid Build Coastguard Worker     mTagConsumed = true;
123*e1eccf28SAndroid Build Coastguard Worker     return found;
124*e1eccf28SAndroid Build Coastguard Worker }
125*e1eccf28SAndroid Build Coastguard Worker 
findOptionalTag(const char * tag)126*e1eccf28SAndroid Build Coastguard Worker bool Scanner::findOptionalTag(const char* tag) {
127*e1eccf28SAndroid Build Coastguard Worker     if (mTagConsumed) {
128*e1eccf28SAndroid Build Coastguard Worker         if (!getNextEntry()) {
129*e1eccf28SAndroid Build Coastguard Worker             return false;
130*e1eccf28SAndroid Build Coastguard Worker         }
131*e1eccf28SAndroid Build Coastguard Worker     }
132*e1eccf28SAndroid Build Coastguard Worker     mTagConsumed = (mTag == tag);
133*e1eccf28SAndroid Build Coastguard Worker     return mTagConsumed;
134*e1eccf28SAndroid Build Coastguard Worker }
135*e1eccf28SAndroid Build Coastguard Worker 
skipUntilTag(const char * tag)136*e1eccf28SAndroid Build Coastguard Worker void Scanner::skipUntilTag(const char* tag) {
137*e1eccf28SAndroid Build Coastguard Worker     while(!findOptionalTag(tag)) {
138*e1eccf28SAndroid Build Coastguard Worker         mTagConsumed = true;
139*e1eccf28SAndroid Build Coastguard Worker     }
140*e1eccf28SAndroid Build Coastguard Worker }
141*e1eccf28SAndroid Build Coastguard Worker 
checkNoValue()142*e1eccf28SAndroid Build Coastguard Worker void Scanner::checkNoValue() {
143*e1eccf28SAndroid Build Coastguard Worker     if (!mValue.empty()) {
144*e1eccf28SAndroid Build Coastguard Worker         error() << "Did not expect \"" << mValue << "\" after \"" << mTag << "\".\n";
145*e1eccf28SAndroid Build Coastguard Worker     }
146*e1eccf28SAndroid Build Coastguard Worker }
147*e1eccf28SAndroid Build Coastguard Worker 
parseDocumentation(string * s,string * documentation)148*e1eccf28SAndroid Build Coastguard Worker void Scanner::parseDocumentation(string* s, string* documentation) {
149*e1eccf28SAndroid Build Coastguard Worker     size_t docStart = s->find(", \"");
150*e1eccf28SAndroid Build Coastguard Worker     if (docStart == string::npos) {
151*e1eccf28SAndroid Build Coastguard Worker         documentation->erase();
152*e1eccf28SAndroid Build Coastguard Worker     } else {
153*e1eccf28SAndroid Build Coastguard Worker         size_t first = docStart + 3;
154*e1eccf28SAndroid Build Coastguard Worker         size_t last = s->find('\"', first);
155*e1eccf28SAndroid Build Coastguard Worker         if (last == string::npos) {
156*e1eccf28SAndroid Build Coastguard Worker             error() << "Missing closing double quote\n";
157*e1eccf28SAndroid Build Coastguard Worker         }
158*e1eccf28SAndroid Build Coastguard Worker         *documentation = s->substr(first, last - first);
159*e1eccf28SAndroid Build Coastguard Worker         s->erase(docStart);
160*e1eccf28SAndroid Build Coastguard Worker     }
161*e1eccf28SAndroid Build Coastguard Worker }
162*e1eccf28SAndroid Build Coastguard Worker 
parseArgString(bool isReturn)163*e1eccf28SAndroid Build Coastguard Worker ParameterEntry* Scanner::parseArgString(bool isReturn) {
164*e1eccf28SAndroid Build Coastguard Worker     string s = mValue;
165*e1eccf28SAndroid Build Coastguard Worker     ParameterEntry* p = new ParameterEntry();
166*e1eccf28SAndroid Build Coastguard Worker     parseDocumentation(&s, &p->documentation);
167*e1eccf28SAndroid Build Coastguard Worker 
168*e1eccf28SAndroid Build Coastguard Worker     size_t optionStart = s.find(", ");
169*e1eccf28SAndroid Build Coastguard Worker     if (optionStart != string::npos) {
170*e1eccf28SAndroid Build Coastguard Worker         p->testOption = s.substr(optionStart + 2);
171*e1eccf28SAndroid Build Coastguard Worker         s.erase(optionStart);
172*e1eccf28SAndroid Build Coastguard Worker     }
173*e1eccf28SAndroid Build Coastguard Worker 
174*e1eccf28SAndroid Build Coastguard Worker     trimSpaces(&s);
175*e1eccf28SAndroid Build Coastguard Worker     if (!isReturn) {
176*e1eccf28SAndroid Build Coastguard Worker         size_t nameStart = s.rfind(' ');
177*e1eccf28SAndroid Build Coastguard Worker         if (nameStart == string::npos) {
178*e1eccf28SAndroid Build Coastguard Worker             if (s == "...") {
179*e1eccf28SAndroid Build Coastguard Worker                 p->name = s;
180*e1eccf28SAndroid Build Coastguard Worker                 p->type = s;
181*e1eccf28SAndroid Build Coastguard Worker                 p->lineNumber = mLineNumber;
182*e1eccf28SAndroid Build Coastguard Worker                 return p;
183*e1eccf28SAndroid Build Coastguard Worker             } else {
184*e1eccf28SAndroid Build Coastguard Worker                 error() << "Missing variable name\n";
185*e1eccf28SAndroid Build Coastguard Worker             }
186*e1eccf28SAndroid Build Coastguard Worker         } else {
187*e1eccf28SAndroid Build Coastguard Worker             p->name = s.substr(nameStart + 1);
188*e1eccf28SAndroid Build Coastguard Worker             s.erase(nameStart);
189*e1eccf28SAndroid Build Coastguard Worker             if (p->name.find('*') != string::npos) {
190*e1eccf28SAndroid Build Coastguard Worker                 error() << "The '*' should be attached to the type\n";
191*e1eccf28SAndroid Build Coastguard Worker             }
192*e1eccf28SAndroid Build Coastguard Worker         }
193*e1eccf28SAndroid Build Coastguard Worker     }
194*e1eccf28SAndroid Build Coastguard Worker 
195*e1eccf28SAndroid Build Coastguard Worker     if (s == "void" && !isReturn) {
196*e1eccf28SAndroid Build Coastguard Worker         error() << "void is only allowed for ret:\n";
197*e1eccf28SAndroid Build Coastguard Worker     }
198*e1eccf28SAndroid Build Coastguard Worker     p->type = s;
199*e1eccf28SAndroid Build Coastguard Worker     p->lineNumber = mLineNumber;
200*e1eccf28SAndroid Build Coastguard Worker     return p;
201*e1eccf28SAndroid Build Coastguard Worker }
202