123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $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"
- #if defined(__linux__) || defined(CSRG_BASED) || defined(sun)
- #include <iostream>
- #include <fstream>
- using namespace std;
- #else
- #include <iostream.h>
- #include <fstream.h>
- #endif
- #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
- #if defined(__linux__) || defined(CSRG_BASED) || defined(sun)
- return file.open(filename, ios::out|ios::trunc) != 0;
- #else
- return file.open(filename, ios::out|ios::trunc|IOS_BINARY) != 0;
- #endif
- #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
|