Add new features to the config command for control of the config file:
- manipulate the autoexec section - display information on sections and values - show the used config files and startup command line parameters - restart capability - save config files either in the config or program directory Imported-from: https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk@3651
This commit is contained in:
parent
0d7b792d05
commit
143beec6b1
15 changed files with 847 additions and 248 deletions
89
README
89
README
|
@ -622,7 +622,19 @@ VER set major_version [minor_version]
|
|||
|
||||
|
||||
CONFIG -writeconf filelocation
|
||||
CONFIG -writeconf
|
||||
CONFIG -wcp filelocation
|
||||
CONFIG -wcd
|
||||
CONFIG -writelang filelocation
|
||||
CONFIG -axadd
|
||||
CONFIG -axclear
|
||||
CONFIG -axtype
|
||||
CONFIG -r [parameters]
|
||||
CONFIG -l
|
||||
CONFIG -help
|
||||
CONFIG -help sections
|
||||
CONFIG -help section
|
||||
CONFIG -help section property
|
||||
CONFIG -securemode
|
||||
CONFIG -set "section property=value"
|
||||
CONFIG -get "section property"
|
||||
|
@ -633,20 +645,74 @@ CONFIG -get "section property"
|
|||
be found in Section 13: "The configuration (options) file".
|
||||
|
||||
-writeconf filelocation
|
||||
Write the current configuration settings to a file in a specified location.
|
||||
"filelocation" is located on the local drive, not a mounted drive in DOSBox.
|
||||
(or -wc filelocation)
|
||||
Write the current configuration settings to a file in a specified location
|
||||
relative to the DOSBox config directory. Relative and absolute paths are
|
||||
possible. "filelocation" is located on the local drive, not a mounted
|
||||
drive in DOSBox.
|
||||
|
||||
The configuration file controls various settings of DOSBox:
|
||||
the amount of emulated memory, the emulated sound cards and many more
|
||||
things. It allows access to AUTOEXEC.BAT as well.
|
||||
See Section 13: "The configuration (options) file" for more information.
|
||||
|
||||
-writeconf
|
||||
(or -wc)
|
||||
Write the configuration to the primary loaded config file.
|
||||
|
||||
-wcp filelocation
|
||||
Write the current configuration settings to the specified file in or
|
||||
relative to the DOSBox program start directory. Realtive and absolute
|
||||
paths are possible. This is located on a drive on the host, not a mounted
|
||||
drive in DOSBox. It is useful if you keep DOSBox on a removable media.
|
||||
If file is omitted, the configuration will be written to dosbox.conf.
|
||||
|
||||
-wcd
|
||||
Write the current configuration to the default config file.
|
||||
|
||||
|
||||
-writelang filelocation
|
||||
(or -wl filelocation)
|
||||
Write the current language settings to a file in a specified location.
|
||||
"filelocation" is located on the local drive, not a mounted drive
|
||||
in DOSBox. The language file controls all visible output of the internal
|
||||
commands and the internal DOS.
|
||||
See Section 14: "The Language File" for more information.
|
||||
|
||||
-axadd "line1" "line2" ...
|
||||
Adds a command line to the autoexec section.
|
||||
|
||||
-axclear
|
||||
Clears the autoexec section.
|
||||
|
||||
-axtype
|
||||
Prints the content of the autoexec section.
|
||||
|
||||
-r [parameters]
|
||||
Restart DOSBox, either with the parameters that were used to start the
|
||||
current instance or any that are appended.
|
||||
|
||||
-l
|
||||
lists DOSBox parameters:
|
||||
- the configuration directory
|
||||
- the config files that were used when starting this session
|
||||
- the command line parameters DOSBox was started with
|
||||
|
||||
-h, -help, -?
|
||||
Displays an overvie of the config commands.
|
||||
|
||||
-h, -help, -? sections
|
||||
Displays the list of sections in the config file.
|
||||
|
||||
-h, -help, -? section
|
||||
Displays the list of properties contained in the specified section.
|
||||
|
||||
-h, -help, -? section property
|
||||
Shows information about the specified property in the specified section:
|
||||
- purpose of the property
|
||||
- possible values, current value, default value
|
||||
- wether it can definitely not be changed at runtime
|
||||
|
||||
-securemode
|
||||
Switches DOSBox to a more secure mode. In this mode the internal
|
||||
commands MOUNT, IMGMOUNT and BOOT won't work. It's not possible either
|
||||
|
@ -655,7 +721,6 @@ CONFIG -get "section property"
|
|||
|
||||
-set "section property=value"
|
||||
CONFIG will attempt to set the property to new value.
|
||||
Currently CONFIG can not report whether the command succeeded or not.
|
||||
|
||||
-get "section property"
|
||||
The current value of the property is reported and stored in the
|
||||
|
@ -675,7 +740,22 @@ CONFIG -get "section property"
|
|||
config -set "dos ems=false"
|
||||
4. To check which cpu core is being used.
|
||||
config -get "cpu core"
|
||||
|
||||
5. To view the list of possible cpu cores:
|
||||
config -help cpu core
|
||||
6. To change the machine type and restart:
|
||||
config -set "machine cga"
|
||||
config -wc -r
|
||||
7. To configure the autoexec section to auto-mount a directory at start:
|
||||
config -axadd "mount c c:\dosgames" "c:"
|
||||
config -wc
|
||||
8. To create a specific config file in the config directory:
|
||||
config -set "dos ems=false"
|
||||
config -set "cpu cycles=10000"
|
||||
config -set "core dynamic"
|
||||
config -axadd "mount c c:\dosgames" "c:" "cd my_game" "my_game"
|
||||
config -wc my_config.conf
|
||||
9. To restart DOSBox from a specific config file in the config directory:
|
||||
config -r -conf my_config.conf
|
||||
|
||||
LOADFIX [-size] [program] [program-parameters]
|
||||
LOADFIX -f
|
||||
|
@ -985,6 +1065,7 @@ CTRL-F10 Capture/Release the mouse.
|
|||
CTRL-F11 Slow down emulation (Decrease DOSBox Cycles).
|
||||
CTRL-F12 Speed up emulation (Increase DOSBox Cycles)*.
|
||||
ALT-F12 Unlock speed (turbo button/fast forward)**.
|
||||
CTRL-ALT-HOME Restart DOSBox.
|
||||
F11, ALT-F11 (machine=cga) change tint in NTSC output modes***
|
||||
F11 (machine=hercules) cycle through amber, green, white colouring***
|
||||
|
||||
|
|
|
@ -63,7 +63,14 @@ private:
|
|||
void (* _start_function)(void);
|
||||
bool secure_mode; //Sandbox mode
|
||||
public:
|
||||
Config(CommandLine * cmd):cmdline(cmd),secure_mode(false){}
|
||||
bool initialised;
|
||||
std::vector<std::string> startup_params;
|
||||
std::vector<std::string> configfiles;
|
||||
Config(CommandLine * cmd):cmdline(cmd),secure_mode(false) {
|
||||
startup_params.push_back(cmdline->GetFileName());
|
||||
cmdline->FillVector(startup_params);
|
||||
initialised=false;
|
||||
}
|
||||
~Config();
|
||||
|
||||
Section_line * AddSection_line(char const * const _name,void (*_initfunction)(Section*));
|
||||
|
|
|
@ -74,6 +74,7 @@ public:
|
|||
static void CreatePlatformConfigDir(std::string& in);
|
||||
static void ResolveHomedir(std::string & temp_line);
|
||||
static void CreateDir(std::string const& temp);
|
||||
static bool Cross::IsPathAbsolute(std::string const& in);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
enum MapKeys {
|
||||
MK_f1,MK_f2,MK_f3,MK_f4,MK_f5,MK_f6,MK_f7,MK_f8,MK_f9,MK_f10,MK_f11,MK_f12,
|
||||
MK_return,MK_kpminus,MK_scrolllock,MK_printscreen,MK_pause
|
||||
MK_return,MK_kpminus,MK_scrolllock,MK_printscreen,MK_pause,MK_home
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ public:
|
|||
bool FindStringBegin(char const * const begin,std::string & value, bool remove=false);
|
||||
bool FindStringRemain(char const * const name,std::string & value);
|
||||
bool GetStringRemain(std::string & value);
|
||||
int GetParameterFromList(const char* const params[], std::vector<std::string> & output);
|
||||
void FillVector(std::vector<std::string> & vector);
|
||||
unsigned int GetCount(void);
|
||||
void Shift(unsigned int amount=1);
|
||||
Bit16u Get_arglength();
|
||||
|
|
|
@ -104,18 +104,18 @@ public:
|
|||
operator int () const throw(WrongType);
|
||||
operator double () const throw(WrongType);
|
||||
operator char const* () const throw(WrongType);
|
||||
void SetValue(std::string const& in,Etype _type = V_CURRENT) throw(WrongType);
|
||||
bool SetValue(std::string const& in,Etype _type = V_CURRENT) throw(WrongType);
|
||||
std::string ToString() const;
|
||||
|
||||
private:
|
||||
void destroy() throw();
|
||||
Value& copy(Value const& in) throw(WrongType);
|
||||
void plaincopy(Value const& in) throw();
|
||||
void set_hex(std::string const& in);
|
||||
void set_int(std::string const&in);
|
||||
void set_bool(std::string const& in);
|
||||
bool set_hex(std::string const& in);
|
||||
bool set_int(std::string const&in);
|
||||
bool set_bool(std::string const& in);
|
||||
void set_string(std::string const& in);
|
||||
void set_double(std::string const& in);
|
||||
bool set_double(std::string const& in);
|
||||
};
|
||||
|
||||
class Property {
|
||||
|
@ -127,7 +127,7 @@ public:
|
|||
void Set_values(const char * const * in);
|
||||
void Set_help(std::string const& str);
|
||||
char const* Get_help();
|
||||
virtual void SetValue(std::string const& str)=0;
|
||||
virtual bool SetValue(std::string const& str)=0;
|
||||
Value const& GetValue() const { return value;}
|
||||
Value const& Get_Default_Value() const { return default_value; }
|
||||
//CheckValue returns true if value is in suggested_values;
|
||||
|
@ -135,10 +135,12 @@ public:
|
|||
//specific features.
|
||||
virtual bool CheckValue(Value const& in, bool warn);
|
||||
//Set interval value to in or default if in is invalid. force always sets the value.
|
||||
void SetVal(Value const& in, bool forced,bool warn=true) {if(forced || CheckValue(in,warn)) value = in; else value = default_value;}
|
||||
bool SetVal(Value const& in, bool forced,bool warn=true) {
|
||||
if(forced || CheckValue(in,warn)) {value = in; return true;} else { value = default_value; return false;}}
|
||||
virtual ~Property(){ }
|
||||
virtual const std::vector<Value>& GetValues() const;
|
||||
Value::Etype Get_type(){return default_value.type;}
|
||||
Changeable::Value getChange() {return change;}
|
||||
|
||||
protected:
|
||||
Value value;
|
||||
|
@ -161,8 +163,10 @@ public:
|
|||
min = _min;
|
||||
max = _max;
|
||||
}
|
||||
int getMin() { return min;}
|
||||
int getMax() { return max;}
|
||||
void SetMinMax(Value const& min,Value const& max) {this->min = min; this->max=max;}
|
||||
void SetValue(std::string const& in);
|
||||
bool SetValue(std::string const& in);
|
||||
~Prop_int(){ }
|
||||
virtual bool CheckValue(Value const& in, bool warn);
|
||||
private:
|
||||
|
@ -175,7 +179,7 @@ public:
|
|||
:Property(_propname,when){
|
||||
default_value = value = _value;
|
||||
}
|
||||
void SetValue(std::string const& input);
|
||||
bool SetValue(std::string const& input);
|
||||
~Prop_double(){ }
|
||||
};
|
||||
|
||||
|
@ -185,7 +189,7 @@ public:
|
|||
:Property(_propname,when) {
|
||||
default_value = value = _value;
|
||||
}
|
||||
void SetValue(std::string const& in);
|
||||
bool SetValue(std::string const& in);
|
||||
~Prop_bool(){ }
|
||||
};
|
||||
|
||||
|
@ -195,7 +199,7 @@ public:
|
|||
:Property(_propname,when) {
|
||||
default_value = value = _value;
|
||||
}
|
||||
void SetValue(std::string const& in);
|
||||
bool SetValue(std::string const& in);
|
||||
virtual bool CheckValue(Value const& in, bool warn);
|
||||
~Prop_string(){ }
|
||||
};
|
||||
|
@ -207,7 +211,7 @@ public:
|
|||
default_value = value = _value;
|
||||
realpath = _value;
|
||||
}
|
||||
void SetValue(std::string const& in);
|
||||
bool SetValue(std::string const& in);
|
||||
~Prop_path(){ }
|
||||
};
|
||||
|
||||
|
@ -217,7 +221,7 @@ public:
|
|||
:Property(_propname,when) {
|
||||
default_value = value = _value;
|
||||
}
|
||||
void SetValue(std::string const& in);
|
||||
bool SetValue(std::string const& in);
|
||||
~Prop_hex(){ }
|
||||
};
|
||||
|
||||
|
@ -248,7 +252,7 @@ public:
|
|||
const char* GetName() const {return sectionname.c_str();}
|
||||
|
||||
virtual std::string GetPropValue(std::string const& _property) const =0;
|
||||
virtual void HandleInputline(std::string const& _line)=0;
|
||||
virtual bool HandleInputline(std::string const& _line)=0;
|
||||
virtual void PrintData(FILE* outfile) const =0;
|
||||
virtual ~Section() { /*Children must call executedestroy ! */}
|
||||
};
|
||||
|
@ -281,7 +285,7 @@ public:
|
|||
Prop_path* Get_path(std::string const& _propname) const;
|
||||
Prop_multival* Get_multival(std::string const& _propname) const;
|
||||
Prop_multival_remain* Get_multivalremain(std::string const& _propname) const;
|
||||
void HandleInputline(std::string const& gegevens);
|
||||
bool HandleInputline(std::string const& gegevens);
|
||||
void PrintData(FILE* outfile) const;
|
||||
virtual std::string GetPropValue(std::string const& _property) const;
|
||||
//ExecuteDestroy should be here else the destroy functions use destroyed properties
|
||||
|
@ -299,7 +303,7 @@ public:
|
|||
}
|
||||
Section_prop *GetSection() { return section; }
|
||||
const Section_prop *GetSection() const { return section; }
|
||||
virtual void SetValue(std::string const& input);
|
||||
virtual bool SetValue(std::string const& input);
|
||||
virtual const std::vector<Value>& GetValues() const;
|
||||
~Prop_multival() { delete section; }
|
||||
}; //value bevat totale string. setvalue zet elk van de sub properties en checked die.
|
||||
|
@ -308,7 +312,7 @@ class Prop_multival_remain:public Prop_multival{
|
|||
public:
|
||||
Prop_multival_remain(std::string const& _propname, Changeable::Value when,std::string const& sep):Prop_multival(_propname,when,sep){ }
|
||||
|
||||
virtual void SetValue(std::string const& input);
|
||||
virtual bool SetValue(std::string const& input);
|
||||
};
|
||||
|
||||
|
||||
|
@ -316,7 +320,7 @@ class Section_line: public Section{
|
|||
public:
|
||||
Section_line(std::string const& _sectionname):Section(_sectionname){}
|
||||
~Section_line(){ExecuteDestroy(true);}
|
||||
void HandleInputline(std::string const& gegevens);
|
||||
bool HandleInputline(std::string const& gegevens);
|
||||
void PrintData(FILE* outfile) const;
|
||||
virtual std::string GetPropValue(std::string const& _property) const;
|
||||
std::string data;
|
||||
|
|
|
@ -2113,7 +2113,7 @@ void DEBUG_SetupConsole(void) {
|
|||
DBGUI_StartUp();
|
||||
}
|
||||
|
||||
static void DEBUG_ShutDown(Section * /*sec*/) {
|
||||
void DEBUG_ShutDown(Section * /*sec*/) {
|
||||
CBreakpoint::DeleteAll();
|
||||
CDebugVar::DeleteAll();
|
||||
curs_set(old_cursor_state);
|
||||
|
|
|
@ -340,7 +340,7 @@ void DOSBOX_Init(void) {
|
|||
|
||||
Pstring = secprop->Add_string("machine",Property::Changeable::OnlyAtStart,"svga_s3");
|
||||
Pstring->Set_values(machines);
|
||||
Pstring->Set_help("The type of machine tries to emulate.");
|
||||
Pstring->Set_help("The type of machine DOSBox tries to emulate.");
|
||||
|
||||
Pstring = secprop->Add_path("captures",Property::Changeable::Always,"capture");
|
||||
Pstring->Set_help("Directory where things like wave, midi, screenshot get captured.");
|
||||
|
@ -376,8 +376,8 @@ void DOSBOX_Init(void) {
|
|||
|
||||
Pmulti = secprop->Add_multi("scaler",Property::Changeable::Always," ");
|
||||
Pmulti->SetValue("normal2x");
|
||||
Pmulti->Set_help("Scaler used to enlarge/enhance low resolution modes.\n"
|
||||
" If 'forced' is appended, then the scaler will be used even if the result might not be desired.");
|
||||
Pmulti->Set_help("Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended,\n"
|
||||
"then the scaler will be used even if the result might not be desired.");
|
||||
Pstring = Pmulti->GetSection()->Add_string("type",Property::Changeable::Always,"normal2x");
|
||||
|
||||
const char *scalers[] = {
|
||||
|
@ -403,7 +403,8 @@ void DOSBOX_Init(void) {
|
|||
"normal", "simple",0 };
|
||||
Pstring = secprop->Add_string("core",Property::Changeable::WhenIdle,"auto");
|
||||
Pstring->Set_values(cores);
|
||||
Pstring->Set_help("CPU Core used in emulation. auto will switch to dynamic if available and appropriate.");
|
||||
Pstring->Set_help("CPU Core used in emulation. auto will switch to dynamic if available and\n"
|
||||
"appropriate.");
|
||||
|
||||
const char* cputype_values[] = { "auto", "386", "386_slow", "486_slow", "pentium_slow", "386_prefetch", 0};
|
||||
Pstring = secprop->Add_string("cputype",Property::Changeable::Always,"auto");
|
||||
|
@ -418,9 +419,10 @@ void DOSBOX_Init(void) {
|
|||
"Cycles can be set in 3 ways:\n"
|
||||
" 'auto' tries to guess what a game needs.\n"
|
||||
" It usually works, but can fail for certain games.\n"
|
||||
" 'fixed #number' will set a fixed amount of cycles. This is what you usually need if 'auto' fails.\n"
|
||||
" (Example: fixed 4000).\n"
|
||||
" 'max' will allocate as much cycles as your computer is able to handle.\n");
|
||||
" 'fixed #number' will set a fixed amount of cycles. This is what you usually\n"
|
||||
" need if 'auto' fails (Example: fixed 4000).\n"
|
||||
" 'max' will allocate as much cycles as your computer is able to\n"
|
||||
" handle.");
|
||||
|
||||
const char* cyclest[] = { "auto","fixed","max","%u",0 };
|
||||
Pstring = Pmulti_remain->GetSection()->Add_string("type",Property::Changeable::Always,"auto");
|
||||
|
@ -431,7 +433,7 @@ void DOSBOX_Init(void) {
|
|||
|
||||
Pint = secprop->Add_int("cycleup",Property::Changeable::Always,10);
|
||||
Pint->SetMinMax(1,1000000);
|
||||
Pint->Set_help("Amount of cycles to decrease/increase with keycombo.(CTRL-F11/CTRL-F12)");
|
||||
Pint->Set_help("Amount of cycles to decrease/increase with keycombos.(CTRL-F11/CTRL-F12)");
|
||||
|
||||
Pint = secprop->Add_int("cycledown",Property::Changeable::Always,20);
|
||||
Pint->SetMinMax(1,1000000);
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
extern Bit8u int10_font_14[256 * 14];
|
||||
extern Program * first_shell;
|
||||
extern void MSG_Write(const char *);
|
||||
extern bool MSG_Write(const char *);
|
||||
extern void GFX_SetTitle(Bit32s cycles, Bits frameskip, bool paused);
|
||||
|
||||
static int cursor, saved_bpp;
|
||||
|
|
|
@ -1584,6 +1584,9 @@ public:
|
|||
case MK_printscreen:
|
||||
key=SDLK_PRINT;
|
||||
break;
|
||||
case MK_home:
|
||||
key=SDLK_HOME;
|
||||
break;
|
||||
}
|
||||
sprintf(buf,"%s \"key %d%s%s%s\"",
|
||||
entry,
|
||||
|
|
|
@ -989,6 +989,8 @@ static unsigned char logo[32*32*4]= {
|
|||
#include "dosbox_splash.h"
|
||||
|
||||
//extern void UI_Run(bool);
|
||||
void Restart(bool pressed);
|
||||
|
||||
static void GUI_StartUp(Section * sec) {
|
||||
sec->AddDestroyFunction(&GUI_ShutDown);
|
||||
Section_prop * section=static_cast<Section_prop *>(sec);
|
||||
|
@ -1234,6 +1236,7 @@ static void GUI_StartUp(Section * sec) {
|
|||
MAPPER_AddHandler(KillSwitch,MK_f9,MMOD1,"shutdown","ShutDown");
|
||||
MAPPER_AddHandler(CaptureMouse,MK_f10,MMOD1,"capmouse","Cap Mouse");
|
||||
MAPPER_AddHandler(SwitchFullScreen,MK_return,MMOD2,"fullscr","Fullscreen");
|
||||
MAPPER_AddHandler(Restart,MK_home,MMOD1|MMOD2,"restart","Restart");
|
||||
#if C_DEBUG
|
||||
/* Pause binds with activate-debugger */
|
||||
#else
|
||||
|
@ -1586,6 +1589,32 @@ static void launcheditor() {
|
|||
printf("can't find editor(s) specified at the command line.\n");
|
||||
exit(1);
|
||||
}
|
||||
#if C_DEBUG
|
||||
extern void DEBUG_ShutDown(Section * /*sec*/);
|
||||
#endif
|
||||
|
||||
void restart_program(std::vector<std::string> & parameters) {
|
||||
char** newargs = new char* [parameters.size()+1];
|
||||
// parameter 0 is the executable path
|
||||
// contents of the vector follow
|
||||
// last one is NULL
|
||||
for(Bitu i = 0; i < parameters.size(); i++) newargs[i]=(char*)parameters[i].c_str();
|
||||
newargs[parameters.size()] = NULL;
|
||||
SDL_CloseAudio();
|
||||
SDL_Delay(50);
|
||||
SDL_Quit();
|
||||
#if C_DEBUG
|
||||
// shutdown curses
|
||||
DEBUG_ShutDown(NULL);
|
||||
#endif
|
||||
|
||||
execvp(newargs[0], newargs);
|
||||
free(newargs);
|
||||
}
|
||||
void Restart(bool pressed) { // mapper handler
|
||||
restart_program(control->startup_params);
|
||||
}
|
||||
|
||||
static void launchcaptures(std::string const& edit) {
|
||||
std::string path,file;
|
||||
Section* t = control->GetSection("dosbox");
|
||||
|
@ -1790,15 +1819,16 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
/* Parse configuration files */
|
||||
std::string config_file,config_path;
|
||||
bool parsed_anyconfigfile = false;
|
||||
//First Parse -userconf
|
||||
Cross::GetPlatformConfigDir(config_path);
|
||||
|
||||
//First parse -userconf
|
||||
if(control->cmdline->FindExist("-userconf",true)){
|
||||
config_file.clear();
|
||||
Cross::GetPlatformConfigDir(config_path);
|
||||
Cross::GetPlatformConfigName(config_file);
|
||||
config_path += config_file;
|
||||
if(control->ParseConfigFile(config_path.c_str())) parsed_anyconfigfile = true;
|
||||
if(!parsed_anyconfigfile) {
|
||||
control->ParseConfigFile(config_path.c_str());
|
||||
if(!control->configfiles.size()) {
|
||||
//Try to create the userlevel configfile.
|
||||
config_file.clear();
|
||||
Cross::CreatePlatformConfigDir(config_path);
|
||||
|
@ -1807,29 +1837,29 @@ int main(int argc, char* argv[]) {
|
|||
if(control->PrintConfig(config_path.c_str())) {
|
||||
LOG_MSG("CONFIG: Generating default configuration.\nWriting it to %s",config_path.c_str());
|
||||
//Load them as well. Makes relative paths much easier
|
||||
if(control->ParseConfigFile(config_path.c_str())) parsed_anyconfigfile = true;
|
||||
control->ParseConfigFile(config_path.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Second parse -conf entries
|
||||
while(control->cmdline->FindString("-conf",config_file,true))
|
||||
if (control->ParseConfigFile(config_file.c_str())) parsed_anyconfigfile = true;
|
||||
//Second parse -conf switches
|
||||
while(control->cmdline->FindString("-conf",config_file,true)) {
|
||||
if(!control->ParseConfigFile(config_file.c_str())) {
|
||||
// try to load it from the user directory
|
||||
control->ParseConfigFile((config_path + config_file).c_str());
|
||||
}
|
||||
}
|
||||
// if none found => parse localdir conf
|
||||
if(!control->configfiles.size()) control->ParseConfigFile("dosbox.conf");
|
||||
|
||||
//if none found => parse localdir conf
|
||||
config_file = "dosbox.conf";
|
||||
if (!parsed_anyconfigfile && control->ParseConfigFile(config_file.c_str())) parsed_anyconfigfile = true;
|
||||
|
||||
//if none found => parse userlevel conf
|
||||
if(!parsed_anyconfigfile) {
|
||||
// if none found => parse userlevel conf
|
||||
if(!control->configfiles.size()) {
|
||||
config_file.clear();
|
||||
Cross::GetPlatformConfigDir(config_path);
|
||||
Cross::GetPlatformConfigName(config_file);
|
||||
config_path += config_file;
|
||||
if(control->ParseConfigFile(config_path.c_str())) parsed_anyconfigfile = true;
|
||||
control->ParseConfigFile((config_path + config_file).c_str());
|
||||
}
|
||||
|
||||
if(!parsed_anyconfigfile) {
|
||||
if(!control->configfiles.size()) {
|
||||
//Try to create the userlevel configfile.
|
||||
config_file.clear();
|
||||
Cross::CreatePlatformConfigDir(config_path);
|
||||
|
|
|
@ -122,6 +122,19 @@ void Cross::CreateDir(std::string const& in) {
|
|||
#endif
|
||||
}
|
||||
|
||||
bool Cross::IsPathAbsolute(std::string const& in) {
|
||||
// Absolute paths
|
||||
#if defined (WIN32) || defined(OS2)
|
||||
// drive letter
|
||||
if (in.size() > 2 && in[1] == ':' ) return true;
|
||||
// UNC path
|
||||
else if (in.size() > 2 && in[0]=='\\' && in[1]=='\\') return true;
|
||||
#else
|
||||
if (in.size() > 1 && in[0] == '/' ) return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined (WIN32)
|
||||
|
||||
dir_information* open_directory(const char* dirname) {
|
||||
|
|
|
@ -124,13 +124,14 @@ const char * MSG_Get(char const * msg) {
|
|||
}
|
||||
|
||||
|
||||
void MSG_Write(const char * location) {
|
||||
bool MSG_Write(const char * location) {
|
||||
FILE* out=fopen(location,"w+t");
|
||||
if(out==NULL) return;//maybe an error?
|
||||
if(out==NULL) return false;//maybe an error?
|
||||
for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
|
||||
fprintf(out,":%s\n%s\n.\n",(*tel).name.c_str(),(*tel).val.c_str());
|
||||
}
|
||||
fclose(out);
|
||||
return true;
|
||||
}
|
||||
|
||||
void MSG_Init(Section_prop * section) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
/* $Id: programs.cpp,v 1.37 2009-05-27 09:15:42 qbix79 Exp $ */
|
||||
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -78,7 +79,7 @@ static Bitu PROGRAMS_Handler(void) {
|
|||
HostPt writer=(HostPt)&index;
|
||||
for (;size>0;size--) *writer++=mem_readb(reader++);
|
||||
Program * new_program;
|
||||
if(index > internal_progs.size()) E_Exit("something is messing with the memory");
|
||||
if (index > internal_progs.size()) E_Exit("something is messing with the memory");
|
||||
PROGRAMS_Main * handler = internal_progs[index];
|
||||
(*handler)(&new_program);
|
||||
new_program->Run();
|
||||
|
@ -120,7 +121,7 @@ void Program::ChangeToLongCmd() {
|
|||
* Length of arguments can be ~120. but switch when above 100 to be sure
|
||||
*/
|
||||
|
||||
if(/*control->SecureMode() ||*/ cmd->Get_arglength() > 100) {
|
||||
if (/*control->SecureMode() ||*/ cmd->Get_arglength() > 100) {
|
||||
CommandLine* temp = new CommandLine(cmd->GetFileName(),full_arguments.c_str());
|
||||
delete cmd;
|
||||
cmd = temp;
|
||||
|
@ -139,7 +140,7 @@ void Program::WriteOut(const char * format,...) {
|
|||
Bit16u size = (Bit16u)strlen(buf);
|
||||
for(Bit16u i = 0; i < size;i++) {
|
||||
Bit8u out;Bit16u s=1;
|
||||
if(buf[i] == 0xA && i > 0 && buf[i-1] !=0xD) {
|
||||
if (buf[i] == 0xA && i > 0 && buf[i-1] !=0xD) {
|
||||
out = 0xD;DOS_WriteFile(STDOUT,&out,&s);
|
||||
}
|
||||
out = buf[i];
|
||||
|
@ -154,7 +155,7 @@ void Program::WriteOut_NoParsing(const char * format) {
|
|||
char const* buf = format;
|
||||
for(Bit16u i = 0; i < size;i++) {
|
||||
Bit8u out;Bit16u s=1;
|
||||
if(buf[i] == 0xA && i > 0 && buf[i-1] !=0xD) {
|
||||
if (buf[i] == 0xA && i > 0 && buf[i-1] !=0xD) {
|
||||
out = 0xD;DOS_WriteFile(STDOUT,&out,&s);
|
||||
}
|
||||
out = buf[i];
|
||||
|
@ -243,149 +244,457 @@ bool Program::SetEnv(const char * entry,const char * new_string) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool MSG_Write(const char *);
|
||||
void restart_program(std::vector<std::string> & parameters);
|
||||
|
||||
class CONFIG : public Program {
|
||||
public:
|
||||
void Run(void);
|
||||
};
|
||||
|
||||
void MSG_Write(const char *);
|
||||
|
||||
void CONFIG::Run(void) {
|
||||
FILE * f;
|
||||
if (cmd->FindString("-writeconf",temp_line,true)
|
||||
|| cmd->FindString("-wc",temp_line,true)) {
|
||||
/* In secure mode don't allow a new configfile to be created */
|
||||
if(control->SecureMode()) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
|
||||
return;
|
||||
private:
|
||||
void restart(const char* useconfig);
|
||||
|
||||
void writeconf(std::string name, bool configdir) {
|
||||
if (configdir) {
|
||||
// write file to the default config directory
|
||||
std::string config_path;
|
||||
Cross::GetPlatformConfigDir(config_path);
|
||||
name = config_path + name;
|
||||
}
|
||||
f=fopen(temp_line.c_str(),"wb+");
|
||||
if (!f) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
|
||||
return;
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_WHICH"),name.c_str());
|
||||
if (!control->PrintConfig(name.c_str())) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),name.c_str());
|
||||
}
|
||||
fclose(f);
|
||||
control->PrintConfig(temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
if (cmd->FindString("-writelang",temp_line,true)
|
||||
||cmd->FindString("-wl",temp_line,true)) {
|
||||
/* In secure mode don't allow a new languagefile to be created
|
||||
* Who knows which kind of file we would overwriting. */
|
||||
if(control->SecureMode()) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
|
||||
return;
|
||||
}
|
||||
f=fopen(temp_line.c_str(),"wb+");
|
||||
if (!f) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
fclose(f);
|
||||
MSG_Write(temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
/* Code for switching to secure mode */
|
||||
if(cmd->FindExist("-securemode",true)) {
|
||||
control->SwitchToSecureMode();
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_ON"));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Code for getting the current configuration. *
|
||||
* Official format: config -get "section property" *
|
||||
* As a bonus it will set %CONFIG% to this value as well */
|
||||
if(cmd->FindString("-get",temp_line,true)) {
|
||||
std::string temp2 = "";
|
||||
cmd->GetStringRemain(temp2);//So -get n1 n2= can be used without quotes
|
||||
if(temp2 != "") temp_line = temp_line + " " + temp2;
|
||||
|
||||
std::string::size_type space = temp_line.find(" ");
|
||||
if(space == std::string::npos) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_GET_SYNTAX"));
|
||||
return;
|
||||
}
|
||||
//Copy the found property to a new string and erase from templine (mind the space)
|
||||
std::string prop = temp_line.substr(space+1); temp_line.erase(space);
|
||||
|
||||
Section* sec = control->GetSection(temp_line.c_str());
|
||||
if(!sec) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
std::string val = sec->GetPropValue(prop.c_str());
|
||||
if(val == NO_SUCH_PROPERTY) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),prop.c_str(),temp_line.c_str());
|
||||
return;
|
||||
}
|
||||
WriteOut("%s",val.c_str());
|
||||
first_shell->SetEnv("CONFIG",val.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Code for the configuration changes *
|
||||
* Official format: config -set "section property=value" *
|
||||
* Accepted: without quotes and/or without -set and/or without section *
|
||||
* and/or the "=" replaced by a " " */
|
||||
|
||||
if (cmd->FindString("-set",temp_line,true)) { //get all arguments
|
||||
std::string temp2 = "";
|
||||
cmd->GetStringRemain(temp2);//So -set n1 n2=n3 can be used without quotes
|
||||
if(temp2!="") temp_line = temp_line + " " + temp2;
|
||||
} else if(!cmd->GetStringRemain(temp_line)) {//no set
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE")); //and no arguments specified
|
||||
return;
|
||||
};
|
||||
//Wanted input: n1 n2=n3
|
||||
char copy[1024];
|
||||
strcpy(copy,temp_line.c_str());
|
||||
//seperate section from property
|
||||
const char* temp = strchr(copy,' ');
|
||||
if((temp && *temp) || (temp=strchr(copy,'=')) ) copy[temp++ - copy]= 0;
|
||||
else {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
|
||||
return;
|
||||
}
|
||||
//if n1 n2 n3 then replace last space with =
|
||||
const char* sign = strchr(temp,'=');
|
||||
if(!sign) {
|
||||
sign = strchr(temp,' ');
|
||||
if(sign) {
|
||||
copy[sign - copy] = '=';
|
||||
} else {
|
||||
//2 items specified (no space nor = between n2 and n3
|
||||
//assume that they posted: property value
|
||||
//Try to determine the section.
|
||||
Section* sec=control->GetSectionFromProperty(copy);
|
||||
if(!sec){
|
||||
if(control->GetSectionFromProperty(temp)) return; //Weird situation:ignore
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"),copy);
|
||||
return;
|
||||
} //Hack to allow config ems true
|
||||
char buffer[1024];strcpy(buffer,copy);strcat(buffer,"=");strcat(buffer,temp);
|
||||
sign = strchr(buffer,' ');
|
||||
if(sign) buffer[sign - buffer] = '=';
|
||||
strcpy(copy,sec->GetName());
|
||||
temp = buffer;
|
||||
}
|
||||
}
|
||||
|
||||
/* Input processed. Now the real job starts
|
||||
* copy contains the likely "sectionname"
|
||||
* temp contains "property=value"
|
||||
* the section is destroyed and a new input line is given to
|
||||
* the configuration parser. Then the section is restarted.
|
||||
*/
|
||||
char* inputline = const_cast<char*>(temp);
|
||||
Section* sec = 0;
|
||||
sec = control->GetSection(copy);
|
||||
if(!sec) { WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),copy);return;}
|
||||
sec->ExecuteDestroy(false);
|
||||
sec->HandleInputline(inputline);
|
||||
sec->ExecuteInit(false);
|
||||
bool securemode_check() {
|
||||
if (control->SecureMode()) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
void CONFIG::Run(void) {
|
||||
static const char* const params[] = {
|
||||
"-r", "-wcp", "-wcd", "-wc", "-writeconf", "-l", "-rmconf",
|
||||
"-h", "-help", "-?", "-axclear", "-axadd", "-axtype", "-get", "-set",
|
||||
"-writelang", "-wl", "-securemode", "" };
|
||||
enum prs {
|
||||
P_NOMATCH, P_NOPARAMS, // fixed return values for GetParameterFromList
|
||||
P_RESTART,
|
||||
P_WRITECONF_PORTABLE, P_WRITECONF_DEFAULT, P_WRITECONF, P_WRITECONF2,
|
||||
P_LISTCONF, P_KILLCONF,
|
||||
P_HELP, P_HELP2, P_HELP3,
|
||||
P_AUTOEXEC_CLEAR, P_AUTOEXEC_ADD, P_AUTOEXEC_TYPE,
|
||||
P_GETPROP, P_SETPROP,
|
||||
P_WRITELANG, P_WRITELANG2,
|
||||
P_SECURE
|
||||
} presult = P_NOMATCH;
|
||||
|
||||
bool first = true;
|
||||
std::vector<std::string> pvars;
|
||||
while(presult != P_NOPARAMS) {
|
||||
presult = (enum prs)cmd->GetParameterFromList(params, pvars);
|
||||
switch(presult) {
|
||||
|
||||
case P_RESTART:
|
||||
if (securemode_check()) return;
|
||||
if (pvars.size() == 0) restart_program(control->startup_params);
|
||||
else {
|
||||
std::vector<std::string> restart_params;
|
||||
restart_params.push_back(control->cmdline->GetFileName());
|
||||
for(size_t i = 0; i < pvars.size(); i++) {
|
||||
restart_params.push_back(pvars[i]);
|
||||
if (pvars[i].find(' ') != std::string::npos) {
|
||||
pvars[i] = "\""+pvars[i]+"\""; // add back spaces
|
||||
}
|
||||
}
|
||||
// the rest on the commandline, too
|
||||
cmd->FillVector(restart_params);
|
||||
restart_program(restart_params);
|
||||
}
|
||||
return;
|
||||
|
||||
case P_LISTCONF: {
|
||||
Bitu size = control->configfiles.size();
|
||||
std::string config_path;
|
||||
Cross::GetPlatformConfigDir(config_path);
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_CONFDIR"), VERSION,config_path.c_str());
|
||||
if (size==0) WriteOut(MSG_Get("PROGRAM_CONFIG_NOCONFIGFILE"));
|
||||
else {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PRIMARY_CONF"),control->configfiles.front().c_str());
|
||||
if (size > 1) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_ADDITIONAL_CONF"));
|
||||
for(Bitu i = 1; i < size; i++)
|
||||
WriteOut("%s\n",control->configfiles[i].c_str());
|
||||
}
|
||||
}
|
||||
if (control->startup_params.size() > 0) {
|
||||
std::string test;
|
||||
for(size_t k = 0; k < control->startup_params.size(); k++)
|
||||
test += control->startup_params[k] + " ";
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PRINT_STARTUP"), test.c_str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case P_WRITECONF: case P_WRITECONF2:
|
||||
if (securemode_check()) return;
|
||||
if (pvars.size() > 1) return;
|
||||
else if (pvars.size() == 1) {
|
||||
// write config to specific file, except if it is an absolute path
|
||||
writeconf(pvars[0], !Cross::IsPathAbsolute(pvars[0]));
|
||||
} else {
|
||||
// -wc without parameter: write primary config file
|
||||
if (control->configfiles.size()) writeconf(control->configfiles[0], false);
|
||||
else WriteOut(MSG_Get("PROGRAM_CONFIG_NOCONFIGFILE"));
|
||||
}
|
||||
break;
|
||||
case P_WRITECONF_DEFAULT: {
|
||||
// write to /userdir/dosbox0.xx.conf
|
||||
if (securemode_check()) return;
|
||||
if (pvars.size() > 0) return;
|
||||
std::string confname;
|
||||
Cross::GetPlatformConfigName(confname);
|
||||
writeconf(confname, true);
|
||||
break;
|
||||
}
|
||||
case P_WRITECONF_PORTABLE:
|
||||
if (securemode_check()) return;
|
||||
if (pvars.size() > 1) return;
|
||||
else if (pvars.size() == 1) {
|
||||
// write config to startup directory
|
||||
writeconf(pvars[0], false);
|
||||
} else {
|
||||
// -wcp without parameter: write dosbox.conf to startup directory
|
||||
if (control->configfiles.size()) writeconf(std::string("dosbox.conf"), false);
|
||||
else WriteOut(MSG_Get("PROGRAM_CONFIG_NOCONFIGFILE"));
|
||||
}
|
||||
break;
|
||||
|
||||
case P_NOPARAMS:
|
||||
if (!first) break;
|
||||
|
||||
case P_HELP: case P_HELP2: case P_HELP3: {
|
||||
switch(pvars.size()) {
|
||||
case 0:
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
|
||||
return;
|
||||
case 1: {
|
||||
if (!strcasecmp("sections",pvars[0].c_str())) {
|
||||
// list the sections
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_SECTLIST"));
|
||||
Bitu i = 0;
|
||||
while(true) {
|
||||
Section* sec = control->GetSection(i++);
|
||||
if (!sec) break;
|
||||
WriteOut("%s\n",sec->GetName());
|
||||
}
|
||||
return;
|
||||
}
|
||||
// if it's a section, leave it as one-param
|
||||
Section* sec = control->GetSection(pvars[0].c_str());
|
||||
if (!sec) {
|
||||
// could be a property
|
||||
sec = control->GetSectionFromProperty(pvars[0].c_str());
|
||||
if (!sec) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
|
||||
return;
|
||||
}
|
||||
pvars.insert(pvars.begin(),std::string(sec->GetName()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// sanity check
|
||||
Section* sec = control->GetSection(pvars[0].c_str());
|
||||
Section* sec2 = control->GetSectionFromProperty(pvars[1].c_str());
|
||||
if (sec != sec2) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
|
||||
return;
|
||||
}
|
||||
// if we have one value in pvars, it's a section
|
||||
// two values are section + property
|
||||
Section* sec = control->GetSection(pvars[0].c_str());
|
||||
if (sec==NULL) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
|
||||
return;
|
||||
}
|
||||
Section_prop* psec = dynamic_cast <Section_prop*>(sec);
|
||||
if (psec==NULL) {
|
||||
// failed; maybe it's the autoexec section?
|
||||
Section_line* pline = dynamic_cast <Section_line*>(sec);
|
||||
if (pline==NULL) E_Exit("Section dynamic cast failed.");
|
||||
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_LINEHLP"),
|
||||
pline->GetName(),
|
||||
// this is 'unclean' but the autoexec section has no help associated
|
||||
MSG_Get("AUTOEXEC_CONFIGFILE_HELP"),
|
||||
pline->data.c_str() );
|
||||
return;
|
||||
}
|
||||
if (pvars.size()==1) {
|
||||
size_t i = 0;
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_SECTHLP"),pvars[0].c_str());
|
||||
while(true) {
|
||||
// list the properties
|
||||
Property* p = psec->Get_prop(i++);
|
||||
if (p==NULL) break;
|
||||
WriteOut("%s\n", p->propname.c_str());
|
||||
}
|
||||
} else {
|
||||
// find the property by it's name
|
||||
size_t i = 0;
|
||||
while (true) {
|
||||
Property *p = psec->Get_prop(i++);
|
||||
if (p==NULL) break;
|
||||
if (!strcasecmp(p->propname.c_str(),pvars[1].c_str())) {
|
||||
// found it; make the list of possible values
|
||||
std::string propvalues;
|
||||
std::vector<Value> pv = p->GetValues();
|
||||
|
||||
if (p->Get_type()==Value::Etype::V_BOOL) {
|
||||
// possible values for boolean are true, false
|
||||
propvalues += "true, false";
|
||||
} else if (p->Get_type()==Value::Etype::V_INT) {
|
||||
// print min, max for integer values if used
|
||||
Prop_int* pint = dynamic_cast <Prop_int*>(p);
|
||||
if (pint==NULL) E_Exit("Int property dynamic cast failed.");
|
||||
if (pint->getMin() != pint->getMax()) {
|
||||
std::ostringstream oss;
|
||||
oss << pint->getMin();
|
||||
oss << "..";
|
||||
oss << pint->getMax();
|
||||
propvalues += oss.str();
|
||||
}
|
||||
}
|
||||
for(Bitu k = 0; k < pv.size(); k++) {
|
||||
if (pv[k].ToString() =="%u")
|
||||
propvalues += MSG_Get("PROGRAM_CONFIG_HLP_POSINT");
|
||||
else propvalues += pv[k].ToString();
|
||||
if ((k+1) < pv.size()) propvalues += ", ";
|
||||
}
|
||||
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_PROPHLP"),
|
||||
p->propname.c_str(),
|
||||
sec->GetName(),
|
||||
p->Get_help(),propvalues.c_str(),
|
||||
p->Get_Default_Value().ToString().c_str(),
|
||||
p->GetValue().ToString().c_str());
|
||||
// print 'changability'
|
||||
if (p->getChange()==Property::Changeable::OnlyAtStart) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_HLP_NOCHANGE"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
case P_AUTOEXEC_CLEAR: {
|
||||
Section_line* sec = dynamic_cast <Section_line*>
|
||||
(control->GetSection(std::string("autoexec")));
|
||||
sec->data.clear();
|
||||
break;
|
||||
}
|
||||
case P_AUTOEXEC_ADD: {
|
||||
if (pvars.size() == 0) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_MISSINGPARAM"));
|
||||
return;
|
||||
}
|
||||
Section_line* sec = dynamic_cast <Section_line*>
|
||||
(control->GetSection(std::string("autoexec")));
|
||||
|
||||
for(Bitu i = 0; i < pvars.size(); i++) sec->HandleInputline(pvars[i]);
|
||||
break;
|
||||
}
|
||||
case P_AUTOEXEC_TYPE: {
|
||||
Section_line* sec = dynamic_cast <Section_line*>
|
||||
(control->GetSection(std::string("autoexec")));
|
||||
WriteOut("\n%s",sec->data.c_str());
|
||||
break;
|
||||
}
|
||||
case P_GETPROP: {
|
||||
// "section property"
|
||||
// "property"
|
||||
// "section" "property"
|
||||
if (pvars.size()==0) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_GET_SYNTAX"));
|
||||
return;
|
||||
}
|
||||
std::string::size_type spcpos = pvars[0].find_first_of(' ');
|
||||
// split on the ' '
|
||||
if (spcpos != std::string::npos) {
|
||||
pvars.insert(++pvars.begin(),pvars[0].substr(spcpos+1));
|
||||
pvars[0].erase(spcpos);
|
||||
}
|
||||
switch(pvars.size()) {
|
||||
case 1: {
|
||||
// property only
|
||||
Section* sec = control->GetSectionFromProperty(pvars[0].c_str());
|
||||
if (!sec) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
|
||||
return;
|
||||
}
|
||||
std::string val = sec->GetPropValue(pvars[0].c_str());
|
||||
WriteOut("%s",val.c_str());
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
// section + property
|
||||
Section* sec = control->GetSection(pvars[0].c_str());
|
||||
if (!sec) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"));
|
||||
return;
|
||||
}
|
||||
std::string val = sec->GetPropValue(pvars[1].c_str());
|
||||
if (val == NO_SUCH_PROPERTY) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),pvars[1].c_str(),pvars[0].c_str());
|
||||
return;
|
||||
}
|
||||
WriteOut("%s",val.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
case P_SETPROP: case P_NOMATCH: {
|
||||
// Code for the configuration changes
|
||||
// Official format: config -set "section property=value"
|
||||
// Accepted: with or without -set,
|
||||
// "section property value"
|
||||
// "section property=value"
|
||||
// "property" "value"
|
||||
// "section" "property=value"
|
||||
// "section" "property=value" "value" "value" ...
|
||||
// "section" "property" "value" "value" ...
|
||||
// "section property" "value" "value" ...
|
||||
// "property" "value" "value" ...
|
||||
// "property=value" "value" "value" ...
|
||||
|
||||
if (pvars.size()==0) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SET_SYNTAX"));
|
||||
return;
|
||||
}
|
||||
|
||||
// add rest of command
|
||||
std::string rest;
|
||||
if (cmd->GetStringRemain(rest)) pvars.push_back(rest);
|
||||
|
||||
// attempt to split off the first word
|
||||
std::string::size_type spcpos = pvars[0].find_first_of(' ');
|
||||
std::string::size_type equpos = pvars[0].find_first_of('=');
|
||||
|
||||
if ((equpos != std::string::npos) &&
|
||||
((spcpos == std::string::npos) || (equpos < spcpos))) {
|
||||
// If we have a '=' possibly before a ' ' split on the =
|
||||
pvars.insert(++pvars.begin(),pvars[0].substr(equpos+1));
|
||||
pvars[0].erase(equpos);
|
||||
// As we had a = the first thing must be a property now
|
||||
Section* sec=control->GetSectionFromProperty(pvars[0].c_str());
|
||||
if (sec) pvars.insert(pvars.begin(),std::string(sec->GetName()));
|
||||
else {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
|
||||
return;
|
||||
}
|
||||
// order in the vector should be ok now
|
||||
} else {
|
||||
if ((spcpos != std::string::npos) &&
|
||||
((equpos == std::string::npos) || (spcpos < equpos))) {
|
||||
// ' ' before a possible '=', split on the ' '
|
||||
pvars.insert(++pvars.begin(),pvars[0].substr(spcpos+1));
|
||||
pvars[0].erase(spcpos);
|
||||
}
|
||||
// check if the first parameter is a section or property
|
||||
Section* sec = control->GetSection(pvars[0].c_str());
|
||||
if (!sec) {
|
||||
// not a section: little duplicate from above
|
||||
Section* sec=control->GetSectionFromProperty(pvars[0].c_str());
|
||||
if (sec) pvars.insert(pvars.begin(),std::string(sec->GetName()));
|
||||
else {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// first of pvars is most likely a section, but could still be gus
|
||||
// have a look at the second parameter
|
||||
if (pvars.size() < 2) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SET_SYNTAX"));
|
||||
return;
|
||||
}
|
||||
std::string::size_type spcpos2 = pvars[1].find_first_of(' ');
|
||||
std::string::size_type equpos2 = pvars[1].find_first_of('=');
|
||||
if ((equpos2 != std::string::npos) &&
|
||||
((spcpos2 == std::string::npos) || (equpos2 < spcpos2))) {
|
||||
// split on the =
|
||||
pvars.insert(pvars.begin()+2,pvars[1].substr(equpos2+1));
|
||||
pvars[1].erase(equpos2);
|
||||
} else if ((spcpos2 != std::string::npos) &&
|
||||
((equpos2 == std::string::npos) || (spcpos2 < equpos2))) {
|
||||
// split on the ' '
|
||||
pvars.insert(pvars.begin()+2,pvars[1].substr(spcpos2+1));
|
||||
pvars[1].erase(spcpos2);
|
||||
}
|
||||
// is this a property?
|
||||
Section* sec2 = control->GetSectionFromProperty(pvars[1].c_str());
|
||||
if (!sec2) {
|
||||
// not a property,
|
||||
Section* sec3 = control->GetSectionFromProperty(pvars[0].c_str());
|
||||
if (sec3) {
|
||||
// section and property name are identical
|
||||
pvars.insert(pvars.begin(),pvars[0]);
|
||||
} // else has been checked above already
|
||||
}
|
||||
}
|
||||
}
|
||||
// Input has been parsed (pvar[0]=section, [1]=property, [2]=value
|
||||
// now execute
|
||||
Section* tsec = control->GetSection(pvars[0]);
|
||||
std::string value;
|
||||
value += pvars[2];
|
||||
for(Bitu i = 3; i < pvars.size(); i++) value += (std::string(" ") + pvars[i]);
|
||||
std::string inputline = pvars[1] + "=" + value;
|
||||
|
||||
tsec->ExecuteDestroy(false);
|
||||
bool change_success = tsec->HandleInputline(inputline.c_str());
|
||||
if (!change_success) WriteOut(MSG_Get("PROGRAM_CONFIG_VALUE_ERROR"),
|
||||
value.c_str(),pvars[1].c_str());
|
||||
tsec->ExecuteInit(false);
|
||||
return;
|
||||
}
|
||||
case P_WRITELANG: case P_WRITELANG2:
|
||||
// In secure mode don't allow a new languagefile to be created
|
||||
// Who knows which kind of file we would overwrite.
|
||||
if (securemode_check()) return;
|
||||
if (pvars.size() < 1) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_MISSINGPARAM"));
|
||||
return;
|
||||
}
|
||||
if (!MSG_Write(pvars[0].c_str())) {
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),pvars[0].c_str());
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case P_SECURE:
|
||||
// Code for switching to secure mode
|
||||
control->SwitchToSecureMode();
|
||||
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_ON"));
|
||||
return;
|
||||
|
||||
default:
|
||||
E_Exit("bug");
|
||||
break;
|
||||
}
|
||||
first = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -401,12 +710,48 @@ void PROGRAMS_Init(Section* /*sec*/) {
|
|||
CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF,"internal program");
|
||||
PROGRAMS_MakeFile("CONFIG.COM",CONFIG_ProgramStart);
|
||||
|
||||
MSG_Add("PROGRAM_CONFIG_FILE_ERROR","Can't open file %s\n");
|
||||
MSG_Add("PROGRAM_CONFIG_USAGE","Config tool:\nUse -writeconf filename to write the current config.\nUse -writelang filename to write the current language strings.\n");
|
||||
// listconf
|
||||
MSG_Add("PROGRAM_CONFIG_NOCONFIGFILE","No config file loaded!\n");
|
||||
MSG_Add("PROGRAM_CONFIG_PRIMARY_CONF","Primary config file: \n%s\n");
|
||||
MSG_Add("PROGRAM_CONFIG_ADDITIONAL_CONF","Additional config files:\n");
|
||||
MSG_Add("PROGRAM_CONFIG_CONFDIR","DOSBox %s configuration directory: \n%s\n\n");
|
||||
|
||||
// writeconf
|
||||
MSG_Add("PROGRAM_CONFIG_FILE_ERROR","\nCan't open file %s\n");
|
||||
MSG_Add("PROGRAM_CONFIG_FILE_WHICH","Writing config file %s");
|
||||
|
||||
// help
|
||||
MSG_Add("PROGRAM_CONFIG_USAGE","Config tool:\n"\
|
||||
"-writeconf or -wc without parameter: write to primary loaded config file.\n"\
|
||||
"-writeconf or -wc with filename: write file to config directory.\n"\
|
||||
"Use -writelang or -wl filename to write the current language strings.\n"\
|
||||
"-r [parameters]\n Restart DOSBox, either using the previous parameters or any that are appended.\n"\
|
||||
"-wcp [filename]\n Write config file to the program directory, dosbox.conf or the specified \n filename.\n"\
|
||||
"-wcd\n Write to the default config file in the config directory.\n"\
|
||||
"-l lists configuration parameters.\n"\
|
||||
"-h, -help, -? sections / sectionname / propertyname\n"\
|
||||
" Without parameters, displays this help screen. Add \"sections\" for a list of\n sections."\
|
||||
" For info about a specific section or property add it's name behind.\n"\
|
||||
"-axclear clears the autoexec section.\n"\
|
||||
"-axadd [line] adds a line to the autoexec section.\n"\
|
||||
"-axtype prints the content of the autoexec section.\n"\
|
||||
"-securemode switches to secure mode.\n"\
|
||||
"-get \"section property\" returns the value of the property.\n"\
|
||||
"-set \"section property=value\" sets the value." );
|
||||
MSG_Add("PROGRAM_CONFIG_HLP_PROPHLP","Purpose of property \"%s\" (contained in section \"%s\"):\n%s\n\nPossible Values: %s\nDefault value: %s\nCurrent value: %s\n");
|
||||
MSG_Add("PROGRAM_CONFIG_HLP_LINEHLP","Purpose of section \"%s\":\n%s\nCurrent value:\n%s\n");
|
||||
MSG_Add("PROGRAM_CONFIG_HLP_NOCHANGE","This property cannot be changed at runtime.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_HLP_POSINT","positive integer");
|
||||
MSG_Add("PROGRAM_CONFIG_HLP_SECTHLP","Section %s contains the following properties:\n");
|
||||
MSG_Add("PROGRAM_CONFIG_HLP_SECTLIST","DOSBox configuration contains the following sections:\n\n");
|
||||
|
||||
MSG_Add("PROGRAM_CONFIG_SECURE_ON","Switched to secure mode.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_SECURE_DISALLOW","This operation is not permitted in secure mode.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_SECTION_ERROR","Section %s doesn't exist.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_VALUE_ERROR","\"%s\" is not a valid value for property %s.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_PROPERTY_ERROR","No such section or property.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_NO_PROPERTY","There is no property %s in section %s.\n");
|
||||
MSG_Add("PROGRAM_CONFIG_GET_SYNTAX","Correct syntax: config -get \"section property\".\n");
|
||||
MSG_Add("PROGRAM_CONFIG_PRINT_STARTUP","\nDOSBox was started with the following command line parameters:\n%s");
|
||||
MSG_Add("PROGRAM_CONFIG_MISSINGPARAM","Missing parameter.");
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#include <list>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <limits>
|
||||
#include <limits.h>
|
||||
|
||||
using namespace std;
|
||||
static std::string current_config_dir; // Set by parseconfigfile so Prop_path can use it to construct the realpath
|
||||
|
@ -104,7 +106,7 @@ bool Value::operator==(Value const& other) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
void Value::SetValue(string const& in,Etype _type) throw(WrongType) {
|
||||
bool Value::SetValue(string const& in,Etype _type) throw(WrongType) {
|
||||
/* Throw exception if the current type isn't the wanted type
|
||||
* Unless the wanted type is current.
|
||||
*/
|
||||
|
@ -113,21 +115,22 @@ void Value::SetValue(string const& in,Etype _type) throw(WrongType) {
|
|||
if(type != V_NONE && type != _type) throw WrongType();
|
||||
type = _type;
|
||||
}
|
||||
bool retval = true;
|
||||
switch(type){
|
||||
case V_HEX:
|
||||
set_hex(in);
|
||||
retval = set_hex(in);
|
||||
break;
|
||||
case V_INT:
|
||||
set_int(in);
|
||||
retval = set_int(in);
|
||||
break;
|
||||
case V_BOOL:
|
||||
set_bool(in);
|
||||
retval = set_bool(in);
|
||||
break;
|
||||
case V_STRING:
|
||||
set_string(in);
|
||||
break;
|
||||
case V_DOUBLE:
|
||||
set_double(in);
|
||||
retval = set_double(in);
|
||||
break;
|
||||
|
||||
case V_NONE:
|
||||
|
@ -137,39 +140,51 @@ void Value::SetValue(string const& in,Etype _type) throw(WrongType) {
|
|||
throw WrongType();
|
||||
break;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Value::set_hex(std::string const& in) {
|
||||
bool Value::set_hex(std::string const& in) {
|
||||
istringstream input(in);
|
||||
input.flags(ios::hex);
|
||||
int result = 0;
|
||||
Bits result = INT_MIN;
|
||||
input >> result;
|
||||
if(result == INT_MIN) return false;
|
||||
_hex = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Value::set_int(string const &in) {
|
||||
bool Value::set_int(string const &in) {
|
||||
istringstream input(in);
|
||||
int result = 0;
|
||||
Bits result = INT_MIN;
|
||||
input >> result;
|
||||
if(result == INT_MIN) return false;
|
||||
_int = result;
|
||||
return true;
|
||||
}
|
||||
void Value::set_double(string const &in) {
|
||||
bool Value::set_double(string const &in) {
|
||||
istringstream input(in);
|
||||
double result = 0;
|
||||
double result = std::numeric_limits<double>::infinity();
|
||||
input >> result;
|
||||
if(result == std::numeric_limits<double>::infinity()) return false;
|
||||
_double = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Value::set_bool(string const &in) {
|
||||
bool Value::set_bool(string const &in) {
|
||||
istringstream input(in);
|
||||
string result;
|
||||
input >> result;
|
||||
_bool = true;
|
||||
lowcase(result);
|
||||
/* valid false entries: 0 ,d*, f*, off everything else gets true */
|
||||
if( !result.size() ) return;
|
||||
if(result[0] == '0' || result[0] == 'd' || result[0] == 'f' || result == "off")
|
||||
_bool = true; // TODO
|
||||
if(!result.size()) return false;
|
||||
|
||||
if(result=="0" || result=="disabled" || result=="false" || result=="off") {
|
||||
_bool = false;
|
||||
} else if(result=="1" || result=="enabled" || result=="true" || result=="on") {
|
||||
_bool = true;
|
||||
} else return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Value::set_string(string const & in) {
|
||||
|
@ -242,27 +257,30 @@ bool Prop_int::CheckValue(Value const& in, bool warn) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void Prop_double::SetValue(std::string const& input){
|
||||
Value val(input,Value::V_DOUBLE);
|
||||
SetVal(val,false,true);
|
||||
bool Prop_double::SetValue(std::string const& input){
|
||||
Value val;
|
||||
if(!val.SetValue(input,Value::V_DOUBLE)) return false;
|
||||
return SetVal(val,false,true);
|
||||
}
|
||||
|
||||
//void Property::SetValue(char* input){
|
||||
// value.SetValue(input, Value::V_CURRENT);
|
||||
//}
|
||||
void Prop_int::SetValue(std::string const& input){;
|
||||
Value val(input,Value::V_INT);
|
||||
SetVal(val,false,true);
|
||||
bool Prop_int::SetValue(std::string const& input){;
|
||||
Value val;
|
||||
if(!val.SetValue(input,Value::V_INT)) return false;
|
||||
bool retval = SetVal(val,false,true);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Prop_string::SetValue(std::string const& input){
|
||||
bool Prop_string::SetValue(std::string const& input){
|
||||
//Special version for lowcase stuff
|
||||
std::string temp(input);
|
||||
//suggested values always case insensitive.
|
||||
//If there are none then it can be paths and such which are case sensitive
|
||||
if(!suggested_values.empty()) lowcase(temp);
|
||||
Value val(temp,Value::V_STRING);
|
||||
SetVal(val,false,true);
|
||||
return SetVal(val,false,true);
|
||||
}
|
||||
bool Prop_string::CheckValue(Value const& in, bool warn){
|
||||
if(suggested_values.empty()) return true;
|
||||
|
@ -281,15 +299,15 @@ bool Prop_string::CheckValue(Value const& in, bool warn){
|
|||
return false;
|
||||
}
|
||||
|
||||
void Prop_path::SetValue(std::string const& input){
|
||||
bool Prop_path::SetValue(std::string const& input){
|
||||
//Special version to merge realpath with it
|
||||
|
||||
Value val(input,Value::V_STRING);
|
||||
SetVal(val,false,true);
|
||||
bool retval = SetVal(val,false,true);
|
||||
|
||||
if(input.empty()) {
|
||||
realpath = "";
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
std::string workcopy(input);
|
||||
Cross::ResolveHomedir(workcopy); //Parse ~ and friends
|
||||
|
@ -297,20 +315,18 @@ void Prop_path::SetValue(std::string const& input){
|
|||
if( current_config_dir.empty()) realpath = workcopy;
|
||||
else realpath = current_config_dir + CROSS_FILESPLIT + workcopy;
|
||||
//Absolute paths
|
||||
#if defined (WIN32) || defined(OS2)
|
||||
if( workcopy.size() > 2 && workcopy[1] == ':' ) realpath = workcopy;
|
||||
#else
|
||||
if( workcopy.size() > 1 && workcopy[0] == '/' ) realpath = workcopy;
|
||||
#endif
|
||||
if (Cross::IsPathAbsolute(workcopy)) realpath = workcopy;
|
||||
return retval;
|
||||
}
|
||||
|
||||
void Prop_bool::SetValue(std::string const& input){
|
||||
value.SetValue(input,Value::V_BOOL);
|
||||
bool Prop_bool::SetValue(std::string const& input){
|
||||
return value.SetValue(input,Value::V_BOOL);
|
||||
}
|
||||
|
||||
void Prop_hex::SetValue(std::string const& input){
|
||||
Value val(input,Value::V_HEX);
|
||||
SetVal(val,false,true);
|
||||
bool Prop_hex::SetValue(std::string const& input){
|
||||
Value val;
|
||||
val.SetValue(input,Value::V_HEX);
|
||||
return SetVal(val,false,true);
|
||||
}
|
||||
|
||||
void Prop_multival::make_default_value(){
|
||||
|
@ -331,15 +347,15 @@ void Prop_multival::make_default_value(){
|
|||
|
||||
|
||||
//TODO checkvalue stuff
|
||||
void Prop_multival_remain::SetValue(std::string const& input) {
|
||||
bool Prop_multival_remain::SetValue(std::string const& input) {
|
||||
Value val(input,Value::V_STRING);
|
||||
SetVal(val,false,true);
|
||||
bool retval = SetVal(val,false,true);
|
||||
|
||||
std::string local(input);
|
||||
int i = 0,number_of_properties = 0;
|
||||
Property *p = section->Get_prop(0);
|
||||
//No properties in this section. do nothing
|
||||
if(!p) return;
|
||||
if(!p) return false;
|
||||
|
||||
while( (section->Get_prop(number_of_properties)) )
|
||||
number_of_properties++;
|
||||
|
@ -364,22 +380,23 @@ void Prop_multival_remain::SetValue(std::string const& input) {
|
|||
Value valtest (in,p->Get_type());
|
||||
if(!p->CheckValue(valtest,true)) {
|
||||
make_default_value();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
p->SetValue(in);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
//TODO checkvalue stuff
|
||||
void Prop_multival::SetValue(std::string const& input) {
|
||||
bool Prop_multival::SetValue(std::string const& input) {
|
||||
Value val(input,Value::V_STRING);
|
||||
SetVal(val,false,true);
|
||||
bool retval = SetVal(val,false,true);
|
||||
|
||||
std::string local(input);
|
||||
int i = 0;
|
||||
Property *p = section->Get_prop(0);
|
||||
//No properties in this section. do nothing
|
||||
if(!p) return;
|
||||
if(!p) return false;
|
||||
string::size_type loc = string::npos;
|
||||
while( (p = section->Get_prop(i++)) ) {
|
||||
//trim leading seperators
|
||||
|
@ -398,11 +415,12 @@ void Prop_multival::SetValue(std::string const& input) {
|
|||
Value valtest (in,p->Get_type());
|
||||
if(!p->CheckValue(valtest,true)) {
|
||||
make_default_value();
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
p->SetValue(in);
|
||||
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
const std::vector<Value>& Property::GetValues() const {
|
||||
|
@ -563,20 +581,20 @@ void trim(string& in) {
|
|||
}
|
||||
|
||||
//TODO double c_str
|
||||
void Section_prop::HandleInputline(string const& gegevens){
|
||||
bool Section_prop::HandleInputline(string const& gegevens){
|
||||
string str1 = gegevens;
|
||||
string::size_type loc = str1.find('=');
|
||||
if(loc == string::npos) return;
|
||||
if(loc == string::npos) return false;
|
||||
string name = str1.substr(0,loc);
|
||||
string val = str1.substr(loc + 1);
|
||||
/* trim the results incase there were spaces somewhere */
|
||||
trim(name);trim(val);
|
||||
for(it tel=properties.begin();tel!=properties.end();tel++){
|
||||
if(!strcasecmp((*tel)->propname.c_str(),name.c_str())){
|
||||
(*tel)->SetValue(val);
|
||||
return;
|
||||
return (*tel)->SetValue(val);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Section_prop::PrintData(FILE* outfile) const {
|
||||
|
@ -596,9 +614,10 @@ string Section_prop::GetPropValue(string const& _property) const{
|
|||
return NO_SUCH_PROPERTY;
|
||||
}
|
||||
|
||||
void Section_line::HandleInputline(string const& line){
|
||||
bool Section_line::HandleInputline(string const& line){
|
||||
data+=line;
|
||||
data+="\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
void Section_line::PrintData(FILE* outfile) const {
|
||||
|
@ -770,11 +789,13 @@ Section* Config::GetSectionFromProperty(char const * const prop) const{
|
|||
|
||||
|
||||
bool Config::ParseConfigFile(char const * const configfilename){
|
||||
static bool first_configfile = true;
|
||||
//static bool first_configfile = true;
|
||||
ifstream in(configfilename);
|
||||
if (!in) return false;
|
||||
const char * settings_type = first_configfile?"primary":"additional";
|
||||
first_configfile = false;
|
||||
const char * settings_type;
|
||||
settings_type = (configfiles.size() == 0)? "primary":"additional";
|
||||
configfiles.push_back(configfilename);
|
||||
|
||||
LOG_MSG("CONFIG:Loading %s settings from config file %s", settings_type,configfilename);
|
||||
|
||||
//Get directory from configfilename, used with relative paths.
|
||||
|
@ -824,6 +845,10 @@ bool Config::ParseConfigFile(char const * const configfilename){
|
|||
return true;
|
||||
}
|
||||
|
||||
/*const char* Config::GetPrimaryConfigFile() {
|
||||
return configfile.c_str();
|
||||
}*/
|
||||
|
||||
void Config::ParseEnv(char ** envp) {
|
||||
for(char** env=envp; *env;env++) {
|
||||
char copy[1024];
|
||||
|
@ -850,6 +875,7 @@ void Config::SetStartUp(void (*_function)(void)) {
|
|||
|
||||
|
||||
void Config::StartUp(void) {
|
||||
initialised=true;
|
||||
(*_start_function)();
|
||||
}
|
||||
|
||||
|
@ -946,6 +972,90 @@ unsigned int CommandLine::GetCount(void) {
|
|||
return (unsigned int)cmds.size();
|
||||
}
|
||||
|
||||
void CommandLine::FillVector(std::vector<std::string> & vector) {
|
||||
for(cmd_it it=cmds.begin(); it != cmds.end(); it++) {
|
||||
vector.push_back((*it));
|
||||
}
|
||||
// add back the \" if the parameter contained a space
|
||||
for(Bitu i = 0; i < vector.size(); i++) {
|
||||
if(vector[i].find(' ') != std::string::npos) {
|
||||
vector[i] = "\""+vector[i]+"\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CommandLine::GetParameterFromList(const char* const params[], std::vector<std::string> & output) {
|
||||
// return values: 0 = P_NOMATCH, 1 = P_NOPARAMS
|
||||
// TODO return nomoreparams
|
||||
int retval = 1;
|
||||
output.clear();
|
||||
enum {
|
||||
P_START, P_FIRSTNOMATCH, P_FIRSTMATCH
|
||||
} parsestate = P_START;
|
||||
cmd_it it = cmds.begin();
|
||||
while(it!=cmds.end()) {
|
||||
bool found = false;
|
||||
for(Bitu i = 0; params[i]!=""; i++) {
|
||||
if (!strcasecmp((*it).c_str(),params[i])) {
|
||||
// found a parameter
|
||||
found = true;
|
||||
switch(parsestate) {
|
||||
case P_START:
|
||||
retval = i+2;
|
||||
parsestate = P_FIRSTMATCH;
|
||||
break;
|
||||
case P_FIRSTMATCH:
|
||||
case P_FIRSTNOMATCH:
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
switch(parsestate) {
|
||||
case P_START:
|
||||
retval = 0; // no match
|
||||
parsestate = P_FIRSTNOMATCH;
|
||||
output.push_back(*it);
|
||||
break;
|
||||
case P_FIRSTMATCH:
|
||||
case P_FIRSTNOMATCH:
|
||||
output.push_back(*it);
|
||||
break;
|
||||
}
|
||||
cmd_it itold = it;
|
||||
it++;
|
||||
cmds.erase(itold);
|
||||
|
||||
}
|
||||
|
||||
return retval;
|
||||
/*
|
||||
bool CommandLine::FindEntry(char const * const name,cmd_it & it,bool neednext) {
|
||||
for (it=cmds.begin();it!=cmds.end();it++) {
|
||||
if (!strcasecmp((*it).c_str(),name)) {
|
||||
cmd_it itnext=it;itnext++;
|
||||
if (neednext && (itnext==cmds.end())) return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
cmd_it it=cmds.begin();value=(*it++);
|
||||
while(it != cmds.end()) {
|
||||
if(params.
|
||||
|
||||
it++;
|
||||
}
|
||||
*/
|
||||
// find next parameter
|
||||
//return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
CommandLine::CommandLine(int argc,char const * const argv[]) {
|
||||
if (argc>0) {
|
||||
file_name=argv[0];
|
||||
|
|
Loading…
Add table
Reference in a new issue