Link with C++ linker
[oweals/cde.git] / cde / programs / nsgmls / nsgmls.C
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
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)
10  * any later version.
11  *
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
16  * details.
17  *
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
22  */
23 /* $XConsortium: nsgmls.C /main/1 1996/07/29 17:08:59 cde-hp $ */
24 // Copyright (c) 1994, 1995 James Clark
25 // See the file COPYING for copying permission.
26
27 #include "config.h"
28 #include "Event.h"
29 #include "MessageEventHandler.h"
30 #include "SgmlsEventHandler.h"
31 #include "RastEventHandler.h"
32 #include "OutputCharStream.h"
33 #include "Boolean.h"
34 #include "NsgmlsMessages.h"
35 #include "MessageArg.h"
36 #include "ErrnoMessageArg.h"
37 #include "ParserApp.h"
38 #include "sptchar.h"
39 #include "macros.h"
40
41 #include <iostream.h>
42 #include <fstream.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <errno.h>
46 #include <limits.h>
47
48 #ifdef SP_NAMESPACE
49 using namespace SP_NAMESPACE;
50 #endif
51
52 class NsgmlsApp : public ParserApp {
53 public:
54   NsgmlsApp();
55   int processArguments(int argc, AppChar **argv);
56   ErrorCountEventHandler *makeEventHandler();
57   void processOption(AppChar opt, const AppChar *arg);
58   void allLinkTypesActivated();
59 private:
60   Boolean suppressOutput_;
61   Boolean prologOnly_;
62   unsigned outputFlags_;
63   String<AppChar> rastFile_;
64   const AppChar *rastOption_;
65   Boolean batchMode_;
66 };
67
68 SP_DEFINE_APP(NsgmlsApp)
69
70 class PrologMessageEventHandler : public MessageEventHandler {
71 public:
72   PrologMessageEventHandler(Messenger *messenger);
73   void endProlog(EndPrologEvent *);
74 };
75
76 class XRastEventHandler : public RastEventHandler {
77 public:
78   XRastEventHandler(SgmlParser *,
79                     const AppChar *filename,
80                     const StringC &filenameStr,
81                     const OutputCodingSystem *,
82                     Messenger *messenger);
83   ~XRastEventHandler();
84   void message(MessageEvent *);
85   void truncateOutput();
86   void allLinkTypesActivated();
87 private:
88   Messenger *messenger_;
89   // file_ must come before os_ so it gets inited first
90   filebuf file_;
91   IosOutputCharStream os_;
92   const AppChar *filename_;
93   const StringC filenameStr_;
94 };
95
96 NsgmlsApp::NsgmlsApp()
97 : suppressOutput_(0),
98   batchMode_(0),
99   prologOnly_(0),
100   outputFlags_(0),
101   rastOption_(0)
102 {
103   registerOption('B');
104   registerOption('d');
105   registerOption('l');
106   registerOption('m', SP_T("catalog_sysid"));
107   registerOption('o', SP_T("output_option"));
108   registerOption('p');
109   registerOption('r');
110   registerOption('s');
111   registerOption('t', SP_T("rast_file"));
112   registerOption('u');
113 }
114
115 void NsgmlsApp::processOption(AppChar opt, const AppChar *arg)
116 {
117   switch (opt) {
118   case 'B':
119     batchMode_ = 1;
120     break;
121   case 'd':
122     // warn about duplicate entity declarations
123     options_.warnDuplicateEntity = 1;
124     break;
125   case 'l':
126     // output L commands
127     outputFlags_ |= SgmlsEventHandler::outputLine;
128     break;
129   case 'm':
130     processOption(SP_T('c'), arg);
131     break;
132   case 'o':
133     {
134       static struct {
135         const AppChar *name;
136         unsigned flag;
137       } outputOptions[] = {
138         { SP_T("line"), SgmlsEventHandler::outputLine },
139         { SP_T("entity"), SgmlsEventHandler::outputEntity },
140         { SP_T("id"), SgmlsEventHandler::outputId },
141         { SP_T("included"), SgmlsEventHandler::outputIncluded },
142         { SP_T("notation-sysid"), SgmlsEventHandler::outputNotationSysid },
143       };
144       Boolean found = 0;
145       for (size_t i = 0; i < SIZEOF(outputOptions); i++)
146         if (tcscmp(arg, outputOptions[i].name) == 0) {
147           outputFlags_ |= outputOptions[i].flag;
148           found = 1;
149           break;
150         }
151       if (!found)
152         message(NsgmlsMessages::unknownOutputOption,
153                 StringMessageArg(convertInput(arg)));
154     }
155     break;
156   case 'p':
157     prologOnly_ = 1;
158     break;
159   case 'r':
160     // warn about defaulted entity reference
161     options_.warnDefaultEntityReference = 1;
162     break;
163   case 's':
164     suppressOutput_ = 1;
165     break;
166   case 't':
167     rastOption_ = arg;
168     break;
169   case 'u':
170     // warn about undefined elements
171     options_.warnUndefinedElement = 1;
172     break;
173   default:
174     ParserApp::processOption(opt, arg);
175     break;
176   }
177 }
178
179 int NsgmlsApp::processArguments(int argc, AppChar **argv)
180 {
181   if (batchMode_) {
182     int ret = 0;
183     for (int i = 0; i < argc; i++) {
184       if (rastOption_) {
185         rastFile_.assign(rastOption_, tcslen(rastOption_));
186         rastFile_.append(argv[i], tcslen(argv[i]));
187         rastFile_ += SP_T('\0');
188       }
189       int tem = ParserApp::processArguments(1, argv + i);
190       if (tem > ret)
191         ret = tem;
192     }
193     return ret;
194   }
195   else
196     return ParserApp::processArguments(argc, argv);
197 }
198
199 void NsgmlsApp::allLinkTypesActivated()
200 {
201   if (!rastOption_)
202     ParserApp::allLinkTypesActivated();
203 }
204
205 ErrorCountEventHandler *NsgmlsApp::makeEventHandler()
206 {
207   if (prologOnly_)
208     return new PrologMessageEventHandler(this);
209   else if (rastOption_) {
210     const AppChar *s = batchMode_ ? rastFile_.data() : rastOption_;
211     return new XRastEventHandler(&parser_, s, convertInput(s),
212                                  outputCodingSystem_, this);
213   }
214   else if (suppressOutput_)
215     return new MessageEventHandler(this, &parser_);
216   else
217     return new SgmlsEventHandler(&parser_,
218                                  makeStdOut(),
219                                  this,
220                                  outputFlags_);
221 }
222
223 PrologMessageEventHandler::PrologMessageEventHandler(Messenger *messenger)
224 : MessageEventHandler(messenger)
225 {
226 }
227
228 void PrologMessageEventHandler::endProlog(EndPrologEvent *event)
229 {
230   cancel();
231   delete event;
232 }
233
234 XRastEventHandler::XRastEventHandler(SgmlParser *parser,
235                                      const AppChar *filename,
236                                      const StringC &filenameStr,
237                                      const OutputCodingSystem *codingSystem,
238                                      Messenger *messenger)
239 : RastEventHandler(parser, messenger),
240   messenger_(messenger),
241   filename_(filename),
242   filenameStr_(filenameStr)
243 {
244   errno = 0;
245   if (!CmdLineApp::openFilebufWrite(file_, filename)) {
246     messenger->message(NsgmlsMessages::cannotOpenOutputError,
247                       StringMessageArg(filenameStr),
248                       ErrnoMessageArg(errno));
249     exit(1);
250   }
251   os_.open(&file_, codingSystem);
252   setOutputStream(&os_);
253 }
254
255 XRastEventHandler::~XRastEventHandler()
256 {
257   end();
258 }
259
260 void XRastEventHandler::truncateOutput()
261 {
262   os_.flush();
263   errno = 0;
264   if (!file_.close())
265     messenger_->message(NsgmlsMessages::closeOutputError,
266                         StringMessageArg(filenameStr_),
267                         ErrnoMessageArg(errno));
268   errno = 0;
269   if (!CmdLineApp::openFilebufWrite(file_, filename_)) {
270     messenger_->message(NsgmlsMessages::cannotOpenOutputError,
271                         StringMessageArg(filenameStr_),
272                         ErrnoMessageArg(errno));
273     exit(1);
274   }
275 }
276
277 void XRastEventHandler::message(MessageEvent *event)
278 {
279   messenger_->dispatchMessage(event->message());
280   ErrorCountEventHandler::message(event);
281 }