fix 'ret' have not initialized
[mfgtools.git] / uuu / buildincmd.cpp
blobf2f22655acf8c64bfe7a82009742a4dda1dddfde
1 /*
2 * Copyright 2018-2021 NXP.
4 * Redistribution and use in source and binary forms, with or without modification,
5 * are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice, this
11 * list of conditions and the following disclaimer in the documentation and/or
12 * other materials provided with the distribution.
14 * Neither the name of the NXP Semiconductor nor the names of its
15 * contributors may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
32 #include "buildincmd.h"
34 #include <algorithm>
35 #include <locale>
36 #include <regex>
38 static std::string replace_str(std::string str, std::string key, std::string replace);
39 static std::string str_to_upper(const std::string &str);
41 /**
42 * @brief Parse characters between argument name and its description and check
43 * if its an optional one
44 * @param[in] option The characters between argument name and its description to
45 * be parsed
46 * @return `0` in any case
48 void BuiltInScript::Arg::parser(const std::string &option)
50 const auto pos = option.find('[');
51 if (pos == std::string::npos)
53 return;
55 m_fallback_option = option.substr(pos + 1, option.find(']') - pos - 1);
56 m_flags = ARG_OPTION | ARG_OPTION_KEY;
59 /**
60 * @brief Create a new BuiltInScript instance by extracting information from a
61 * BuiltInScriptRawData instance
62 * @param[in] p The BuiltInScriptRawData containing all data of the script this
63 * BuiltInScript instance shall represent
65 BuiltInScript::BuiltInScript(const BuiltInScriptRawData * const p) :
66 m_text{p->m_text},
67 m_desc{p->m_desc ? p->m_desc : ""},
68 m_name{p->m_name ? p->m_name : ""}
70 // Regular expression to detect script argument name occurrences
71 static const std::regex arg_name_regexp{R"####((@| )(_\S+))####"};
73 for (std::sregex_iterator it
74 = std::sregex_iterator{m_text.cbegin(), m_text.cend(), arg_name_regexp};
75 it != std::sregex_iterator{}; ++it)
77 const std::string param{it->str(2)};
78 if (!find_args(param))
80 Arg a;
81 a.m_name = param;
82 a.m_flags = Arg::ARG_MUST;
83 m_args.emplace_back(std::move(a));
87 for (size_t i = 0; i < m_args.size(); i++)
89 std::string str;
90 str += "@";
91 str += m_args[i].m_name;
92 const auto pos = m_text.find(str);
93 if (pos != std::string::npos) {
94 const auto start_descript = m_text.find('|', pos);
95 if (start_descript != std::string::npos)
97 m_args[i].m_desc = m_text.substr(start_descript + 1,
98 m_text.find('\n', start_descript) - start_descript - 1);
99 const std::string def{m_text.substr(pos, start_descript - pos)};
100 m_args[i].parser(def);
107 * @brief Check if the BuiltInScript instance has an argument called `arg`
108 * @param[in] arg The argument for which its existence in the BuiltInScript
109 * shall be checked
110 * @return `true` if BuiltInScript has an argument named `arg`, `false`
111 * otherwise
113 bool BuiltInScript::find_args(const std::string &arg) const
115 return std::any_of(m_args.cbegin(), m_args.cend(),
116 [&arg](const Arg &brg){ return brg.m_name == arg; });
120 * @brief Replace built-in script's arguments by actual values given in `args`
121 * @param[in] args The actual values that shall replace the arguments (the order
122 * must fit the order of the arguments in the script)
123 * @return A copy of the built-in script with the arguments replaced by their
124 * actual values
126 std::string BuiltInScript::replace_script_args(const std::vector<std::string> &args) const
128 std::string script = m_text;
129 for (size_t i = 0; i < args.size() && i < m_args.size(); i++)
131 script = replace_str(script, m_args[i].m_name, args[i]);
134 //handle option args;
135 for (size_t i = args.size(); i < m_args.size(); i++)
137 if (m_args[i].m_flags & Arg::ARG_OPTION_KEY)
139 for (size_t j = 0; j < args.size(); j++)
141 if (m_args[j].m_name == m_args[i].m_fallback_option)
143 script = replace_str(script, m_args[i].m_name, args[j]);
144 break;
149 return script;
153 * @brief Print the built-in script to `stdout` followed by a newline
155 void BuiltInScript::show() const
157 printf("%s\n", m_text.c_str());
161 * @brief Print the script's name, its description and its arguments to stdout
163 void BuiltInScript::show_cmd() const
165 printf("\t%s%s%s\t%s\n", g_vt_boldwhite, m_name.c_str(), g_vt_default, m_desc.c_str());
166 for (auto i = 0u; i < m_args.size(); ++i)
168 std::string desc{m_args[i].m_name};
169 if (m_args[i].m_flags & Arg::ARG_OPTION)
171 desc += g_vt_boldwhite;
172 desc += "[Optional]";
173 desc += g_vt_default;
175 desc += " ";
176 desc += m_args[i].m_desc;
177 printf("\t\targ%u: %s\n", i, desc.c_str());
182 * @brief Create a new map by parsing an array of BuiltInScriptRawData instances
183 * @param[in] p Pointer to the first element of a BuiltInScriptRawData array
185 BuiltInScriptMap::BuiltInScriptMap(const BuiltInScriptRawData*p)
187 while (p->m_name)
189 emplace(p->m_name, p);
190 ++p;
195 * @brief Auto-complete names of built-in scripts if they match `match`
196 * @param[in] match The string against which the scripts' names will be matched
197 * @param[in] space A separator character which shall be printed after the
198 * completed script name
200 void BuiltInScriptMap::PrintAutoComplete(const std::string &match, const char *space) const
202 for (const auto &script_pair : *this)
204 if(script_pair.first.substr(0, match.size()) == match)
206 printf("%s%s\n", script_pair.first.c_str(), space);
212 * @brief Print information about all contained scripts to stdout
214 void BuiltInScriptMap::ShowAll() const
216 for (const auto &script_pair : *this)
218 script_pair.second.show_cmd();
223 * @brief Print the names of all contained scripts to the given stream
224 * @param[in] file The stream to which the names shall be printed
226 void BuiltInScriptMap::ShowCmds(FILE * const file) const
228 fprintf(file, "<");
229 for (auto iCol = begin(); iCol != end(); ++iCol)
231 fprintf(file, "%s", iCol->first.c_str());
233 auto i = iCol;
234 i++;
235 if(i != end())
237 fprintf(file, "|");
240 fprintf(file, ">");
244 * @brief Replace a `key` substring of a string `str` by a replacement `replace`
245 * @param[in] str The string of which a copy with the replacements shall be
246 * created
247 * @param[in] key The string which shall be replaced
248 * @param[in] replace The string that shall replace occurrences of `key`
249 * @return A new string instance with the replacements conducted on it
251 static std::string replace_str(std::string str, std::string key, std::string replace)
253 std::string s5, s4;
254 std::string match[] = { ".BZ2", ".ZST" };
255 if (replace.size() > 4)
257 if (replace[replace.size() - 1] == '\"')
259 s5 = str_to_upper(replace.substr(replace.size() - 5));
260 for (std::string it : match)
262 if (s5 == it)
264 replace = replace.substr(0, replace.size() - 1);
265 replace += "/*\"";
270 else
272 s4 = str_to_upper(replace.substr(replace.size() - 4));
273 for (std::string it : match)
275 if (it == s4)
277 replace += "/*";
283 for (size_t j = 0; (j = str.find(key, j)) != std::string::npos;)
285 if (j == 0 || (j!=0 && str[j - 1] == ' '))
286 str.replace(j, key.size(), replace);
287 j += key.size();
289 return str;
293 * @brief Returns a copy of `str` with all applicable characters converted to
294 * uppercase
295 * @param[in] str The string for which an uppercase copy shall be created
296 * @return The copy of `str` converted to uppercase
298 static std::string str_to_upper(const std::string &str)
300 const std::locale loc;
301 std::string s;
302 s.reserve(str.size());
304 for (size_t i = 0; i < str.size(); ++i)
306 s.push_back(std::toupper(str[i], loc));
309 return s;
312 //! Array containing raw information about all the built-in scripts of uuu
313 static constexpr BuiltInScriptRawData g_builtin_cmd[] =
316 "emmc",
317 #include "emmc_burn_loader.clst"
318 ,"burn boot loader to eMMC boot partition"
321 "emmc_all",
322 #include "emmc_burn_all.clst"
323 ,"burn whole image to eMMC"
326 "fat_write",
327 #include "fat_write.clst"
328 ,"update one file in fat partition, require uboot fastboot running in board"
331 "nand",
332 #include "nand_burn_loader.clst"
333 ,"burn boot loader to NAND flash"
336 "qspi",
337 #include "qspi_burn_loader.clst"
338 ,"burn boot loader to qspi nor flash"
341 "spi_nand",
342 #include "fspinand_burn_loader.clst"
343 ,"burn boot loader to spi nand flash"
346 "sd",
347 #include "sd_burn_loader.clst"
348 ,"burn boot loader to sd card"
351 "sd_all",
352 #include "sd_burn_all.clst"
353 ,"burn whole image to sd card"
356 "spl",
357 #include "spl_boot.clst"
358 ,"boot spl and uboot"
361 "nvme_all",
362 #include "nvme_burn_all.clst"
363 ,"burn whole image io nvme storage"
366 nullptr,
367 nullptr,
368 nullptr,
372 //! A map of the built-in scripts' names to their BuiltInScript representations
373 BuiltInScriptMap g_BuildScripts(g_builtin_cmd);