-// Split a line on whitespace, e.g. "foo bar baz" -> {"foo", "bar", "baz"}.
-vector<string> split_tokens(const string &line)
-{
- vector<string> ret;
- string current_token;
-
- for (size_t i = 0; i < line.size(); ++i) {
- if (isspace(line[i])) {
- if (!current_token.empty()) {
- ret.push_back(current_token);
- }
- current_token.clear();
- } else {
- current_token.push_back(line[i]);
- }
- }
- if (!current_token.empty()) {
- ret.push_back(current_token);
- }
- return ret;
-}
-
-struct ConfigLine {
- string keyword;
- vector<string> arguments;
- map<string, string> parameters;
-};
-
-// Parse the configuration file.
-vector<ConfigLine> parse_config(const string &filename)
-{
- vector<ConfigLine> ret;
-
- FILE *fp = fopen(filename.c_str(), "r");
- if (fp == NULL) {
- perror(filename.c_str());
- exit(1);
- }
-
- char buf[4096];
- while (!feof(fp)) {
- if (fgets(buf, sizeof(buf), fp) == NULL) {
- break;
- }
-
- // Chop off the string at the first #, \r or \n.
- buf[strcspn(buf, "#\r\n")] = 0;
-
- // Remove all whitespace from the end of the string.
- size_t len = strlen(buf);
- while (len > 0 && isspace(buf[len - 1])) {
- buf[--len] = 0;
- }
-
- // If the line is now all blank, ignore it.
- if (len == 0) {
- continue;
- }
-
- vector<string> tokens = split_tokens(buf);
- assert(!tokens.empty());
-
- ConfigLine line;
- line.keyword = tokens[0];
-
- for (size_t i = 1; i < tokens.size(); ++i) {
- // foo=bar is a parameter; anything else is an argument.
- size_t equals_pos = tokens[i].find_first_of('=');
- if (equals_pos == string::npos) {
- line.arguments.push_back(tokens[i]);
- } else {
- string key = tokens[i].substr(0, equals_pos);
- string value = tokens[i].substr(equals_pos + 1, string::npos);
- line.parameters.insert(make_pair(key, value));
- }
- }
-
- ret.push_back(line);
- }
-
- fclose(fp);
- return ret;
-}
-