static bool read_config(ZString filename) { bool rv = true; io::ReadFile in(filename); if (!in.is_open()) { FPRINTF(stderr, "Monitor config file not found: %s\n", filename); exit(1); } FString line; while (in.getline(line)) { if (is_comment(line)) continue; XString name; ZString value; if (!config_split(line, &name, &value)) { PRINTF("Bad line: %s\n", line); rv = false; continue; } if (!parse_option(name, value)) { PRINTF("Bad key/value: %s\n", line); rv = false; continue; } } return rv; }
/// Master config parser. This handles 'import' and 'version-ge' etc. /// Then it defers to the inferior parser for a line it does not understand. /// /// Note: old-style 'version-ge: 1.2.3' etc apply to the rest of the file, but /// new-style 'version: >= 1.2.3' apply only up to the next 'version:' bool load_config_file(ZString filename, ConfigItemParser slave) { io::LineReader in(filename); if (!in.is_open()) { PRINTF("Unable to open file: %s\n"_fmt, filename); return false; } io::Line line_; bool rv = true; bool good_version = true; while (in.read_line(line_)) { if (is_comment(line_.text)) continue; auto line = io::respan(line_.to_span(), ZString(line_.text)); io::Spanned<XString> key; io::Spanned<ZString> value; if (!config_split(line, &key, &value)) { line.span.error("Bad config line"_s); rv = false; continue; } if (key.data == "version"_s) { if (value.data == "all"_s) { good_version = true; } else { good_version = true; while (good_version && value.data) { ZString::iterator it = std::find(value.data.begin(), value.data.end(), ' '); io::Spanned<XString> value_head; value_head.data = value.data.xislice_h(it); value_head.span = value.span; value.data = value.data.xislice_t(it).lstrip(); value_head.span.end.column = value_head.span.begin.column + value_head.data.size() - 1; value.span.begin.column = value.span.end.column - value.data.size() + 1; good_version &= check_version(value_head, borrow(rv)); } } continue; } if (!good_version) { continue; } if (key.data == "import"_s) { if (!load_config_file(value.data, slave)) { value.span.error("Failed to include file"_s); rv = false; } continue; } else if (key.data == "version-lt"_s) { Version vers; if (!extract(value.data, &vers)) { value.span.error("Bad value"_s); rv = false; continue; } if (CURRENT_VERSION < vers) continue; break; } else if (key.data == "version-le"_s) { Version vers; if (!extract(value.data, &vers)) { rv = false; value.span.error("Bad value"_s); continue; } if (CURRENT_VERSION <= vers) continue; break; } else if (key.data == "version-gt"_s) { Version vers; if (!extract(value.data, &vers)) { rv = false; value.span.error("Bad value"_s); continue; } if (CURRENT_VERSION > vers) continue; break; } else if (key.data == "version-ge"_s) { Version vers; if (!extract(value.data, &vers)) { rv = false; value.span.error("Bad value"_s); continue; } if (CURRENT_VERSION >= vers) continue; break; } else { rv &= slave(key, value); } // nothing to see here, move along } return rv; }