OpenASIP  2.0
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.
37 const std::string HDLTemplateInstantiator::PLACEHOLDERSEPARATOR = ",";
39  "<<placeholder" + PLACEHOLDERSEPARATOR;
40 const 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  */
61 void
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  */
88 void
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  */
112 void
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  */
152 void
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  */
188 TCEString
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  */
214 TCEString
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  */
246 TCEString
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 }
KeyAlreadyExists
Definition: Exception.hh:268
Path
Definition: FileSystem.hh:197
FileSystem.hh
UnreachableStream
Definition: Exception.hh:171
HDLTemplateInstantiator
Definition: HDLTemplateInstantiator.hh:45
Exception.hh
HDLTemplateInstantiator::findPlaceholder
TCEString findPlaceholder(const TCEString &str)
Definition: HDLTemplateInstantiator.cc:189
HDLTemplateInstantiator::HDLTemplateInstantiator
HDLTemplateInstantiator()
Definition: HDLTemplateInstantiator.cc:42
HDLTemplateInstantiator::getPlaceholderDefault
TCEString getPlaceholderDefault(const TCEString &str)
Definition: HDLTemplateInstantiator.cc:247
HDLTemplateInstantiator.hh
HDLTemplateInstantiator::replacePlaceholderFromFile
void replacePlaceholderFromFile(const std::string &key, const Path &filePath, bool append=false)
Definition: HDLTemplateInstantiator.cc:89
StringTools.hh
assert
#define assert(condition)
Definition: Application.hh:86
HDLTemplateInstantiator::replacers_
ReplacerMap replacers_
Definition: HDLTemplateInstantiator.hh:79
HDLTemplateInstantiator::fillPlaceholders
void fillPlaceholders(TCEString &str)
Definition: HDLTemplateInstantiator.cc:153
THROW_EXCEPTION
#define THROW_EXCEPTION(exceptionType, message)
Exception wrapper macro that automatically includes file name, line number and function name where th...
Definition: Exception.hh:39
__func__
#define __func__
Definition: Application.hh:67
HDLTemplateInstantiator::getPlaceholderKey
TCEString getPlaceholderKey(const TCEString &str)
Definition: HDLTemplateInstantiator.cc:215
TCEString::replaceString
TCEString & replaceString(const std::string &old, const std::string &newString)
Definition: TCEString.cc:94
StringTools::trim
static std::string trim(const std::string &source)
Definition: StringTools.cc:55
HDLTemplateInstantiator::replacePlaceholder
void replacePlaceholder(const std::string &key, const std::string &replacer, bool append=false)
Definition: HDLTemplateInstantiator.cc:62
HDLTemplateInstantiator::entityStr_
TCEString entityStr_
Definition: HDLTemplateInstantiator.hh:78
TCEString
Definition: TCEString.hh:53
HDLTemplateInstantiator::PLACEHOLDEREND
static const std::string PLACEHOLDEREND
Definition: HDLTemplateInstantiator.hh:76
HDLTemplateInstantiator::instantiateTemplateFile
void instantiateTemplateFile(const std::string &templateFile, const std::string &dstFile)
Definition: HDLTemplateInstantiator.cc:113
HDLTemplateInstantiator::PLACEHOLDERSEPARATOR
static const std::string PLACEHOLDERSEPARATOR
Definition: HDLTemplateInstantiator.hh:74
HDLTemplateInstantiator::PLACEHOLDERBEGIN
static const std::string PLACEHOLDERBEGIN
Definition: HDLTemplateInstantiator.hh:75