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"
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
);
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
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
)
55 m_fallback_option
= option
.substr(pos
+ 1, option
.find(']') - pos
- 1);
56 m_flags
= ARG_OPTION
| ARG_OPTION_KEY
;
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
) :
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
))
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
++)
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
110 * @return `true` if BuiltInScript has an argument named `arg`, `false`
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
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
]);
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
;
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
)
189 emplace(p
->m_name
, 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
229 for (auto iCol
= begin(); iCol
!= end(); ++iCol
)
231 fprintf(file
, "%s", iCol
->first
.c_str());
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
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
)
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
)
264 replace
= replace
.substr(0, replace
.size() - 1);
272 s4
= str_to_upper(replace
.substr(replace
.size() - 4));
273 for (std::string it
: match
)
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
);
293 * @brief Returns a copy of `str` with all applicable characters converted to
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
;
302 s
.reserve(str
.size());
304 for (size_t i
= 0; i
< str
.size(); ++i
)
306 s
.push_back(std::toupper(str
[i
], loc
));
312 //! Array containing raw information about all the built-in scripts of uuu
313 static constexpr BuiltInScriptRawData g_builtin_cmd
[] =
317 #include "emmc_burn_loader.clst"
318 ,"burn boot loader to eMMC boot partition"
322 #include "emmc_burn_all.clst"
323 ,"burn whole image to eMMC"
327 #include "fat_write.clst"
328 ,"update one file in fat partition, require uboot fastboot running in board"
332 #include "nand_burn_loader.clst"
333 ,"burn boot loader to NAND flash"
337 #include "qspi_burn_loader.clst"
338 ,"burn boot loader to qspi nor flash"
342 #include "fspinand_burn_loader.clst"
343 ,"burn boot loader to spi nand flash"
347 #include "sd_burn_loader.clst"
348 ,"burn boot loader to sd card"
352 #include "sd_burn_all.clst"
353 ,"burn whole image to sd card"
357 #include "spl_boot.clst"
358 ,"boot spl and uboot"
362 #include "nvme_burn_all.clst"
363 ,"burn whole image io nvme storage"
372 //! A map of the built-in scripts' names to their BuiltInScript representations
373 BuiltInScriptMap
g_BuildScripts(g_builtin_cmd
);