GenerateHeaderFiles.cpp revision 7c07854a959eb70ff9623202b2ca064407a1cc68
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
41c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet// Write #ifdef's that ensure that the specified version is present
42c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic void writeVersionGuardStart(GeneratedFile* file, VersionInfo info) {
43c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (info.intSize == 32) {
44c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "#ifndef __LP64__\n";
45c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else if (info.intSize == 64) {
46c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "#ifdef __LP64__\n";
47c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
48c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
49c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (info.minVersion <= 1) {
50c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        // No minimum
51c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (info.maxVersion > 0) {
52c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "#if !defined(RS_VERSION) || (RS_VERSION <= " << info.maxVersion << ")\n";
53c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
54c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
55c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (info.maxVersion == 0) {
56c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            // No maximum
57c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "#if (defined(RS_VERSION) && (RS_VERSION >= " << info.minVersion << "))\n";
58c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else {
59c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "#if (defined(RS_VERSION) && (RS_VERSION >= " << info.minVersion
60c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                  << ") && (RS_VERSION <= " << info.maxVersion << "))\n";
61c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
62c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
63c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
64c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
65c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic void writeVersionGuardEnd(GeneratedFile* file, VersionInfo info) {
66c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (info.minVersion > 1 || info.maxVersion != 0) {
67c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "#endif\n";
68c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
69c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (info.intSize != 0) {
70c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "#endif\n";
71c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
72c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
73c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
74c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic void writeComment(GeneratedFile* file, const string& name, const string& briefComment,
75c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                         const vector<string>& comment, bool closeBlock) {
76c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (briefComment.empty() && comment.size() == 0) {
77c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return;
78c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
79c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << "/*\n";
80c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!briefComment.empty()) {
81c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " * " << name << ": " << briefComment << "\n";
82c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " *\n";
83c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
84c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (size_t ct = 0; ct < comment.size(); ct++) {
85c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        string s = stripHtml(comment[ct]);
86c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        s = stringReplace(s, "@", "");
87c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (!s.empty()) {
88c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << " * " << s << "\n";
89c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else {
90c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << " *\n";
91c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
92c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
93c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (closeBlock) {
94c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " */\n";
95c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
96c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
97c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
987c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeConstantComment(GeneratedFile* file, const Constant& constant) {
99c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string name = constant.getName();
100c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeComment(file, name, constant.getSummary(), constant.getDescription(), true);
1017c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet}
102c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
1037c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeConstantSpecification(GeneratedFile* file, const ConstantSpecification& spec) {
1047c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    VersionInfo info = spec.getVersionInfo();
1057c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    writeVersionGuardStart(file, info);
1067c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    *file << "#define " << spec.getConstant()->getName() << " " << spec.getValue() << "\n\n";
1077c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    writeVersionGuardEnd(file, info);
108c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
109c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
1107c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeTypeSpecification(GeneratedFile* file, const TypeSpecification& spec) {
1117c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    const string& typeName = spec.getType()->getName();
112c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const VersionInfo info = spec.getVersionInfo();
113c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeVersionGuardStart(file, info);
114c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    switch (spec.getKind()) {
115c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        case SIMPLE:
116c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "typedef " << spec.getSimpleType() << " " << typeName << ";\n";
117c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            break;
118c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        case ENUM: {
119c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "typedef enum ";
120c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const string name = spec.getEnumName();
121c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (!name.empty()) {
122c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << name << " ";
123c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
124c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "{\n";
125c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
126c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const vector<string>& values = spec.getValues();
127c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const vector<string>& valueComments = spec.getValueComments();
128c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const size_t last = values.size() - 1;
129c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            for (size_t i = 0; i <= last; i++) {
130c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "    " << values[i];
131c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                if (i != last) {
132c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                    *file << ",";
133c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                }
134c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                if (valueComments.size() > i && !valueComments[i].empty()) {
135c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                    *file << " // " << valueComments[i];
136c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                }
137c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "\n";
138c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
139c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "} " << typeName << ";\n";
140c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            break;
141c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
142c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        case STRUCT: {
143c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "typedef struct ";
144c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const string name = spec.getStructName();
145c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (!name.empty()) {
146c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << name << " ";
147c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
148c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "{\n";
149c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
150c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const vector<string>& fields = spec.getFields();
151c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const vector<string>& fieldComments = spec.getFieldComments();
152c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            for (size_t i = 0; i < fields.size(); i++) {
153c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "    " << fields[i] << ";";
154c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                if (fieldComments.size() > i && !fieldComments[i].empty()) {
155c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                    *file << " // " << fieldComments[i];
156c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                }
157c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "\n";
158c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
159c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "} ";
160c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            const string attrib = spec.getAttrib();
161c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (!attrib.empty()) {
162c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << attrib << " ";
163c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
164c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << typeName << ";\n";
165c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            break;
166c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
167c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
168c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeVersionGuardEnd(file, info);
169c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << "\n";
170c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
171c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
1727c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeTypeComment(GeneratedFile* file, const Type& type) {
173c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string name = type.getName();
174c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeComment(file, name, type.getSummary(), type.getDescription(), true);
175c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
176c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
177c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouilletstatic void writeFunctionPermutation(GeneratedFile* file, const FunctionSpecification& spec,
178c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                                     const FunctionPermutation& permutation) {
179c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeVersionGuardStart(file, spec.getVersionInfo());
180c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
181c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write linkage info.
182c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const auto inlineCodeLines = permutation.getInline();
183c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (inlineCodeLines.size() > 0) {
184c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "static inline ";
185c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
186c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "extern ";
187c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
188c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
189c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the return type.
190c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    auto ret = permutation.getReturn();
191c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (ret) {
192c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << ret->rsType;
193c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
194c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "void";
195c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
196c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
197c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the attribute.
198c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << " __attribute__((";
199c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string attrib = spec.getAttribute();
200c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (attrib.empty()) {
201c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "overloadable";
202c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else if (attrib[0] == '=') {
203c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        /* If starts with an equal, we don't automatically add overloadable.
204c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet         * This is because of the error we made defining rsUnpackColor8888().
205c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet         */
206c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << attrib.substr(1);
207c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
208c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << attrib << ", overloadable";
209c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
210c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << "))\n";
211c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
212c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the function name.
213c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << "    " << permutation.getName() << "(";
214c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const int offset = 4 + permutation.getName().size() + 1;  // Size of above
215c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
216c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the arguments.  We wrap on mulitple lines if a line gets too long.
217c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    int charsOnLine = offset;
218c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    bool hasGenerated = false;
219c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto p : permutation.getParams()) {
220c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (hasGenerated) {
221c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << ",";
222c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            charsOnLine++;
223c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
224c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        ostringstream ps;
225c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        ps << p->rsType;
226c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (p->isOutParameter) {
227c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            ps << "*";
228c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
229c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (!p->specName.empty()) {
230c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            ps << " " << p->specName;
231c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
232c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        const string s = ps.str();
233c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        if (charsOnLine + s.size() >= 100) {
234c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << "\n" << string(offset, ' ');
235c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            charsOnLine = offset;
236c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        } else if (hasGenerated) {
237c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            *file << " ";
238c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            charsOnLine++;
239c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
240c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << s;
241c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        charsOnLine += s.size();
242c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        hasGenerated = true;
243c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
244c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // In C, if no parameters, we need to output void, e.g. fn(void).
245c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!hasGenerated) {
246c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "void";
247c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
248c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << ")";
249c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
250c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the inline code, if any.
251c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (inlineCodeLines.size() > 0) {
252c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " {\n";
253c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        for (size_t ct = 0; ct < inlineCodeLines.size(); ct++) {
254c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (inlineCodeLines[ct].empty()) {
255c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "\n";
256c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            } else {
257c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << "    " << inlineCodeLines[ct] << "\n";
258c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
259c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
260c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << "}\n";
261c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    } else {
262c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << ";\n";
263c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
264c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
265c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeVersionGuardEnd(file, spec.getVersionInfo());
266c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << "\n";
267c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
268c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
2697c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeFunctionComment(GeneratedFile* file, const Function& function) {
270c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the generic documentation.
271c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeComment(file, function.getName(), function.getSummary(), function.getDescription(), false);
272c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
273c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Comment the parameters.
274c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (function.someParametersAreDocumented()) {
275c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " *\n";
276c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " * Parameters:\n";
277c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        for (auto p : function.getParameters()) {
278c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            if (!p->documentation.empty()) {
279c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                *file << " *   " << p->name << " " << p->documentation << "\n";
280c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            }
281c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
282c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
283c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
284c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Comment the return type.
285c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string returnDoc = function.getReturnDocumentation();
286c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (!returnDoc.empty()) {
287c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " *\n";
288c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        *file << " * Returns: " << returnDoc << "\n";
289c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
290c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
291c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    *file << " */\n";
2927c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet}
293c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
2947c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouilletstatic void writeFunctionSpecification(GeneratedFile* file, const FunctionSpecification& spec) {
295c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write all the variants.
2967c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto permutation : spec.getPermutations()) {
2977c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        writeFunctionPermutation(file, spec, *permutation);
298c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
299c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
300c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
30162e099314bb1831035083a50616024ffa6253bdeJean-Luc Brouilletstatic bool writeHeaderFile(const string& directory, const SpecFile& specFile) {
302c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string headerFileName = specFile.getHeaderFileName();
303c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
304c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // We generate one header file for each spec file.
305c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    GeneratedFile file;
30662e099314bb1831035083a50616024ffa6253bdeJean-Luc Brouillet    if (!file.start(directory, headerFileName)) {
307c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        return false;
308c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
309c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
310c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the comments that start the file.
311c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file.writeNotices();
312c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    writeComment(&file, headerFileName, specFile.getBriefDescription(),
313c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet                 specFile.getFullDescription(), true);
314c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
315c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Write the ifndef that prevents the file from being included twice.
316c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    const string guard = makeGuardString(headerFileName);
317c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file << "#ifndef " << guard << "\n";
318c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file << "#define " << guard << "\n\n";
319c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
320c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    // Add lines that need to be put in "as is".
321c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    if (specFile.getVerbatimInclude().size() > 0) {
322c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        for (auto s : specFile.getVerbatimInclude()) {
323c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            file << s << "\n";
324c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
325c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        file << "\n";
326c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
327c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
328c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    /* Write the constants, types, and functions in the same order as
329c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet     * encountered in the spec file.
330c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet     */
3317c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    set<Constant*> documentedConstants;
3327c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto spec : specFile.getConstantSpecifications()) {
3337c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        Constant* constant = spec->getConstant();
3347c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        if (documentedConstants.find(constant) == documentedConstants.end()) {
3357c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            documentedConstants.insert(constant);
3367c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            writeConstantComment(&file, *constant);
3377c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        }
3387c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        writeConstantSpecification(&file, *spec);
339c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
3407c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    set<Type*> documentedTypes;
3417c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto spec : specFile.getTypeSpecifications()) {
3427c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        Type* type = spec->getType();
3437c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        if (documentedTypes.find(type) == documentedTypes.end()) {
3447c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            documentedTypes.insert(type);
3457c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            writeTypeComment(&file, *type);
3467c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        }
3477c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        writeTypeSpecification(&file, *spec);
348c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
3497c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet
3507c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    set<Function*> documentedFunctions;
3517c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet    for (auto spec : specFile.getFunctionSpecifications()) {
3527c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        Function* function = spec->getFunction();
3537c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        if (documentedFunctions.find(function) == documentedFunctions.end()) {
3547c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            documentedFunctions.insert(function);
3557c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet            writeFunctionComment(&file, *function);
3567c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        }
3577c07854a959eb70ff9623202b2ca064407a1cc68Jean-Luc Brouillet        writeFunctionSpecification(&file, *spec);
358c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
359c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
360c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file << "#endif // " << guard << "\n";
361c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    file.close();
362c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return true;
363c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
364c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet
36562e099314bb1831035083a50616024ffa6253bdeJean-Luc Brouilletbool GenerateHeaderFiles(const string& directory) {
366c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    bool success = true;
367c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    for (auto specFile : systemSpecification.getSpecFiles()) {
36862e099314bb1831035083a50616024ffa6253bdeJean-Luc Brouillet        if (!writeHeaderFile(directory, *specFile)) {
369c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet            success = false;
370c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet        }
371c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    }
372c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet    return success;
373c5184e202ced435258adb2cfe2013570e7190954Jean-Luc Brouillet}
374