//------------------------------------------------- // throw_options_exception_if_appropriate //------------------------------------------------- void throw_options_exception_if_appropriate(condition_type condition, string error_stream) { switch (condition) { case condition_type.NONE: // do nothing break; case condition_type.WARN: throw new options_warning_exception(error_stream); case condition_type.ERR: throw new options_error_exception(error_stream); default: // should not get here throw new emu_exception(); // false; } }
//------------------------------------------------- // parse_ini_file - parse a series of entries in // an INI file //------------------------------------------------- public void parse_ini_file(util.core_file inifile, int priority, bool ignore_unknown_options, bool always_override) { string error_stream = ""; //std::ostringstream error_stream; condition_type condition = condition_type.NONE; // loop over lines in the file string buffer; //char buffer[4096]; while (inifile.gets(out buffer, 4096) != null) //while (inifile.gets(buffer, std::size(buffer)) != nullptr) { // find the extent of the name int optionnameIdx = 0; //char *optionname; for (optionnameIdx = 0; optionnameIdx < buffer.Length; optionnameIdx++) //for (optionname = buffer; *optionname != 0; optionname++) { if (isspace(buffer[optionnameIdx]) == 0) //if (!isspace((uint8_t)*optionname)) { break; } } // skip comments if (optionnameIdx >= buffer.Length || buffer[optionnameIdx] == 0 || buffer[optionnameIdx] == '#') //if (*optionname == 0 || *optionname == '#') { continue; } // scan forward to find the first space int tempIdx; //char *temp; for (tempIdx = optionnameIdx; tempIdx < buffer.Length; tempIdx++) //for (temp = optionname; *temp != 0; temp++) { if (isspace(buffer[tempIdx]) != 0) //if (isspace((uint8_t)*temp)) { break; } } // if we hit the end early, print a warning and continue if (tempIdx >= buffer.Length || buffer[tempIdx] == 0) //if (*temp == 0) { condition = (condition_type)std.max((UInt32)condition, (UInt32)condition_type.WARN); util.stream_format(ref error_stream, "Warning: invalid line in INI: {0}", buffer); continue; } // NULL-terminate tempIdx++; //*temp++ = 0; int optiondataIdx = tempIdx; //char *optiondata = temp; // scan the data, stopping when we hit a comment bool inquotes = false; for (tempIdx = optiondataIdx; tempIdx < buffer.Length; tempIdx++) //for (temp = optiondata; *temp != 0; temp++) { if (buffer[tempIdx] == '"') { inquotes = !inquotes; } if (buffer[tempIdx] == '#' && !inquotes) { break; } } //*temp = 0; string optionname = buffer.Substring(optionnameIdx, optiondataIdx - optionnameIdx - 1); string optiondata = buffer.Substring(optiondataIdx); // find our entry entry curentry = get_entry(optionname); //entry::shared_ptr curentry = get_entry(optionname); if (curentry == null) { if (!ignore_unknown_options) { condition = (condition_type)std.max((UInt32)condition, (UInt32)condition_type.WARN); util.stream_format(ref error_stream, "Warning: unknown option in INI: {0}\n", optionname); } continue; } // set the new data do_set_value(curentry, trim_spaces_and_quotes(optiondata), priority, ref error_stream, condition); } // did we have any errors that may need to be aggregated? throw_options_exception_if_appropriate(condition, error_stream); }
// parsing/input //------------------------------------------------- // parse_command_line - parse a series of // command line arguments //------------------------------------------------- public void parse_command_line(std.vector <string> args, int priority, bool ignore_unknown_options = false) { string error_stream = ""; //std::ostringstream error_stream; condition_type condition = condition_type.NONE; // reset the errors and the command m_command = ""; // we want to identify commands first for (int arg = 1; arg < args.Count; arg++) { if (!args[(int)arg].empty() && args[(int)arg][0] == '-') { var curentry = get_entry(args[arg].Substring(1)); if (curentry != null && curentry.type() == OPTION_COMMAND) { // can only have one command if (!m_command.empty()) { throw new options_error_exception("Error: multiple commands specified -{0} and {1}\n", m_command, args[arg]); } m_command = curentry.name(); } } } // iterate through arguments int unadorned_index = 0; for (int arg = 1; arg < args.Count; arg++) { // determine the entry name to search for string curarg = args[(int)arg]; bool is_unadorned = curarg[0] != '-'; string optionname = is_unadorned ? core_options.unadorned(unadorned_index++) : curarg.Remove(0, 1); // curarg[1]; // special case - collect unadorned arguments after commands into a special place if (is_unadorned && !m_command.empty()) { m_command_arguments.push_back(args[(int)arg]); command_argument_processed(); continue; } // find our entry; if not found, continue var curentry = get_entry(optionname); if (curentry == null) { if (!ignore_unknown_options) { throw new options_error_exception("Error: unknown option: -{0}\n", optionname); } continue; } // at this point, we've already processed commands if (curentry.type() == OPTION_COMMAND) { continue; } // get the data for this argument, special casing booleans string newdata; if (curentry.type() == OPTION_BOOLEAN) { newdata = string.Compare(curarg.Remove(0, 1), 0, "no", 0, 2) == 0 ? "0" : "1"; //(strncmp(&curarg[1], "no", 2) == 0) ? "0" : "1"; } else if (is_unadorned) { newdata = curarg; } else if (arg + 1 < args.Count) { newdata = args[++arg]; } else { throw new options_error_exception("Error: option {0} expected a parameter\n", curarg); } // set the new data do_set_value(curentry, newdata, priority, ref error_stream, condition); } // did we have any errors that may need to be aggregated? throw_options_exception_if_appropriate(condition, error_stream); }
//------------------------------------------------- // do_set_value //------------------------------------------------- void do_set_value(entry curentry, string data, int priority, ref string error_stream, condition_type condition) { // this is called when parsing a command line or an INI - we want to catch the option_exception and write // any exception messages to the error stream try { curentry.set_value(data, priority); } catch (options_warning_exception ex) { // we want to aggregate option exceptions error_stream += ex.message(); condition = (condition_type)std.max((int)condition, (int)condition_type.WARN); } catch (options_error_exception ex) { // we want to aggregate option exceptions error_stream += ex.message(); condition = (condition_type)std.max((int)condition, (int)condition_type.ERR); } }