static int matchMeta( struct RE *rexp, const int chr ){ switch( rexp->ptr[1] ){ case 'a' : return isAlpha( chr ); case 'A' : return !isAlpha( chr ); case 'd' : return isDigit( chr ); case 'D' : return !isDigit( chr ); case 'w' : return isAlnum( chr ); case 'W' : return !isAlnum( chr ); case 's' : return isSpace( chr ); case 'S' : return !isSpace( chr ); default : return rexp->ptr[1] == chr; } }
static std::string parseIdentifier( char const*& si) { std::string rt; for (; *si && isAlnum(*si); ++si) { rt.push_back( *si); } return rt; }
static char CharToVms(int c) { if (c == PERIOD) { if (leaf_dot++) c = '$'; } else if (!isAlnum(c) && !strchr("_-", c)) { c = '$'; } return (c); }
void ConfigManager::loadFromStream(SeekableReadStream &stream) { String domainName; String comment; Domain domain; int lineno = 0; _appDomain.clear(); _gameDomains.clear(); _miscDomains.clear(); _transientDomain.clear(); _domainSaveOrder.clear(); #ifdef ENABLE_KEYMAPPER _keymapperDomain.clear(); #endif // TODO: Detect if a domain occurs multiple times (or likewise, if // a key occurs multiple times inside one domain). while (!stream.eos() && !stream.err()) { lineno++; // Read a line String line = stream.readLine(); if (line.size() == 0) { // Do nothing } else if (line[0] == '#') { // Accumulate comments here. Once we encounter either the start // of a new domain, or a key-value-pair, we associate the value // of the 'comment' variable with that entity. comment += line; comment += "\n"; } else if (line[0] == '[') { // It's a new domain which begins here. // Determine where the previously accumulated domain goes, if we accumulated anything. addDomain(domainName, domain); domain.clear(); const char *p = line.c_str() + 1; // Get the domain name, and check whether it's valid (that // is, verify that it only consists of alphanumerics, // dashes and underscores). while (*p && (isAlnum(*p) || *p == '-' || *p == '_')) p++; if (*p == '\0') error("Config file buggy: missing ] in line %d", lineno); else if (*p != ']') error("Config file buggy: Invalid character '%c' occurred in section name in line %d", *p, lineno); domainName = String(line.c_str() + 1, p); domain.setDomainComment(comment); comment.clear(); } else { // This line should be a line with a 'key=value' pair, or an empty one. // Skip leading whitespaces const char *t = line.c_str(); while (isSpace(*t)) t++; // Skip empty lines / lines with only whitespace if (*t == 0) continue; // If no domain has been set, this config file is invalid! if (domainName.empty()) { error("Config file buggy: Key/value pair found outside a domain in line %d", lineno); } // Split string at '=' into 'key' and 'value'. First, find the "=" delimeter. const char *p = strchr(t, '='); if (!p) error("Config file buggy: Junk found in line line %d: '%s'", lineno, t); // Extract the key/value pair String key(t, p); String value(p + 1); // Trim of spaces key.trim(); value.trim(); // Finally, store the key/value pair in the active domain domain[key] = value; // Store comment domain.setKVComment(key, comment); comment.clear(); } } addDomain(domainName, domain); // Add the last domain found }
bool ConfigFile::loadFromStream(SeekableReadStream &stream) { Section section; KeyValue kv; String comment; int lineno = 0; // TODO: Detect if a section occurs multiple times (or likewise, if // a key occurs multiple times inside one section). while (!stream.eos() && !stream.err()) { lineno++; // Read a line String line = stream.readLine(); if (line.size() == 0) { // Do nothing } else if (line[0] == '#' || line[0] == ';' || line.hasPrefix("//")) { // Accumulate comments here. Once we encounter either the start // of a new section, or a key-value-pair, we associate the value // of the 'comment' variable with that entity. The semicolon and // C++-style comments are used for Living Books games in Mohawk. comment += line; comment += "\n"; } else if (line[0] == '(') { // HACK: The following is a hack added by Kirben to support the // "map.ini" used in the HE SCUMM game "SPY Fox in Hold the Mustard". // // It would be nice if this hack could be restricted to that game, // but the current design of this class doesn't allow to do that // in a nice fashion (a "isMustard" parameter is *not* a nice // solution). comment += line; comment += "\n"; } else if (line[0] == '[') { // It's a new section which begins here. const char *p = line.c_str() + 1; // Get the section name, and check whether it's valid (that // is, verify that it only consists of alphanumerics, // periods, dashes and underscores). Mohawk Living Books games // can have periods in their section names. while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.')) p++; if (*p == '\0') error("ConfigFile::loadFromStream: missing ] in line %d", lineno); else if (*p != ']') error("ConfigFile::loadFromStream: Invalid character '%c' occurred in section name in line %d", *p, lineno); // Previous section is finished now, store it. if (!section.name.empty()) _sections.push_back(section); section.name = String(line.c_str() + 1, p); section.keys.clear(); section.comment = comment; comment.clear(); assert(isValidName(section.name)); } else { // This line should be a line with a 'key=value' pair, or an empty one. // Skip leading whitespaces const char *t = line.c_str(); while (isSpace(*t)) t++; // Skip empty lines / lines with only whitespace if (*t == 0) continue; // If no section has been set, this config file is invalid! if (section.name.empty()) { error("ConfigFile::loadFromStream: Key/value pair found outside a section in line %d", lineno); } // Split string at '=' into 'key' and 'value'. First, find the "=" delimeter. const char *p = strchr(t, '='); if (!p) error("Config file buggy: Junk found in line line %d: '%s'", lineno, t); // Extract the key/value pair kv.key = String(t, p); kv.value = String(p + 1); // Trim of spaces kv.key.trim(); kv.value.trim(); // Store comment kv.comment = comment; comment.clear(); assert(isValidName(kv.key)); section.keys.push_back(kv); } } // Save last section if (!section.name.empty()) _sections.push_back(section); return (!stream.err() || stream.eos()); }
bool ConfigFile::isValidName(const String &name) { const char *p = name.c_str(); while (*p && (isAlnum(*p) || *p == '-' || *p == '_' || *p == '.')) p++; return *p == 0; }