GenerateHeaderFiles.cpp revision fab6947a18e00964f79e6c802dc70bbaed981730
1c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet/*
2c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * Copyright (C) 2015 The Android Open Source Project
3c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet *
4c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * Licensed under the Apache License, Version 2.0 (the "License");
5c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * you may not use this file except in compliance with the License.
6c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * You may obtain a copy of the License at
7c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet *
8c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet *      http://www.apache.org/licenses/LICENSE-2.0
9c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet *
10c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * Unless required by applicable law or agreed to in writing, software
11c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * distributed under the License is distributed on an "AS IS" BASIS,
12c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * See the License for the specific language governing permissions and
14c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet * limitations under the License.
15c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet */
16c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
17c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <iostream>
18c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include <sstream>
19c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
20c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include "Generator.h"
21c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include "Specification.h"
22c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet#include "Utilities.h"
23c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
24c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletusing namespace std;
25c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
26c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet// Convert a file name into a string that can be used to guard the include file with #ifdef...
27c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic string makeGuardString(const string& filename) {
28c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    string s;
29c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    s.resize(15 + filename.size());
30c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    s = "RENDERSCRIPT_";
31c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (char c : filename) {
32c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (c == '.') {
33c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            s += '_';
34c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else {
35c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            s += toupper(c);
36c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
37c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
38c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return s;
39c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
40c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
4167923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet/* Write #ifdef's that ensure that the specified version is present.  If we're at the final version,
4267923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet * add a check on a flag that can be set for internal builds.  This enables us to keep supporting
4367923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet * old APIs in the runtime code.
4467923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet */
4512398d81f32e5e0479d02b8608a83c75cd991bb3Yang Nistatic void writeVersionGuardStart(GeneratedFile* file, VersionInfo info, unsigned int finalVersion) {
46c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (info.intSize == 32) {
47c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "#ifndef __LP64__\n";
48c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else if (info.intSize == 64) {
49c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "#ifdef __LP64__\n";
50c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
51c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
5267923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    ostringstream checkMaxVersion;
5367923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    if (info.maxVersion > 0) {
5467923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet        checkMaxVersion << "(";
5567923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet        if (info.maxVersion == finalVersion) {
5667923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet            checkMaxVersion << "defined(RS_DECLARE_EXPIRED_APIS) || ";
5767923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet        }
5867923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet        checkMaxVersion << "RS_VERSION <= " << info.maxVersion << ")";
5967923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    }
6067923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet
61c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (info.minVersion <= 1) {
62c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        // No minimum
63c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (info.maxVersion > 0) {
6467923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet            *file << "#if !defined(RS_VERSION) || " << checkMaxVersion.str() << "\n";
65c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
66c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
6767923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet        *file << "#if (defined(RS_VERSION) && (RS_VERSION >= " << info.minVersion << ")";
6867923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet        if (info.maxVersion > 0) {
6967923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet            *file << " && " << checkMaxVersion.str();
70c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
7167923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet        *file << ")\n";
72c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
73c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
74c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
75c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic void writeVersionGuardEnd(GeneratedFile* file, VersionInfo info) {
76c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (info.minVersion > 1 || info.maxVersion != 0) {
77c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "#endif\n";
78c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
79c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (info.intSize != 0) {
80c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "#endif\n";
81c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
82c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
83c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
84c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic void writeComment(GeneratedFile* file, const string& name, const string& briefComment,
854a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet                         const vector<string>& comment, bool addDeprecatedWarning,
864a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet                         bool closeBlock) {
87c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (briefComment.empty() && comment.size() == 0) {
88c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return;
89c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
90c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << "/*\n";
91c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!briefComment.empty()) {
92c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " * " << name << ": " << briefComment << "\n";
93c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " *\n";
94c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
954a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet    if (addDeprecatedWarning) {
964a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet        *file << " * DEPRECATED.  Do not use.\n";
974a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet        *file << " *\n";
984a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet    }
99c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (size_t ct = 0; ct < comment.size(); ct++) {
100c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        string s = stripHtml(comment[ct]);
101c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        s = stringReplace(s, "@", "");
102c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (!s.empty()) {
103c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << " * " << s << "\n";
104c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else {
105c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << " *\n";
106c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
107c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
108c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (closeBlock) {
109c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " */\n";
110c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
111c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
112c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
1137c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeConstantComment(GeneratedFile* file, const Constant& constant) {
114c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string name = constant.getName();
1154a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet    writeComment(file, name, constant.getSummary(), constant.getDescription(),
1164a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet                 constant.deprecated(), true);
1177c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet}
118c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
1197c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeConstantSpecification(GeneratedFile* file, const ConstantSpecification& spec) {
12067923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    const Constant* constant = spec.getConstant();
1217c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    VersionInfo info = spec.getVersionInfo();
12267923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    writeVersionGuardStart(file, info, constant->getFinalVersion());
12367923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    *file << "#define " << constant->getName() << " " << spec.getValue() << "\n\n";
1247c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    writeVersionGuardEnd(file, info);
125c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
126c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
1277c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeTypeSpecification(GeneratedFile* file, const TypeSpecification& spec) {
12867923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    const Type* type = spec.getType();
12967923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    const string& typeName = type->getName();
130c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const VersionInfo info = spec.getVersionInfo();
13167923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    writeVersionGuardStart(file, info, type->getFinalVersion());
13236e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet
13336e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet    const string attribute =
13436e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet                makeAttributeTag(spec.getAttribute(), "", type->getDeprecatedApiLevel(),
13536e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet                                 type->getDeprecatedMessage());
13636e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet    *file << "typedef ";
137c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    switch (spec.getKind()) {
138c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        case SIMPLE:
13936e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet            *file << spec.getSimpleType() << attribute;
140c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            break;
141ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines        case RS_OBJECT:
142ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines            *file << "struct " << typeName << " _RS_OBJECT_DECL" << attribute;
143ca51c78b9e3097ee31dd24cdc5982f550ee563d1Stephen Hines            break;
144c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        case ENUM: {
14536e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet            *file << "enum" << attribute << " ";
146c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const string name = spec.getEnumName();
147c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (!name.empty()) {
148c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << name << " ";
149c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
150c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "{\n";
151c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
152c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const vector<string>& values = spec.getValues();
153c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const vector<string>& valueComments = spec.getValueComments();
154c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const size_t last = values.size() - 1;
155c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            for (size_t i = 0; i <= last; i++) {
156c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "    " << values[i];
157c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                if (i != last) {
158c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                    *file << ",";
159c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                }
160c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                if (valueComments.size() > i && !valueComments[i].empty()) {
161c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                    *file << " // " << valueComments[i];
162c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                }
163c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "\n";
164c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
16536e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet            *file << "}";
166c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            break;
167c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
168c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        case STRUCT: {
16936e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet            *file << "struct" << attribute << " ";
170c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const string name = spec.getStructName();
171c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (!name.empty()) {
172c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << name << " ";
173c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
174c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "{\n";
175c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
176c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const vector<string>& fields = spec.getFields();
177c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const vector<string>& fieldComments = spec.getFieldComments();
178c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            for (size_t i = 0; i < fields.size(); i++) {
179c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "    " << fields[i] << ";";
180c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                if (fieldComments.size() > i && !fieldComments[i].empty()) {
181c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                    *file << " // " << fieldComments[i];
182c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                }
183c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "\n";
184c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
18536e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet            *file << "}";
186c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            break;
187c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
188c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
18936e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet    *file << " " << typeName << ";\n";
19036e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet
191c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeVersionGuardEnd(file, info);
192c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << "\n";
193c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
194c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
1957c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeTypeComment(GeneratedFile* file, const Type& type) {
196c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string name = type.getName();
1974a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet    writeComment(file, name, type.getSummary(), type.getDescription(), type.deprecated(), true);
198c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
199c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
200c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic void writeFunctionPermutation(GeneratedFile* file, const FunctionSpecification& spec,
201c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                     const FunctionPermutation& permutation) {
20267923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    Function* function = spec.getFunction();
20367923a9e829d89522bb5338a6d635d807a7ee59bJean-Luc Brouillet    writeVersionGuardStart(file, spec.getVersionInfo(), function->getFinalVersion());
204c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
205c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write linkage info.
206c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const auto inlineCodeLines = permutation.getInline();
207c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (inlineCodeLines.size() > 0) {
208c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "static inline ";
209c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
210c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "extern ";
211c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
212c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
213c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the return type.
214c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    auto ret = permutation.getReturn();
215c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (ret) {
216c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << ret->rsType;
217c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
218c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "void";
219c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
220c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
22112398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni    *file << makeAttributeTag(spec.getAttribute(), spec.isOverloadable() ? "overloadable" : "",
22236e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet                              function->getDeprecatedApiLevel(), function->getDeprecatedMessage());
22336e2be56cd398bf4a318114bbc9fa3f4573c158fJean-Luc Brouillet    *file << "\n";
224c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
225c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the function name.
226c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << "    " << permutation.getName() << "(";
227c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const int offset = 4 + permutation.getName().size() + 1;  // Size of above
228c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
229c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the arguments.  We wrap on mulitple lines if a line gets too long.
230c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    int charsOnLine = offset;
231c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    bool hasGenerated = false;
232c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto p : permutation.getParams()) {
233c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (hasGenerated) {
234c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << ",";
235c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            charsOnLine++;
236c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
237c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        ostringstream ps;
238c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        ps << p->rsType;
239c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (p->isOutParameter) {
240c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            ps << "*";
241c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
242fab6947a18e00964f79e6c802dc70bbaed981730Yang Ni        if (!p->specName.empty() && p->rsType != "...") {
243c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            ps << " " << p->specName;
244c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
245c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        const string s = ps.str();
246c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (charsOnLine + s.size() >= 100) {
247c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "\n" << string(offset, ' ');
248c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            charsOnLine = offset;
249c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else if (hasGenerated) {
250c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << " ";
251c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            charsOnLine++;
252c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
253c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << s;
254c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        charsOnLine += s.size();
255c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        hasGenerated = true;
256c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
257c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // In C, if no parameters, we need to output void, e.g. fn(void).
258c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!hasGenerated) {
259c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "void";
260c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
261c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << ")";
262c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
263c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the inline code, if any.
264c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (inlineCodeLines.size() > 0) {
265c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " {\n";
266c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        for (size_t ct = 0; ct < inlineCodeLines.size(); ct++) {
267c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (inlineCodeLines[ct].empty()) {
268c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "\n";
269c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            } else {
270c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "    " << inlineCodeLines[ct] << "\n";
271c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
272c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
273c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "}\n";
274c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
275c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << ";\n";
276c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
277c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
278c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeVersionGuardEnd(file, spec.getVersionInfo());
279c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << "\n";
280c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
281c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
2827c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeFunctionComment(GeneratedFile* file, const Function& function) {
283c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the generic documentation.
2844a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet    writeComment(file, function.getName(), function.getSummary(), function.getDescription(),
2854a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet                 function.deprecated(), false);
286c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
287c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Comment the parameters.
288c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (function.someParametersAreDocumented()) {
289c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " *\n";
290c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " * Parameters:\n";
291c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        for (auto p : function.getParameters()) {
292c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (!p->documentation.empty()) {
2934a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet                *file << " *   " << p->name << ": " << p->documentation << "\n";
294c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
295c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
296c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
297c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
298c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Comment the return type.
299c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string returnDoc = function.getReturnDocumentation();
300c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!returnDoc.empty()) {
301c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " *\n";
302c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " * Returns: " << returnDoc << "\n";
303c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
304c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
305c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << " */\n";
3067c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet}
307c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
3087c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeFunctionSpecification(GeneratedFile* file, const FunctionSpecification& spec) {
309c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write all the variants.
3107c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto permutation : spec.getPermutations()) {
3117c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        writeFunctionPermutation(file, spec, *permutation);
312c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
313c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
314c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
31562e099314bb1831035083a50616024ffa6253bdeJean-Luc Brouilletstatic bool writeHeaderFile(const string& directory, const SpecFile& specFile) {
316c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string headerFileName = specFile.getHeaderFileName();
317c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
318c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // We generate one header file for each spec file.
319c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    GeneratedFile file;
32062e099314bb1831035083a50616024ffa6253bdeJean-Luc Brouillet    if (!file.start(directory, headerFileName)) {
321c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return false;
322c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
323c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
324c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the comments that start the file.
325c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file.writeNotices();
326c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeComment(&file, headerFileName, specFile.getBriefDescription(),
3274a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet                 specFile.getFullDescription(), false, true);
3284a73004df5231d188c41267fee17c566ae7c3631Jean-Luc Brouillet    file << "\n";
329c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
330c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the ifndef that prevents the file from being included twice.
331c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string guard = makeGuardString(headerFileName);
332c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file << "#ifndef " << guard << "\n";
333c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file << "#define " << guard << "\n\n";
334c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
335c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Add lines that need to be put in "as is".
336c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (specFile.getVerbatimInclude().size() > 0) {
337c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        for (auto s : specFile.getVerbatimInclude()) {
338c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            file << s << "\n";
339c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
340c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        file << "\n";
341c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
342c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
343c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    /* Write the constants, types, and functions in the same order as
344c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet     * encountered in the spec file.
345c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet     */
3467c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    set<Constant*> documentedConstants;
3477c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto spec : specFile.getConstantSpecifications()) {
3487c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        Constant* constant = spec->getConstant();
3497c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        if (documentedConstants.find(constant) == documentedConstants.end()) {
3507c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            documentedConstants.insert(constant);
3517c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            writeConstantComment(&file, *constant);
3527c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        }
3537c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        writeConstantSpecification(&file, *spec);
354c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
3557c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    set<Type*> documentedTypes;
3567c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto spec : specFile.getTypeSpecifications()) {
3577c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        Type* type = spec->getType();
3587c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        if (documentedTypes.find(type) == documentedTypes.end()) {
3597c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            documentedTypes.insert(type);
3607c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            writeTypeComment(&file, *type);
3617c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        }
3627c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        writeTypeSpecification(&file, *spec);
363c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
3647c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet
3657c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    set<Function*> documentedFunctions;
3667c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto spec : specFile.getFunctionSpecifications()) {
36712398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni        // Do not include internal APIs in the header files.
36812398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni        if (spec->isInternal()) {
36912398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni            continue;
37012398d81f32e5e0479d02b8608a83c75cd991bb3Yang Ni        }
3717c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        Function* function = spec->getFunction();
3727c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        if (documentedFunctions.find(function) == documentedFunctions.end()) {
3737c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            documentedFunctions.insert(function);
3747c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            writeFunctionComment(&file, *function);
3757c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        }
3767c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        writeFunctionSpecification(&file, *spec);
377c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
378c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
379c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file << "#endif // " << guard << "\n";
380c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file.close();
381c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return true;
382c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
383c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
38466fea24fb5f3a02b744a9c71ae0fc22c03c4fc6eJean-Luc Brouilletbool generateHeaderFiles(const string& directory) {
385c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    bool success = true;
386c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto specFile : systemSpecification.getSpecFiles()) {
38762e099314bb1831035083a50616024ffa6253bdeJean-Luc Brouillet        if (!writeHeaderFile(directory, *specFile)) {
388c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            success = false;
389c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
390c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
391c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return success;
392c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
393