/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdio.h>
#include <cctype>
#include <cstdlib>
#include <fstream>
#include <functional>
#include <iostream>
#include <memory>
#include <sstream>
#include <strings.h>

#include "Generator.h"
#include "Scanner.h"
#include "Specification.h"
#include "Utilities.h"

using namespace std;

// API level when RenderScript was added.
const int MIN_API_LEVEL = 9;

const NumericalType TYPES[] = {
            {"f16", "FLOAT_16", "half", "float", FLOATING_POINT, 11, 5},
            {"f32", "FLOAT_32", "float", "float", FLOATING_POINT, 24, 8},
            {"f64", "FLOAT_64", "double", "double", FLOATING_POINT, 53, 11},
            {"i8", "SIGNED_8", "char", "byte", SIGNED_INTEGER, 7, 0},
            {"u8", "UNSIGNED_8", "uchar", "byte", UNSIGNED_INTEGER, 8, 0},
            {"i16", "SIGNED_16", "short", "short", SIGNED_INTEGER, 15, 0},
            {"u16", "UNSIGNED_16", "ushort", "short", UNSIGNED_INTEGER, 16, 0},
            {"i32", "SIGNED_32", "int", "int", SIGNED_INTEGER, 31, 0},
            {"u32", "UNSIGNED_32", "uint", "int", UNSIGNED_INTEGER, 32, 0},
            {"i64", "SIGNED_64", "long", "long", SIGNED_INTEGER, 63, 0},
            {"u64", "UNSIGNED_64", "ulong", "long", UNSIGNED_INTEGER, 64, 0},
};

const int NUM_TYPES = sizeof(TYPES) / sizeof(TYPES[0]);

// The singleton of the collected information of all the spec files.
SystemSpecification systemSpecification;

// Returns the index in TYPES for the provided cType
static int findCType(const string& cType) {
    for (int i = 0; i < NUM_TYPES; i++) {
        if (cType == TYPES[i].cType) {
            return i;
        }
    }
    return -1;
}

/* Converts a string like "u8, u16" to a vector of "ushort", "uint".
 * For non-numerical types, we don't need to convert the abbreviation.
 */
static vector<string> convertToTypeVector(const string& input) {
    // First convert the string to an array of strings.
    vector<string> entries;
    stringstream stream(input);
    string entry;
    while (getline(stream, entry, ',')) {
        trimSpaces(&entry);
        entries.push_back(entry);
    }

    /* Second, we look for present numerical types. We do it this way
     * so the order of numerical types is always the same, no matter
     * how specified in the spec file.
     */
    vector<string> result;
    for (auto t : TYPES) {
        for (auto i = entries.begin(); i != entries.end(); ++i) {
            if (*i == t.specType) {
                result.push_back(t.cType);
                entries.erase(i);
                break;
            }
        }
    }

    // Add the remaining; they are not numerical types.
    for (auto s : entries) {
        result.push_back(s);
    }

    return result;
}

void ParameterDefinition::parseParameterDefinition(const string& type, const string& name,
                                                   const string& testOption, int lineNumber,
                                                   bool isReturn, Scanner* scanner) {
    rsType = type;
    specName = name;

    // Determine if this is an output.
    isOutParameter = isReturn || charRemoved('*', &rsType);

    rsBaseType = rsType;
    mVectorSize = "1";
    /* If it's a vector type, we need to split the base type from the size.
     * We know that's it's a vector type if the last character is a digit and
     * the rest is an actual base type.   We used to only verify the first part,
     * which created a problem with rs_matrix2x2.
     */
    const int last = rsType.size() - 1;
    const char lastChar = rsType[last];
    if (lastChar >= '0' && lastChar <= '9') {
        const string trimmed = rsType.substr(0, last);
        int i = findCType(trimmed);
        if (i >= 0) {
            rsBaseType = trimmed;
            mVectorSize = lastChar;
        }
    }
    typeIndex = findCType(rsBaseType);

    if (mVectorSize == "3") {
        vectorWidth = "4";
    } else {
        vectorWidth = mVectorSize;
    }

    /* Create variable names to be used in the java and .rs files.  Because x and
     * y are reserved in .rs files, we prefix variable names with "in" or "out".
     */
    if (isOutParameter) {
        variableName = "out";
        if (!specName.empty()) {
            variableName += capitalize(specName);
        } else if (!isReturn) {
            scanner->error(lineNumber) << "Should have a name.\n";
        }
    } else {
        variableName = "in";
        if (specName.empty()) {
            scanner->error(lineNumber) << "Should have a name.\n";
        }
        variableName += capitalize(specName);
    }
    rsAllocName = "gAlloc" + capitalize(variableName);
    javaAllocName = variableName;
    javaArrayName = "array" + capitalize(javaAllocName);

    // Process the option.
    undefinedIfOutIsNan = false;
    compatibleTypeIndex = -1;
    if (!testOption.empty()) {
        if (testOption.compare(0, 6, "range(") == 0) {
            size_t pComma = testOption.find(',');
            size_t pParen = testOption.find(')');
            if (pComma == string::npos || pParen == string::npos) {
                scanner->error(lineNumber) << "Incorrect range " << testOption << "\n";
            } else {
                minValue = testOption.substr(6, pComma - 6);
                maxValue = testOption.substr(pComma + 1, pParen - pComma - 1);
            }
        } else if (testOption.compare(0, 6, "above(") == 0) {
            size_t pParen = testOption.find(')');
            if (pParen == string::npos) {
                scanner->error(lineNumber) << "Incorrect testOption " << testOption << "\n";
            } else {
                smallerParameter = testOption.substr(6, pParen - 6);
            }
        } else if (testOption.compare(0, 11, "compatible(") == 0) {
            size_t pParen = testOption.find(')');
            if (pParen == string::npos) {
                scanner->error(lineNumber) << "Incorrect testOption " << testOption << "\n";
            } else {
                compatibleTypeIndex = findCType(testOption.substr(11, pParen - 11));
            }
        } else if (testOption.compare(0, 11, "conditional") == 0) {
            undefinedIfOutIsNan = true;
        } else {
            scanner->error(lineNumber) << "Unrecognized testOption " << testOption << "\n";
        }
    }

    isFloatType = false;
    if (typeIndex >= 0) {
        javaBaseType = TYPES[typeIndex].javaType;
        specType = TYPES[typeIndex].specType;
        isFloatType = TYPES[typeIndex].exponentBits > 0;
    }
    if (!minValue.empty()) {
        if (typeIndex < 0 || TYPES[typeIndex].kind != FLOATING_POINT) {
            scanner->error(lineNumber) << "range(,) is only supported for floating point\n";
        }
    }
}

bool VersionInfo::scan(Scanner* scanner, int maxApiLevel) {
    if (scanner->findOptionalTag("version:")) {
        const string s = scanner->getValue();
        sscanf(s.c_str(), "%i %i", &minVersion, &maxVersion);
        if (minVersion && minVersion < MIN_API_LEVEL) {
            scanner->error() << "Minimum version must >= 9\n";
        }
        if (minVersion == MIN_API_LEVEL) {
            minVersion = 0;
        }
        if (maxVersion && maxVersion < MIN_API_LEVEL) {
            scanner->error() << "Maximum version must >= 9\n";
        }
    }
    if (scanner->findOptionalTag("size:")) {
        sscanf(scanner->getValue().c_str(), "%i", &intSize);
    }
    if (maxVersion > maxApiLevel) {
        maxVersion = maxApiLevel;
    }
    return minVersion == 0 || minVersion <= maxApiLevel;
}

Definition::Definition(const std::string& name)
    : mName(name), mDeprecatedApiLevel(0), mHidden(false), mFinalVersion(-1) {
}

void Definition::updateFinalVersion(const VersionInfo& info) {
    /* We set it if:
     * - We have never set mFinalVersion before, or
     * - The max version is 0, which means we have not expired this API, or
     * - We have a max that's later than what we currently have.
     */
    if (mFinalVersion < 0 || info.maxVersion == 0 ||
        (mFinalVersion > 0 && info.maxVersion > mFinalVersion)) {
        mFinalVersion = info.maxVersion;
    }
}

void Definition::scanDocumentationTags(Scanner* scanner, bool firstOccurence,
                                       const SpecFile* specFile) {
    if (scanner->findOptionalTag("hidden:")) {
        scanner->checkNoValue();
        mHidden = true;
    }
    if (scanner->findOptionalTag("deprecated:")) {
        string value = scanner->getValue();
        size_t pComma = value.find(", ");
        if (pComma != string::npos) {
            mDeprecatedMessage = value.substr(pComma + 2);
            value.erase(pComma);
        }
        sscanf(value.c_str(), "%i", &mDeprecatedApiLevel);
        if (mDeprecatedApiLevel <= 0) {
            scanner->error() << "deprecated entries should have a level > 0\n";
        }
    }
    if (firstOccurence) {
        if (scanner->findTag("summary:")) {
            mSummary = scanner->getValue();
        }
        if (scanner->findTag("description:")) {
            scanner->checkNoValue();
            while (scanner->findOptionalTag("")) {
                mDescription.push_back(scanner->getValue());
            }
        }
        mUrl = specFile->getDetailedDocumentationUrl() + "#android_rs:" + mName;
    } else if (scanner->findOptionalTag("summary:")) {
        scanner->error() << "Only the first specification should have a summary.\n";
    }
}

Constant::~Constant() {
    for (auto i : mSpecifications) {
        delete i;
    }
}

Type::~Type() {
    for (auto i : mSpecifications) {
        delete i;
    }
}

Function::Function(const string& name) : Definition(name) {
    mCapitalizedName = capitalize(mName);
}

Function::~Function() {
    for (auto i : mSpecifications) {
        delete i;
    }
}

bool Function::someParametersAreDocumented() const {
    for (auto p : mParameters) {
        if (!p->documentation.empty()) {
            return true;
        }
    }
    return false;
}

void Function::addParameter(ParameterEntry* entry, Scanner* scanner) {
    for (auto i : mParameters) {
        if (i->name == entry->name) {
            // It's a duplicate.
            if (!entry->documentation.empty()) {
                scanner->error(entry->lineNumber)
                            << "Only the first occurence of an arg should have the "
                               "documentation.\n";
            }
            return;
        }
    }
    mParameters.push_back(entry);
}

void Function::addReturn(ParameterEntry* entry, Scanner* scanner) {
    if (entry->documentation.empty()) {
        return;
    }
    if (!mReturnDocumentation.empty()) {
        scanner->error() << "ret: should be documented only for the first variant\n";
    }
    mReturnDocumentation = entry->documentation;
}

void ConstantSpecification::scanConstantSpecification(Scanner* scanner, SpecFile* specFile,
                                                      int maxApiLevel) {
    string name = scanner->getValue();
    VersionInfo info;
    if (!info.scan(scanner, maxApiLevel)) {
        cout << "Skipping some " << name << " definitions.\n";
        scanner->skipUntilTag("end:");
        return;
    }

    bool created = false;
    Constant* constant = systemSpecification.findOrCreateConstant(name, &created);
    ConstantSpecification* spec = new ConstantSpecification(constant);
    constant->addSpecification(spec);
    constant->updateFinalVersion(info);
    specFile->addConstantSpecification(spec, created);
    spec->mVersionInfo = info;

    if (scanner->findTag("value:")) {
        spec->mValue = scanner->getValue();
    }
    constant->scanDocumentationTags(scanner, created, specFile);

    scanner->findTag("end:");
}

void TypeSpecification::scanTypeSpecification(Scanner* scanner, SpecFile* specFile,
                                              int maxApiLevel) {
    string name = scanner->getValue();
    VersionInfo info;
    if (!info.scan(scanner, maxApiLevel)) {
        cout << "Skipping some " << name << " definitions.\n";
        scanner->skipUntilTag("end:");
        return;
    }

    bool created = false;
    Type* type = systemSpecification.findOrCreateType(name, &created);
    TypeSpecification* spec = new TypeSpecification(type);
    type->addSpecification(spec);
    type->updateFinalVersion(info);
    specFile->addTypeSpecification(spec, created);
    spec->mVersionInfo = info;

    if (scanner->findOptionalTag("simple:")) {
        spec->mKind = SIMPLE;
        spec->mSimpleType = scanner->getValue();
    }
    if (scanner->findOptionalTag("struct:")) {
        spec->mKind = STRUCT;
        spec->mStructName = scanner->getValue();
        while (scanner->findOptionalTag("field:")) {
            string s = scanner->getValue();
            string comment;
            scanner->parseDocumentation(&s, &comment);
            spec->mFields.push_back(s);
            spec->mFieldComments.push_back(comment);
        }
    }
    if (scanner->findOptionalTag("enum:")) {
        spec->mKind = ENUM;
        spec->mEnumName = scanner->getValue();
        while (scanner->findOptionalTag("value:")) {
            string s = scanner->getValue();
            string comment;
            scanner->parseDocumentation(&s, &comment);
            spec->mValues.push_back(s);
            spec->mValueComments.push_back(comment);
        }
    }
    if (scanner->findOptionalTag("attrib:")) {
        spec->mAttribute = scanner->getValue();
    }
    type->scanDocumentationTags(scanner, created, specFile);

    scanner->findTag("end:");
}

FunctionSpecification::~FunctionSpecification() {
    for (auto i : mParameters) {
        delete i;
    }
    delete mReturn;
    for (auto i : mPermutations) {
        delete i;
    }
}

string FunctionSpecification::expandString(string s,
                                           int replacementIndexes[MAX_REPLACEABLES]) const {
    if (mReplaceables.size() > 0) {
        s = stringReplace(s, "#1", mReplaceables[0][replacementIndexes[0]]);
    }
    if (mReplaceables.size() > 1) {
        s = stringReplace(s, "#2", mReplaceables[1][replacementIndexes[1]]);
    }
    if (mReplaceables.size() > 2) {
        s = stringReplace(s, "#3", mReplaceables[2][replacementIndexes[2]]);
    }
    if (mReplaceables.size() > 3) {
        s = stringReplace(s, "#4", mReplaceables[3][replacementIndexes[3]]);
    }
    return s;
}

void FunctionSpecification::expandStringVector(const vector<string>& in,
                                               int replacementIndexes[MAX_REPLACEABLES],
                                               vector<string>* out) const {
    out->clear();
    for (vector<string>::const_iterator iter = in.begin(); iter != in.end(); iter++) {
        out->push_back(expandString(*iter, replacementIndexes));
    }
}

void FunctionSpecification::createPermutations(Function* function, Scanner* scanner) {
    int start[MAX_REPLACEABLES];
    int end[MAX_REPLACEABLES];
    for (int i = 0; i < MAX_REPLACEABLES; i++) {
        if (i < (int)mReplaceables.size()) {
            start[i] = 0;
            end[i] = mReplaceables[i].size();
        } else {
            start[i] = -1;
            end[i] = 0;
        }
    }
    int replacementIndexes[MAX_REPLACEABLES];
    // TODO: These loops assume that MAX_REPLACEABLES is 4.
    for (replacementIndexes[3] = start[3]; replacementIndexes[3] < end[3];
         replacementIndexes[3]++) {
        for (replacementIndexes[2] = start[2]; replacementIndexes[2] < end[2];
             replacementIndexes[2]++) {
            for (replacementIndexes[1] = start[1]; replacementIndexes[1] < end[1];
                 replacementIndexes[1]++) {
                for (replacementIndexes[0] = start[0]; replacementIndexes[0] < end[0];
                     replacementIndexes[0]++) {
                    auto p = new FunctionPermutation(function, this, replacementIndexes, scanner);
                    mPermutations.push_back(p);
                }
            }
        }
    }
}

string FunctionSpecification::getName(int replacementIndexes[MAX_REPLACEABLES]) const {
    return expandString(mUnexpandedName, replacementIndexes);
}

void FunctionSpecification::getReturn(int replacementIndexes[MAX_REPLACEABLES],
                                      std::string* retType, int* lineNumber) const {
    *retType = expandString(mReturn->type, replacementIndexes);
    *lineNumber = mReturn->lineNumber;
}

void FunctionSpecification::getParam(size_t index, int replacementIndexes[MAX_REPLACEABLES],
                                     std::string* type, std::string* name, std::string* testOption,
                                     int* lineNumber) const {
    ParameterEntry* p = mParameters[index];
    *type = expandString(p->type, replacementIndexes);
    *name = p->name;
    *testOption = expandString(p->testOption, replacementIndexes);
    *lineNumber = p->lineNumber;
}

void FunctionSpecification::getInlines(int replacementIndexes[MAX_REPLACEABLES],
                                       std::vector<std::string>* inlines) const {
    expandStringVector(mInline, replacementIndexes, inlines);
}

void FunctionSpecification::parseTest(Scanner* scanner) {
    const string value = scanner->getValue();
    if (value == "scalar" || value == "vector" || value == "noverify" || value == "custom" ||
        value == "none") {
        mTest = value;
    } else if (value.compare(0, 7, "limited") == 0) {
        mTest = "limited";
        if (value.compare(7, 1, "(") == 0) {
            size_t pParen = value.find(')');
            if (pParen == string::npos) {
                scanner->error() << "Incorrect test: \"" << value << "\"\n";
            } else {
                mPrecisionLimit = value.substr(8, pParen - 8);
            }
        }
    } else {
        scanner->error() << "Unrecognized test option: \"" << value << "\"\n";
    }
}

bool FunctionSpecification::hasTests(int versionOfTestFiles) const {
    if (mVersionInfo.maxVersion != 0 && mVersionInfo.maxVersion < versionOfTestFiles) {
        return false;
    }
    if (mTest == "none") {
        return false;
    }
    return true;
}

void FunctionSpecification::scanFunctionSpecification(Scanner* scanner, SpecFile* specFile,
                                                      int maxApiLevel) {
    // Some functions like convert have # part of the name.  Truncate at that point.
    const string& unexpandedName = scanner->getValue();
    string name = unexpandedName;
    size_t p = name.find('#');
    if (p != string::npos) {
        if (p > 0 && name[p - 1] == '_') {
            p--;
        }
        name.erase(p);
    }
    VersionInfo info;
    if (!info.scan(scanner, maxApiLevel)) {
        cout << "Skipping some " << name << " definitions.\n";
        scanner->skipUntilTag("end:");
        return;
    }

    bool created = false;
    Function* function = systemSpecification.findOrCreateFunction(name, &created);
    FunctionSpecification* spec = new FunctionSpecification(function);
    function->addSpecification(spec);
    function->updateFinalVersion(info);
    specFile->addFunctionSpecification(spec, created);

    spec->mUnexpandedName = unexpandedName;
    spec->mTest = "scalar";  // default
    spec->mVersionInfo = info;

    if (scanner->findOptionalTag("attrib:")) {
        spec->mAttribute = scanner->getValue();
    }
    if (scanner->findOptionalTag("w:")) {
        vector<string> t;
        if (scanner->getValue().find("1") != string::npos) {
            t.push_back("");
        }
        if (scanner->getValue().find("2") != string::npos) {
            t.push_back("2");
        }
        if (scanner->getValue().find("3") != string::npos) {
            t.push_back("3");
        }
        if (scanner->getValue().find("4") != string::npos) {
            t.push_back("4");
        }
        spec->mReplaceables.push_back(t);
    }

    while (scanner->findOptionalTag("t:")) {
        spec->mReplaceables.push_back(convertToTypeVector(scanner->getValue()));
    }

    if (scanner->findTag("ret:")) {
        ParameterEntry* p = scanner->parseArgString(true);
        function->addReturn(p, scanner);
        spec->mReturn = p;
    }
    while (scanner->findOptionalTag("arg:")) {
        ParameterEntry* p = scanner->parseArgString(false);
        function->addParameter(p, scanner);
        spec->mParameters.push_back(p);
    }

    function->scanDocumentationTags(scanner, created, specFile);

    if (scanner->findOptionalTag("inline:")) {
        scanner->checkNoValue();
        while (scanner->findOptionalTag("")) {
            spec->mInline.push_back(scanner->getValue());
        }
    }
    if (scanner->findOptionalTag("test:")) {
        spec->parseTest(scanner);
    }

    scanner->findTag("end:");

    spec->createPermutations(function, scanner);
}

FunctionPermutation::FunctionPermutation(Function* func, FunctionSpecification* spec,
                                         int replacementIndexes[MAX_REPLACEABLES], Scanner* scanner)
    : mReturn(nullptr), mInputCount(0), mOutputCount(0) {
    // We expand the strings now to make capitalization easier.  The previous code preserved
    // the #n
    // markers just before emitting, which made capitalization difficult.
    mName = spec->getName(replacementIndexes);
    mNameTrunk = func->getName();
    mTest = spec->getTest();
    mPrecisionLimit = spec->getPrecisionLimit();
    spec->getInlines(replacementIndexes, &mInline);

    mHasFloatAnswers = false;
    for (size_t i = 0; i < spec->getNumberOfParams(); i++) {
        string type, name, testOption;
        int lineNumber = 0;
        spec->getParam(i, replacementIndexes, &type, &name, &testOption, &lineNumber);
        ParameterDefinition* def = new ParameterDefinition();
        def->parseParameterDefinition(type, name, testOption, lineNumber, false, scanner);
        if (def->isOutParameter) {
            mOutputCount++;
        } else {
            mInputCount++;
        }

        if (def->typeIndex < 0 && mTest != "none") {
            scanner->error(lineNumber)
                        << "Could not find " << def->rsBaseType
                        << " while generating automated tests.  Use test: none if not needed.\n";
        }
        if (def->isOutParameter && def->isFloatType) {
            mHasFloatAnswers = true;
        }
        mParams.push_back(def);
    }

    string retType;
    int lineNumber = 0;
    spec->getReturn(replacementIndexes, &retType, &lineNumber);
    if (!retType.empty()) {
        mReturn = new ParameterDefinition();
        mReturn->parseParameterDefinition(retType, "", "", lineNumber, true, scanner);
        if (mReturn->isFloatType) {
            mHasFloatAnswers = true;
        }
        mOutputCount++;
    }
}

FunctionPermutation::~FunctionPermutation() {
    for (auto i : mParams) {
        delete i;
    }
    delete mReturn;
}

SpecFile::SpecFile(const string& specFileName) : mSpecFileName(specFileName) {
    string core = mSpecFileName;
    // Remove .spec
    size_t l = core.length();
    const char SPEC[] = ".spec";
    const int SPEC_SIZE = sizeof(SPEC) - 1;
    const int start = l - SPEC_SIZE;
    if (start >= 0 && core.compare(start, SPEC_SIZE, SPEC) == 0) {
        core.erase(start);
    }

    // The header file name should have the same base but with a ".rsh" extension.
    mHeaderFileName = core + ".rsh";
    mDetailedDocumentationUrl = core + ".html";
}

void SpecFile::addConstantSpecification(ConstantSpecification* spec, bool hasDocumentation) {
    mConstantSpecificationsList.push_back(spec);
    if (hasDocumentation) {
        Constant* constant = spec->getConstant();
        mDocumentedConstants.insert(pair<string, Constant*>(constant->getName(), constant));
    }
}

void SpecFile::addTypeSpecification(TypeSpecification* spec, bool hasDocumentation) {
    mTypeSpecificationsList.push_back(spec);
    if (hasDocumentation) {
        Type* type = spec->getType();
        mDocumentedTypes.insert(pair<string, Type*>(type->getName(), type));
    }
}

void SpecFile::addFunctionSpecification(FunctionSpecification* spec, bool hasDocumentation) {
    mFunctionSpecificationsList.push_back(spec);
    if (hasDocumentation) {
        Function* function = spec->getFunction();
        mDocumentedFunctions.insert(pair<string, Function*>(function->getName(), function));
    }
}

// Read the specification, adding the definitions to the global functions map.
bool SpecFile::readSpecFile(int maxApiLevel) {
    FILE* specFile = fopen(mSpecFileName.c_str(), "rt");
    if (!specFile) {
        cerr << "Error opening input file: " << mSpecFileName << "\n";
        return false;
    }

    Scanner scanner(mSpecFileName, specFile);

    // Scan the header that should start the file.
    scanner.skipBlankEntries();
    if (scanner.findTag("header:")) {
        if (scanner.findTag("summary:")) {
            mBriefDescription = scanner.getValue();
        }
        if (scanner.findTag("description:")) {
            scanner.checkNoValue();
            while (scanner.findOptionalTag("")) {
                mFullDescription.push_back(scanner.getValue());
            }
        }
        if (scanner.findOptionalTag("include:")) {
            scanner.checkNoValue();
            while (scanner.findOptionalTag("")) {
                mVerbatimInclude.push_back(scanner.getValue());
            }
        }
        scanner.findTag("end:");
    }

    while (1) {
        scanner.skipBlankEntries();
        if (scanner.atEnd()) {
            break;
        }
        const string tag = scanner.getNextTag();
        if (tag == "function:") {
            FunctionSpecification::scanFunctionSpecification(&scanner, this, maxApiLevel);
        } else if (tag == "type:") {
            TypeSpecification::scanTypeSpecification(&scanner, this, maxApiLevel);
        } else if (tag == "constant:") {
            ConstantSpecification::scanConstantSpecification(&scanner, this, maxApiLevel);
        } else {
            scanner.error() << "Expected function:, type:, or constant:.  Found: " << tag << "\n";
            return false;
        }
    }

    fclose(specFile);
    return scanner.getErrorCount() == 0;
}

SystemSpecification::~SystemSpecification() {
    for (auto i : mConstants) {
        delete i.second;
    }
    for (auto i : mTypes) {
        delete i.second;
    }
    for (auto i : mFunctions) {
        delete i.second;
    }
    for (auto i : mSpecFiles) {
        delete i;
    }
}

// Returns the named entry in the map.  Creates it if it's not there.
template <class T>
T* findOrCreate(const string& name, map<string, T*>* map, bool* created) {
    auto iter = map->find(name);
    if (iter != map->end()) {
        *created = false;
        return iter->second;
    }
    *created = true;
    T* f = new T(name);
    map->insert(pair<string, T*>(name, f));
    return f;
}

Constant* SystemSpecification::findOrCreateConstant(const string& name, bool* created) {
    return findOrCreate<Constant>(name, &mConstants, created);
}

Type* SystemSpecification::findOrCreateType(const string& name, bool* created) {
    return findOrCreate<Type>(name, &mTypes, created);
}

Function* SystemSpecification::findOrCreateFunction(const string& name, bool* created) {
    return findOrCreate<Function>(name, &mFunctions, created);
}

bool SystemSpecification::readSpecFile(const string& fileName, int maxApiLevel) {
    SpecFile* spec = new SpecFile(fileName);
    if (!spec->readSpecFile(maxApiLevel)) {
        cerr << fileName << ": Failed to parse.\n";
        return false;
    }
    mSpecFiles.push_back(spec);
    return true;
}


static void updateMaxApiLevel(const VersionInfo& info, int* maxApiLevel) {
    *maxApiLevel = max(*maxApiLevel, max(info.minVersion, info.maxVersion));
}

int SystemSpecification::getMaximumApiLevel() {
    int maxApiLevel = 0;
    for (auto i : mConstants) {
        for (auto j: i.second->getSpecifications()) {
            updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
        }
    }
    for (auto i : mTypes) {
        for (auto j: i.second->getSpecifications()) {
            updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
        }
    }
    for (auto i : mFunctions) {
        for (auto j: i.second->getSpecifications()) {
            updateMaxApiLevel(j->getVersionInfo(), &maxApiLevel);
        }
    }
    return maxApiLevel;
}

bool SystemSpecification::generateFiles(bool forVerification, int maxApiLevel) const {
    bool success = generateHeaderFiles("scriptc") &&
                   generateDocumentation("docs", forVerification) &&
                   generateTestFiles("test", maxApiLevel) &&
                   generateStubsWhiteList("slangtest", maxApiLevel);
    if (success) {
        cout << "Successfully processed " << mTypes.size() << " types, " << mConstants.size()
             << " constants, and " << mFunctions.size() << " functions.\n";
    }
    return success;
}

string SystemSpecification::getHtmlAnchor(const string& name) const {
    Definition* d = nullptr;
    auto c = mConstants.find(name);
    if (c != mConstants.end()) {
        d = c->second;
    } else {
        auto t = mTypes.find(name);
        if (t != mTypes.end()) {
            d = t->second;
        } else {
            auto f = mFunctions.find(name);
            if (f != mFunctions.end()) {
                d = f->second;
            } else {
                return string();
            }
        }
    }
    ostringstream stream;
    stream << "<a href='" << d->getUrl() << "'>" << name << "</a>";
    return stream.str();
}
