OpenASIP 2.2
Loading...
Searching...
No Matches
HDLTemplateInstantiator.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2011 Tampere University.
3
4 This file is part of TTA-Based Codesign Environment (TCE).
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 DEALINGS IN THE SOFTWARE.
23 */
24/**
25 * @file HDLTemplateInstantiator.cc
26 * @author Pekka Jääskeläinen 2011
27 * @note rating: red
28 */
30#include <fstream>
31#include <cassert>
32#include "Exception.hh"
33#include "StringTools.hh"
34#include "FileSystem.hh"
35
36// Format for placeholder marker in the template files.
39 "<<placeholder" + PLACEHOLDERSEPARATOR;
40const std::string HDLTemplateInstantiator::PLACEHOLDEREND = ">>";
41
44
46 : entityStr_(entityStr), replacers_() {}
47
48/**
49 * Adds replace string for the template placeholder by key.
50 *
51 * During HDL template instantiation all placeholders by the key will
52 * be replaced with given replace string.
53 *
54 * @param key The key to identify placeholder.
55 * @param replacer The string to replace the placeholder.
56 * @param append Appends the given string to the existing placeholder filler
57 * at the key.
58 * @exception KeyAlreadyExists If a placeholder is already filled by the key
59 * and append flag is false.
60 */
61void
63 const std::string& key, const std::string& replacer, bool append) {
64 // todo: add rule for key (all uppercase)?
65 if (append) {
66 replacers_[key] += replacer;
67 } else {
68 if (replacers_.count(key)) {
71 "The placeholder \"" + key + "\" is already filled. ");
72 }
73 replacers_.insert(std::pair<PlaceholderKey, Replacer>(key, replacer));
74 }
75}
76
77/**
78 * Adds replace string from file for the template placeholder by key.
79 *
80 * During HDL template instantiation all placeholders by the key will
81 * be replaced with given replace string.
82 *
83 * @param key The key to identify placeholder.
84 * @param replacer The string to replace the placeholder.
85 * @param append Appends the given string to the existing placeholder filler
86 * at the key.
87 */
88void
90 const std::string& key, const Path& filePath, bool append) {
91 std::string snippetFileName = filePath;
92 std::ifstream snippetfile(snippetFileName.c_str());
93 if (!snippetfile.is_open()) {
95 UnreachableStream, "Could not open snippet file: \"" +
96 snippetFileName + "\" for reading.");
97 }
98 std::string str(
99 (std::istreambuf_iterator<char>(snippetfile)),
100 std::istreambuf_iterator<char>());
101 replacePlaceholder(key, str, append);
102}
103
104/**
105 * Creates a target HDL file from a HDL template, replacing certain magic
106 * strings with certain variable contents.
107 *
108 * Currently supported magic strings:
109 * ENTITY_STR The entity name string used to make entities unique.
110 * Same as the toplevel entity name.
111 */
112void
114 const std::string& templateFile,
115 const std::string& dstFile) {
116 std::ifstream input(templateFile.c_str());
117
118 if (!input.is_open())
119 throw UnreachableStream(
120 __FILE__, __LINE__, __func__,
121 TCEString("Could not open ") + templateFile + " for reading.");
122
123 std::ofstream output(dstFile.c_str(), std::ios::trunc);
124
125 if (!output.is_open())
126 throw UnreachableStream(
127 __FILE__, __LINE__, __func__,
128 TCEString("Could not open ") + dstFile + " for writing.");
129
130 while (!input.eof()) {
131 char line_buf[1024];
132 input.getline(line_buf, 1024);
133 TCEString line(line_buf);
134 line.replaceString("ENTITY_STR", entityStr_);
135 fillPlaceholders(line);
136 output << line << std::endl;
137 }
138 input.close();
139 output.close();
140}
141
142/**
143 * Fills all placeholder templates with added replace strings by key.
144 *
145 * The placeholder markers are in form "<<placeholder,key>>" or
146 * "<<placeholder,key,default-value>>". If no replacer is not found for the
147 * key the placeholder template is replaced with empty string or default-value
148 * if defined.
149 *
150 * @param str The string to search and fill placeholders.
151 */
152void
154 TCEString target(str);
155 TCEString placeholder;
156 while (!(placeholder = findPlaceholder(target)).empty()) {
157 TCEString replacer("");
158 TCEString key = getPlaceholderKey(placeholder);
159 if (replacers_.count(key)) {
160 replacer = replacers_[key];
161 } else {
162 replacer = getPlaceholderDefault(placeholder);
163 }
164 target.replaceString(placeholder, replacer);
165 }
166
167 // Correct indentation
168 if (!target.empty()) {
169 TCEString identation("");
170 unsigned int i = 0;
171 while (i < target.size() && target.at(i) == ' ') {
172 identation.append(" ");
173 i++;
174 }
175 // Note: only LF newline convention is considered.
176 target.replaceString("\n", "\n" + identation);
177 }
178
179 str = target;
180}
181
182/**
183 * Searches placeholder template over given string.
184 *
185 * @param str The string to search over for placeholder template.
186 * @return The placeholder string or empty string if not found.
187 */
190 size_t beginpos = str.find(PLACEHOLDERBEGIN);
191 if (beginpos == std::string::npos) {
192 return "";
193 }
194 size_t endpos =
195 str.find(PLACEHOLDEREND, beginpos + PLACEHOLDERBEGIN.size());
196 if (endpos == std::string::npos) {
197 return "";
198 }
199 TCEString placeholder;
200 placeholder =
201 str.substr(beginpos, endpos - beginpos + PLACEHOLDEREND.size());
202 return placeholder;
203}
204
205/**
206 * Searches placeholder template over given string and returns its key.
207 *
208 * The placeholder template is in form of <placeholder, keystring, default>
209 * and this function return keystring part.
210 *
211 * @param str The string to search over for placeholder template
212 * @return Key for the placeholder or empty string if not found.
213 */
216 TCEString placeholder = findPlaceholder(str);
217 if (placeholder.empty()) {
218 return "";
219 }
220 // todo Better field separation
221 size_t beginpos = placeholder.find(PLACEHOLDERBEGIN);
222 size_t midpos = placeholder.rfind(PLACEHOLDERSEPARATOR);
223 size_t endpos = placeholder.find(PLACEHOLDEREND);
224 if (beginpos == std::string::npos || endpos == std::string::npos) {
225 return "";
226 }
227 // Check for optional default value field
228 if ((beginpos + PLACEHOLDERBEGIN.size()) < midpos && midpos < endpos) {
229 endpos = midpos;
230 }
231 assert(endpos >= beginpos);
232 TCEString key = placeholder.substr(
233 beginpos + PLACEHOLDERBEGIN.size(),
234 endpos - beginpos - PLACEHOLDERBEGIN.size());
235 return StringTools::trim(key);
236}
237
238/**
239 * Searches placeholder template over given string and returns its default
240 * part.
241 *
242 * The placeholder template is in form of <placeholder,keystring,default>
243 * and this function return default part.
244 *
245 */
248 TCEString placeholder = findPlaceholder(str);
249 if (placeholder.empty()) {
250 return "";
251 }
252 int count = 0;
253 for (size_t offset = placeholder.find(PLACEHOLDERSEPARATOR);
254 offset != std::string::npos;
255 offset = placeholder.find(
256 PLACEHOLDERSEPARATOR, offset + PLACEHOLDERSEPARATOR.size())) {
257 count++;
258 }
259 if (count == 2) {
260 size_t beginpos = placeholder.rfind(PLACEHOLDERSEPARATOR);
261 size_t endpos = placeholder.rfind(PLACEHOLDEREND);
262 if (beginpos == std::string::npos || endpos == std::string::npos) {
263 return "";
264 }
265 assert(endpos >= beginpos);
266 TCEString defaultStr;
267 defaultStr = placeholder.substr(
268 beginpos + PLACEHOLDERSEPARATOR.size(),
269 endpos - beginpos - PLACEHOLDERSEPARATOR.size());
270 return StringTools::trim(defaultStr);
271 } else {
272 return "";
273 }
274}
#define __func__
#define assert(condition)
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition Exception.hh:39
static const std::string PLACEHOLDERBEGIN
void instantiateTemplateFile(const std::string &templateFile, const std::string &dstFile)
void replacePlaceholderFromFile(const std::string &key, const Path &filePath, bool append=false)
TCEString findPlaceholder(const TCEString &str)
void fillPlaceholders(TCEString &str)
TCEString getPlaceholderDefault(const TCEString &str)
TCEString getPlaceholderKey(const TCEString &str)
static const std::string PLACEHOLDERSEPARATOR
void replacePlaceholder(const std::string &key, const std::string &replacer, bool append=false)
static const std::string PLACEHOLDEREND
static std::string trim(const std::string &source)
TCEString & replaceString(const std::string &old, const std::string &newString)
Definition TCEString.cc:94