This commit is contained in:
dborth 2009-11-10 09:07:29 +00:00
parent 5ef584b880
commit 336d2c0758
9 changed files with 4541 additions and 4541 deletions

View File

@ -1,265 +1,265 @@
/* /*
* Copyright (C) 2002-2009 The DOSBox Team * Copyright (C) 2002-2009 The DOSBox Team
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: cross.cpp,v 1.7 2009/05/26 17:43:39 qbix79 Exp $ */ /* $Id: cross.cpp,v 1.7 2009-05-26 17:43:39 qbix79 Exp $ */
#include "dosbox.h" #include "dosbox.h"
#include "cross.h" #include "cross.h"
#include "support.h" #include "support.h"
#include <string> #include <string>
#include <stdlib.h> #include <stdlib.h>
#ifdef HW_RVL #ifdef HW_RVL
#include "wiihardware.h" #include "wiihardware.h"
#endif #endif
#ifdef WIN32 #ifdef WIN32
#ifndef _WIN32_IE #ifndef _WIN32_IE
#define _WIN32_IE 0x0400 #define _WIN32_IE 0x0400
#endif #endif
#include <shlobj.h> #include <shlobj.h>
#endif #endif
#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H #if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h> #include <pwd.h>
#endif #endif
#ifdef WIN32 #ifdef WIN32
static void W32_ConfDir(std::string& in,bool create) { static void W32_ConfDir(std::string& in,bool create) {
int c = create?1:0; int c = create?1:0;
char result[MAX_PATH] = { 0 }; char result[MAX_PATH] = { 0 };
BOOL r = SHGetSpecialFolderPath(NULL,result,CSIDL_LOCAL_APPDATA,c); BOOL r = SHGetSpecialFolderPath(NULL,result,CSIDL_LOCAL_APPDATA,c);
if(!r || result[0] == 0) r = SHGetSpecialFolderPath(NULL,result,CSIDL_APPDATA,c); if(!r || result[0] == 0) r = SHGetSpecialFolderPath(NULL,result,CSIDL_APPDATA,c);
if(!r || result[0] == 0) { if(!r || result[0] == 0) {
char const * windir = getenv("windir"); char const * windir = getenv("windir");
if(!windir) windir = "c:\\windows"; if(!windir) windir = "c:\\windows";
safe_strncpy(result,windir,MAX_PATH); safe_strncpy(result,windir,MAX_PATH);
char const* appdata = "\\Application Data"; char const* appdata = "\\Application Data";
size_t len = strlen(result); size_t len = strlen(result);
if(len + strlen(appdata) < MAX_PATH) strcat(result,appdata); if(len + strlen(appdata) < MAX_PATH) strcat(result,appdata);
if(create) mkdir(result); if(create) mkdir(result);
} }
in = result; in = result;
} }
#endif #endif
void Cross::GetPlatformConfigDir(std::string& in) { void Cross::GetPlatformConfigDir(std::string& in) {
#ifdef WIN32 #ifdef WIN32
W32_ConfDir(in,false); W32_ConfDir(in,false);
in += "\\DOSBox"; in += "\\DOSBox";
#elif defined(MACOSX) #elif defined(MACOSX)
in = "~/Library/Preferences"; in = "~/Library/Preferences";
ResolveHomedir(in); ResolveHomedir(in);
#elif defined(HW_RVL) #elif defined(HW_RVL)
in = "sd:/DOSBox"; in = "sd:/DOSBox";
#else #else
in = "~/.dosbox"; in = "~/.dosbox";
ResolveHomedir(in); ResolveHomedir(in);
#endif #endif
in += CROSS_FILESPLIT; in += CROSS_FILESPLIT;
} }
void Cross::GetPlatformConfigName(std::string& in) { void Cross::GetPlatformConfigName(std::string& in) {
#ifdef WIN32 #ifdef WIN32
#define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf" #define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
#elif defined(MACOSX) #elif defined(MACOSX)
#define DEFAULT_CONFIG_FILE "DOSBox " VERSION " Preferences" #define DEFAULT_CONFIG_FILE "DOSBox " VERSION " Preferences"
#elif defined(HW_RVL) #elif defined(HW_RVL)
#define DEFAULT_CONFIG_FILE "dosbox.conf" #define DEFAULT_CONFIG_FILE "dosbox.conf"
#else /*linux freebsd*/ #else /*linux freebsd*/
#define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf" #define DEFAULT_CONFIG_FILE "dosbox-" VERSION ".conf"
#endif #endif
in = DEFAULT_CONFIG_FILE; in = DEFAULT_CONFIG_FILE;
} }
void Cross::CreatePlatformConfigDir(std::string& in) { void Cross::CreatePlatformConfigDir(std::string& in) {
#ifdef WIN32 #ifdef WIN32
W32_ConfDir(in,true); W32_ConfDir(in,true);
in += "\\DOSBox"; in += "\\DOSBox";
mkdir(in.c_str()); mkdir(in.c_str());
#elif defined(MACOSX) #elif defined(MACOSX)
in = "~/Library/Preferences/"; in = "~/Library/Preferences/";
ResolveHomedir(in); ResolveHomedir(in);
//Don't create it. Assume it exists //Don't create it. Assume it exists
#elif defined(HW_RVL) #elif defined(HW_RVL)
in = "sd:/DOSBox"; in = "sd:/DOSBox";
CreateDir(in); CreateDir(in);
#else #else
in = "~/.dosbox"; in = "~/.dosbox";
ResolveHomedir(in); ResolveHomedir(in);
mkdir(in.c_str(),0700); mkdir(in.c_str(),0700);
#endif #endif
in += CROSS_FILESPLIT; in += CROSS_FILESPLIT;
} }
void Cross::ResolveHomedir(std::string & temp_line) { void Cross::ResolveHomedir(std::string & temp_line) {
if(!temp_line.size() || temp_line[0] != '~') return; //No ~ if(!temp_line.size() || temp_line[0] != '~') return; //No ~
if(temp_line.size() == 1 || temp_line[1] == CROSS_FILESPLIT) { //The ~ and ~/ variant if(temp_line.size() == 1 || temp_line[1] == CROSS_FILESPLIT) { //The ~ and ~/ variant
char * home = getenv("HOME"); char * home = getenv("HOME");
if(home) temp_line.replace(0,1,std::string(home)); if(home) temp_line.replace(0,1,std::string(home));
#if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H #if defined HAVE_SYS_TYPES_H && defined HAVE_PWD_H
} else { // The ~username variant } else { // The ~username variant
std::string::size_type namelen = temp_line.find(CROSS_FILESPLIT); std::string::size_type namelen = temp_line.find(CROSS_FILESPLIT);
if(namelen == std::string::npos) namelen = temp_line.size(); if(namelen == std::string::npos) namelen = temp_line.size();
std::string username = temp_line.substr(1,namelen - 1); std::string username = temp_line.substr(1,namelen - 1);
struct passwd* pass = getpwnam(username.c_str()); struct passwd* pass = getpwnam(username.c_str());
if(pass) temp_line.replace(0,namelen,pass->pw_dir); //namelen -1 +1(for the ~) if(pass) temp_line.replace(0,namelen,pass->pw_dir); //namelen -1 +1(for the ~)
#endif // USERNAME lookup code #endif // USERNAME lookup code
} }
} }
void Cross::CreateDir(std::string const& in) { void Cross::CreateDir(std::string const& in) {
#ifdef WIN32 #ifdef WIN32
mkdir(in.c_str()); mkdir(in.c_str());
#else #else
mkdir(in.c_str(),0700); mkdir(in.c_str(),0700);
#endif #endif
} }
#if defined (WIN32) #if defined (WIN32)
dir_information* open_directory(const char* dirname) { dir_information* open_directory(const char* dirname) {
if (dirname == NULL) return NULL; if (dirname == NULL) return NULL;
size_t len = strlen(dirname); size_t len = strlen(dirname);
if (len == 0) return NULL; if (len == 0) return NULL;
static dir_information dir; static dir_information dir;
safe_strncpy(dir.base_path,dirname,MAX_PATH); safe_strncpy(dir.base_path,dirname,MAX_PATH);
if (dirname[len-1] == '\\') strcat(dir.base_path,"*.*"); if (dirname[len-1] == '\\') strcat(dir.base_path,"*.*");
else strcat(dir.base_path,"\\*.*"); else strcat(dir.base_path,"\\*.*");
dir.handle = INVALID_HANDLE_VALUE; dir.handle = INVALID_HANDLE_VALUE;
return (access(dirname,0) ? NULL : &dir); return (access(dirname,0) ? NULL : &dir);
} }
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) { bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
dirp->handle = FindFirstFile(dirp->base_path, &dirp->search_data); dirp->handle = FindFirstFile(dirp->base_path, &dirp->search_data);
if (INVALID_HANDLE_VALUE == dirp->handle) { if (INVALID_HANDLE_VALUE == dirp->handle) {
return false; return false;
} }
safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN); safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
if (dirp->search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true; if (dirp->search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
else is_directory = false; else is_directory = false;
return true; return true;
} }
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) { bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
int result = FindNextFile(dirp->handle, &dirp->search_data); int result = FindNextFile(dirp->handle, &dirp->search_data);
if (result==0) return false; if (result==0) return false;
safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN); safe_strncpy(entry_name,dirp->search_data.cFileName,(MAX_PATH<CROSS_LEN)?MAX_PATH:CROSS_LEN);
if (dirp->search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true; if (dirp->search_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) is_directory = true;
else is_directory = false; else is_directory = false;
return true; return true;
} }
void close_directory(dir_information* dirp) { void close_directory(dir_information* dirp) {
if (dirp->handle != INVALID_HANDLE_VALUE) { if (dirp->handle != INVALID_HANDLE_VALUE) {
FindClose(dirp->handle); FindClose(dirp->handle);
dirp->handle = INVALID_HANDLE_VALUE; dirp->handle = INVALID_HANDLE_VALUE;
} }
} }
#else #else
dir_information* open_directory(const char* dirname) { dir_information* open_directory(const char* dirname) {
static dir_information dir; static dir_information dir;
dir.dir=opendir(dirname); dir.dir=opendir(dirname);
safe_strncpy(dir.base_path,dirname,CROSS_LEN); safe_strncpy(dir.base_path,dirname,CROSS_LEN);
return dir.dir?&dir:NULL; return dir.dir?&dir:NULL;
} }
bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) { bool read_directory_first(dir_information* dirp, char* entry_name, bool& is_directory) {
struct dirent* dentry = readdir(dirp->dir); struct dirent* dentry = readdir(dirp->dir);
if (dentry==NULL) { if (dentry==NULL) {
return false; return false;
} }
// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf() // safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf()
safe_strncpy(entry_name,dentry->d_name,CROSS_LEN); safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
#ifdef DIRENT_HAS_D_TYPE #ifdef DIRENT_HAS_D_TYPE
if(dentry->d_type == DT_DIR) { if(dentry->d_type == DT_DIR) {
is_directory = true; is_directory = true;
return true; return true;
} else if(dentry->d_type == DT_REG) { } else if(dentry->d_type == DT_REG) {
is_directory = false; is_directory = false;
return true; return true;
} }
#endif #endif
// probably use d_type here instead of a full stat() // probably use d_type here instead of a full stat()
static char buffer[2*CROSS_LEN] = { 0 }; static char buffer[2*CROSS_LEN] = { 0 };
buffer[0] = 0; buffer[0] = 0;
strcpy(buffer,dirp->base_path); strcpy(buffer,dirp->base_path);
strcat(buffer,entry_name); strcat(buffer,entry_name);
struct stat status; struct stat status;
if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0); if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
else is_directory = false; else is_directory = false;
return true; return true;
} }
bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) { bool read_directory_next(dir_information* dirp, char* entry_name, bool& is_directory) {
struct dirent* dentry = readdir(dirp->dir); struct dirent* dentry = readdir(dirp->dir);
if (dentry==NULL) { if (dentry==NULL) {
return false; return false;
} }
// safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf() // safe_strncpy(entry_name,dentry->d_name,(FILENAME_MAX<MAX_PATH)?FILENAME_MAX:MAX_PATH); // [include stdio.h], maybe pathconf()
safe_strncpy(entry_name,dentry->d_name,CROSS_LEN); safe_strncpy(entry_name,dentry->d_name,CROSS_LEN);
#ifdef DIRENT_HAS_D_TYPE #ifdef DIRENT_HAS_D_TYPE
if(dentry->d_type == DT_DIR) { if(dentry->d_type == DT_DIR) {
is_directory = true; is_directory = true;
return true; return true;
} else if(dentry->d_type == DT_REG) { } else if(dentry->d_type == DT_REG) {
is_directory = false; is_directory = false;
return true; return true;
} }
#endif #endif
// probably use d_type here instead of a full stat() // probably use d_type here instead of a full stat()
static char buffer[2*CROSS_LEN] = { 0 }; static char buffer[2*CROSS_LEN] = { 0 };
buffer[0] = 0; buffer[0] = 0;
strcpy(buffer,dirp->base_path); strcpy(buffer,dirp->base_path);
strcat(buffer,entry_name); strcat(buffer,entry_name);
struct stat status; struct stat status;
if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0); if (stat(buffer,&status)==0) is_directory = (S_ISDIR(status.st_mode)>0);
else is_directory = false; else is_directory = false;
return true; return true;
} }
void close_directory(dir_information* dirp) { void close_directory(dir_information* dirp) {
closedir(dirp->dir); closedir(dirp->dir);
} }
#endif #endif

View File

@ -1,144 +1,144 @@
/* /*
* Copyright (C) 2002-2009 The DOSBox Team * Copyright (C) 2002-2009 The DOSBox Team
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: messages.cpp,v 1.23 2009/06/17 08:52:35 qbix79 Exp $ */ /* $Id: messages.cpp,v 1.23 2009-06-17 08:52:35 qbix79 Exp $ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "dosbox.h" #include "dosbox.h"
#include "cross.h" #include "cross.h"
#include "support.h" #include "support.h"
#include "setup.h" #include "setup.h"
#include "control.h" #include "control.h"
#include <list> #include <list>
#include <string> #include <string>
using namespace std; using namespace std;
#define LINE_IN_MAXLEN 2048 #define LINE_IN_MAXLEN 2048
struct MessageBlock { struct MessageBlock {
string name; string name;
string val; string val;
MessageBlock(const char* _name, const char* _val): MessageBlock(const char* _name, const char* _val):
name(_name),val(_val){} name(_name),val(_val){}
}; };
static list<MessageBlock> Lang; static list<MessageBlock> Lang;
typedef list<MessageBlock>::iterator itmb; typedef list<MessageBlock>::iterator itmb;
void MSG_Add(const char * _name, const char* _val) { void MSG_Add(const char * _name, const char* _val) {
/* Find the message */ /* Find the message */
for(itmb tel=Lang.begin();tel!=Lang.end();tel++) { for(itmb tel=Lang.begin();tel!=Lang.end();tel++) {
if((*tel).name==_name) { if((*tel).name==_name) {
// LOG_MSG("double entry for %s",_name); //Message file might be loaded before default text messages // LOG_MSG("double entry for %s",_name); //Message file might be loaded before default text messages
return; return;
} }
} }
/* if the message doesn't exist add it */ /* if the message doesn't exist add it */
Lang.push_back(MessageBlock(_name,_val)); Lang.push_back(MessageBlock(_name,_val));
} }
void MSG_Replace(const char * _name, const char* _val) { void MSG_Replace(const char * _name, const char* _val) {
/* Find the message */ /* Find the message */
for(itmb tel=Lang.begin();tel!=Lang.end();tel++) { for(itmb tel=Lang.begin();tel!=Lang.end();tel++) {
if((*tel).name==_name) { if((*tel).name==_name) {
Lang.erase(tel); Lang.erase(tel);
break; break;
} }
} }
/* Even if the message doesn't exist add it */ /* Even if the message doesn't exist add it */
Lang.push_back(MessageBlock(_name,_val)); Lang.push_back(MessageBlock(_name,_val));
} }
static void LoadMessageFile(const char * fname) { static void LoadMessageFile(const char * fname) {
if (!fname) return; if (!fname) return;
if(*fname=='\0') return;//empty string=no languagefile if(*fname=='\0') return;//empty string=no languagefile
FILE * mfile=fopen(fname,"rt"); FILE * mfile=fopen(fname,"rt");
/* This should never happen and since other modules depend on this use a normal printf */ /* This should never happen and since other modules depend on this use a normal printf */
if (!mfile) { if (!mfile) {
E_Exit("MSG:Can't load messages: %s",fname); E_Exit("MSG:Can't load messages: %s",fname);
} }
char linein[LINE_IN_MAXLEN]; char linein[LINE_IN_MAXLEN];
char name[LINE_IN_MAXLEN]; char name[LINE_IN_MAXLEN];
char string[LINE_IN_MAXLEN*10]; char string[LINE_IN_MAXLEN*10];
/* Start out with empty strings */ /* Start out with empty strings */
name[0]=0;string[0]=0; name[0]=0;string[0]=0;
while(fgets(linein, LINE_IN_MAXLEN, mfile)!=0) { while(fgets(linein, LINE_IN_MAXLEN, mfile)!=0) {
/* Parse the read line */ /* Parse the read line */
/* First remove characters 10 and 13 from the line */ /* First remove characters 10 and 13 from the line */
char * parser=linein; char * parser=linein;
char * writer=linein; char * writer=linein;
while (*parser) { while (*parser) {
if (*parser!=10 && *parser!=13) { if (*parser!=10 && *parser!=13) {
*writer++=*parser; *writer++=*parser;
} }
*parser++; *parser++;
} }
*writer=0; *writer=0;
/* New string name */ /* New string name */
if (linein[0]==':') { if (linein[0]==':') {
string[0]=0; string[0]=0;
strcpy(name,linein+1); strcpy(name,linein+1);
/* End of string marker */ /* End of string marker */
} else if (linein[0]=='.') { } else if (linein[0]=='.') {
/* Replace/Add the string to the internal langaugefile */ /* Replace/Add the string to the internal langaugefile */
/* Remove last newline (marker is \n.\n) */ /* Remove last newline (marker is \n.\n) */
size_t ll = strlen(string); size_t ll = strlen(string);
if(ll && string[ll - 1] == '\n') string[ll - 1] = 0; //Second if should not be needed, but better be safe. if(ll && string[ll - 1] == '\n') string[ll - 1] = 0; //Second if should not be needed, but better be safe.
MSG_Replace(name,string); MSG_Replace(name,string);
} else { } else {
/* Normal string to be added */ /* Normal string to be added */
strcat(string,linein); strcat(string,linein);
strcat(string,"\n"); strcat(string,"\n");
} }
} }
fclose(mfile); fclose(mfile);
} }
const char * MSG_Get(char const * msg) { const char * MSG_Get(char const * msg) {
for(itmb tel=Lang.begin();tel!=Lang.end();tel++){ for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
if((*tel).name==msg) if((*tel).name==msg)
{ {
return (*tel).val.c_str(); return (*tel).val.c_str();
} }
} }
return "Message not Found!\n"; return "Message not Found!\n";
} }
void MSG_Write(const char * location) { void MSG_Write(const char * location) {
FILE* out=fopen(location,"w+t"); FILE* out=fopen(location,"w+t");
if(out==NULL) return;//maybe an error? if(out==NULL) return;//maybe an error?
for(itmb tel=Lang.begin();tel!=Lang.end();tel++){ for(itmb tel=Lang.begin();tel!=Lang.end();tel++){
fprintf(out,":%s\n%s\n.\n",(*tel).name.c_str(),(*tel).val.c_str()); fprintf(out,":%s\n%s\n.\n",(*tel).name.c_str(),(*tel).val.c_str());
} }
fclose(out); fclose(out);
} }
void MSG_Init(Section_prop * section) { void MSG_Init(Section_prop * section) {
std::string file_name; std::string file_name;
if (control->cmdline->FindString("-lang",file_name,true)) { if (control->cmdline->FindString("-lang",file_name,true)) {
LoadMessageFile(file_name.c_str()); LoadMessageFile(file_name.c_str());
} else { } else {
Prop_path* pathprop = section->Get_path("language"); Prop_path* pathprop = section->Get_path("language");
if(pathprop) LoadMessageFile(pathprop->realpath.c_str()); if(pathprop) LoadMessageFile(pathprop->realpath.c_str());
} }
} }

View File

@ -1,392 +1,392 @@
/* /*
* Copyright (C) 2002-2009 The DOSBox Team * Copyright (C) 2002-2009 The DOSBox Team
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: programs.cpp,v 1.37 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: programs.cpp,v 1.37 2009-05-27 09:15:42 qbix79 Exp $ */
#include <vector> #include <vector>
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "programs.h" #include "programs.h"
#include "callback.h" #include "callback.h"
#include "regs.h" #include "regs.h"
#include "support.h" #include "support.h"
#include "cross.h" #include "cross.h"
#include "control.h" #include "control.h"
#include "shell.h" #include "shell.h"
Bitu call_program; Bitu call_program;
/* This registers a file on the virtual drive and creates the correct structure for it*/ /* This registers a file on the virtual drive and creates the correct structure for it*/
static Bit8u exe_block[]={ static Bit8u exe_block[]={
0xbc,0x00,0x04, //MOV SP,0x400 decrease stack size 0xbc,0x00,0x04, //MOV SP,0x400 decrease stack size
0xbb,0x40,0x00, //MOV BX,0x040 for memory resize 0xbb,0x40,0x00, //MOV BX,0x040 for memory resize
0xb4,0x4a, //MOV AH,0x4A Resize memory block 0xb4,0x4a, //MOV AH,0x4A Resize memory block
0xcd,0x21, //INT 0x21 0xcd,0x21, //INT 0x21
//pos 12 is callback number //pos 12 is callback number
0xFE,0x38,0x00,0x00, //CALLBack number 0xFE,0x38,0x00,0x00, //CALLBack number
0xb8,0x00,0x4c, //Mov ax,4c00 0xb8,0x00,0x4c, //Mov ax,4c00
0xcd,0x21, //INT 0x21 0xcd,0x21, //INT 0x21
}; };
#define CB_POS 12 #define CB_POS 12
static std::vector<PROGRAMS_Main*> internal_progs; static std::vector<PROGRAMS_Main*> internal_progs;
void PROGRAMS_MakeFile(char const * const name,PROGRAMS_Main * main) { void PROGRAMS_MakeFile(char const * const name,PROGRAMS_Main * main) {
Bit8u * comdata=(Bit8u *)malloc(32); //MEM LEAK Bit8u * comdata=(Bit8u *)malloc(32); //MEM LEAK
memcpy(comdata,&exe_block,sizeof(exe_block)); memcpy(comdata,&exe_block,sizeof(exe_block));
comdata[CB_POS]=(Bit8u)(call_program&0xff); comdata[CB_POS]=(Bit8u)(call_program&0xff);
comdata[CB_POS+1]=(Bit8u)((call_program>>8)&0xff); comdata[CB_POS+1]=(Bit8u)((call_program>>8)&0xff);
/* Copy save the pointer in the vector and save it's index */ /* Copy save the pointer in the vector and save it's index */
if (internal_progs.size()>255) E_Exit("PROGRAMS_MakeFile program size too large (%d)",static_cast<int>(internal_progs.size())); if (internal_progs.size()>255) E_Exit("PROGRAMS_MakeFile program size too large (%d)",static_cast<int>(internal_progs.size()));
Bit8u index = (Bit8u)internal_progs.size(); Bit8u index = (Bit8u)internal_progs.size();
internal_progs.push_back(main); internal_progs.push_back(main);
memcpy(&comdata[sizeof(exe_block)],&index,sizeof(index)); memcpy(&comdata[sizeof(exe_block)],&index,sizeof(index));
Bit32u size=sizeof(exe_block)+sizeof(index); Bit32u size=sizeof(exe_block)+sizeof(index);
VFILE_Register(name,comdata,size); VFILE_Register(name,comdata,size);
} }
static Bitu PROGRAMS_Handler(void) { static Bitu PROGRAMS_Handler(void) {
/* This sets up everything for a program start up call */ /* This sets up everything for a program start up call */
Bitu size=sizeof(Bit8u); Bitu size=sizeof(Bit8u);
Bit8u index; Bit8u index;
/* Read the index from program code in memory */ /* Read the index from program code in memory */
PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block)); PhysPt reader=PhysMake(dos.psp(),256+sizeof(exe_block));
HostPt writer=(HostPt)&index; HostPt writer=(HostPt)&index;
for (;size>0;size--) *writer++=mem_readb(reader++); for (;size>0;size--) *writer++=mem_readb(reader++);
Program * new_program; 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]; PROGRAMS_Main * handler = internal_progs[index];
(*handler)(&new_program); (*handler)(&new_program);
new_program->Run(); new_program->Run();
delete new_program; delete new_program;
return CBRET_NONE; return CBRET_NONE;
} }
/* Main functions used in all program */ /* Main functions used in all program */
Program::Program() { Program::Program() {
/* Find the command line and setup the PSP */ /* Find the command line and setup the PSP */
psp = new DOS_PSP(dos.psp()); psp = new DOS_PSP(dos.psp());
/* Scan environment for filename */ /* Scan environment for filename */
PhysPt envscan=PhysMake(psp->GetEnvironment(),0); PhysPt envscan=PhysMake(psp->GetEnvironment(),0);
while (mem_readb(envscan)) envscan+=mem_strlen(envscan)+1; while (mem_readb(envscan)) envscan+=mem_strlen(envscan)+1;
envscan+=3; envscan+=3;
CommandTail tail; CommandTail tail;
MEM_BlockRead(PhysMake(dos.psp(),128),&tail,128); MEM_BlockRead(PhysMake(dos.psp(),128),&tail,128);
if (tail.count<127) tail.buffer[tail.count]=0; if (tail.count<127) tail.buffer[tail.count]=0;
else tail.buffer[126]=0; else tail.buffer[126]=0;
char filename[256+1]; char filename[256+1];
MEM_StrCopy(envscan,filename,256); MEM_StrCopy(envscan,filename,256);
cmd = new CommandLine(filename,tail.buffer); cmd = new CommandLine(filename,tail.buffer);
} }
extern std::string full_arguments; extern std::string full_arguments;
void Program::ChangeToLongCmd() { void Program::ChangeToLongCmd() {
/* /*
* Get arguments directly from the shell instead of the psp. * Get arguments directly from the shell instead of the psp.
* this is done in securemode: (as then the arguments to mount and friends * this is done in securemode: (as then the arguments to mount and friends
* can only be given on the shell ( so no int 21 4b) * can only be given on the shell ( so no int 21 4b)
* Securemode part is disabled as each of the internal command has already * Securemode part is disabled as each of the internal command has already
* protection for it. (and it breaks games like cdman) * protection for it. (and it breaks games like cdman)
* it is also done for long arguments to as it is convient (as the total commandline can be longer then 127 characters. * it is also done for long arguments to as it is convient (as the total commandline can be longer then 127 characters.
* imgmount with lot's of parameters * imgmount with lot's of parameters
* Length of arguments can be ~120. but switch when above 100 to be sure * 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()); CommandLine* temp = new CommandLine(cmd->GetFileName(),full_arguments.c_str());
delete cmd; delete cmd;
cmd = temp; cmd = temp;
} }
full_arguments.assign(""); //Clear so it gets even more save full_arguments.assign(""); //Clear so it gets even more save
} }
void Program::WriteOut(const char * format,...) { void Program::WriteOut(const char * format,...) {
char buf[2048]; char buf[2048];
va_list msg; va_list msg;
va_start(msg,format); va_start(msg,format);
vsnprintf(buf,2047,format,msg); vsnprintf(buf,2047,format,msg);
va_end(msg); va_end(msg);
Bit16u size = (Bit16u)strlen(buf); Bit16u size = (Bit16u)strlen(buf);
DOS_WriteFile(STDOUT,(Bit8u *)buf,&size); DOS_WriteFile(STDOUT,(Bit8u *)buf,&size);
} }
void Program::WriteOut_NoParsing(const char * format) { void Program::WriteOut_NoParsing(const char * format) {
Bit16u size = (Bit16u)strlen(format); Bit16u size = (Bit16u)strlen(format);
DOS_WriteFile(STDOUT,(Bit8u *)format,&size); DOS_WriteFile(STDOUT,(Bit8u *)format,&size);
} }
bool Program::GetEnvStr(const char * entry,std::string & result) { bool Program::GetEnvStr(const char * entry,std::string & result) {
/* Walk through the internal environment and see for a match */ /* Walk through the internal environment and see for a match */
PhysPt env_read=PhysMake(psp->GetEnvironment(),0); PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
char env_string[1024+1]; char env_string[1024+1];
result.erase(); result.erase();
if (!entry[0]) return false; if (!entry[0]) return false;
do { do {
MEM_StrCopy(env_read,env_string,1024); MEM_StrCopy(env_read,env_string,1024);
if (!env_string[0]) return false; if (!env_string[0]) return false;
env_read += (PhysPt)(strlen(env_string)+1); env_read += (PhysPt)(strlen(env_string)+1);
char* equal = strchr(env_string,'='); char* equal = strchr(env_string,'=');
if (!equal) continue; if (!equal) continue;
/* replace the = with \0 to get the length */ /* replace the = with \0 to get the length */
*equal = 0; *equal = 0;
if (strlen(env_string) != strlen(entry)) continue; if (strlen(env_string) != strlen(entry)) continue;
if (strcasecmp(entry,env_string)!=0) continue; if (strcasecmp(entry,env_string)!=0) continue;
/* restore the = to get the original result */ /* restore the = to get the original result */
*equal = '='; *equal = '=';
result = env_string; result = env_string;
return true; return true;
} while (1); } while (1);
return false; return false;
} }
bool Program::GetEnvNum(Bitu num,std::string & result) { bool Program::GetEnvNum(Bitu num,std::string & result) {
char env_string[1024+1]; char env_string[1024+1];
PhysPt env_read=PhysMake(psp->GetEnvironment(),0); PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
do { do {
MEM_StrCopy(env_read,env_string,1024); MEM_StrCopy(env_read,env_string,1024);
if (!env_string[0]) break; if (!env_string[0]) break;
if (!num) { result=env_string;return true;} if (!num) { result=env_string;return true;}
env_read += (PhysPt)(strlen(env_string)+1); env_read += (PhysPt)(strlen(env_string)+1);
num--; num--;
} while (1); } while (1);
return false; return false;
} }
Bitu Program::GetEnvCount(void) { Bitu Program::GetEnvCount(void) {
PhysPt env_read=PhysMake(psp->GetEnvironment(),0); PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
Bitu num=0; Bitu num=0;
while (mem_readb(env_read)!=0) { while (mem_readb(env_read)!=0) {
for (;mem_readb(env_read);env_read++) {}; for (;mem_readb(env_read);env_read++) {};
env_read++; env_read++;
num++; num++;
} }
return num; return num;
} }
bool Program::SetEnv(const char * entry,const char * new_string) { bool Program::SetEnv(const char * entry,const char * new_string) {
PhysPt env_read=PhysMake(psp->GetEnvironment(),0); PhysPt env_read=PhysMake(psp->GetEnvironment(),0);
PhysPt env_write=env_read; PhysPt env_write=env_read;
char env_string[1024+1]; char env_string[1024+1];
do { do {
MEM_StrCopy(env_read,env_string,1024); MEM_StrCopy(env_read,env_string,1024);
if (!env_string[0]) break; if (!env_string[0]) break;
env_read += (PhysPt)(strlen(env_string)+1); env_read += (PhysPt)(strlen(env_string)+1);
if (!strchr(env_string,'=')) continue; /* Remove corrupt entry? */ if (!strchr(env_string,'=')) continue; /* Remove corrupt entry? */
if ((strncasecmp(entry,env_string,strlen(entry))==0) && if ((strncasecmp(entry,env_string,strlen(entry))==0) &&
env_string[strlen(entry)]=='=') continue; env_string[strlen(entry)]=='=') continue;
MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1)); MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1));
env_write += (PhysPt)(strlen(env_string)+1); env_write += (PhysPt)(strlen(env_string)+1);
} while (1); } while (1);
/* TODO Maybe save the program name sometime. not really needed though */ /* TODO Maybe save the program name sometime. not really needed though */
/* Save the new entry */ /* Save the new entry */
if (new_string[0]) { if (new_string[0]) {
std::string bigentry(entry); std::string bigentry(entry);
for (std::string::iterator it = bigentry.begin(); it != bigentry.end(); ++it) *it = toupper(*it); for (std::string::iterator it = bigentry.begin(); it != bigentry.end(); ++it) *it = toupper(*it);
sprintf(env_string,"%s=%s",bigentry.c_str(),new_string); sprintf(env_string,"%s=%s",bigentry.c_str(),new_string);
// sprintf(env_string,"%s=%s",entry,new_string); //oldcode // sprintf(env_string,"%s=%s",entry,new_string); //oldcode
MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1)); MEM_BlockWrite(env_write,env_string,(Bitu)(strlen(env_string)+1));
env_write += (PhysPt)(strlen(env_string)+1); env_write += (PhysPt)(strlen(env_string)+1);
} }
/* Clear out the final piece of the environment */ /* Clear out the final piece of the environment */
mem_writed(env_write,0); mem_writed(env_write,0);
return true; return true;
} }
class CONFIG : public Program { class CONFIG : public Program {
public: public:
void Run(void); void Run(void);
}; };
void MSG_Write(const char *); void MSG_Write(const char *);
void CONFIG::Run(void) { void CONFIG::Run(void) {
FILE * f; FILE * f;
if (cmd->FindString("-writeconf",temp_line,true) if (cmd->FindString("-writeconf",temp_line,true)
|| cmd->FindString("-wc",temp_line,true)) { || cmd->FindString("-wc",temp_line,true)) {
/* In secure mode don't allow a new configfile to be created */ /* In secure mode don't allow a new configfile to be created */
if(control->SecureMode()) { if(control->SecureMode()) {
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
return; return;
} }
f=fopen(temp_line.c_str(),"wb+"); f=fopen(temp_line.c_str(),"wb+");
if (!f) { if (!f) {
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str()); WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
return; return;
} }
fclose(f); fclose(f);
control->PrintConfig(temp_line.c_str()); control->PrintConfig(temp_line.c_str());
return; return;
} }
if (cmd->FindString("-writelang",temp_line,true) if (cmd->FindString("-writelang",temp_line,true)
||cmd->FindString("-wl",temp_line,true)) { ||cmd->FindString("-wl",temp_line,true)) {
/* In secure mode don't allow a new languagefile to be created /* In secure mode don't allow a new languagefile to be created
* Who knows which kind of file we would overwriting. */ * Who knows which kind of file we would overwriting. */
if(control->SecureMode()) { if(control->SecureMode()) {
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW")); WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_DISALLOW"));
return; return;
} }
f=fopen(temp_line.c_str(),"wb+"); f=fopen(temp_line.c_str(),"wb+");
if (!f) { if (!f) {
WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str()); WriteOut(MSG_Get("PROGRAM_CONFIG_FILE_ERROR"),temp_line.c_str());
return; return;
} }
fclose(f); fclose(f);
MSG_Write(temp_line.c_str()); MSG_Write(temp_line.c_str());
return; return;
} }
/* Code for switching to secure mode */ /* Code for switching to secure mode */
if(cmd->FindExist("-securemode",true)) { if(cmd->FindExist("-securemode",true)) {
control->SwitchToSecureMode(); control->SwitchToSecureMode();
WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_ON")); WriteOut(MSG_Get("PROGRAM_CONFIG_SECURE_ON"));
return; return;
} }
/* Code for getting the current configuration. * /* Code for getting the current configuration. *
* Official format: config -get "section property" * * Official format: config -get "section property" *
* As a bonus it will set %CONFIG% to this value as well */ * As a bonus it will set %CONFIG% to this value as well */
if(cmd->FindString("-get",temp_line,true)) { if(cmd->FindString("-get",temp_line,true)) {
std::string temp2 = ""; std::string temp2 = "";
cmd->GetStringRemain(temp2);//So -get n1 n2= can be used without quotes cmd->GetStringRemain(temp2);//So -get n1 n2= can be used without quotes
if(temp2 != "") temp_line = temp_line + " " + temp2; if(temp2 != "") temp_line = temp_line + " " + temp2;
std::string::size_type space = temp_line.find(" "); std::string::size_type space = temp_line.find(" ");
if(space == std::string::npos) { if(space == std::string::npos) {
WriteOut(MSG_Get("PROGRAM_CONFIG_GET_SYNTAX")); WriteOut(MSG_Get("PROGRAM_CONFIG_GET_SYNTAX"));
return; return;
} }
//Copy the found property to a new string and erase from templine (mind the space) //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); std::string prop = temp_line.substr(space+1); temp_line.erase(space);
Section* sec = control->GetSection(temp_line.c_str()); Section* sec = control->GetSection(temp_line.c_str());
if(!sec) { if(!sec) {
WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),temp_line.c_str()); WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),temp_line.c_str());
return; return;
} }
std::string val = sec->GetPropValue(prop.c_str()); std::string val = sec->GetPropValue(prop.c_str());
if(val == NO_SUCH_PROPERTY) { if(val == NO_SUCH_PROPERTY) {
WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),prop.c_str(),temp_line.c_str()); WriteOut(MSG_Get("PROGRAM_CONFIG_NO_PROPERTY"),prop.c_str(),temp_line.c_str());
return; return;
} }
WriteOut("%s",val.c_str()); WriteOut("%s",val.c_str());
first_shell->SetEnv("CONFIG",val.c_str()); first_shell->SetEnv("CONFIG",val.c_str());
return; return;
} }
/* Code for the configuration changes * /* Code for the configuration changes *
* Official format: config -set "section property=value" * * Official format: config -set "section property=value" *
* Accepted: without quotes and/or without -set and/or without section * * Accepted: without quotes and/or without -set and/or without section *
* and/or the "=" replaced by a " " */ * and/or the "=" replaced by a " " */
if (cmd->FindString("-set",temp_line,true)) { //get all arguments if (cmd->FindString("-set",temp_line,true)) { //get all arguments
std::string temp2 = ""; std::string temp2 = "";
cmd->GetStringRemain(temp2);//So -set n1 n2=n3 can be used without quotes cmd->GetStringRemain(temp2);//So -set n1 n2=n3 can be used without quotes
if(temp2!="") temp_line = temp_line + " " + temp2; if(temp2!="") temp_line = temp_line + " " + temp2;
} else if(!cmd->GetStringRemain(temp_line)) {//no set } else if(!cmd->GetStringRemain(temp_line)) {//no set
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE")); //and no arguments specified WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE")); //and no arguments specified
return; return;
}; };
//Wanted input: n1 n2=n3 //Wanted input: n1 n2=n3
char copy[1024]; char copy[1024];
strcpy(copy,temp_line.c_str()); strcpy(copy,temp_line.c_str());
//seperate section from property //seperate section from property
const char* temp = strchr(copy,' '); const char* temp = strchr(copy,' ');
if((temp && *temp) || (temp=strchr(copy,'=')) ) copy[temp++ - copy]= 0; if((temp && *temp) || (temp=strchr(copy,'=')) ) copy[temp++ - copy]= 0;
else { else {
WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE")); WriteOut(MSG_Get("PROGRAM_CONFIG_USAGE"));
return; return;
} }
//if n1 n2 n3 then replace last space with = //if n1 n2 n3 then replace last space with =
const char* sign = strchr(temp,'='); const char* sign = strchr(temp,'=');
if(!sign) { if(!sign) {
sign = strchr(temp,' '); sign = strchr(temp,' ');
if(sign) { if(sign) {
copy[sign - copy] = '='; copy[sign - copy] = '=';
} else { } else {
//2 items specified (no space nor = between n2 and n3 //2 items specified (no space nor = between n2 and n3
//assume that they posted: property value //assume that they posted: property value
//Try to determine the section. //Try to determine the section.
Section* sec=control->GetSectionFromProperty(copy); Section* sec=control->GetSectionFromProperty(copy);
if(!sec){ if(!sec){
if(control->GetSectionFromProperty(temp)) return; //Weird situation:ignore if(control->GetSectionFromProperty(temp)) return; //Weird situation:ignore
WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"),copy); WriteOut(MSG_Get("PROGRAM_CONFIG_PROPERTY_ERROR"),copy);
return; return;
} //Hack to allow config ems true } //Hack to allow config ems true
char buffer[1024];strcpy(buffer,copy);strcat(buffer,"=");strcat(buffer,temp); char buffer[1024];strcpy(buffer,copy);strcat(buffer,"=");strcat(buffer,temp);
sign = strchr(buffer,' '); sign = strchr(buffer,' ');
if(sign) buffer[sign - buffer] = '='; if(sign) buffer[sign - buffer] = '=';
strcpy(copy,sec->GetName()); strcpy(copy,sec->GetName());
temp = buffer; temp = buffer;
} }
} }
/* Input processed. Now the real job starts /* Input processed. Now the real job starts
* copy contains the likely "sectionname" * copy contains the likely "sectionname"
* temp contains "property=value" * temp contains "property=value"
* the section is destroyed and a new input line is given to * the section is destroyed and a new input line is given to
* the configuration parser. Then the section is restarted. * the configuration parser. Then the section is restarted.
*/ */
char* inputline = const_cast<char*>(temp); char* inputline = const_cast<char*>(temp);
Section* sec = 0; Section* sec = 0;
sec = control->GetSection(copy); sec = control->GetSection(copy);
if(!sec) { WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),copy);return;} if(!sec) { WriteOut(MSG_Get("PROGRAM_CONFIG_SECTION_ERROR"),copy);return;}
sec->ExecuteDestroy(false); sec->ExecuteDestroy(false);
sec->HandleInputline(inputline); sec->HandleInputline(inputline);
sec->ExecuteInit(false); sec->ExecuteInit(false);
return; return;
} }
static void CONFIG_ProgramStart(Program * * make) { static void CONFIG_ProgramStart(Program * * make) {
*make=new CONFIG; *make=new CONFIG;
} }
void PROGRAMS_Init(Section* /*sec*/) { void PROGRAMS_Init(Section* /*sec*/) {
/* Setup a special callback to start virtual programs */ /* Setup a special callback to start virtual programs */
call_program=CALLBACK_Allocate(); call_program=CALLBACK_Allocate();
CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF,"internal program"); CALLBACK_Setup(call_program,&PROGRAMS_Handler,CB_RETF,"internal program");
PROGRAMS_MakeFile("CONFIG.COM",CONFIG_ProgramStart); PROGRAMS_MakeFile("CONFIG.COM",CONFIG_ProgramStart);
MSG_Add("PROGRAM_CONFIG_FILE_ERROR","Can't open file %s\n"); 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"); 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");
MSG_Add("PROGRAM_CONFIG_SECURE_ON","Switched to secure mode.\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_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_SECTION_ERROR","Section %s doesn't exist.\n");
MSG_Add("PROGRAM_CONFIG_PROPERTY_ERROR","No such section or property.\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_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_GET_SYNTAX","Correct syntax: config -get \"section property\".\n");
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,185 +1,185 @@
/* /*
* Copyright (C) 2002-2009 The DOSBox Team * Copyright (C) 2002-2009 The DOSBox Team
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: support.cpp,v 1.37 2009/05/27 09:15:42 qbix79 Exp $ */ /* $Id: support.cpp,v 1.37 2009-05-27 09:15:42 qbix79 Exp $ */
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <assert.h> #include <assert.h>
#include <ctype.h> #include <ctype.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
#include <string> #include <string>
#include "dosbox.h" #include "dosbox.h"
#include "debug.h" #include "debug.h"
#include "support.h" #include "support.h"
#include "video.h" #include "video.h"
void upcase(std::string &str) { void upcase(std::string &str) {
int (*tf)(int) = std::toupper; int (*tf)(int) = std::toupper;
std::transform(str.begin(), str.end(), str.begin(), tf); std::transform(str.begin(), str.end(), str.begin(), tf);
} }
void lowcase(std::string &str) { void lowcase(std::string &str) {
int (*tf)(int) = std::tolower; int (*tf)(int) = std::tolower;
std::transform(str.begin(), str.end(), str.begin(), tf); std::transform(str.begin(), str.end(), str.begin(), tf);
} }
/* /*
Ripped some source from freedos for this one. Ripped some source from freedos for this one.
*/ */
/* /*
* replaces all instances of character o with character c * replaces all instances of character o with character c
*/ */
void strreplace(char * str,char o,char n) { void strreplace(char * str,char o,char n) {
while (*str) { while (*str) {
if (*str==o) *str=n; if (*str==o) *str=n;
str++; str++;
} }
} }
char *ltrim(char *str) { char *ltrim(char *str) {
while (*str && isspace(*reinterpret_cast<unsigned char*>(str))) str++; while (*str && isspace(*reinterpret_cast<unsigned char*>(str))) str++;
return str; return str;
} }
char *rtrim(char *str) { char *rtrim(char *str) {
char *p; char *p;
p = strchr(str, '\0'); p = strchr(str, '\0');
while (--p >= str && isspace(*reinterpret_cast<unsigned char*>(p))) {}; while (--p >= str && isspace(*reinterpret_cast<unsigned char*>(p))) {};
p[1] = '\0'; p[1] = '\0';
return str; return str;
} }
char *trim(char *str) { char *trim(char *str) {
return ltrim(rtrim(str)); return ltrim(rtrim(str));
} }
char * upcase(char * str) { char * upcase(char * str) {
for (char* idx = str; *idx ; idx++) *idx = toupper(*reinterpret_cast<unsigned char*>(idx)); for (char* idx = str; *idx ; idx++) *idx = toupper(*reinterpret_cast<unsigned char*>(idx));
return str; return str;
} }
char * lowcase(char * str) { char * lowcase(char * str) {
for(char* idx = str; *idx ; idx++) *idx = tolower(*reinterpret_cast<unsigned char*>(idx)); for(char* idx = str; *idx ; idx++) *idx = tolower(*reinterpret_cast<unsigned char*>(idx));
return str; return str;
} }
bool ScanCMDBool(char * cmd,char const * const check) { bool ScanCMDBool(char * cmd,char const * const check) {
char * scan=cmd;size_t c_len=strlen(check); char * scan=cmd;size_t c_len=strlen(check);
while ((scan=strchr(scan,'/'))) { while ((scan=strchr(scan,'/'))) {
/* found a / now see behind it */ /* found a / now see behind it */
scan++; scan++;
if (strncasecmp(scan,check,c_len)==0 && (scan[c_len]==' ' || scan[c_len]=='\t' || scan[c_len]=='/' || scan[c_len]==0)) { if (strncasecmp(scan,check,c_len)==0 && (scan[c_len]==' ' || scan[c_len]=='\t' || scan[c_len]=='/' || scan[c_len]==0)) {
/* Found a math now remove it from the string */ /* Found a math now remove it from the string */
memmove(scan-1,scan+c_len,strlen(scan+c_len)+1); memmove(scan-1,scan+c_len,strlen(scan+c_len)+1);
trim(scan-1); trim(scan-1);
return true; return true;
} }
} }
return false; return false;
} }
/* This scans the command line for a remaining switch and reports it else returns 0*/ /* This scans the command line for a remaining switch and reports it else returns 0*/
char * ScanCMDRemain(char * cmd) { char * ScanCMDRemain(char * cmd) {
char * scan,*found;; char * scan,*found;;
if ((scan=found=strchr(cmd,'/'))) { if ((scan=found=strchr(cmd,'/'))) {
while ( *scan && !isspace(*reinterpret_cast<unsigned char*>(scan)) ) scan++; while ( *scan && !isspace(*reinterpret_cast<unsigned char*>(scan)) ) scan++;
*scan=0; *scan=0;
return found; return found;
} else return 0; } else return 0;
} }
char * StripWord(char *&line) { char * StripWord(char *&line) {
char * scan=line; char * scan=line;
scan=ltrim(scan); scan=ltrim(scan);
if (*scan=='"') { if (*scan=='"') {
char * end_quote=strchr(scan+1,'"'); char * end_quote=strchr(scan+1,'"');
if (end_quote) { if (end_quote) {
*end_quote=0; *end_quote=0;
line=ltrim(++end_quote); line=ltrim(++end_quote);
return (scan+1); return (scan+1);
} }
} }
char * begin=scan; char * begin=scan;
for (char c = *scan ;(c = *scan);scan++) { for (char c = *scan ;(c = *scan);scan++) {
if (isspace(*reinterpret_cast<unsigned char*>(&c))) { if (isspace(*reinterpret_cast<unsigned char*>(&c))) {
*scan++=0; *scan++=0;
break; break;
} }
} }
line=scan; line=scan;
return begin; return begin;
} }
Bits ConvDecWord(char * word) { Bits ConvDecWord(char * word) {
bool negative=false;Bitu ret=0; bool negative=false;Bitu ret=0;
if (*word=='-') { if (*word=='-') {
negative=true; negative=true;
word++; word++;
} }
while (char c=*word) { while (char c=*word) {
ret*=10; ret*=10;
ret+=c-'0'; ret+=c-'0';
word++; word++;
} }
if (negative) return 0-ret; if (negative) return 0-ret;
else return ret; else return ret;
} }
Bits ConvHexWord(char * word) { Bits ConvHexWord(char * word) {
Bitu ret=0; Bitu ret=0;
while (char c=toupper(*reinterpret_cast<unsigned char*>(word))) { while (char c=toupper(*reinterpret_cast<unsigned char*>(word))) {
ret*=16; ret*=16;
if (c>='0' && c<='9') ret+=c-'0'; if (c>='0' && c<='9') ret+=c-'0';
else if (c>='A' && c<='F') ret+=10+(c-'A'); else if (c>='A' && c<='F') ret+=10+(c-'A');
word++; word++;
} }
return ret; return ret;
} }
double ConvDblWord(char * word) { double ConvDblWord(char * word) {
return 0.0f; return 0.0f;
} }
static char buf[1024]; //greater scope as else it doesn't always gets thrown right (linux/gcc2.95) static char buf[1024]; //greater scope as else it doesn't always gets thrown right (linux/gcc2.95)
void E_Exit(const char * format,...) { void E_Exit(const char * format,...) {
#if C_DEBUG && C_HEAVY_DEBUG #if C_DEBUG && C_HEAVY_DEBUG
DEBUG_HeavyWriteLogInstruction(); DEBUG_HeavyWriteLogInstruction();
#endif #endif
va_list msg; va_list msg;
va_start(msg,format); va_start(msg,format);
vsprintf(buf,format,msg); vsprintf(buf,format,msg);
va_end(msg); va_end(msg);
strcat(buf,"\n"); strcat(buf,"\n");
throw(buf); throw(buf);
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,202 +1,202 @@
/* /*
* Copyright (C) 2002-2009 The DOSBox Team * Copyright (C) 2002-2009 The DOSBox Team
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
/* $Id: shell_batch.cpp,v 1.36 2009/07/03 19:36:56 qbix79 Exp $ */ /* $Id: shell_batch.cpp,v 1.36 2009-07-03 19:36:56 qbix79 Exp $ */
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "shell.h" #include "shell.h"
#include "support.h" #include "support.h"
BatchFile::BatchFile(DOS_Shell * host,char const * const name, char const * const cmd_line) { BatchFile::BatchFile(DOS_Shell * host,char const * const name, char const * const cmd_line) {
location = 0; location = 0;
prev=host->bf; prev=host->bf;
echo=host->echo; echo=host->echo;
shell=host; shell=host;
char totalname[DOS_PATHLENGTH+4]; char totalname[DOS_PATHLENGTH+4];
DOS_Canonicalize(name,totalname); // Get fullname including drive specificiation DOS_Canonicalize(name,totalname); // Get fullname including drive specificiation
cmd = new CommandLine(totalname,cmd_line); cmd = new CommandLine(totalname,cmd_line);
filename = totalname; filename = totalname;
//Test if file is openable //Test if file is openable
if (!DOS_OpenFile(totalname,128,&file_handle)) { if (!DOS_OpenFile(totalname,128,&file_handle)) {
//TODO Come up with something better //TODO Come up with something better
E_Exit("SHELL:Can't open BatchFile %s",totalname); E_Exit("SHELL:Can't open BatchFile %s",totalname);
} }
DOS_CloseFile(file_handle); DOS_CloseFile(file_handle);
} }
BatchFile::~BatchFile() { BatchFile::~BatchFile() {
delete cmd; delete cmd;
shell->bf=prev; shell->bf=prev;
shell->echo=echo; shell->echo=echo;
} }
bool BatchFile::ReadLine(char * line) { bool BatchFile::ReadLine(char * line) {
//Open the batchfile and seek to stored postion //Open the batchfile and seek to stored postion
if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) { if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) {
LOG(LOG_MISC,LOG_ERROR)("ReadLine Can't open BatchFile %s",filename.c_str()); LOG(LOG_MISC,LOG_ERROR)("ReadLine Can't open BatchFile %s",filename.c_str());
delete this; delete this;
return false; return false;
} }
DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_SET); DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_SET);
Bit8u c=0;Bit16u n=1; Bit8u c=0;Bit16u n=1;
char temp[CMD_MAXLINE]; char temp[CMD_MAXLINE];
emptyline: emptyline:
char * cmd_write=temp; char * cmd_write=temp;
do { do {
n=1; n=1;
DOS_ReadFile(file_handle,&c,&n); DOS_ReadFile(file_handle,&c,&n);
if (n>0) { if (n>0) {
/* Why are we filtering this ? /* Why are we filtering this ?
* Exclusion list: tab for batch files * Exclusion list: tab for batch files
* escape for ansi * escape for ansi
* backspace for alien odyssey */ * backspace for alien odyssey */
if (c>31 || c==0x1b || c=='\t' || c==8) if (c>31 || c==0x1b || c=='\t' || c==8)
*cmd_write++=c; *cmd_write++=c;
} }
} while (c!='\n' && n); } while (c!='\n' && n);
*cmd_write=0; *cmd_write=0;
if (!n && cmd_write==temp) { if (!n && cmd_write==temp) {
//Close file and delete bat file //Close file and delete bat file
DOS_CloseFile(file_handle); DOS_CloseFile(file_handle);
delete this; delete this;
return false; return false;
} }
if (!strlen(temp)) goto emptyline; if (!strlen(temp)) goto emptyline;
if (temp[0]==':') goto emptyline; if (temp[0]==':') goto emptyline;
/* Now parse the line read from the bat file for % stuff */ /* Now parse the line read from the bat file for % stuff */
cmd_write=line; cmd_write=line;
char * cmd_read=temp; char * cmd_read=temp;
char env_name[256];char * env_write; char env_name[256];char * env_write;
while (*cmd_read) { while (*cmd_read) {
env_write=env_name; env_write=env_name;
if (*cmd_read=='%') { if (*cmd_read=='%') {
cmd_read++; cmd_read++;
if (cmd_read[0] == '%') { if (cmd_read[0] == '%') {
cmd_read++; cmd_read++;
*cmd_write++='%'; *cmd_write++='%';
continue; continue;
} }
if (cmd_read[0] == '0') { /* Handle %0 */ if (cmd_read[0] == '0') { /* Handle %0 */
const char *file_name = cmd->GetFileName(); const char *file_name = cmd->GetFileName();
cmd_read++; cmd_read++;
strcpy(cmd_write,file_name); strcpy(cmd_write,file_name);
cmd_write+=strlen(file_name); cmd_write+=strlen(file_name);
continue; continue;
} }
char next = cmd_read[0]; char next = cmd_read[0];
if(next > '0' && next <= '9') { if(next > '0' && next <= '9') {
/* Handle %1 %2 .. %9 */ /* Handle %1 %2 .. %9 */
cmd_read++; //Progress reader cmd_read++; //Progress reader
next -= '0'; next -= '0';
if (cmd->GetCount()<(unsigned int)next) continue; if (cmd->GetCount()<(unsigned int)next) continue;
std::string word; std::string word;
if (!cmd->FindCommand(next,word)) continue; if (!cmd->FindCommand(next,word)) continue;
strcpy(cmd_write,word.c_str()); strcpy(cmd_write,word.c_str());
cmd_write+=strlen(word.c_str()); cmd_write+=strlen(word.c_str());
continue; continue;
} else { } else {
/* Not a command line number has to be an environment */ /* Not a command line number has to be an environment */
char * first=strchr(cmd_read,'%'); char * first=strchr(cmd_read,'%');
/* No env afterall.Somewhat of a hack though as %% and % aren't handled consistent in dosbox. Maybe echo needs to parse % and %% as well. */ /* No env afterall.Somewhat of a hack though as %% and % aren't handled consistent in dosbox. Maybe echo needs to parse % and %% as well. */
if (!first) {*cmd_write++ = '%';continue;} if (!first) {*cmd_write++ = '%';continue;}
*first++ = 0; *first++ = 0;
std::string env; std::string env;
if (shell->GetEnvStr(cmd_read,env)) { if (shell->GetEnvStr(cmd_read,env)) {
const char * equals=strchr(env.c_str(),'='); const char * equals=strchr(env.c_str(),'=');
if (!equals) continue; if (!equals) continue;
equals++; equals++;
strcpy(cmd_write,equals); strcpy(cmd_write,equals);
cmd_write+=strlen(equals); cmd_write+=strlen(equals);
} }
cmd_read=first; cmd_read=first;
} }
} else { } else {
*cmd_write++=*cmd_read++; *cmd_write++=*cmd_read++;
} }
} }
*cmd_write=0; *cmd_write=0;
//Store current location and close bat file //Store current location and close bat file
this->location = 0; this->location = 0;
DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR); DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR);
DOS_CloseFile(file_handle); DOS_CloseFile(file_handle);
return true; return true;
} }
bool BatchFile::Goto(char * where) { bool BatchFile::Goto(char * where) {
//Open bat file and search for the where string //Open bat file and search for the where string
if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) { if (!DOS_OpenFile(filename.c_str(),128,&file_handle)) {
LOG(LOG_MISC,LOG_ERROR)("SHELL:Goto Can't open BatchFile %s",filename.c_str()); LOG(LOG_MISC,LOG_ERROR)("SHELL:Goto Can't open BatchFile %s",filename.c_str());
delete this; delete this;
return false; return false;
} }
char cmd_buffer[CMD_MAXLINE]; char cmd_buffer[CMD_MAXLINE];
char * cmd_write; char * cmd_write;
/* Scan till we have a match or return false */ /* Scan till we have a match or return false */
Bit8u c;Bit16u n; Bit8u c;Bit16u n;
again: again:
cmd_write=cmd_buffer; cmd_write=cmd_buffer;
do { do {
n=1; n=1;
DOS_ReadFile(file_handle,&c,&n); DOS_ReadFile(file_handle,&c,&n);
if (n>0) { if (n>0) {
if (c>31) if (c>31)
*cmd_write++=c; *cmd_write++=c;
} }
} while (c!='\n' && n); } while (c!='\n' && n);
*cmd_write++ = 0; *cmd_write++ = 0;
char *nospace = trim(cmd_buffer); char *nospace = trim(cmd_buffer);
if (nospace[0] == ':') { if (nospace[0] == ':') {
nospace++; //Skip : nospace++; //Skip :
//Strip spaces and = from it. //Strip spaces and = from it.
while(*nospace && (isspace(*reinterpret_cast<unsigned char*>(nospace)) || (*nospace == '='))) while(*nospace && (isspace(*reinterpret_cast<unsigned char*>(nospace)) || (*nospace == '=')))
nospace++; nospace++;
//label is until space/=/eol //label is until space/=/eol
char* const beginlabel = nospace; char* const beginlabel = nospace;
while(*nospace && !isspace(*reinterpret_cast<unsigned char*>(nospace)) && (*nospace != '=')) while(*nospace && !isspace(*reinterpret_cast<unsigned char*>(nospace)) && (*nospace != '='))
nospace++; nospace++;
*nospace = 0; *nospace = 0;
if (strcasecmp(beginlabel,where)==0) { if (strcasecmp(beginlabel,where)==0) {
//Found it! Store location and continue //Found it! Store location and continue
this->location = 0; this->location = 0;
DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR); DOS_SeekFile(file_handle,&(this->location),DOS_SEEK_CUR);
DOS_CloseFile(file_handle); DOS_CloseFile(file_handle);
return true; return true;
} }
} }
if (!n) { if (!n) {
DOS_CloseFile(file_handle); DOS_CloseFile(file_handle);
delete this; delete this;
return false; return false;
} }
goto again; goto again;
return false; return false;
} }
void BatchFile::Shift(void) { void BatchFile::Shift(void) {
cmd->Shift(1); cmd->Shift(1);
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff