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