1c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet/*
2c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * Copyright (C) 2013 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 <stdio.h>
18c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <cctype>
19c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <cstdlib>
20c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <fstream>
21c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <functional>
22c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <iostream>
23c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <memory>
24c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <sstream>
25c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <strings.h>
26c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
27c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include "Generator.h"
28c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include "Scanner.h"
29c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include "Specification.h"
30c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include "Utilities.h"
31c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
32c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletusing namespace std;
33c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
34c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet// API level when RenderScript was added.
3512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Niconst unsigned int MIN_API_LEVEL = 9;
36c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
37c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletconst NumericalType TYPES[] = {
383b2be14b4f4e1932f4e67c12d691ca85e937d936Pirama Arumuga Nainar            {"f16", "FLOAT_16", "half", "short", FLOATING_POINT, 11, 5},
39c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"f32", "FLOAT_32", "float", "float", FLOATING_POINT, 24, 8},
40c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"f64", "FLOAT_64", "double", "double", FLOATING_POINT, 53, 11},
41c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"i8", "SIGNED_8", "char", "byte", SIGNED_INTEGER, 7, 0},
42c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"u8", "UNSIGNED_8", "uchar", "byte", UNSIGNED_INTEGER, 8, 0},
43c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"i16", "SIGNED_16", "short", "short", SIGNED_INTEGER, 15, 0},
44c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"u16", "UNSIGNED_16", "ushort", "short", UNSIGNED_INTEGER, 16, 0},
45c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"i32", "SIGNED_32", "int", "int", SIGNED_INTEGER, 31, 0},
46c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"u32", "UNSIGNED_32", "uint", "int", UNSIGNED_INTEGER, 32, 0},
47c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"i64", "SIGNED_64", "long", "long", SIGNED_INTEGER, 63, 0},
48c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            {"u64", "UNSIGNED_64", "ulong", "long", UNSIGNED_INTEGER, 64, 0},
49c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet};
50c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
51c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletconst int NUM_TYPES = sizeof(TYPES) / sizeof(TYPES[0]);
52c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
5312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nistatic const char kTagUnreleased[] = "UNRELEASED";
5412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni
5543d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar// Patterns that get substituted with C type or RS Data type names in function
5643d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar// names, arguments, return types, and inlines.
5743d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainarstatic const string kCTypePatterns[] = {"#1", "#2", "#3", "#4"};
5843d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainarstatic const string kRSTypePatterns[] = {"#RST_1", "#RST_2", "#RST_3", "#RST_4"};
5943d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
60c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet// The singleton of the collected information of all the spec files.
61c5184e202ced435258adb2cfe2013570e7190954Jean-Luc BrouilletSystemSpecification systemSpecification;
62c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
63c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet// Returns the index in TYPES for the provided cType
64c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic int findCType(const string& cType) {
65c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (int i = 0; i < NUM_TYPES; i++) {
66c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (cType == TYPES[i].cType) {
67c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            return i;
68c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
69c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
70c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return -1;
71c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
72c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
73c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet/* Converts a string like "u8, u16" to a vector of "ushort", "uint".
74c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * For non-numerical types, we don't need to convert the abbreviation.
75c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet */
76c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic vector<string> convertToTypeVector(const string& input) {
77c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // First convert the string to an array of strings.
78c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    vector<string> entries;
79c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    stringstream stream(input);
80c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    string entry;
81c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    while (getline(stream, entry, ',')) {
82c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        trimSpaces(&entry);
83c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        entries.push_back(entry);
84c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
85c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
86c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    /* Second, we look for present numerical types. We do it this way
87c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet     * so the order of numerical types is always the same, no matter
88c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet     * how specified in the spec file.
89c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet     */
90c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    vector<string> result;
91c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto t : TYPES) {
92c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        for (auto i = entries.begin(); i != entries.end(); ++i) {
93c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (*i == t.specType) {
94c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                result.push_back(t.cType);
95c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                entries.erase(i);
96c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                break;
97c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
98c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
99c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
100c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
101c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Add the remaining; they are not numerical types.
102c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto s : entries) {
103c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        result.push_back(s);
104c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
105c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
106c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return result;
107c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
108c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
10943d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar// Returns true if each entry in typeVector is an RS numerical type
11043d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainarstatic bool isRSTValid(const vector<string> &typeVector) {
11143d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    for (auto type: typeVector) {
11243d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        if (findCType(type) == -1)
11343d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar            return false;
11443d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    }
11543d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    return true;
11643d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar}
11743d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
1189309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leovoid getVectorSizeAndBaseType(const string& type, string& vectorSize, string& baseType) {
1199309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo    vectorSize = "1";
1209309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo    baseType = type;
121c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
12266fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet    /* If it's a vector type, we need to split the base type from the size.
12366fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet     * We know that's it's a vector type if the last character is a digit and
12466fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet     * the rest is an actual base type.   We used to only verify the first part,
12566fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet     * which created a problem with rs_matrix2x2.
12666fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet     */
1279309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo    const int last = type.size() - 1;
1289309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo    const char lastChar = type[last];
129c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (lastChar >= '0' && lastChar <= '9') {
1309309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo        const string trimmed = type.substr(0, last);
13166fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet        int i = findCType(trimmed);
13266fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet        if (i >= 0) {
1339309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo            baseType = trimmed;
1349309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo            vectorSize = lastChar;
13566fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet        }
136c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
1379309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo}
1389309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo
1399309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leovoid ParameterDefinition::parseParameterDefinition(const string& type, const string& name,
1409309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo                                                   const string& testOption, int lineNumber,
1419309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo                                                   bool isReturn, Scanner* scanner) {
1429309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo    rsType = type;
1439309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo    specName = name;
1449309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo
1459309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo    // Determine if this is an output.
1469309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo    isOutParameter = isReturn || charRemoved('*', &rsType);
1479309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo
1489309a0665a4866f708db9ae67e43b5ea6a27cf27Dean De Leo    getVectorSizeAndBaseType(rsType, mVectorSize, rsBaseType);
14966fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet    typeIndex = findCType(rsBaseType);
15066fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouillet
151c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (mVectorSize == "3") {
152c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        vectorWidth = "4";
153c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
154c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        vectorWidth = mVectorSize;
155c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
156c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
157c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    /* Create variable names to be used in the java and .rs files.  Because x and
158c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet     * y are reserved in .rs files, we prefix variable names with "in" or "out".
159c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet     */
160c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (isOutParameter) {
161c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        variableName = "out";
162c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (!specName.empty()) {
163c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            variableName += capitalize(specName);
164c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else if (!isReturn) {
165c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner->error(lineNumber) << "Should have a name.\n";
166c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
167f8ccbb19e0d3140114f9512bfd685f37089800d1Pirama Arumuga Nainar        doubleVariableName = variableName + "Double";
168c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
169c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        variableName = "in";
170c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (specName.empty()) {
171c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner->error(lineNumber) << "Should have a name.\n";
172c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
173c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        variableName += capitalize(specName);
1743b2be14b4f4e1932f4e67c12d691ca85e937d936Pirama Arumuga Nainar        doubleVariableName = variableName + "Double";
175c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
176c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    rsAllocName = "gAlloc" + capitalize(variableName);
177c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    javaAllocName = variableName;
178c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    javaArrayName = "array" + capitalize(javaAllocName);
179c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
180c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Process the option.
181c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    undefinedIfOutIsNan = false;
182c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    compatibleTypeIndex = -1;
183c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!testOption.empty()) {
184c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (testOption.compare(0, 6, "range(") == 0) {
185c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            size_t pComma = testOption.find(',');
186c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            size_t pParen = testOption.find(')');
187c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (pComma == string::npos || pParen == string::npos) {
188c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                scanner->error(lineNumber) << "Incorrect range " << testOption << "\n";
189c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            } else {
190c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                minValue = testOption.substr(6, pComma - 6);
191c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                maxValue = testOption.substr(pComma + 1, pParen - pComma - 1);
192c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
193c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else if (testOption.compare(0, 6, "above(") == 0) {
194c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            size_t pParen = testOption.find(')');
195c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (pParen == string::npos) {
196c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                scanner->error(lineNumber) << "Incorrect testOption " << testOption << "\n";
197c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            } else {
198c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                smallerParameter = testOption.substr(6, pParen - 6);
199c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
200c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else if (testOption.compare(0, 11, "compatible(") == 0) {
201c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            size_t pParen = testOption.find(')');
202c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (pParen == string::npos) {
203c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                scanner->error(lineNumber) << "Incorrect testOption " << testOption << "\n";
204c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            } else {
205c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                compatibleTypeIndex = findCType(testOption.substr(11, pParen - 11));
206c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
207c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else if (testOption.compare(0, 11, "conditional") == 0) {
208c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            undefinedIfOutIsNan = true;
209c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else {
210c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner->error(lineNumber) << "Unrecognized testOption " << testOption << "\n";
211c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
212c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
213c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
214c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    isFloatType = false;
215c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (typeIndex >= 0) {
216c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        javaBaseType = TYPES[typeIndex].javaType;
217c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        specType = TYPES[typeIndex].specType;
218c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        isFloatType = TYPES[typeIndex].exponentBits > 0;
219c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
220c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!minValue.empty()) {
221c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (typeIndex < 0 || TYPES[typeIndex].kind != FLOATING_POINT) {
222c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner->error(lineNumber) << "range(,) is only supported for floating point\n";
223c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
224c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
225c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
226c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
22712398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nibool VersionInfo::scan(Scanner* scanner, unsigned int maxApiLevel) {
228c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("version:")) {
229c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        const string s = scanner->getValue();
23012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni        if (s.compare(0, sizeof(kTagUnreleased), kTagUnreleased) == 0) {
23112398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            // The API is still under development and does not have
23212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            // an official version number.
23312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            minVersion = maxVersion = kUnreleasedVersion;
23412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni        } else {
23512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            sscanf(s.c_str(), "%u %u", &minVersion, &maxVersion);
23612398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            if (minVersion && minVersion < MIN_API_LEVEL) {
23712398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni                scanner->error() << "Minimum version must >= 9\n";
23812398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            }
23912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            if (minVersion == MIN_API_LEVEL) {
24012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni                minVersion = 0;
24112398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            }
24212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            if (maxVersion && maxVersion < MIN_API_LEVEL) {
24312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni                scanner->error() << "Maximum version must >= 9\n";
24412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            }
245c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
246c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
247c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("size:")) {
248c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        sscanf(scanner->getValue().c_str(), "%i", &intSize);
249c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
25012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni
2512217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    if (maxVersion > maxApiLevel) {
2522217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        maxVersion = maxApiLevel;
2532217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    }
25412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni
2552217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    return minVersion == 0 || minVersion <= maxApiLevel;
256c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
257c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
25867923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc BrouilletDefinition::Definition(const std::string& name)
25936e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet    : mName(name), mDeprecatedApiLevel(0), mHidden(false), mFinalVersion(-1) {
26067923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet}
26167923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet
26267923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouilletvoid Definition::updateFinalVersion(const VersionInfo& info) {
26367923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    /* We set it if:
26467923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet     * - We have never set mFinalVersion before, or
26567923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet     * - The max version is 0, which means we have not expired this API, or
26667923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet     * - We have a max that's later than what we currently have.
26767923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet     */
26867923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    if (mFinalVersion < 0 || info.maxVersion == 0 ||
26967923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet        (mFinalVersion > 0 && info.maxVersion > mFinalVersion)) {
27067923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet        mFinalVersion = info.maxVersion;
27167923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    }
272c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
273c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
2747c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletvoid Definition::scanDocumentationTags(Scanner* scanner, bool firstOccurence,
2757c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet                                       const SpecFile* specFile) {
276c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("hidden:")) {
277c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        scanner->checkNoValue();
278c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        mHidden = true;
279c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
2804a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet    if (scanner->findOptionalTag("deprecated:")) {
28136e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet        string value = scanner->getValue();
28236e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet        size_t pComma = value.find(", ");
28336e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet        if (pComma != string::npos) {
28436e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet            mDeprecatedMessage = value.substr(pComma + 2);
28536e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet            value.erase(pComma);
28636e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet        }
28736e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet        sscanf(value.c_str(), "%i", &mDeprecatedApiLevel);
28836e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet        if (mDeprecatedApiLevel <= 0) {
28936e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet            scanner->error() << "deprecated entries should have a level > 0\n";
29036e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet        }
2914a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet    }
292c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (firstOccurence) {
293c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner->findTag("summary:")) {
294c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            mSummary = scanner->getValue();
295c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
296c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner->findTag("description:")) {
297c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner->checkNoValue();
298c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            while (scanner->findOptionalTag("")) {
299c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                mDescription.push_back(scanner->getValue());
300c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
301c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
3027c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        mUrl = specFile->getDetailedDocumentationUrl() + "#android_rs:" + mName;
303c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else if (scanner->findOptionalTag("summary:")) {
304c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        scanner->error() << "Only the first specification should have a summary.\n";
305c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
306c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
307c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
308c5184e202ced435258adb2cfe2013570e7190954Jean-Luc BrouilletConstant::~Constant() {
309c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto i : mSpecifications) {
310c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        delete i;
311c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
312c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
313c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
314c5184e202ced435258adb2cfe2013570e7190954Jean-Luc BrouilletType::~Type() {
315c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto i : mSpecifications) {
316c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        delete i;
317c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
318c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
319c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
3207c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc BrouilletFunction::Function(const string& name) : Definition(name) {
321c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mCapitalizedName = capitalize(mName);
322c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
323c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
324c5184e202ced435258adb2cfe2013570e7190954Jean-Luc BrouilletFunction::~Function() {
325c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto i : mSpecifications) {
326c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        delete i;
327c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
328c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
329c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
330c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletbool Function::someParametersAreDocumented() const {
331c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto p : mParameters) {
332c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (!p->documentation.empty()) {
333c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            return true;
334c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
335c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
336c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return false;
337c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
338c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
339c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletvoid Function::addParameter(ParameterEntry* entry, Scanner* scanner) {
340c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto i : mParameters) {
341c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (i->name == entry->name) {
342c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            // It's a duplicate.
343c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (!entry->documentation.empty()) {
344c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                scanner->error(entry->lineNumber)
345c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                            << "Only the first occurence of an arg should have the "
346c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                               "documentation.\n";
347c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
348c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            return;
349c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
350c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
351c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mParameters.push_back(entry);
352c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
353c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
354c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletvoid Function::addReturn(ParameterEntry* entry, Scanner* scanner) {
355c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (entry->documentation.empty()) {
356c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return;
357c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
358c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!mReturnDocumentation.empty()) {
359c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        scanner->error() << "ret: should be documented only for the first variant\n";
360c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
361c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mReturnDocumentation = entry->documentation;
362c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
363c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
3642217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouilletvoid ConstantSpecification::scanConstantSpecification(Scanner* scanner, SpecFile* specFile,
36512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni                                                      unsigned int maxApiLevel) {
366c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    string name = scanner->getValue();
3672217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    VersionInfo info;
3682217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    if (!info.scan(scanner, maxApiLevel)) {
3692217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        cout << "Skipping some " << name << " definitions.\n";
3702217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        scanner->skipUntilTag("end:");
3712217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        return;
3722217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    }
373c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
374c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    bool created = false;
3757c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    Constant* constant = systemSpecification.findOrCreateConstant(name, &created);
3767c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    ConstantSpecification* spec = new ConstantSpecification(constant);
377c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    constant->addSpecification(spec);
37867923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    constant->updateFinalVersion(info);
3797c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    specFile->addConstantSpecification(spec, created);
3802217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    spec->mVersionInfo = info;
381c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
382c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findTag("value:")) {
383c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mValue = scanner->getValue();
384c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
385cb25a819dbb5bda7e5554ec5ff09d29586d84493David Gross    if (scanner->findTag("type:")) {
386cb25a819dbb5bda7e5554ec5ff09d29586d84493David Gross        spec->mType = scanner->getValue();
387cb25a819dbb5bda7e5554ec5ff09d29586d84493David Gross    }
3887c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    constant->scanDocumentationTags(scanner, created, specFile);
389c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
390c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    scanner->findTag("end:");
391c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
392c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
3932217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouilletvoid TypeSpecification::scanTypeSpecification(Scanner* scanner, SpecFile* specFile,
39412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni                                              unsigned int maxApiLevel) {
395c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    string name = scanner->getValue();
3962217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    VersionInfo info;
3972217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    if (!info.scan(scanner, maxApiLevel)) {
3982217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        cout << "Skipping some " << name << " definitions.\n";
3992217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        scanner->skipUntilTag("end:");
4002217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        return;
4012217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    }
402c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
403c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    bool created = false;
4047c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    Type* type = systemSpecification.findOrCreateType(name, &created);
4057c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    TypeSpecification* spec = new TypeSpecification(type);
406c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    type->addSpecification(spec);
40767923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    type->updateFinalVersion(info);
4087c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    specFile->addTypeSpecification(spec, created);
4092217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    spec->mVersionInfo = info;
410c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
411c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("simple:")) {
412c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mKind = SIMPLE;
413c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mSimpleType = scanner->getValue();
414c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
415ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines    if (scanner->findOptionalTag("rs_object:")) {
416ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines        spec->mKind = RS_OBJECT;
417ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines    }
418c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("struct:")) {
419c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mKind = STRUCT;
420c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mStructName = scanner->getValue();
421c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        while (scanner->findOptionalTag("field:")) {
422c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            string s = scanner->getValue();
423c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            string comment;
424c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner->parseDocumentation(&s, &comment);
425c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            spec->mFields.push_back(s);
426c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            spec->mFieldComments.push_back(comment);
427c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
428c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
429c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("enum:")) {
430c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mKind = ENUM;
431c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mEnumName = scanner->getValue();
432c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        while (scanner->findOptionalTag("value:")) {
433c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            string s = scanner->getValue();
434c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            string comment;
435c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner->parseDocumentation(&s, &comment);
436c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            spec->mValues.push_back(s);
437c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            spec->mValueComments.push_back(comment);
438c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
439c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
44036e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet    if (scanner->findOptionalTag("attrib:")) {
44136e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet        spec->mAttribute = scanner->getValue();
44236e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet    }
4437c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    type->scanDocumentationTags(scanner, created, specFile);
444c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
445c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    scanner->findTag("end:");
446c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
447c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
448c5184e202ced435258adb2cfe2013570e7190954Jean-Luc BrouilletFunctionSpecification::~FunctionSpecification() {
449c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto i : mParameters) {
450c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        delete i;
451c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
452c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    delete mReturn;
453c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto i : mPermutations) {
454c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        delete i;
455c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
456c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
457c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
45843d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainarstring FunctionSpecification::expandRSTypeInString(const string &s,
45943d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar                                                   const string &pattern,
46043d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar                                                   const string &cTypeStr) const {
46143d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    // Find index of numerical type corresponding to cTypeStr.  The case where
46243d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    // pattern is found in s but cTypeStr is not a numerical type is checked in
46343d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    // checkRSTPatternValidity.
46443d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    int typeIdx = findCType(cTypeStr);
46543d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    if (typeIdx == -1) {
46643d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        return s;
46743d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    }
46843d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    // If index exists, perform replacement.
46943d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    return stringReplace(s, pattern, TYPES[typeIdx].rsDataType);
47043d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar}
47143d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
472c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstring FunctionSpecification::expandString(string s,
473c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                           int replacementIndexes[MAX_REPLACEABLES]) const {
47443d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
47543d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
47643d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    for (unsigned idx = 0; idx < mReplaceables.size(); idx ++) {
47743d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        string toString = mReplaceables[idx][replacementIndexes[idx]];
47843d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
47943d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        // replace #RST_i patterns with RS datatype corresponding to toString
48043d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        s = expandRSTypeInString(s, kRSTypePatterns[idx], toString);
48143d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
48243d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        // replace #i patterns with C type from mReplaceables
48343d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        s = stringReplace(s, kCTypePatterns[idx], toString);
484c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
48543d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
486c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return s;
487c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
488c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
489c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletvoid FunctionSpecification::expandStringVector(const vector<string>& in,
490c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                               int replacementIndexes[MAX_REPLACEABLES],
491c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                               vector<string>* out) const {
492c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    out->clear();
493c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (vector<string>::const_iterator iter = in.begin(); iter != in.end(); iter++) {
494c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        out->push_back(expandString(*iter, replacementIndexes));
495c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
496c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
497c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
498c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletvoid FunctionSpecification::createPermutations(Function* function, Scanner* scanner) {
499c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    int start[MAX_REPLACEABLES];
500c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    int end[MAX_REPLACEABLES];
501c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (int i = 0; i < MAX_REPLACEABLES; i++) {
502c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (i < (int)mReplaceables.size()) {
503c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            start[i] = 0;
504c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            end[i] = mReplaceables[i].size();
505c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else {
506c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            start[i] = -1;
507c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            end[i] = 0;
508c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
509c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
510c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    int replacementIndexes[MAX_REPLACEABLES];
511c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // TODO: These loops assume that MAX_REPLACEABLES is 4.
512c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (replacementIndexes[3] = start[3]; replacementIndexes[3] < end[3];
513c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet         replacementIndexes[3]++) {
514c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        for (replacementIndexes[2] = start[2]; replacementIndexes[2] < end[2];
515c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet             replacementIndexes[2]++) {
516c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            for (replacementIndexes[1] = start[1]; replacementIndexes[1] < end[1];
517c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                 replacementIndexes[1]++) {
518c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                for (replacementIndexes[0] = start[0]; replacementIndexes[0] < end[0];
519c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                     replacementIndexes[0]++) {
520c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                    auto p = new FunctionPermutation(function, this, replacementIndexes, scanner);
521c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                    mPermutations.push_back(p);
522c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                }
523c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
524c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
525c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
526c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
527c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
528c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstring FunctionSpecification::getName(int replacementIndexes[MAX_REPLACEABLES]) const {
529c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return expandString(mUnexpandedName, replacementIndexes);
530c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
531c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
532c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletvoid FunctionSpecification::getReturn(int replacementIndexes[MAX_REPLACEABLES],
533c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                      std::string* retType, int* lineNumber) const {
534c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *retType = expandString(mReturn->type, replacementIndexes);
535c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *lineNumber = mReturn->lineNumber;
536c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
537c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
538c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletvoid FunctionSpecification::getParam(size_t index, int replacementIndexes[MAX_REPLACEABLES],
539c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                     std::string* type, std::string* name, std::string* testOption,
540c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                     int* lineNumber) const {
541c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    ParameterEntry* p = mParameters[index];
542c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *type = expandString(p->type, replacementIndexes);
543c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *name = p->name;
544c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *testOption = expandString(p->testOption, replacementIndexes);
545c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *lineNumber = p->lineNumber;
546c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
547c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
548c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletvoid FunctionSpecification::getInlines(int replacementIndexes[MAX_REPLACEABLES],
549c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                       std::vector<std::string>* inlines) const {
550c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    expandStringVector(mInline, replacementIndexes, inlines);
551c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
552c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
553c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletvoid FunctionSpecification::parseTest(Scanner* scanner) {
554c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string value = scanner->getValue();
555c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (value == "scalar" || value == "vector" || value == "noverify" || value == "custom" ||
556c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        value == "none") {
557c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        mTest = value;
558c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else if (value.compare(0, 7, "limited") == 0) {
559c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        mTest = "limited";
560c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (value.compare(7, 1, "(") == 0) {
561c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            size_t pParen = value.find(')');
562c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (pParen == string::npos) {
563c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                scanner->error() << "Incorrect test: \"" << value << "\"\n";
564c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            } else {
565c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                mPrecisionLimit = value.substr(8, pParen - 8);
566c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
567c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
568c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
569c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        scanner->error() << "Unrecognized test option: \"" << value << "\"\n";
570c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
571c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
572c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
57312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nibool FunctionSpecification::hasTests(unsigned int versionOfTestFiles) const {
574c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (mVersionInfo.maxVersion != 0 && mVersionInfo.maxVersion < versionOfTestFiles) {
575c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return false;
576c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
577c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (mTest == "none") {
578c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return false;
579c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
580c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return true;
581c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
582c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
58343d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainarvoid FunctionSpecification::checkRSTPatternValidity(const string &inlineStr,  bool allow,
58443d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar                                                    Scanner *scanner) {
58543d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    for (int i = 0; i < MAX_REPLACEABLES; i ++) {
58643d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        bool patternFound = inlineStr.find(kRSTypePatterns[i]) != string::npos;
58743d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
58843d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        if (patternFound) {
58943d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar            if (!allow) {
59043d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar                scanner->error() << "RST_i pattern not allowed here\n";
59143d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar            }
59243d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar            else if (mIsRSTAllowed[i] == false) {
59343d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar                scanner->error() << "Found pattern \"" << kRSTypePatterns[i]
59443d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar                    << "\" in spec.  But some entry in the corresponding"
59543d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar                    << " parameter list cannot be translated to an RS type\n";
59643d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar            }
59743d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        }
59843d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    }
59943d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar}
60043d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
6012217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouilletvoid FunctionSpecification::scanFunctionSpecification(Scanner* scanner, SpecFile* specFile,
60212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni                                                      unsigned int maxApiLevel) {
603c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Some functions like convert have # part of the name.  Truncate at that point.
6042217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    const string& unexpandedName = scanner->getValue();
6052217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    string name = unexpandedName;
606c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    size_t p = name.find('#');
607c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (p != string::npos) {
608c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (p > 0 && name[p - 1] == '_') {
609c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            p--;
610c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
611c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        name.erase(p);
612c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
6132217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    VersionInfo info;
6142217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    if (!info.scan(scanner, maxApiLevel)) {
6152217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        cout << "Skipping some " << name << " definitions.\n";
6162217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        scanner->skipUntilTag("end:");
6172217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet        return;
6182217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    }
619c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
620c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    bool created = false;
6217c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    Function* function = systemSpecification.findOrCreateFunction(name, &created);
6227c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    FunctionSpecification* spec = new FunctionSpecification(function);
623c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    function->addSpecification(spec);
62467923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    function->updateFinalVersion(info);
6257c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    specFile->addFunctionSpecification(spec, created);
626c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
6272217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    spec->mUnexpandedName = unexpandedName;
628c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    spec->mTest = "scalar";  // default
6292217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    spec->mVersionInfo = info;
630c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
63112398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni    if (scanner->findOptionalTag("internal:")) {
63212398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni        spec->mInternal = (scanner->getValue() == "true");
63312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni    }
63412398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni    if (scanner->findOptionalTag("intrinsic:")) {
63512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni        spec->mIntrinsic = (scanner->getValue() == "true");
63612398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni    }
637c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("attrib:")) {
638c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mAttribute = scanner->getValue();
639c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
640c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("w:")) {
641c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        vector<string> t;
642c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner->getValue().find("1") != string::npos) {
643c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            t.push_back("");
644c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
645c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner->getValue().find("2") != string::npos) {
646c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            t.push_back("2");
647c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
648c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner->getValue().find("3") != string::npos) {
649c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            t.push_back("3");
650c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
651c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner->getValue().find("4") != string::npos) {
652c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            t.push_back("4");
653c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
654c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mReplaceables.push_back(t);
65543d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        // RST_i pattern not applicable for width.
65643d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        spec->mIsRSTAllowed.push_back(false);
657c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
658c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
659c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    while (scanner->findOptionalTag("t:")) {
660c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mReplaceables.push_back(convertToTypeVector(scanner->getValue()));
66143d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        spec->mIsRSTAllowed.push_back(isRSTValid(spec->mReplaceables.back()));
662c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
663c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
66443d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    // Disallow RST_* pattern in function name
66543d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    // FIXME the line number for this error would be wrong
66643d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar    spec->checkRSTPatternValidity(unexpandedName, false, scanner);
66743d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
668c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findTag("ret:")) {
669c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        ParameterEntry* p = scanner->parseArgString(true);
670c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        function->addReturn(p, scanner);
671c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mReturn = p;
67243d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
67343d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        // Disallow RST_* pattern in return type
67443d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        spec->checkRSTPatternValidity(p->type, false, scanner);
675c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
676c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    while (scanner->findOptionalTag("arg:")) {
677c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        ParameterEntry* p = scanner->parseArgString(false);
678c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        function->addParameter(p, scanner);
679c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->mParameters.push_back(p);
68043d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
68143d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        // Disallow RST_* pattern in parameter type or testOption
68243d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        spec->checkRSTPatternValidity(p->type, false, scanner);
68343d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar        spec->checkRSTPatternValidity(p->testOption, false, scanner);
684c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
685c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
6867c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    function->scanDocumentationTags(scanner, created, specFile);
687c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
688c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("inline:")) {
689c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        scanner->checkNoValue();
690c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        while (scanner->findOptionalTag("")) {
691c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            spec->mInline.push_back(scanner->getValue());
69243d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar
69343d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar            // Allow RST_* pattern in inline definitions
69443d758c56868560fdd3cdcfeea599819ed037031Pirama Arumuga Nainar            spec->checkRSTPatternValidity(spec->mInline.back(), true, scanner);
695c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
696c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
697c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner->findOptionalTag("test:")) {
698c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->parseTest(scanner);
699c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
700c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
701c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    scanner->findTag("end:");
702c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
703c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    spec->createPermutations(function, scanner);
704c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
705c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
706c5184e202ced435258adb2cfe2013570e7190954Jean-Luc BrouilletFunctionPermutation::FunctionPermutation(Function* func, FunctionSpecification* spec,
707c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                         int replacementIndexes[MAX_REPLACEABLES], Scanner* scanner)
7084a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet    : mReturn(nullptr), mInputCount(0), mOutputCount(0) {
709c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // We expand the strings now to make capitalization easier.  The previous code preserved
710c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // the #n
711c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // markers just before emitting, which made capitalization difficult.
712c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mName = spec->getName(replacementIndexes);
713c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mNameTrunk = func->getName();
714c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mTest = spec->getTest();
715c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mPrecisionLimit = spec->getPrecisionLimit();
716c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    spec->getInlines(replacementIndexes, &mInline);
717c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
718c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mHasFloatAnswers = false;
719c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (size_t i = 0; i < spec->getNumberOfParams(); i++) {
720c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        string type, name, testOption;
721c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        int lineNumber = 0;
722c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        spec->getParam(i, replacementIndexes, &type, &name, &testOption, &lineNumber);
723c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        ParameterDefinition* def = new ParameterDefinition();
724c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        def->parseParameterDefinition(type, name, testOption, lineNumber, false, scanner);
725c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (def->isOutParameter) {
726c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            mOutputCount++;
727c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else {
728c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            mInputCount++;
729c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
730c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
731c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (def->typeIndex < 0 && mTest != "none") {
732c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner->error(lineNumber)
733c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                        << "Could not find " << def->rsBaseType
734c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                        << " while generating automated tests.  Use test: none if not needed.\n";
735c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
736c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (def->isOutParameter && def->isFloatType) {
737c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            mHasFloatAnswers = true;
738c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
739c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        mParams.push_back(def);
740c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
741c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
742c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    string retType;
743c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    int lineNumber = 0;
744c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    spec->getReturn(replacementIndexes, &retType, &lineNumber);
745c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!retType.empty()) {
746c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        mReturn = new ParameterDefinition();
747c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        mReturn->parseParameterDefinition(retType, "", "", lineNumber, true, scanner);
748c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (mReturn->isFloatType) {
749c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            mHasFloatAnswers = true;
750c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
751c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        mOutputCount++;
752c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
753c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
754c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
755c5184e202ced435258adb2cfe2013570e7190954Jean-Luc BrouilletFunctionPermutation::~FunctionPermutation() {
756c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto i : mParams) {
757c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        delete i;
758c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
759c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    delete mReturn;
760c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
761c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
762c5184e202ced435258adb2cfe2013570e7190954Jean-Luc BrouilletSpecFile::SpecFile(const string& specFileName) : mSpecFileName(specFileName) {
763c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    string core = mSpecFileName;
764c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Remove .spec
765c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    size_t l = core.length();
766c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const char SPEC[] = ".spec";
767c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const int SPEC_SIZE = sizeof(SPEC) - 1;
768c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const int start = l - SPEC_SIZE;
769c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (start >= 0 && core.compare(start, SPEC_SIZE, SPEC) == 0) {
770c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        core.erase(start);
771c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
772c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
773c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // The header file name should have the same base but with a ".rsh" extension.
774c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mHeaderFileName = core + ".rsh";
775d9935eeb051068c6049a533f375f0dffa0e6bd16Jean-Luc Brouillet    mDetailedDocumentationUrl = core + ".html";
776c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
777c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
7787c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletvoid SpecFile::addConstantSpecification(ConstantSpecification* spec, bool hasDocumentation) {
7797c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    mConstantSpecificationsList.push_back(spec);
7807c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    if (hasDocumentation) {
7817c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        Constant* constant = spec->getConstant();
7827c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        mDocumentedConstants.insert(pair<string, Constant*>(constant->getName(), constant));
783c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
7847c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet}
7857c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet
7867c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletvoid SpecFile::addTypeSpecification(TypeSpecification* spec, bool hasDocumentation) {
7877c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    mTypeSpecificationsList.push_back(spec);
7887c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    if (hasDocumentation) {
7897c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        Type* type = spec->getType();
7907c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        mDocumentedTypes.insert(pair<string, Type*>(type->getName(), type));
791c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
7927c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet}
7937c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet
7947c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletvoid SpecFile::addFunctionSpecification(FunctionSpecification* spec, bool hasDocumentation) {
7957c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    mFunctionSpecificationsList.push_back(spec);
7967c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    if (hasDocumentation) {
7977c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        Function* function = spec->getFunction();
7987c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        mDocumentedFunctions.insert(pair<string, Function*>(function->getName(), function));
799c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
800c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
801c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
802c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet// Read the specification, adding the definitions to the global functions map.
80312398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nibool SpecFile::readSpecFile(unsigned int maxApiLevel) {
804c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    FILE* specFile = fopen(mSpecFileName.c_str(), "rt");
805c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!specFile) {
806c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        cerr << "Error opening input file: " << mSpecFileName << "\n";
807c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return false;
808c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
809c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
810c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    Scanner scanner(mSpecFileName, specFile);
811c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
812c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Scan the header that should start the file.
813c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    scanner.skipBlankEntries();
814c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (scanner.findTag("header:")) {
815c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner.findTag("summary:")) {
816c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            mBriefDescription = scanner.getValue();
817c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
818c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner.findTag("description:")) {
819c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner.checkNoValue();
820c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            while (scanner.findOptionalTag("")) {
821c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                mFullDescription.push_back(scanner.getValue());
822c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
823c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
824c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner.findOptionalTag("include:")) {
825c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner.checkNoValue();
826c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            while (scanner.findOptionalTag("")) {
827c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                mVerbatimInclude.push_back(scanner.getValue());
828c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
829c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
830c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        scanner.findTag("end:");
831c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
832c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
833c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    while (1) {
834c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        scanner.skipBlankEntries();
835c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (scanner.atEnd()) {
836c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            break;
837c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
838c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        const string tag = scanner.getNextTag();
839c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (tag == "function:") {
8402217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet            FunctionSpecification::scanFunctionSpecification(&scanner, this, maxApiLevel);
841c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else if (tag == "type:") {
8422217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet            TypeSpecification::scanTypeSpecification(&scanner, this, maxApiLevel);
843c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else if (tag == "constant:") {
8442217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet            ConstantSpecification::scanConstantSpecification(&scanner, this, maxApiLevel);
845c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else {
846c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            scanner.error() << "Expected function:, type:, or constant:.  Found: " << tag << "\n";
847c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            return false;
848c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
849c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
850c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
851c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    fclose(specFile);
852c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return scanner.getErrorCount() == 0;
853c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
854c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
8557c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc BrouilletSystemSpecification::~SystemSpecification() {
8567c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto i : mConstants) {
8577c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        delete i.second;
8587c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    }
8597c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto i : mTypes) {
8607c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        delete i.second;
8617c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    }
8627c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto i : mFunctions) {
8637c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        delete i.second;
8647c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    }
8657c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto i : mSpecFiles) {
8667c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        delete i;
8677c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    }
8687c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet}
8697c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet
870c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet// Returns the named entry in the map.  Creates it if it's not there.
871c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillettemplate <class T>
8727c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc BrouilletT* findOrCreate(const string& name, map<string, T*>* map, bool* created) {
873c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    auto iter = map->find(name);
874c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (iter != map->end()) {
875c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *created = false;
876c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return iter->second;
877c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
878c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *created = true;
8797c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    T* f = new T(name);
880c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    map->insert(pair<string, T*>(name, f));
881c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return f;
882c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
883c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
8847c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc BrouilletConstant* SystemSpecification::findOrCreateConstant(const string& name, bool* created) {
8857c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    return findOrCreate<Constant>(name, &mConstants, created);
886c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
887c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
8887c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc BrouilletType* SystemSpecification::findOrCreateType(const string& name, bool* created) {
8897c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    return findOrCreate<Type>(name, &mTypes, created);
890c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
891c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
8927c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc BrouilletFunction* SystemSpecification::findOrCreateFunction(const string& name, bool* created) {
8937c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    return findOrCreate<Function>(name, &mFunctions, created);
894c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
895c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
89612398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nibool SystemSpecification::readSpecFile(const string& fileName, unsigned int maxApiLevel) {
897c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    SpecFile* spec = new SpecFile(fileName);
8982217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet    if (!spec->readSpecFile(maxApiLevel)) {
899c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        cerr << fileName << ": Failed to parse.\n";
900c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return false;
901c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
902c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    mSpecFiles.push_back(spec);
9037c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    return true;
904c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
905c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
90636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet
90712398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nistatic void updateMaxApiLevel(const VersionInfo& info, unsigned int* maxApiLevel) {
90812398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni    if (info.minVersion == VersionInfo::kUnreleasedVersion) {
90912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni        // Ignore development API level in consideration of max API level.
91012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni        return;
91112398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni    }
91236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet    *maxApiLevel = max(*maxApiLevel, max(info.minVersion, info.maxVersion));
91336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet}
91436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet
91512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Niunsigned int SystemSpecification::getMaximumApiLevel() {
91612398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni    unsigned int maxApiLevel = 0;
91736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet    for (auto i : mConstants) {
91836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet        for (auto j: i.second->getSpecifications()) {
91936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet            updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
92036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet        }
92136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet    }
92236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet    for (auto i : mTypes) {
92336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet        for (auto j: i.second->getSpecifications()) {
92436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet            updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
92536090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet        }
92636090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet    }
92736090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet    for (auto i : mFunctions) {
92836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet        for (auto j: i.second->getSpecifications()) {
92936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet            updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
93036090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet        }
93136090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet    }
93236090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet    return maxApiLevel;
93336090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet}
93436090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet
93512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nibool SystemSpecification::generateFiles(bool forVerification, unsigned int maxApiLevel) const {
9362a85b6b9d6f9cb8f1b20d573c1c5ceafe901b011Jean-Luc Brouillet    bool success = generateHeaderFiles("include") &&
9372217eb7b12e598e5b435a732207647918c171560Jean-Luc Brouillet                   generateDocumentation("docs", forVerification) &&
93836090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet                   generateTestFiles("test", maxApiLevel) &&
93936090673baf50cf3c70bdc89f9a4a872c05cf0f6Jean-Luc Brouillet                   generateStubsWhiteList("slangtest", maxApiLevel);
940c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (success) {
941c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        cout << "Successfully processed " << mTypes.size() << " types, " << mConstants.size()
942c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet             << " constants, and " << mFunctions.size() << " functions.\n";
943c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
944c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return success;
945c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
946c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
947c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstring SystemSpecification::getHtmlAnchor(const string& name) const {
948c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    Definition* d = nullptr;
949c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    auto c = mConstants.find(name);
950c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (c != mConstants.end()) {
951c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        d = c->second;
952c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
953c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        auto t = mTypes.find(name);
954c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (t != mTypes.end()) {
955c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            d = t->second;
956c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else {
957c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            auto f = mFunctions.find(name);
958c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (f != mFunctions.end()) {
959c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                d = f->second;
960c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            } else {
961c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                return string();
962c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
963c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
964c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
965c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    ostringstream stream;
966c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    stream << "<a href='" << d->getUrl() << "'>" << name << "</a>";
967c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return stream.str();
968c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
969