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 ¶ms)
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 ¶ms)
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