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"
71 #ifdef SP_HAVE_SETMODE
75 #ifdef SP_HAVE_SETMODE
76 #define IOS_BINARY ios::binary
84 #else /* not SP_WIDE_SYSTEM */
86 #include <sys/types.h>
87 #ifdef SP_INCLUDE_UNISTD_H
90 #ifdef SP_INCLUDE_IO_H
94 #endif /* not SP_WIDE_SYSTEM */
97 namespace SP_NAMESPACE {
101 static UTF8CodingSystem utf8CodingSystem;
102 static Fixed2CodingSystem fixed2CodingSystem;
103 static UnicodeCodingSystem unicodeCodingSystem;
104 static EUCJPCodingSystem eucjpCodingSystem;
105 static SJISCodingSystem sjisCodingSystem;
107 static Win32CodingSystem ansiCodingSystem(Win32CodingSystem::codePageAnsi);
108 static Win32CodingSystem oemCodingSystem(Win32CodingSystem::codePageOEM);
109 static UnicodeCodingSystem maybeUnicodeCodingSystem(&ansiCodingSystem);
111 #endif /* SP_MULTI_BYTE */
112 static IdentityCodingSystem identityCodingSystem;
116 const CodingSystem *cs;
117 } codingSystems[] = {
119 { "UTF-8", &utf8CodingSystem },
120 { "FIXED-2", &fixed2CodingSystem },
121 { "UNICODE", &unicodeCodingSystem },
122 { "EUC-JP", &eucjpCodingSystem },
123 { "SJIS", &sjisCodingSystem },
125 { "WINDOWS", &ansiCodingSystem },
126 { "MS-DOS", &oemCodingSystem },
127 { "WUNICODE", &maybeUnicodeCodingSystem },
129 #endif /* SP_MULTI_BYTE */
130 { "IS8859-1", &identityCodingSystem },
131 { "IDENTITY", &identityCodingSystem },
134 const CodingSystem *CmdLineApp::codingSystem_ = 0;
136 static const SP_TCHAR *progName = 0;
138 static const SP_TCHAR versionString[] = SP_VERSION;
140 CmdLineApp::CmdLineApp()
142 outputCodingSystem_(0),
143 // Colon at beginning is Posix.2ism that says to return : rather than ? for
144 // missing option argument.
145 optstr_(SP_T(":"), 1),
146 MessageReporter(makeStdErr())
148 registerOption('b', SP_T("bctf"));
149 registerOption('f', SP_T("error_file"));
153 void CmdLineApp::registerOption(AppChar c, const AppChar *argName)
157 optstr_ += SP_T(':');
158 optArgNames_.push_back(argName);
162 StringC CmdLineApp::usageString()
164 String<AppChar> result;
168 result.assign(progName, tcslen(progName));
169 PackedBoolean hadOption[128];
170 for (i = 0; i < 128; i++)
172 Boolean hadNoArgOption = 0;
173 for (i = 1; i < optstr_.size(); i++) {
176 if (i + 1 < optstr_.size() && optstr_[i + 1] == ':')
178 else if (!hadOption[optstr_[i]]) {
179 hadOption[optstr_[i]] = 1;
180 if (!hadNoArgOption) {
182 result.append(SP_T(" [-"), 3);
184 result += optstr_[i];
190 for (i = 1; i < optstr_.size(); i++) {
191 if (i + 1 < optstr_.size() && optstr_[i + 1] == ':') {
192 if (!hadOption[optstr_[i]]) {
193 hadOption[optstr_[i]] = 1;
197 result += optstr_[i];
199 result.append(optArgNames_[j], tcslen(optArgNames_[j]));
206 result.append(SP_T(" sysid..."), tcslen(SP_T(" sysid...")));
208 return convertInput(result.data());
212 void ewrite(const AppChar *s)
214 #ifdef SP_WIDE_SYSTEM
217 int n = (int)strlen(s);
219 int nw = write(2, s, n);
229 #ifdef SP_FANCY_NEW_HANDLER
230 int outOfMemory(size_t)
239 ewrite(SP_T(": out of memory\n"));
241 #ifdef SP_FANCY_NEW_HANDLER
246 int CmdLineApp::init(int, AppChar **argv)
248 set_new_handler(outOfMemory);
249 #ifdef SP_HAVE_LOCALE
250 setlocale(LC_ALL, "");
252 #ifdef SP_HAVE_SETMODE
253 _setmode(1, _O_BINARY);
254 _setmode(2, _O_BINARY);
258 setProgramName(convertInput(progName));
260 // cout is a performance disaster in libg++ unless we do this.
261 ios::sync_with_stdio(0);
266 int CmdLineApp::run(int argc, AppChar **argv)
268 int ret = init(argc, argv);
272 ret = processOptions(argc, argv, firstArg);
275 ret = processArguments(argc - firstArg, argv + firstArg);
280 Boolean CmdLineApp::openFilebufWrite(filebuf &file,
281 const AppChar *filename)
283 #ifdef SP_WIDE_SYSTEM
284 int fd = _wopen(filename, _O_CREAT|_O_WRONLY|_O_TRUNC|_O_BINARY);
287 return file.attach(fd) != 0;
289 return file.open(filename, ios::out|ios::trunc|IOS_BINARY) != 0;
293 int CmdLineApp::processOptions(int argc, AppChar **argv, int &nextArg)
296 optstr_ += SP_T('\0');
297 Options<AppChar> options(argc, argv, optstr_.data());
299 while (options.get(opt)) {
302 ostr[0] = options.opt();
303 ostr[1] = SP_T('\0');
304 message(CmdLineAppMessages::missingOptionArgError,
305 StringMessageArg(convertInput(ostr)));
306 message(CmdLineAppMessages::usage,
307 StringMessageArg(usageString()));
310 ostr[0] = options.opt();
311 ostr[1] = SP_T('\0');
312 message(CmdLineAppMessages::invalidOptionError,
313 StringMessageArg(convertInput(ostr)));
314 message(CmdLineAppMessages::usage,
315 StringMessageArg(usageString()));
318 processOption(opt, options.arg());
322 nextArg = options.ind();
325 if (!openFilebufWrite(file, errorFile_)) {
326 message(CmdLineAppMessages::cannotOpenOutputError,
327 StringMessageArg(convertInput(errorFile_)),
328 ErrnoMessageArg(errno));
331 setMessageStream(new IosOutputCharStream(&file, codingSystem()));
333 if (!outputCodingSystem_)
334 outputCodingSystem_ = codingSystem();
338 void CmdLineApp::processOption(AppChar opt, const AppChar *arg)
342 outputCodingSystem_ = lookupCodingSystem(arg);
343 if (!outputCodingSystem_)
344 message(CmdLineAppMessages::unknownBctf,
345 StringMessageArg(convertInput(arg)));
351 // print the version number
352 message(CmdLineAppMessages::versionInfo,
353 StringMessageArg(convertInput(versionString)));
360 Boolean CmdLineApp::getMessageText(const MessageFragment &frag,
363 String<SP_TCHAR> str;
364 if (!MessageTable::instance()->getText(frag, str))
366 #ifdef SP_WIDE_SYSTEM
367 text.assign((const Char *)str.data(), str.size());
370 text = codingSystem()->convertIn(str.data());
375 const CodingSystem *CmdLineApp::codingSystem()
377 if (!codingSystem_) {
378 const SP_TCHAR *codingName = tgetenv(SP_T("SP_BCTF"));
380 codingSystem_ = lookupCodingSystem(codingName);
382 #ifndef SP_WIDE_SYSTEM
383 || codingSystem_->fixedBytesPerChar() > 1
386 codingSystem_ = &identityCodingSystem;
388 return codingSystem_;
392 CmdLineApp::lookupCodingSystem(const SP_TCHAR *codingName)
394 #define MAX_CS_NAME 50
395 if (tcslen(codingName) < MAX_CS_NAME) {
396 char buf[MAX_CS_NAME];
398 for (i = 0; codingName[i] != SP_T('\0'); i++) {
399 SP_TUCHAR c = totupper((SP_TUCHAR)(codingName[i]));
400 #ifdef SP_WIDE_SYSTEM
401 if (c > (unsigned char)-1)
408 for (size_t i = 0; i < SIZEOF(codingSystems); i++)
409 if (strcmp(buf, codingSystems[i].name) == 0)
410 return codingSystems[i].cs;
417 CmdLineApp::codingSystem(size_t i, const char *&name)
419 if (i < SIZEOF(codingSystems)) {
420 name = codingSystems[i].name;
421 return codingSystems[i].cs;
426 StringC CmdLineApp::convertInput(const SP_TCHAR *s)
428 #ifdef SP_WIDE_SYSTEM
429 StringC str(s, wcslen(s));
431 StringC str(codingSystem()->convertIn(s));
433 for (size_t i = 0; i < str.size(); i++)
439 OutputCharStream *CmdLineApp::makeStdErr()
441 OutputCharStream *os = ConsoleOutput::makeOutputCharStream(2);
444 return new IosOutputCharStream(cerr.rdbuf(), codingSystem());
447 OutputCharStream *CmdLineApp::makeStdOut()
449 OutputCharStream *os = ConsoleOutput::makeOutputCharStream(1);
452 return new IosOutputCharStream(cout.rdbuf(), outputCodingSystem_);