static void AppendIniArgs(const char *filename, Arglist &Args) { if (auto f = PHYSFSX_openReadBuffered(filename)) { PHYSFSX_gets_line_t<1024> line; while (Args.size() < MAX_ARGS && PHYSFSX_fgets(line, f)) { const auto separator = " \t"; for(char *token = strtok(line, separator); token != NULL; token = strtok(NULL, separator)) { if (*token == ';') break; Args.push_back(token); } } } }
static void ReadCmdArgs(Inilist &ini, Arglist &Args) { for (Arglist::iterator pp = Args.begin(), end = Args.end(); pp != end; ++pp) { const char *p = pp->c_str(); // System Options if (!d_stricmp(p, "-help") || !d_stricmp(p, "-h") || !d_stricmp(p, "-?") || !d_stricmp(p, "?")) CGameArg.SysShowCmdHelp = true; else if (!d_stricmp(p, "-nonicefps")) CGameArg.SysNoNiceFPS = true; else if (!d_stricmp(p, "-maxfps")) CGameArg.SysMaxFPS = arg_integer(pp, end); else if (!d_stricmp(p, "-hogdir")) CGameArg.SysHogDir = arg_string(pp, end); #if PHYSFS_VER_MAJOR >= 2 else if (!d_stricmp(p, "-add-missions-dir")) CGameArg.SysMissionDir = arg_string(pp, end); #endif else if (!d_stricmp(p, "-nohogdir")) { /* No effect on non-Unix. Ignore it so that players can * pass it via a cross-platform ini. */ #if defined(__unix__) CGameArg.SysNoHogDir = true; #endif } else if (!d_stricmp(p, "-use_players_dir")) CGameArg.SysUsePlayersDir = static_cast<int8_t>(- (sizeof(PLAYER_DIRECTORY_TEXT) - 1)); else if (!d_stricmp(p, "-lowmem")) CGameArg.SysLowMem = true; else if (!d_stricmp(p, "-pilot")) CGameArg.SysPilot = arg_string(pp, end); else if (!d_stricmp(p, "-record-demo-format")) CGameArg.SysRecordDemoNameTemplate = arg_string(pp, end); else if (!d_stricmp(p, "-auto-record-demo")) CGameArg.SysAutoRecordDemo = true; else if (!d_stricmp(p, "-window")) CGameArg.SysWindow = true; else if (!d_stricmp(p, "-noborders")) CGameArg.SysNoBorders = true; else if (!d_stricmp(p, "-notitles")) CGameArg.SysNoTitles = true; #if defined(DXX_BUILD_DESCENT_II) else if (!d_stricmp(p, "-nomovies")) GameArg.SysNoMovies = 1; #endif else if (!d_stricmp(p, "-autodemo")) CGameArg.SysAutoDemo = true; // Control Options else if (!d_stricmp(p, "-nocursor")) CGameArg.CtlNoCursor = true; else if (!d_stricmp(p, "-nomouse")) CGameArg.CtlNoMouse = true; else if (!d_stricmp(p, "-nojoystick")) { #if DXX_MAX_JOYSTICKS CGameArg.CtlNoJoystick = 1; #endif } else if (!d_stricmp(p, "-nostickykeys")) CGameArg.CtlNoStickyKeys = true; // Sound Options else if (!d_stricmp(p, "-nosound")) CGameArg.SndNoSound = 1; else if (!d_stricmp(p, "-nomusic")) CGameArg.SndNoMusic = true; #if defined(DXX_BUILD_DESCENT_II) else if (!d_stricmp(p, "-sound11k")) GameArg.SndDigiSampleRate = SAMPLE_RATE_11K; #endif else if (!d_stricmp(p, "-nosdlmixer")) { #if DXX_USE_SDLMIXER CGameArg.SndDisableSdlMixer = true; #endif } // Graphics Options else if (!d_stricmp(p, "-lowresfont")) CGameArg.GfxSkipHiresFNT = true; #if defined(DXX_BUILD_DESCENT_II) else if (!d_stricmp(p, "-lowresgraphics")) GameArg.GfxSkipHiresGFX = 1; else if (!d_stricmp(p, "-lowresmovies")) GameArg.GfxSkipHiresMovie = 1; #endif #if DXX_USE_OGL // OpenGL Options else if (!d_stricmp(p, "-gl_fixedfont")) CGameArg.OglFixedFont = true; else if (!d_stricmp(p, "-gl_syncmethod")) CGameArg.OglSyncMethod = arg_enum<SyncGLMethod>(pp, end); else if (!d_stricmp(p, "-gl_syncwait")) CGameArg.OglSyncWait = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_darkedges")) CGameArg.OglDarkEdges = true; #endif // Multiplayer Options #if DXX_USE_UDP else if (!d_stricmp(p, "-udp_hostaddr")) CGameArg.MplUdpHostAddr = arg_string(pp, end); else if (!d_stricmp(p, "-udp_hostport")) /* Peers use -udp_myport to change, so peer cannot set a * privileged port. */ arg_port_number(pp, end, CGameArg.MplUdpHostPort, false); else if (!d_stricmp(p, "-udp_myport")) { arg_port_number(pp, end, CGameArg.MplUdpMyPort, false); } else if (!d_stricmp(p, "-no-tracker")) { /* Always recognized. No-op if tracker support compiled * out. */ #if DXX_USE_TRACKER CGameArg.MplTrackerAddr.clear(); #endif } #if DXX_USE_TRACKER else if (!d_stricmp(p, "-tracker_hostaddr")) { CGameArg.MplTrackerAddr = arg_string(pp, end); } else if (!d_stricmp(p, "-tracker_hostport")) arg_port_number(pp, end, CGameArg.MplTrackerPort, true); #endif #endif #if defined(DXX_BUILD_DESCENT_I) else if (!d_stricmp(p, "-nobm")) GameArg.EdiNoBm = 1; #elif defined(DXX_BUILD_DESCENT_II) #if DXX_USE_EDITOR // Editor Options else if (!d_stricmp(p, "-autoload")) GameArg.EdiAutoLoad = arg_string(pp, end); else if (!d_stricmp(p, "-macdata")) GameArg.EdiMacData = 1; else if (!d_stricmp(p, "-hoarddata")) GameArg.EdiSaveHoardData = 1; #endif #endif // Debug Options else if (!d_stricmp(p, "-debug")) CGameArg.DbgVerbose = CON_DEBUG; else if (!d_stricmp(p, "-verbose")) CGameArg.DbgVerbose = CON_VERBOSE; else if (!d_stricmp(p, "-no-grab")) CGameArg.DbgForbidConsoleGrab = true; else if (!d_stricmp(p, "-safelog")) CGameArg.DbgSafelog = true; else if (!d_stricmp(p, "-norun")) CGameArg.DbgNoRun = true; else if (!d_stricmp(p, "-renderstats")) CGameArg.DbgRenderStats = true; else if (!d_stricmp(p, "-text")) CGameArg.DbgAltTex = arg_string(pp, end); else if (!d_stricmp(p, "-tmap")) CGameArg.DbgTexMap = arg_string(pp, end); else if (!d_stricmp(p, "-showmeminfo")) CGameArg.DbgShowMemInfo = 1; else if (!d_stricmp(p, "-nodoublebuffer")) CGameArg.DbgNoDoubleBuffer = true; else if (!d_stricmp(p, "-bigpig")) CGameArg.DbgNoCompressPigBitmap = true; else if (!d_stricmp(p, "-16bpp")) CGameArg.DbgBpp = 16; #if DXX_USE_OGL else if (!d_stricmp(p, "-gl_oldtexmerge")) CGameArg.DbgUseOldTextureMerge = true; else if (!d_stricmp(p, "-gl_intensity4_ok")) CGameArg.DbgGlIntensity4Ok = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_luminance4_alpha4_ok")) CGameArg.DbgGlLuminance4Alpha4Ok = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_rgba2_ok")) CGameArg.DbgGlRGBA2Ok = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_readpixels_ok")) CGameArg.DbgGlReadPixelsOk = arg_integer(pp, end); else if (!d_stricmp(p, "-gl_gettexlevelparam_ok")) CGameArg.DbgGlGetTexLevelParamOk = arg_integer(pp, end); #else else if (!d_stricmp(p, "-hwsurface")) CGameArg.DbgSdlHWSurface = true; else if (!d_stricmp(p, "-asyncblit")) CGameArg.DbgSdlASyncBlit = true; #endif else if (!d_stricmp(p, "-ini")) { ini.emplace_back(arg_string(pp, end)); if (ini.size() > 10) throw nesting_depth_exceeded(); ReadIniArgs(ini); } else throw unhandled_argument(std::move(*pp)); } }
void CmdLine :: parse (int argc, char** argv, bool strict) { // prepare the parameters and call cmdline_s get_opt Arglist arglist; Optdict optdict; // allocate storage for long options spec unsigned longopts_no = 0; KeysFormat::iterator kitr; char longopts_spec_buf [MAX_LONGOPTS][MAX_LONGOPT_LEN]; char* longopts_spec [MAX_LONGOPTS]; for (kitr = keys_format_.begin (); kitr != keys_format_.end (); kitr ++) longopts_no += (*kitr).longopts_.size (); if (longopts_no + 1 >= MAX_LONGOPTS) ers << "Too many command line options in command line format definition" << ThrowEx(InternalError); // fill in options specs and make option->spec map std::map <std::string, KeyFormat*> opt2spec; std::string shortopts_spec (EMPTY_STR); int lidx = 0; for (kitr = keys_format_.begin (); kitr != keys_format_.end (); kitr ++) { // short svec::iterator soi = (*kitr).shortopts_.begin (); for (; soi != (*kitr).shortopts_.end (); soi ++) { const char* optstr = (*soi).c_str (); shortopts_spec+= optstr; if ((*kitr).has_arg_) shortopts_spec += ":"; std::string keystr ("-"); keystr.append (optstr); opt2spec [keystr] = &(*kitr); } // long svec::iterator loi = (*kitr).longopts_.begin (); for (; loi != (*kitr).longopts_.end (); loi ++, lidx ++) { unsigned lolen = (*loi).length () + 1; if ((*kitr).has_arg_) lolen ++; if (lolen + 1 >= MAX_LONGOPT_LEN) ers << "Command line option " << *loi << " is too long" << Throw; // longopts_spec [lidx] = new char [lolen]; const char* optstr = (*loi).c_str (); longopts_spec [lidx] = longopts_spec_buf [lidx]; strcpy (longopts_spec [lidx], optstr); if ((*kitr).has_arg_) strcat (longopts_spec [lidx], "="); std::string keystr ("--"); keystr.append (optstr); opt2spec [keystr] = &(*kitr); } } longopts_spec [lidx] = NULL; // actually parse command line get_opt (argc, argv, shortopts_spec.c_str (), arglist, optdict, longopts_spec); // fill in the keys_ Optdict::iterator oi = optdict.begin (); for (;oi != optdict.end (); oi ++) { const char* key = (*oi).first.c_str (); // find what parameter this name corresponds to std::map <std::string, KeyFormat*>::iterator k = opt2spec.find (key); if (k != opt2spec.end ()) { svec values = (*oi).second; if ((*k).second->has_arg_) { if (values.size () == 0) { error_report_ += "\nParameter "; error_report_ += key; error_report_ += "("; error_report_ += (*k).second->name_; error_report_ += ") requires argument"; ok_ = false; break; } const char* val = values [values.size () - 1].c_str (); keys_ [(*k).second->name_] = val; } else { keys_ [(*k).second->name_] = EMPTY_STR; } // DEBUG // printf ("CMDL PAR '%s' : '%s'", (*k).second->name_.c_str (), val); } } // check weather all non-optional keys are found if (ok_ && strict) { for (kitr = keys_format_.begin (); kitr != keys_format_.end (); kitr ++) { if (!kitr->optional_) { std::map<std::string, std::string>::iterator valitr = keys_.find (kitr->name_); if (valitr == keys_.end ()) { // add notes about missing ones to the error_report error_report_ += "Required option missing from command line: "; error_report_ += kitr->name_; error_report_ += "\n"; ok_ = false; } } } } // fill in the arguments_ if (ok_) std::copy (arglist.begin (), arglist.end (), std::back_inserter (arguments_)); // check if the number of arguments is valid if (strict && ok_ && repeatable_pos_ == -1 && arglist.size () > args_format_.size ()) { // add the note to error_report error_report_ += "Too many command-line arguments\n"; ok_ = false; } unsigned min_arg_number = ((first_optional_pos_ != -1) ? first_optional_pos_ : 0) + args_format_.size () - ((last_optional_pos_ == -1) ? 0 : last_optional_pos_); if (strict && ok_ && arguments_.size () < min_arg_number) { // add the note to error_report error_report_ += "Too few command-line arguments. Please use -h for help.\n"; ok_ = false; } }