SECURITY fix for dtappintegrate: Use mktemp(1) to generate a template.
[oweals/cde.git] / cde / programs / nsgmls / ParserApp.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: ParserApp.C /main/1 1996/07/29 17:00:34 cde-hp $ */
24 // Copyright (c) 1996 James Clark
25 // See the file COPYING for copying permission.
26
27 #ifdef __GNUG__
28 #pragma implementation
29 #endif
30
31 #include "splib.h"
32 #include "ParserApp.h"
33 #include "ParserAppMessages.h"
34 #include "MessageArg.h"
35 #include "Location.h"
36 #include "macros.h"
37 #include "sptchar.h"
38 #include "ArcEngine.h"
39
40 #include <limits.h>
41 #include <errno.h>
42 #include <stdlib.h>
43
44 #ifndef DEFAULT_ERROR_LIMIT
45 #define DEFAULT_ERROR_LIMIT 200
46 #endif
47
48 #ifdef SP_NAMESPACE
49 namespace SP_NAMESPACE {
50 #endif
51
52 ParserApp::ParserApp()
53 : errorLimit_(DEFAULT_ERROR_LIMIT)
54 {
55   registerOption('a', SP_T("link_type"));
56   registerOption('A', SP_T("arch"));
57   registerOption('e');
58   registerOption('E', SP_T("max_errors"));
59   registerOption('g');
60   registerOption('i', SP_T("entity"));
61   registerOption('w', SP_T("warning_type"));
62 }
63
64 void ParserApp::initParser(const StringC &sysid)
65 {
66   SgmlParser::Params params;
67   params.sysid = sysid;
68   params.entityManager = entityManager().pointer();
69   params.initialCharset = &systemCharset_.desc();
70   params.options = &options_;
71   parser_.init(params);
72   if (arcNames_.size() > 0)
73     parser_.activateLinkType(arcNames_[0]);
74   for (size_t i = 0; i < activeLinkTypes_.size(); i++) 
75     parser_.activateLinkType(convertInput(activeLinkTypes_[i]));
76   allLinkTypesActivated();
77 }
78
79 void ParserApp::allLinkTypesActivated()
80 {
81   parser_.allLinkTypesActivated();
82 }
83
84 int ParserApp::processSysid(const StringC &sysid)
85 {
86   initParser(sysid);
87   ErrorCountEventHandler *eceh = makeEventHandler();
88   if (errorLimit_)
89     eceh->setErrorLimit(errorLimit_);   
90   return generateEvents(eceh);
91 }
92
93 int ParserApp::generateEvents(ErrorCountEventHandler *eceh)
94 {
95   Owner<EventHandler> eh(eceh);
96   parseAll(parser_, *eh, (SP_CONST sig_atomic_t*) eceh->cancelPtr());
97   unsigned errorCount = eceh->errorCount();
98   if (errorLimit_ != 0 && errorCount >= errorLimit_)
99     message(ParserAppMessages::errorLimitExceeded,
100             NumberMessageArg(errorLimit_));
101   return errorCount > 0;
102 }
103
104 void ParserApp::parseAll(SgmlParser &parser,
105                          EventHandler &eh,
106                          SP_CONST SP_VOLATILE sig_atomic_t *cancelPtr)
107 {
108   if (arcNames_.size() > 0) {
109     SelectOneArcDirector director(arcNames_, eh);
110     ArcEngine::parseAll(parser, director, director, cancelPtr);
111   }
112   else
113     parser.parseAll(eh, cancelPtr);
114 }
115
116 void ParserApp::processOption(AppChar opt, const AppChar *arg)
117 {
118   switch (opt) {
119   case 'a':
120     // activate link
121     activeLinkTypes_.push_back(arg);
122     break;
123   case 'A':
124     arcNames_.push_back(convertInput(arg));
125     break;
126   case 'E':
127     {
128       AppChar *end;
129       unsigned long n = tcstoul((AppChar *)arg, &end, 10);
130       if ((n == 0 && end == arg)
131           || *end != SP_T('\0')
132           || (n == ULONG_MAX && errno == ERANGE)
133           || n > UINT_MAX)
134         message(ParserAppMessages::badErrorLimit);
135       else
136         errorLimit_ = unsigned(n);
137     }
138     break;
139   case 'e':
140     // describe open entities in error messages
141     addOption(MessageReporter::openEntities);
142     break;
143   case 'g':
144     // show gis of open elements in error messages
145     addOption(MessageReporter::openElements);
146     break;
147   case 'i':
148     // pretend that arg is defined as INCLUDE
149     options_.includes.push_back(convertInput(arg));
150     break;
151   case 'w':
152     if (!enableWarning(arg))
153       message(ParserAppMessages::unknownWarning,
154               StringMessageArg(convertInput(arg)));
155     break;
156   default:
157     EntityApp::processOption(opt, arg);
158     break;
159   }
160 }
161
162 Boolean ParserApp::enableWarning(const AppChar *s)
163 {
164   struct {
165     const AppChar *name;
166     PackedBoolean ParserOptions::*ptr;
167     PackedBoolean partOfAll;
168   } table[] = {
169     { SP_T("mixed"), &ParserOptions::warnMixedContent, 1 },
170     { SP_T("should"), &ParserOptions::warnShould, 1 },
171     { SP_T("duplicate"), &ParserOptions::warnDuplicateEntity, 0 },
172     { SP_T("default"), &ParserOptions::warnDefaultEntityReference, 1 },
173     { SP_T("undefined"), &ParserOptions::warnUndefinedElement, 1 },
174     { SP_T("sgmldecl"), &ParserOptions::warnSgmlDecl, 1 },
175     { SP_T("unclosed"), &ParserOptions::warnUnclosedTag, 1 },
176     { SP_T("empty"), &ParserOptions::warnEmptyTag, 1 },
177     { SP_T("net"), &ParserOptions::warnNet, 0 },
178     { SP_T("unused-map"), &ParserOptions::warnUnusedMap, 1 },
179     { SP_T("unused-param"), &ParserOptions::warnUnusedParam, 1 },
180     { SP_T("notation-sysid"), &ParserOptions::warnNotationSystemId, 0 },
181     { SP_T("idref"), &ParserOptions::errorIdref, 0 },
182     { SP_T("significant"), &ParserOptions::errorSignificant, 0 },
183     { SP_T("afdr"), &ParserOptions::errorAfdr, 0 },
184     { SP_T("lpd-notation"), &ParserOptions::errorLpdNotation, 0 },
185   };
186   PackedBoolean val = 1;
187   if (tcsncmp(s, SP_T("no-"), 3) == 0) {
188     s += 3;
189     val = 0;
190   }
191   if (tcscmp(s, SP_T("all")) == 0) {
192     for (size_t i = 0; i < SIZEOF(table); i++)
193       if (table[i].partOfAll) {
194         // Use parentheses to work around Watcom 10.0a bug.
195         (options_.*(table[i].ptr)) = val;
196       }
197     return 1;
198   }
199   for (size_t i = 0; i < SIZEOF(table); i++)
200     if (tcscmp(s, table[i].name) == 0) {
201       // Use parentheses to work around Watcom 10.0a bug.
202       (options_.*(table[i].ptr)) = val;
203       return 1;
204     }
205   if (tcscmp(s, SP_T("min-tag")) == 0) {
206     options_.warnUnclosedTag = val;
207     options_.warnEmptyTag = val;
208     options_.warnNet = val;
209     return 1;
210   }
211   return 0;
212 }
213
214 #ifdef SP_NAMESPACE
215 }
216 #endif