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