Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
435
cde/programs/nsgmls/CmdLineApp.C
Normal file
435
cde/programs/nsgmls/CmdLineApp.C
Normal file
@@ -0,0 +1,435 @@
|
||||
/* $XConsortium: CmdLineApp.C /main/2 1996/08/12 12:36:14 mgreess $ */
|
||||
// Copyright (c) 1996 James Clark
|
||||
// See the file COPYING for copying permission.
|
||||
|
||||
// Need option registration method that allows derived class to change
|
||||
// option names.
|
||||
|
||||
#ifdef __GNUG__
|
||||
#pragma implementation
|
||||
#endif
|
||||
|
||||
#include "splib.h"
|
||||
#include "CmdLineApp.h"
|
||||
#include "CmdLineAppMessages.h"
|
||||
#include "MessageArg.h"
|
||||
#include "ErrnoMessageArg.h"
|
||||
#include "Options.h"
|
||||
#include "version.h"
|
||||
#include "xnew.h"
|
||||
#include "macros.h"
|
||||
#include "sptchar.h"
|
||||
#include "MessageTable.h"
|
||||
|
||||
#ifdef SP_MULTI_BYTE
|
||||
#include "UTF8CodingSystem.h"
|
||||
#include "Fixed2CodingSystem.h"
|
||||
#include "UnicodeCodingSystem.h"
|
||||
#include "EUCJPCodingSystem.h"
|
||||
#include "SJISCodingSystem.h"
|
||||
#include "ISO8859InputCodingSystem.h"
|
||||
#ifdef WIN32
|
||||
#include "Win32CodingSystem.h"
|
||||
#endif
|
||||
#endif /* SP_MULTI_BYTE */
|
||||
#include "IdentityCodingSystem.h"
|
||||
|
||||
#include "ConsoleOutput.h"
|
||||
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef SP_HAVE_LOCALE
|
||||
#include <locale.h>
|
||||
#endif
|
||||
#ifdef SP_HAVE_SETMODE
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#endif
|
||||
#ifdef SP_HAVE_SETMODE
|
||||
#define IOS_BINARY ios::binary
|
||||
#else
|
||||
#define IOS_BINARY 0
|
||||
#endif
|
||||
#ifdef SP_WIDE_SYSTEM
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#else /* not SP_WIDE_SYSTEM */
|
||||
|
||||
#include <sys/types.h>
|
||||
#ifdef SP_INCLUDE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef SP_INCLUDE_IO_H
|
||||
#include <io.h>
|
||||
#endif
|
||||
|
||||
#endif /* not SP_WIDE_SYSTEM */
|
||||
|
||||
#ifdef SP_NAMESPACE
|
||||
namespace SP_NAMESPACE {
|
||||
#endif
|
||||
|
||||
#ifdef SP_MULTI_BYTE
|
||||
static UTF8CodingSystem utf8CodingSystem;
|
||||
static Fixed2CodingSystem fixed2CodingSystem;
|
||||
static UnicodeCodingSystem unicodeCodingSystem;
|
||||
static EUCJPCodingSystem eucjpCodingSystem;
|
||||
static SJISCodingSystem sjisCodingSystem;
|
||||
#ifdef WIN32
|
||||
static Win32CodingSystem ansiCodingSystem(Win32CodingSystem::codePageAnsi);
|
||||
static Win32CodingSystem oemCodingSystem(Win32CodingSystem::codePageOEM);
|
||||
static UnicodeCodingSystem maybeUnicodeCodingSystem(&ansiCodingSystem);
|
||||
#endif
|
||||
#endif /* SP_MULTI_BYTE */
|
||||
static IdentityCodingSystem identityCodingSystem;
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
const CodingSystem *cs;
|
||||
} codingSystems[] = {
|
||||
#ifdef SP_MULTI_BYTE
|
||||
{ "UTF-8", &utf8CodingSystem },
|
||||
{ "FIXED-2", &fixed2CodingSystem },
|
||||
{ "UNICODE", &unicodeCodingSystem },
|
||||
{ "EUC-JP", &eucjpCodingSystem },
|
||||
{ "SJIS", &sjisCodingSystem },
|
||||
#ifdef WIN32
|
||||
{ "WINDOWS", &ansiCodingSystem },
|
||||
{ "MS-DOS", &oemCodingSystem },
|
||||
{ "WUNICODE", &maybeUnicodeCodingSystem },
|
||||
#endif
|
||||
#endif /* SP_MULTI_BYTE */
|
||||
{ "IS8859-1", &identityCodingSystem },
|
||||
{ "IDENTITY", &identityCodingSystem },
|
||||
};
|
||||
|
||||
const CodingSystem *CmdLineApp::codingSystem_ = 0;
|
||||
|
||||
static const SP_TCHAR *progName = 0;
|
||||
|
||||
static const SP_TCHAR versionString[] = SP_VERSION;
|
||||
|
||||
CmdLineApp::CmdLineApp()
|
||||
: errorFile_(0),
|
||||
outputCodingSystem_(0),
|
||||
// Colon at beginning is Posix.2ism that says to return : rather than ? for
|
||||
// missing option argument.
|
||||
optstr_(SP_T(":"), 1),
|
||||
MessageReporter(makeStdErr())
|
||||
{
|
||||
registerOption('b', SP_T("bctf"));
|
||||
registerOption('f', SP_T("error_file"));
|
||||
registerOption('v');
|
||||
}
|
||||
|
||||
void CmdLineApp::registerOption(AppChar c, const AppChar *argName)
|
||||
{
|
||||
optstr_ += c;
|
||||
if (argName) {
|
||||
optstr_ += SP_T(':');
|
||||
optArgNames_.push_back(argName);
|
||||
}
|
||||
}
|
||||
|
||||
StringC CmdLineApp::usageString()
|
||||
{
|
||||
String<AppChar> result;
|
||||
size_t i;
|
||||
|
||||
if (progName)
|
||||
result.assign(progName, tcslen(progName));
|
||||
PackedBoolean hadOption[128];
|
||||
for (i = 0; i < 128; i++)
|
||||
hadOption[i] = 0;
|
||||
Boolean hadNoArgOption = 0;
|
||||
for (i = 1; i < optstr_.size(); i++) {
|
||||
if (optstr_[i] == 0)
|
||||
break;
|
||||
if (i + 1 < optstr_.size() && optstr_[i + 1] == ':')
|
||||
i++;
|
||||
else if (!hadOption[optstr_[i]]) {
|
||||
hadOption[optstr_[i]] = 1;
|
||||
if (!hadNoArgOption) {
|
||||
hadNoArgOption = 1;
|
||||
result.append(SP_T(" [-"), 3);
|
||||
}
|
||||
result += optstr_[i];
|
||||
}
|
||||
}
|
||||
if (hadNoArgOption)
|
||||
result += SP_T(']');
|
||||
size_t j = 0;
|
||||
for (i = 1; i < optstr_.size(); i++) {
|
||||
if (i + 1 < optstr_.size() && optstr_[i + 1] == ':') {
|
||||
if (!hadOption[optstr_[i]]) {
|
||||
hadOption[optstr_[i]] = 1;
|
||||
result += SP_T(' ');
|
||||
result += SP_T('[');
|
||||
result += SP_T('-');
|
||||
result += optstr_[i];
|
||||
result += SP_T(' ');
|
||||
result.append(optArgNames_[j], tcslen(optArgNames_[j]));
|
||||
result += SP_T(']');
|
||||
}
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
result.append(SP_T(" sysid..."), tcslen(SP_T(" sysid...")));
|
||||
result += 0;
|
||||
return convertInput(result.data());
|
||||
}
|
||||
|
||||
static
|
||||
void ewrite(const AppChar *s)
|
||||
{
|
||||
#ifdef SP_WIDE_SYSTEM
|
||||
fputts(s, stderr);
|
||||
#else
|
||||
int n = (int)strlen(s);
|
||||
while (n > 0) {
|
||||
int nw = write(2, s, n);
|
||||
if (nw < 0)
|
||||
break;
|
||||
n -= nw;
|
||||
s += nw;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static
|
||||
#ifdef SP_FANCY_NEW_HANDLER
|
||||
int outOfMemory(size_t)
|
||||
#else
|
||||
void outOfMemory()
|
||||
#endif
|
||||
{
|
||||
if (progName) {
|
||||
ewrite(progName);
|
||||
ewrite(SP_T(": "));
|
||||
}
|
||||
ewrite(SP_T(": out of memory\n"));
|
||||
exit(1);
|
||||
#ifdef SP_FANCY_NEW_HANDLER
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int CmdLineApp::init(int, AppChar **argv)
|
||||
{
|
||||
set_new_handler(outOfMemory);
|
||||
#ifdef SP_HAVE_LOCALE
|
||||
setlocale(LC_ALL, "");
|
||||
#endif
|
||||
#ifdef SP_HAVE_SETMODE
|
||||
_setmode(1, _O_BINARY);
|
||||
_setmode(2, _O_BINARY);
|
||||
#endif
|
||||
progName = argv[0];
|
||||
if (progName)
|
||||
setProgramName(convertInput(progName));
|
||||
#ifdef __GNUG__
|
||||
// cout is a performance disaster in libg++ unless we do this.
|
||||
ios::sync_with_stdio(0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdLineApp::run(int argc, AppChar **argv)
|
||||
{
|
||||
int ret = init(argc, argv);
|
||||
if (ret)
|
||||
return ret;
|
||||
int firstArg;
|
||||
ret = processOptions(argc, argv, firstArg);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = processArguments(argc - firstArg, argv + firstArg);
|
||||
progName = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Boolean CmdLineApp::openFilebufWrite(filebuf &file,
|
||||
const AppChar *filename)
|
||||
{
|
||||
#ifdef SP_WIDE_SYSTEM
|
||||
int fd = _wopen(filename, _O_CREAT|_O_WRONLY|_O_TRUNC|_O_BINARY);
|
||||
if (fd < 0)
|
||||
return 0;
|
||||
return file.attach(fd) != 0;
|
||||
#else
|
||||
return file.open(filename, ios::out|ios::trunc|IOS_BINARY) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int CmdLineApp::processOptions(int argc, AppChar **argv, int &nextArg)
|
||||
{
|
||||
AppChar ostr[2];
|
||||
optstr_ += SP_T('\0');
|
||||
Options<AppChar> options(argc, argv, optstr_.data());
|
||||
AppChar opt;
|
||||
while (options.get(opt)) {
|
||||
switch (opt) {
|
||||
case ':':
|
||||
ostr[0] = options.opt();
|
||||
ostr[1] = SP_T('\0');
|
||||
message(CmdLineAppMessages::missingOptionArgError,
|
||||
StringMessageArg(convertInput(ostr)));
|
||||
message(CmdLineAppMessages::usage,
|
||||
StringMessageArg(usageString()));
|
||||
return 1;
|
||||
case '?':
|
||||
ostr[0] = options.opt();
|
||||
ostr[1] = SP_T('\0');
|
||||
message(CmdLineAppMessages::invalidOptionError,
|
||||
StringMessageArg(convertInput(ostr)));
|
||||
message(CmdLineAppMessages::usage,
|
||||
StringMessageArg(usageString()));
|
||||
return 1;
|
||||
default:
|
||||
processOption(opt, options.arg());
|
||||
break;
|
||||
}
|
||||
}
|
||||
nextArg = options.ind();
|
||||
if (errorFile_) {
|
||||
static filebuf file;
|
||||
if (!openFilebufWrite(file, errorFile_)) {
|
||||
message(CmdLineAppMessages::cannotOpenOutputError,
|
||||
StringMessageArg(convertInput(errorFile_)),
|
||||
ErrnoMessageArg(errno));
|
||||
return 1;
|
||||
}
|
||||
setMessageStream(new IosOutputCharStream(&file, codingSystem()));
|
||||
}
|
||||
if (!outputCodingSystem_)
|
||||
outputCodingSystem_ = codingSystem();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CmdLineApp::processOption(AppChar opt, const AppChar *arg)
|
||||
{
|
||||
switch (opt) {
|
||||
case 'b':
|
||||
outputCodingSystem_ = lookupCodingSystem(arg);
|
||||
if (!outputCodingSystem_)
|
||||
message(CmdLineAppMessages::unknownBctf,
|
||||
StringMessageArg(convertInput(arg)));
|
||||
break;
|
||||
case 'f':
|
||||
errorFile_ = arg;
|
||||
break;
|
||||
case 'v':
|
||||
// print the version number
|
||||
message(CmdLineAppMessages::versionInfo,
|
||||
StringMessageArg(convertInput(versionString)));
|
||||
break;
|
||||
default:
|
||||
CANNOT_HAPPEN();
|
||||
}
|
||||
}
|
||||
|
||||
Boolean CmdLineApp::getMessageText(const MessageFragment &frag,
|
||||
StringC &text)
|
||||
{
|
||||
String<SP_TCHAR> str;
|
||||
if (!MessageTable::instance()->getText(frag, str))
|
||||
return 0;
|
||||
#ifdef SP_WIDE_SYSTEM
|
||||
text.assign((const Char *)str.data(), str.size());
|
||||
#else
|
||||
str += 0;
|
||||
text = codingSystem()->convertIn(str.data());
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
const CodingSystem *CmdLineApp::codingSystem()
|
||||
{
|
||||
if (!codingSystem_) {
|
||||
const SP_TCHAR *codingName = tgetenv(SP_T("SP_BCTF"));
|
||||
if (codingName)
|
||||
codingSystem_ = lookupCodingSystem(codingName);
|
||||
if (!codingSystem_
|
||||
#ifndef SP_WIDE_SYSTEM
|
||||
|| codingSystem_->fixedBytesPerChar() > 1
|
||||
#endif
|
||||
)
|
||||
codingSystem_ = &identityCodingSystem;
|
||||
}
|
||||
return codingSystem_;
|
||||
}
|
||||
|
||||
const CodingSystem *
|
||||
CmdLineApp::lookupCodingSystem(const SP_TCHAR *codingName)
|
||||
{
|
||||
#define MAX_CS_NAME 50
|
||||
if (tcslen(codingName) < MAX_CS_NAME) {
|
||||
char buf[MAX_CS_NAME];
|
||||
int i;
|
||||
for (i = 0; codingName[i] != SP_T('\0'); i++) {
|
||||
SP_TUCHAR c = totupper((SP_TUCHAR)(codingName[i]));
|
||||
#ifdef SP_WIDE_SYSTEM
|
||||
if (c > (unsigned char)-1)
|
||||
return 0;
|
||||
#endif
|
||||
buf[i] = char(c);
|
||||
}
|
||||
buf[i] = SP_T('\0');
|
||||
{
|
||||
for (size_t i = 0; i < SIZEOF(codingSystems); i++)
|
||||
if (strcmp(buf, codingSystems[i].name) == 0)
|
||||
return codingSystems[i].cs;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const CodingSystem *
|
||||
CmdLineApp::codingSystem(size_t i, const char *&name)
|
||||
{
|
||||
if (i < SIZEOF(codingSystems)) {
|
||||
name = codingSystems[i].name;
|
||||
return codingSystems[i].cs;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
StringC CmdLineApp::convertInput(const SP_TCHAR *s)
|
||||
{
|
||||
#ifdef SP_WIDE_SYSTEM
|
||||
StringC str(s, wcslen(s));
|
||||
#else
|
||||
StringC str(codingSystem()->convertIn(s));
|
||||
#endif
|
||||
for (size_t i = 0; i < str.size(); i++)
|
||||
if (str[i] == '\n')
|
||||
str[i] = '\r';
|
||||
return str;
|
||||
}
|
||||
|
||||
OutputCharStream *CmdLineApp::makeStdErr()
|
||||
{
|
||||
OutputCharStream *os = ConsoleOutput::makeOutputCharStream(2);
|
||||
if (os)
|
||||
return os;
|
||||
return new IosOutputCharStream(cerr.rdbuf(), codingSystem());
|
||||
}
|
||||
|
||||
OutputCharStream *CmdLineApp::makeStdOut()
|
||||
{
|
||||
OutputCharStream *os = ConsoleOutput::makeOutputCharStream(1);
|
||||
if (os)
|
||||
return os;
|
||||
return new IosOutputCharStream(cout.rdbuf(), outputCodingSystem_);
|
||||
}
|
||||
|
||||
#ifdef SP_NAMESPACE
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user