/*
 * 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 unsigned 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]);

static const char kTagUnreleased[] = "UNRELEASED";

// 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, unsigned int maxApiLevel) {
    if (scanner->findOptionalTag("version:")) {
        const string s = scanner->getValue();
        if (s.compare(0, sizeof(kTagUnreleased), kTagUnreleased) == 0) {
            // The API is still under development and does not have
            // an official version number.
            minVersion = maxVersion = kUnreleasedVersion;
        } else {
            sscanf(s.c_str(), "%u %u", &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,
                                                      unsigned 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,
                                              unsigned 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("rs_object:")) {
        spec->mKind = RS_OBJECT;
    }
    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(unsigned 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,
                                                      unsigned 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("internal:")) {
        spec->mInternal = (scanner->getValue() == "true");
    }
    if (scanner->findOptionalTag("intrinsic:")) {
        spec->mIntrinsic = (scanner->getValue() == "true");
    }
    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(unsigned 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, unsigned 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, unsigned int* maxApiLevel) {
    if (info.minVersion == VersionInfo::kUnreleasedVersion) {
        // Ignore development API level in consideration of max API level.
        return;
    }
    *maxApiLevel = max(*maxApiLevel, max(info.minVersion, info.maxVersion));
}

unsigned int SystemSpecification::getMaximumApiLevel() {
    unsigned 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, unsigned 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();
}
