2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: CmdLineApp.C /main/2 1996/08/12 12:36:14 mgreess $ */
24 // Copyright (c) 1996 James Clark
25 // See the file COPYING for copying permission.
27 // Need option registration method that allows derived class to change
31 #pragma implementation
35 #include "CmdLineApp.h"
36 #include "CmdLineAppMessages.h"
37 #include "MessageArg.h"
38 #include "ErrnoMessageArg.h"
44 #include "MessageTable.h"
47 #include "UTF8CodingSystem.h"
48 #include "Fixed2CodingSystem.h"
49 #include "UnicodeCodingSystem.h"
50 #include "EUCJPCodingSystem.h"
51 #include "SJISCodingSystem.h"
52 #include "ISO8859InputCodingSystem.h"
54 #include "Win32CodingSystem.h"
56 #endif /* SP_MULTI_BYTE */
57 #include "IdentityCodingSystem.h"
59 #include "ConsoleOutput.h"
61 #if defined(linux) || defined(CSRG_BASED)
77 #ifdef SP_HAVE_SETMODE
81 #ifdef SP_HAVE_SETMODE
82 #define IOS_BINARY ios::binary
90 #else /* not SP_WIDE_SYSTEM */
92 #include <sys/types.h>
93 #ifdef SP_INCLUDE_UNISTD_H
96 #ifdef SP_INCLUDE_IO_H
100 #endif /* not SP_WIDE_SYSTEM */
103 namespace SP_NAMESPACE {
107 static UTF8CodingSystem utf8CodingSystem;
108 static Fixed2CodingSystem fixed2CodingSystem;
109 static UnicodeCodingSystem unicodeCodingSystem;
110 static EUCJPCodingSystem eucjpCodingSystem;
111 static SJISCodingSystem sjisCodingSystem;
113 static Win32CodingSystem ansiCodingSystem(Win32CodingSystem::codePageAnsi);
114 static Win32CodingSystem oemCodingSystem(Win32CodingSystem::codePageOEM);
115 static UnicodeCodingSystem maybeUnicodeCodingSystem(&ansiCodingSystem);
117 #endif /* SP_MULTI_BYTE */
118 static IdentityCodingSystem identityCodingSystem;
122 const CodingSystem *cs;
123 } codingSystems[] = {
125 { "UTF-8", &utf8CodingSystem },
126 { "FIXED-2", &fixed2CodingSystem },
127 { "UNICODE", &unicodeCodingSystem },
128 { "EUC-JP", &eucjpCodingSystem },
129 { "SJIS", &sjisCodingSystem },
131 { "WINDOWS", &ansiCodingSystem },
132 { "MS-DOS", &oemCodingSystem },
133 { "WUNICODE", &maybeUnicodeCodingSystem },
135 #endif /* SP_MULTI_BYTE */
136 { "IS8859-1", &identityCodingSystem },
137 { "IDENTITY", &identityCodingSystem },
140 const CodingSystem *CmdLineApp::codingSystem_ = 0;
142 static const SP_TCHAR *progName = 0;
144 static const SP_TCHAR versionString[] = SP_VERSION;
146 CmdLineApp::CmdLineApp()
148 outputCodingSystem_(0),
149 // Colon at beginning is Posix.2ism that says to return : rather than ? for
150 // missing option argument.
151 optstr_(SP_T(":"), 1),
152 MessageReporter(makeStdErr())
154 registerOption('b', SP_T("bctf"));
155 registerOption('f', SP_T("error_file"));
159 void CmdLineApp::registerOption(AppChar c, const AppChar *argName)
163 optstr_ += SP_T(':');
164 optArgNames_.push_back(argName);
168 StringC CmdLineApp::usageString()
170 String<AppChar> result;
174 result.assign(progName, tcslen(progName));
175 PackedBoolean hadOption[128];
176 for (i = 0; i < 128; i++)
178 Boolean hadNoArgOption = 0;
179 for (i = 1; i < optstr_.size(); i++) {
182 if (i + 1 < optstr_.size() && optstr_[i + 1] == ':')
184 else if (!hadOption[optstr_[i]]) {
185 hadOption[optstr_[i]] = 1;
186 if (!hadNoArgOption) {
188 result.append(SP_T(" [-"), 3);
190 result += optstr_[i];
196 for (i = 1; i < optstr_.size(); i++) {
197 if (i + 1 < optstr_.size() && optstr_[i + 1] == ':') {
198 if (!hadOption[optstr_[i]]) {
199 hadOption[optstr_[i]] = 1;
203 result += optstr_[i];
205 result.append(optArgNames_[j], tcslen(optArgNames_[j]));
212 result.append(SP_T(" sysid..."), tcslen(SP_T(" sysid...")));
214 return convertInput(result.data());
218 void ewrite(const AppChar *s)
220 #ifdef SP_WIDE_SYSTEM
223 int n = (int)strlen(s);
225 int nw = write(2, s, n);
235 #ifdef SP_FANCY_NEW_HANDLER
236 int outOfMemory(size_t)
245 ewrite(SP_T(": out of memory\n"));
247 #ifdef SP_FANCY_NEW_HANDLER
252 int CmdLineApp::init(int, AppChar **argv)
254 set_new_handler(outOfMemory);
255 #ifdef SP_HAVE_LOCALE
256 setlocale(LC_ALL, "");
258 #ifdef SP_HAVE_SETMODE
259 _setmode(1, _O_BINARY);
260 _setmode(2, _O_BINARY);
264 setProgramName(convertInput(progName));
266 // cout is a performance disaster in libg++ unless we do this.
267 ios::sync_with_stdio(0);
272 int CmdLineApp::run(int argc, AppChar **argv)
274 int ret = init(argc, argv);
278 ret = processOptions(argc, argv, firstArg);
281 ret = processArguments(argc - firstArg, argv + firstArg);
286 Boolean CmdLineApp::openFilebufWrite(filebuf &file,
287 const AppChar *filename)
289 #ifdef SP_WIDE_SYSTEM
290 int fd = _wopen(filename, _O_CREAT|_O_WRONLY|_O_TRUNC|_O_BINARY);
293 return file.attach(fd) != 0;
295 #if defined(linux) || defined(CSRG_BASED)
296 return file.open(filename, ios::out|ios::trunc) != 0;
298 return file.open(filename, ios::out|ios::trunc|IOS_BINARY) != 0;
303 int CmdLineApp::processOptions(int argc, AppChar **argv, int &nextArg)
306 optstr_ += SP_T('\0');
307 Options<AppChar> options(argc, argv, optstr_.data());
309 while (options.get(opt)) {
312 ostr[0] = options.opt();
313 ostr[1] = SP_T('\0');
314 message(CmdLineAppMessages::missingOptionArgError,
315 StringMessageArg(convertInput(ostr)));
316 message(CmdLineAppMessages::usage,
317 StringMessageArg(usageString()));
320 ostr[0] = options.opt();
321 ostr[1] = SP_T('\0');
322 message(CmdLineAppMessages::invalidOptionError,
323 StringMessageArg(convertInput(ostr)));
324 message(CmdLineAppMessages::usage,
325 StringMessageArg(usageString()));
328 processOption(opt, options.arg());
332 nextArg = options.ind();
335 if (!openFilebufWrite(file, errorFile_)) {
336 message(CmdLineAppMessages::cannotOpenOutputError,
337 StringMessageArg(convertInput(errorFile_)),
338 ErrnoMessageArg(errno));
341 setMessageStream(new IosOutputCharStream(&file, codingSystem()));
343 if (!outputCodingSystem_)
344 outputCodingSystem_ = codingSystem();
348 void CmdLineApp::processOption(AppChar opt, const AppChar *arg)
352 outputCodingSystem_ = lookupCodingSystem(arg);
353 if (!outputCodingSystem_)
354 message(CmdLineAppMessages::unknownBctf,
355 StringMessageArg(convertInput(arg)));
361 // print the version number
362 message(CmdLineAppMessages::versionInfo,
363 StringMessageArg(convertInput(versionString)));
370 Boolean CmdLineApp::getMessageText(const MessageFragment &frag,
373 String<SP_TCHAR> str;
374 if (!MessageTable::instance()->getText(frag, str))
376 #ifdef SP_WIDE_SYSTEM
377 text.assign((const Char *)str.data(), str.size());
380 text = codingSystem()->convertIn(str.data());
385 const CodingSystem *CmdLineApp::codingSystem()
387 if (!codingSystem_) {
388 const SP_TCHAR *codingName = tgetenv(SP_T("SP_BCTF"));
390 codingSystem_ = lookupCodingSystem(codingName);
392 #ifndef SP_WIDE_SYSTEM
393 || codingSystem_->fixedBytesPerChar() > 1
396 codingSystem_ = &identityCodingSystem;
398 return codingSystem_;
402 CmdLineApp::lookupCodingSystem(const SP_TCHAR *codingName)
404 #define MAX_CS_NAME 50
405 if (tcslen(codingName) < MAX_CS_NAME) {
406 char buf[MAX_CS_NAME];
408 for (i = 0; codingName[i] != SP_T('\0'); i++) {
409 SP_TUCHAR c = totupper((SP_TUCHAR)(codingName[i]));
410 #ifdef SP_WIDE_SYSTEM
411 if (c > (unsigned char)-1)
418 for (size_t i = 0; i < SIZEOF(codingSystems); i++)
419 if (strcmp(buf, codingSystems[i].name) == 0)
420 return codingSystems[i].cs;
427 CmdLineApp::codingSystem(size_t i, const char *&name)
429 if (i < SIZEOF(codingSystems)) {
430 name = codingSystems[i].name;
431 return codingSystems[i].cs;
436 StringC CmdLineApp::convertInput(const SP_TCHAR *s)
438 #ifdef SP_WIDE_SYSTEM
439 StringC str(s, wcslen(s));
441 StringC str(codingSystem()->convertIn(s));
443 for (size_t i = 0; i < str.size(); i++)
449 OutputCharStream *CmdLineApp::makeStdErr()
451 OutputCharStream *os = ConsoleOutput::makeOutputCharStream(2);
454 return new IosOutputCharStream(cerr.rdbuf(), codingSystem());
457 OutputCharStream *CmdLineApp::makeStdOut()
459 OutputCharStream *os = ConsoleOutput::makeOutputCharStream(1);
462 return new IosOutputCharStream(cout.rdbuf(), outputCodingSystem_);