📄 osutils.cxx
字号:
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";
}
///////////////////////////////////////////////////////////////////////////////
// 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)
{
p_argc = c;
p_argv = v;
p_envp = e;
}
PProcess & PProcess::Current()
{
PAssertNULL(PProcessInstance);
return *PProcessInstance;
}
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::GetVersion(BOOL full) const
{
const char * const statusLetter[NumCodeStatuses] =
{ "alpha", "beta", "pl" };
return psprintf(full && buildNumber != 0 ? "%u.%u%s%u" : "%u.%u",
majorVersion, minorVersion, statusLetter[status], buildNumber);
}
///////////////////////////////////////////////////////////////////////////////
// PThread
#ifndef P_PLATFORM_HAS_THREADS
void PThread::InitialiseProcessThread()
{
// changed from normal to high priority
basePriority = HighPriority; // 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)
{
autoDelete = deletion == AutoDeleteThread;
basePriority = priorityLevel; // Threads user settable priority level
dynamicPriority = 0; // Run immediately
suspendCount = 1;
AllocateStack(stackSize);
PAssert(stackBase != NULL, "Insufficient near heap for thread");
status = Terminated; // Set to this so Restart() works
Restart();
}
void PThread::Restart()
{
if (status != Terminated) // Is already running
return;
ClearBlock(); // No I/O blocking function
PThread * current = Current();
link = current->link;
current->link = this;
status = Starting;
}
void PThread::Terminate()
{
if (link == this || status == Terminated)
return; // Is only thread or already terminated
if (status == Running) {
status = Terminating;
Yield(); // Never returns from here
}
PThread * prev = PThread::Current();
while (prev->link != this)
prev = prev->link;
prev->link = link; // Unlink it from the list
status = Terminated;
}
void PThread::WaitForTermination() const
{
while (!IsTerminated())
Yield();
}
BOOL PThread::WaitForTermination(const PTimeInterval & maxWait) const
{
PTimer timeout = maxWait;
while (!IsTerminated()) {
if (timeout == 0)
return FALSE;
Yield();
}
return TRUE;
}
void PThread::Suspend(BOOL susp)
{
// Suspend/Resume the thread
if (susp)
suspendCount++;
else
suspendCount--;
switch (status) {
case Running : // Suspending itself, yield to next thread
if (IsSuspended()) {
status = Suspended;
Yield();
}
break;
case Waiting :
if (IsSuspended())
status = Suspended;
break;
case BlockedIO :
if (IsSuspended())
status = SuspendedBlockIO;
break;
case BlockedSem :
if (IsSuspended())
status = SuspendedBlockSem;
break;
case Suspended :
if (!IsSuspended())
status = Waiting;
break;
case SuspendedBlockIO :
if (!IsSuspended())
status = BlockedIO;
break;
case SuspendedBlockSem :
if (!IsSuspended())
status = BlockedSem;
break;
default :
break;
}
}
void PThread::Sleep(const PTimeInterval & time)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -