📄 osutils.cxx
字号:
for (;;) {
while (isspace(*str)) // Skip leading whitespace
str++;
if (*str == '\0')
break;
PString & arg = argumentArray[argumentArray.GetSize()];
while (*str != '\0' && !isspace(*str)) {
switch (*str) {
case '"' :
str++;
while (*str != '\0' && *str != '"')
arg += *str++;
if (*str != '\0')
str++;
break;
case '\'' :
str++;
while (*str != '\0' && *str != '\'')
arg += *str++;
if (*str != '\0')
str++;
break;
default :
if (str[0] == '\\' && str[1] != '\0')
str++;
arg += *str++;
}
}
}
SetArgs(argumentArray);
}
void PArgList::SetArgs(const PStringArray & theArgs)
{
argumentArray = theArgs;
shift = 0;
optionLetters = "";
optionNames.SetSize(0);
parameterIndex.SetSize(argumentArray.GetSize());
for (PINDEX i = 0; i < argumentArray.GetSize(); i++)
parameterIndex[i] = i;
}
BOOL PArgList::Parse(const char * spec, BOOL optionsBeforeParams)
{
PAssertNULL(spec);
// Find starting point, start at shift if first Parse() call.
PINDEX arg = optionLetters.IsEmpty() ? shift : 0;
// If not in parse all mode, have been parsed before, and had some parameters
// from last time, then start argument parsing somewhere along instead of start.
if (optionsBeforeParams && !optionLetters && parameterIndex.GetSize() > 0)
arg = parameterIndex[parameterIndex.GetSize()-1] + 1;
// Parse the option specification
optionLetters = "";
optionNames.SetSize(0);
PIntArray canHaveOptionString;
PINDEX codeCount = 0;
while (*spec != '\0') {
if (*spec == '-')
optionLetters += ' ';
else
optionLetters += *spec++;
if (*spec == '-') {
const char * base = ++spec;
while (*spec != '\0' && *spec != '.' && *spec != ':' && *spec != ';')
spec++;
optionNames[codeCount] = PString(base, spec-base);
if (*spec == '.')
spec++;
}
if (*spec == ':' || *spec == ';') {
canHaveOptionString.SetSize(codeCount+1);
canHaveOptionString[codeCount] = *spec == ':' ? 2 : 1;
spec++;
}
codeCount++;
}
// Clear and reset size of option information
optionCount.SetSize(0);
optionCount.SetSize(codeCount);
optionString.SetSize(0);
optionString.SetSize(codeCount);
// Clear parameter indexes
parameterIndex.SetSize(0);
shift = 0;
// Now work through the arguments and split out the options
PINDEX param = 0;
BOOL hadMinusMinus = FALSE;
while (arg < argumentArray.GetSize()) {
const PString & argStr = argumentArray[arg];
if (hadMinusMinus || argStr[0] != '-' || argStr[1] == '\0') {
// have a parameter string
parameterIndex.SetSize(param+1);
parameterIndex[param++] = arg;
}
else if (optionsBeforeParams && parameterIndex.GetSize() > 0)
break;
else if (argStr == "--") // ALL remaining args are parameters not options
hadMinusMinus = TRUE;
else if (argStr[1] == '-')
ParseOption(optionNames.GetValuesIndex(argStr.Mid(2)), 0, arg, canHaveOptionString);
else {
for (PINDEX i = 1; i < argStr.GetLength(); i++)
if (ParseOption(optionLetters.Find(argStr[i]), i+1, arg, canHaveOptionString))
break;
}
arg++;
}
return param > 0;
}
BOOL PArgList::ParseOption(PINDEX idx, PINDEX offset, PINDEX & arg,
const PIntArray & canHaveOptionString)
{
if (idx == P_MAX_INDEX) {
UnknownOption(argumentArray[arg]);
return FALSE;
}
optionCount[idx]++;
if (canHaveOptionString[idx] == 0)
return FALSE;
if (!optionString[idx])
optionString[idx] += '\n';
if (offset != 0 &&
(canHaveOptionString[idx] == 1 || argumentArray[arg][offset] != '\0')) {
optionString[idx] += argumentArray[arg].Mid(offset);
return TRUE;
}
if (++arg >= argumentArray.GetSize())
return FALSE;
optionString[idx] += argumentArray[arg];
return TRUE;
}
PINDEX PArgList::GetOptionCount(char option) const
{
return GetOptionCountByIndex(optionLetters.Find(option));
}
PINDEX PArgList::GetOptionCount(const char * option) const
{
return GetOptionCountByIndex(optionNames.GetValuesIndex(PString(option)));
}
PINDEX PArgList::GetOptionCount(const PString & option) const
{
return GetOptionCountByIndex(optionNames.GetValuesIndex(option));
}
PINDEX PArgList::GetOptionCountByIndex(PINDEX idx) const
{
if (idx < optionCount.GetSize())
return optionCount[idx];
return 0;
}
PString PArgList::GetOptionString(char option, const char * dflt) const
{
return GetOptionStringByIndex(optionLetters.Find(option), dflt);
}
PString PArgList::GetOptionString(const char * option, const char * dflt) const
{
return GetOptionStringByIndex(optionNames.GetValuesIndex(PString(option)), dflt);
}
PString PArgList::GetOptionString(const PString & option, const char * dflt) const
{
return GetOptionStringByIndex(optionNames.GetValuesIndex(option), dflt);
}
PString PArgList::GetOptionStringByIndex(PINDEX idx, const char * dflt) const
{
if (idx < optionString.GetSize() && optionString.GetAt(idx) != NULL)
return optionString[idx];
if (dflt != NULL)
return dflt;
return PString();
}
PString PArgList::GetParameter(PINDEX num) const
{
int idx = shift+(int)num;
if (idx >= 0 && idx < (int)parameterIndex.GetSize())
return argumentArray[parameterIndex[idx]];
IllegalArgumentIndex(idx);
return PString();
}
void PArgList::Shift(int sh)
{
shift += sh;
if (shift < 0)
shift = 0;
else if (shift >= (int)parameterIndex.GetSize())
shift = parameterIndex.GetSize() - 1;
}
void PArgList::IllegalArgumentIndex(PINDEX idx) const
{
PError << "attempt to access undefined argument at index "
<< idx << endl;
}
void PArgList::UnknownOption(const PString & option) const
{
PError << "unknown option \"" << option << "\"\n";
}
void PArgList::MissingArgument(const PString & option) const
{
PError << "option \"" << option << "\" requires argument\n";
}
///////////////////////////////////////////////////////////////////////////////
// PConfigArgs
PConfigArgs::PConfigArgs(const PArgList & args)
: PArgList(args),
sectionName(config.GetDefaultSection()),
negationPrefix("no-")
{
}
PINDEX PConfigArgs::GetOptionCount(char option) const
{
PINDEX count;
if ((count = PArgList::GetOptionCount(option)) > 0)
return count;
PString stropt = CharToString(option);
if (stropt.IsEmpty())
return 0;
return GetOptionCount(stropt);
}
PINDEX PConfigArgs::GetOptionCount(const char * option) const
{
return GetOptionCount(PString(option));
}
PINDEX PConfigArgs::GetOptionCount(const PString & option) const
{
// if specified on the command line, use that option
PINDEX count = PArgList::GetOptionCount(option);
if (count > 0)
return count;
// if user has specified "no-option", then ignore config file
if (PArgList::GetOptionCount(negationPrefix + option) > 0)
return 0;
return config.HasKey(sectionName, option) ? 1 : 0;
}
PString PConfigArgs::GetOptionString(char option, const char * dflt) const
{
if (PArgList::GetOptionCount(option) > 0)
return PArgList::GetOptionString(option, dflt);
PString stropt = CharToString(option);
if (stropt.IsEmpty()) {
if (dflt != NULL)
return dflt;
return PString();
}
return GetOptionString(stropt, dflt);
}
PString PConfigArgs::GetOptionString(const char * option, const char * dflt) const
{
return GetOptionString(PString(option), dflt);
}
PString PConfigArgs::GetOptionString(const PString & option, const char * dflt) const
{
// if specified on the command line, use that option
if (PArgList::GetOptionCount(option) > 0)
return PArgList::GetOptionString(option, dflt);
// if user has specified "no-option", then ignore config file
if (PArgList::HasOption(negationPrefix + option)) {
if (dflt != NULL)
return dflt;
return PString();
}
return config.GetString(sectionName, option, dflt != NULL ? dflt : "");
}
void PConfigArgs::Save(const PString & saveOptionName)
{
if (PArgList::GetOptionCount(saveOptionName) == 0)
return;
config.DeleteSection(sectionName);
for (PINDEX i = 0; i < optionCount.GetSize(); i++) {
PString optionName = optionNames[i];
if (optionCount[i] > 0 && optionName != saveOptionName) {
if (optionString.GetAt(i) != NULL)
config.SetString(sectionName, optionName, optionString[i]);
else
config.SetBoolean(sectionName, optionName, TRUE);
}
}
}
PString PConfigArgs::CharToString(char ch) const
{
PINDEX index = optionLetters.Find(ch);
if (index == P_MAX_INDEX)
return PString();
if (optionNames.GetAt(index) == NULL)
return PString();
return optionNames[index];
}
///////////////////////////////////////////////////////////////////////////////
// PProcess
static PProcess * PProcessInstance;
int PProcess::p_argc;
char ** PProcess::p_argv;
char ** PProcess::p_envp;
#ifndef P_PLATFORM_HAS_THREADS
static BOOL PProcessTerminating = FALSE;
#endif
PProcess::PProcess(const char * manuf, const char * name,
WORD major, WORD minor, CodeStatus stat, WORD build)
: manufacturer(manuf), productName(name)
{
PProcessInstance = this;
terminationValue = 0;
majorVersion = major;
minorVersion = minor;
status = stat;
buildNumber = build;
if (p_argv != 0 && p_argc > 0) {
arguments.SetArgs(p_argc-1, p_argv+1);
executableFile = PString(p_argv[0]);
if (!PFile::Exists(executableFile))
executableFile += ".exe";
if (productName.IsEmpty())
productName = executableFile.GetTitle().ToLower();
}
InitialiseProcessThread();
Construct();
}
int PProcess::_main(void *)
{
Main();
return terminationValue;
}
void PProcess::PreInitialise(int c, char ** v, char ** e)
{
#if PMEMORY_CHECK
PMemoryHeap::SetIgnoreAllocations(FALSE);
#endif
p_argc = c;
p_argv = v;
p_envp = e;
}
PProcess & PProcess::Current()
{
if (PProcessInstance == NULL) {
cerr << "Catastrophic failure, PProcess::Current() = NULL!!\n";
#if defined(_MSC_VER) && defined(_DEBUG) && !defined(_WIN32_WCE)
__asm int 3;
#endif
_exit(1);
}
return *PProcessInstance;
}
BOOL PProcess::IsInitialised()
{
return PProcessInstance != NULL;
}
PObject::Comparison PProcess::Compare(const PObject & obj) const
{
PAssert(obj.IsDescendant(PProcess::Class()), PInvalidCast);
return productName.Compare(((const PProcess &)obj).productName);
}
void PProcess::Terminate()
{
#ifdef _WINDLL
FatalExit(terminationValue);
#else
#ifndef P_PLATFORM_HAS_THREADS
// Can only terminate process from the processes thread
if (currentThread == this)
exit(terminationValue);
else
PProcessTerminating = TRUE;
#else
exit(terminationValue);
#endif
#endif
}
PString PProcess::GetThreadName() const
{
return GetName();
}
void PProcess::SetThreadName(const PString & /*name*/)
{
}
PString PProcess::GetVersion(BOOL full) const
{
const char * const statusLetter[NumCodeStatuses] =
{ "alpha", "beta", "." };
return psprintf(full ? "%u.%u%s%u" : "%u.%u",
majorVersion, minorVersion, statusLetter[status], buildNumber);
}
void PProcess::SetConfigurationPath(const PString & path)
{
configurationPaths = path.Tokenise(";:", FALSE);
}
///////////////////////////////////////////////////////////////////////////////
// PThread
void PThread::PrintOn(ostream & strm) const
{
strm << GetThreadName();
}
PString PThread::GetThreadName() const
{
return threadName;
}
void PThread::SetThreadName(const PString & name)
{
if (name.IsEmpty())
threadName = psprintf("%s:%08x", GetClass(), (INT)this);
else
threadName = psprintf(name, (INT)this);
}
PThread * PThread::Create(const PNotifier & notifier,
INT parameter,
AutoDeleteFlag deletion,
Priority priorityLevel,
const PString & threadName,
PINDEX stackSize)
{
return new PSimpleThread(notifier, parameter, deletion, priorityLevel, threadName, stackSize);
}
PSimpleThread::PSimpleThread(const PNotifier & notifier,
INT param,
AutoDeleteFlag deletion,
Priority priorityLevel,
const PString & threadName,
PINDEX stackSize)
: PThread(stackSize, deletion, priorityLevel, threadName),
callback(notifier),
parameter(param)
{
Resume();
}
void PSimpleThread::Main()
{
callback(*this, parameter);
}
#ifndef P_PLATFORM_HAS_THREADS
void PThread::InitialiseProcessThread()
{
basePriority = NormalPriority; // User settable priority
dynamicPriority = 0; // Only thing running
suspendCount = 0; // Not suspended (would not be a good idea)
ClearBlock(); // No I/O blocking function
status = Running; // Thread is already running
stackBase = NULL;
link = this;
((PProcess*)this)->currentThread = this;
}
PThread::PThread(PINDEX stackSize,
AutoDeleteFlag deletion,
Priority priorityLevel,
const PString & name)
: threadName(name)
{
autoDelete = deletion == AutoDeleteThread;
basePriority = priorityLevel; // Threads user settable priority level
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -