Scan one inputs file, and every file it includes with FILE = <name>, the way ParmParse reads them: names are opened with $AMREX_INPUTS_FILE_PREFIX in front, FILE with more than one value is a parameter, UNSET = <keys> drops the keys, [name] starts a table whose keys are name.<key>, and if AMREX_SPACEDIM / #ifdef AMREX_USE_GPU regions that are off are skipped. Records each key with where it was set, and sets found_duplicates when a key is set twice (see is_override). An inputs file that cannot be opened, or that includes itself directly or through others, sets error and stops the scan.
118 std::ifstream ifs(
name);
120 if (!ifs.is_open()) {
121 state.error =
"Could not open inputs file: " +
name;
125 auto canonical = std::filesystem::weakly_canonical(
name, ec);
126 if (ec) { canonical = std::filesystem::absolute(
name); }
127 for (
const auto& f : state.open_files) {
128 if (f == canonical) {
129 state.error =
"The inputs file " +
name +
" includes itself (FILE = ...)";
133 state.open_files.push_back(canonical);
134 state.includes.push_back(state.next_include++);
137 static const std::regex if_regex(R
"(^\s*#\s*if\s+\(?\s*AMREX_SPACEDIM\s*(>|<|==|>=|<=|!=)\s*([1-3])\s*\)?\s*$)");
138 static const std::regex elif_regex(R
"(^\s*#\s*elif\s+\(?\s*AMREX_SPACEDIM\s*(>|<|==|>=|<=|!=)\s*([1-3])\s*\)?\s*$)");
139 static const std::regex else_regex(R
"(^\s*#\s*else\s*$)");
140 static const std::regex endif_regex(R
"(^\s*#\s*endif\s*$)");
141 static const std::regex if_gpu_regex(R
"(^\s*#\s*ifdef\s+AMREX_USE_GPU\s*$)");
142 static const std::regex if_not_gpu_regex(R
"(^\s*#\s*ifndef\s+AMREX_USE_GPU\s*$)");
143 static const std::regex table_regex(R
"(^\[\s*([A-Za-z][A-Za-z0-9_.\-]*)\s*\]$)");
145 constexpr
bool use_gpu =
true;
147 constexpr
bool use_gpu =
false;
149 auto dim_true = [] (
const std::smatch& sm) {
150 const std::string op = sm[1].str();
151 const int dim = std::stoi(sm[2].str());
152 return (op ==
"<" && AMREX_SPACEDIM < dim) || (op ==
">" && AMREX_SPACEDIM > dim) ||
153 (op ==
"==" && AMREX_SPACEDIM == dim) || (op ==
"<=" && AMREX_SPACEDIM <= dim) ||
154 (op ==
">=" && AMREX_SPACEDIM >= dim) || (op ==
"!=" && AMREX_SPACEDIM != dim);
156 std::vector<bool> region_on;
157 std::vector<bool> region_had;
163 while (std::getline(ifs, line))
168 if (std::regex_match(line, if_gpu_regex) || std::regex_match(line, if_not_gpu_regex)) {
169 const bool r = std::regex_match(line, if_gpu_regex) ? use_gpu : !use_gpu;
170 region_on.push_back(r); region_had.push_back(r);
172 }
else if (std::regex_match(line, sm, if_regex)) {
173 const bool r = dim_true(sm);
174 region_on.push_back(r); region_had.push_back(r);
176 }
else if (!region_on.empty() && std::regex_match(line, sm, elif_regex)) {
177 const bool r = !region_had.back() && dim_true(sm);
178 region_on.back() = r;
179 if (r) { region_had.back() =
true; }
181 }
else if (!region_on.empty() && std::regex_match(line, else_regex)) {
182 region_on.back() = !region_had.back();
183 region_had.back() =
true;
185 }
else if (!region_on.empty() && std::regex_match(line, endif_regex)) {
186 region_on.pop_back(); region_had.pop_back();
190 for (
bool r : region_on) {
if (!r) { skip =
true; } }
191 if (skip) {
continue; }
194 auto hash_pos = line.find(
'#');
195 if (hash_pos != std::string::npos) {
196 line = line.substr(0, hash_pos);
199 line = trim_copy(line);
202 if (line.empty())
continue;
205 if (std::regex_match(line, sm, table_regex)) {
211 auto eq_pos = line.find(
'=');
212 if (eq_pos == std::string::npos)
continue;
214 const std::string def = trim_copy(line.substr(0, eq_pos));
215 const std::string value = trim_copy(line.substr(eq_pos + 1));
220 if (def == amrex::ParmParse::FileKeyword && vals.size() == 1) {
223 if (!state.error.empty()) {
break; }
228 if (def == amrex::ParmParse::UnsetKeyword) {
229 for (
const auto& k : vals) { state.seen.erase(k); }
233 const std::string key = table.empty() ? def : table +
"." + def;
234 auto it = state.seen.find(key);
236 if (it == state.seen.end())
238 state.seen.emplace(key, EntryInfo{
name, line_number, value, state.includes});
242 it->second = EntryInfo{
name, line_number, value, state.includes};
246 state.found_duplicates =
true;
249 <<
"\nDuplicate input detected:\n"
250 <<
" Key : " << key <<
"\n"
251 <<
" First line : " << it->second.line_number <<
" of " << it->second.file <<
"\n"
252 <<
" Value : " << it->second.value <<
"\n"
253 <<
" Second line : " << line_number <<
" of " <<
name <<
"\n"
254 <<
" Value : " << value <<
"\n";
258 state.includes.pop_back();
259 state.open_files.pop_back();