1 // Copyright (c) 1994 James Clark
2 // See the file COPYING for copying permission.
3 
4 #ifdef __GNUG__
5 #pragma implementation
6 #endif
7 
8 #include "splib.h"
9 #include "Parser.h"
10 #include "ParserMessages.h"
11 #include "constant.h"
12 #include "Trie.h"
13 
14 #ifdef SP_NAMESPACE
15 namespace SP_NAMESPACE {
16 #endif
17 
Parser(const SgmlParser::Params & params)18 Parser::Parser(const SgmlParser::Params &params)
19 : ParserState(params.parent
20 	      ? params.parent->parser_->entityManagerPtr()
21 	      : params.entityManager,
22 	      params.options
23 	      ? *params.options
24 	      : params.parent->parser_->options(),
25 	      paramsSubdocLevel(params),
26 	      params.entityType == SgmlParser::Params::dtd
27 	      ? declSubsetPhase
28 	      : contentPhase)
29 {
30   Parser *parent = 0;
31   if (params.parent)
32     parent = params.parent->parser_;
33   if (params.entityType == SgmlParser::Params::document) {
34     Sd *sd = new Sd(entityManagerPtr());
35     const ParserOptions &opt = options();
36     sd->setBooleanFeature(Sd::fDATATAG, opt.datatag);
37     sd->setBooleanFeature(Sd::fOMITTAG, opt.omittag);
38     sd->setBooleanFeature(Sd::fRANK, opt.rank);
39     sd->setShorttag(opt.shorttag);
40     sd->setBooleanFeature(Sd::fEMPTYNRM, opt.emptynrm);
41     sd->setNumberFeature(Sd::fSIMPLE, opt.linkSimple);
42     sd->setBooleanFeature(Sd::fIMPLICIT, opt.linkImplicit);
43     sd->setNumberFeature(Sd::fEXPLICIT, opt.linkExplicit);
44     sd->setNumberFeature(Sd::fCONCUR, opt.concur);
45     sd->setNumberFeature(Sd::fSUBDOC, opt.subdoc);
46     sd->setBooleanFeature(Sd::fFORMAL, opt.formal);
47     setSdOverrides(*sd);
48     PublicId publicId;
49     CharsetDecl docCharsetDecl;
50     docCharsetDecl.addSection(publicId);
51     docCharsetDecl.addRange(0, charMax > 99999999 ? 99999999 : charMax + 1, 0);
52     sd->setDocCharsetDecl(docCharsetDecl);
53     setSd(sd);
54   }
55   else if (params.sd.isNull()) {
56     setSd(parent->sdPointer());
57     setSyntaxes(parent->prologSyntaxPointer(),
58 		parent->instanceSyntaxPointer());
59   }
60   else {
61     setSd(params.sd);
62     setSyntaxes(params.prologSyntax, params.instanceSyntax);
63   }
64 
65   // Make catalog
66   StringC sysid(params.sysid);
67   ConstPtr<EntityCatalog> catalog
68     = entityManager().makeCatalog(sysid,
69 				  sd().docCharset(),
70 				  messenger());
71   if (!catalog.isNull())
72     setEntityCatalog(catalog);
73   else if (parent)
74     setEntityCatalog(parent->entityCatalogPtr());
75   else {
76     allDone();
77     return;
78   }
79 
80   // Set up the input stack.
81   if (sysid.size() == 0) {
82     allDone();
83     return;
84   }
85   Ptr<InputSourceOrigin> origin;
86   if (params.origin.isNull())
87     origin = InputSourceOrigin::make();
88   else
89     origin = params.origin;
90   pushInput(entityManager().open(sysid,
91 				 sd().docCharset(),
92 				 origin.pointer(),
93 				 EntityManager::mayRewind|EntityManager::maySetDocCharset,
94 				 messenger()));
95   if (inputLevel() == 0) {
96     allDone();
97     return;
98   }
99   switch (params.entityType) {
100   case SgmlParser::Params::document:
101     setPhase(initPhase);
102     break;
103   case SgmlParser::Params::subdoc:
104     if (params.subdocInheritActiveLinkTypes && parent)
105       inheritActiveLinkTypes(*parent);
106     if (subdocLevel() == sd().subdoc() + 1)
107       message(ParserMessages::subdocLevel, NumberMessageArg(sd().subdoc()));
108     setPhase(prologPhase);
109     compilePrologModes();
110     break;
111   case SgmlParser::Params::dtd:
112     compilePrologModes();
113     startDtd(params.doctypeName);
114     setPhase(declSubsetPhase);
115     break;
116   }
117 }
118 
setSdOverrides(Sd & sd)119 void Parser::setSdOverrides(Sd &sd)
120 {
121   if (options().typeValid != ParserOptions::sgmlDeclTypeValid) {
122     sd.setTypeValid(options().typeValid);
123     sd.setBooleanFeature(Sd::fIMPLYDEFATTLIST, !options().typeValid);
124     sd.setBooleanFeature(Sd::fIMPLYDEFELEMENT, !options().typeValid);
125   }
126   if (options().noUnclosedTag) {
127     sd.setBooleanFeature(Sd::fSTARTTAGUNCLOSED, 0);
128     sd.setBooleanFeature(Sd::fENDTAGUNCLOSED, 0);
129   }
130   if (options().noNet)
131     sd.setStartTagNetEnable(Sd::netEnableNo);
132 }
133 
giveUp()134 void Parser::giveUp()
135 {
136   if (subdocLevel() > 0)	// FIXME might be subdoc if level == 0
137     message(ParserMessages::subdocGiveUp);
138   else
139     message(ParserMessages::giveUp);
140   allDone();
141 }
142 
paramsSubdocLevel(const SgmlParser::Params & params)143 unsigned Parser::paramsSubdocLevel(const SgmlParser::Params &params)
144 {
145   if (!params.parent)
146     return 0;
147   unsigned n = params.parent->parser_->subdocLevel();
148   if (params.subdocReferenced)
149     return n + 1;
150   else
151     return n;
152 }
153 
nextEvent()154 Event *Parser::nextEvent()
155 {
156   while (eventQueueEmpty()) {
157     switch (phase()) {
158     case noPhase:
159       return 0;
160     case initPhase:
161       doInit();
162       break;
163     case prologPhase:
164       doProlog();
165       break;
166     case declSubsetPhase:
167       doDeclSubset();
168       break;
169     case instanceStartPhase:
170       doInstanceStart();
171       break;
172     case contentPhase:
173       doContent();
174       break;
175     }
176   }
177   return eventQueueGet();
178 }
179 
parseAll(EventHandler & handler,const volatile sig_atomic_t * cancelPtr)180 void Parser::parseAll(EventHandler &handler,
181 		      const volatile sig_atomic_t *cancelPtr)
182 {
183   while (!eventQueueEmpty())
184     eventQueueGet()->handle(handler);
185   // FIXME catch exceptions and reset handler.
186   setHandler(&handler, cancelPtr);
187   for (;;) {
188     switch (phase()) {
189     case noPhase:
190       unsetHandler();
191       return;
192     case initPhase:
193       doInit();
194       break;
195     case prologPhase:
196       doProlog();
197       break;
198     case declSubsetPhase:
199       doDeclSubset();
200       break;
201     case instanceStartPhase:
202       doInstanceStart();
203       break;
204     case contentPhase:
205       doContent();
206       break;
207     }
208   }
209 }
210 
211 #ifdef SP_NAMESPACE
212 }
213 #endif
214