2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
23 /* $XConsortium: parseAttribute.C /main/1 1996/07/29 17:09:07 cde-hp $ */
24 // Copyright (c) 1994, 1995 James Clark
25 // See the file COPYING for copying permission.
29 #include "MessageArg.h"
32 #include "ParserMessages.h"
35 namespace SP_NAMESPACE {
38 Boolean Parser::parseAttributeSpec(Boolean inDecl,
43 unsigned specLength = 0;
44 AttributeParameter::Type curParm;
46 if (!parseAttributeParameter(inDecl, 0, curParm, netEnabling))
48 while (curParm != AttributeParameter::end) {
50 case AttributeParameter::name:
53 text.addChars(currentInput()->currentTokenStart(),
54 currentInput()->currentTokenLength(),
56 size_t nameMarkupIndex;
58 nameMarkupIndex = currentMarkup()->size() - 1;
59 text.subst(*syntax().generalSubstTable(), syntax().space());
60 if (!parseAttributeParameter(inDecl, 1, curParm, netEnabling))
62 if (curParm == AttributeParameter::vi) {
63 specLength += text.size() + syntax().normsep();
64 if (!parseAttributeValueSpec(inDecl, text.string(), atts,
67 // setup for next attribute
68 if (!parseAttributeParameter(inDecl, 0, curParm, netEnabling))
73 currentMarkup()->changeToAttributeValue(nameMarkupIndex);
74 if (!handleAttributeNameToken(text, atts, specLength))
79 case AttributeParameter::nameToken:
82 text.addChars(currentInput()->currentTokenStart(),
83 currentInput()->currentTokenLength(),
85 text.subst(*syntax().generalSubstTable(), syntax().space());
86 if (!handleAttributeNameToken(text, atts, specLength))
88 if (!parseAttributeParameter(inDecl, 0, curParm, netEnabling))
92 case AttributeParameter::recoverUnquoted:
94 if (!atts.recoverUnquoted(currentToken(), currentLocation(), *this)) {
95 // Don't treat it as an unquoted attribute value.
96 currentInput()->endToken(1);
97 if (!atts.handleAsUnterminated(*this))
98 message(ParserMessages::attributeSpecCharacter,
99 StringMessageArg(currentToken()));
102 if (!parseAttributeParameter(inDecl, 0, curParm, netEnabling))
111 if (specLength > syntax().attsplen())
112 message(ParserMessages::attsplen,
113 NumberMessageArg(syntax().attsplen()),
114 NumberMessageArg(specLength));
118 Boolean Parser::handleAttributeNameToken(Text &text,
120 unsigned &specLength)
123 if (!atts.tokenIndex(text.string(), index)) {
124 if (atts.handleAsUnterminated(*this))
126 atts.noteInvalidSpec();
127 message(ParserMessages::noSuchAttributeToken,
128 StringMessageArg(text.string()));
131 if (!sd().shorttag())
132 message(ParserMessages::attributeNameShorttag);
133 atts.setSpec(index, *this);
134 atts.setValueToken(index, text, *this, specLength);
139 Boolean Parser::parseAttributeValueSpec(Boolean inDecl,
142 unsigned &specLength)
144 Mode mode = inDecl ? asMode : tagMode;
145 Markup *markup = currentMarkup();
146 Token token = getToken(mode);
147 if (token == tokenS) {
150 markup->addS(currentChar());
151 token = getToken(mode);
152 } while (token == tokenS);
156 token = getToken(mode);
157 } while (token == tokenS);
161 Boolean valid = atts.attributeIndex(name, index);
163 message(ParserMessages::noSuchAttribute, StringMessageArg(name));
164 atts.noteInvalidSpec();
167 atts.setSpec(index, *this);
170 case tokenUnrecognized:
171 if (reportNonSgmlCharacter())
177 message(ParserMessages::unquotedAttributeValue);
178 extendUnquotedAttributeValue();
180 markup->addAttributeValue(currentInput());
181 text.addChars(currentInput()->currentTokenStart(),
182 currentInput()->currentTokenLength(),
186 message(ParserMessages::attributeSpecEntityEnd);
191 message(ParserMessages::attributeValueExpected);
195 case tokenLcUcNmchar:
196 if (!sd().shorttag())
197 message(ParserMessages::attributeValueShorttag);
198 extendNameToken(syntax().litlen() >= syntax().normsep()
199 ? syntax().litlen() - syntax().normsep()
201 ParserMessages::attributeValueLength);
203 markup->addAttributeValue(currentInput());
204 text.addChars(currentInput()->currentTokenStart(),
205 currentInput()->currentTokenLength(),
211 lita = (token == tokenLita);
212 if (!((valid ? atts.tokenized(index) : 1)
213 ? parseTokenizedAttributeValueLiteral(lita, text)
214 : parseAttributeValueLiteral(lita, text)))
217 markup->addLiteral(text);
223 return atts.setValue(index, text, *this, specLength);
225 return !AttributeValue::handleAsUnterminated(text, *this);
229 Boolean Parser::parseAttributeParameter(Boolean inDecl,
231 AttributeParameter::Type &result,
232 Boolean &netEnabling)
234 Mode mode = inDecl ? asMode : tagMode;
235 Token token = getToken(mode);
236 Markup *markup = currentMarkup();
238 while (token == tokenS) {
239 markup->addS(currentChar());
240 token = getToken(mode);
244 while (token == tokenS)
245 token = getToken(mode);
248 case tokenUnrecognized:
249 if (reportNonSgmlCharacter())
251 extendUnquotedAttributeValue();
252 result = AttributeParameter::recoverUnquoted;
255 message(ParserMessages::attributeSpecEntityEnd);
259 if (!sd().shorttag())
260 message(ParserMessages::minimizedStartTag);
261 else if (options().warnUnclosedTag)
262 message(ParserMessages::unclosedStartTag);
263 result = AttributeParameter::end;
264 currentInput()->ungetToken();
269 markup->addDelim(Syntax::dNET);
270 if (!sd().shorttag())
271 message(ParserMessages::minimizedStartTag);
272 else if (options().warnNet)
273 message(ParserMessages::netStartTag);
275 result = AttributeParameter::end;
279 markup->addDelim(Syntax::dTAGC);
281 result = AttributeParameter::end;
285 markup->addDelim(Syntax::dDSC);
286 result = AttributeParameter::end;
289 extendNameToken(syntax().namelen(), ParserMessages::nameTokenLength);
291 markup->addName(currentInput());
292 result = AttributeParameter::name;
295 case tokenLcUcNmchar:
296 extendNameToken(syntax().namelen(), ParserMessages::nameTokenLength);
298 markup->addName(currentInput());
299 result = AttributeParameter::nameToken;
304 ? ParserMessages::attributeSpecLiteral
305 : ParserMessages::attributeSpecNameTokenExpected);
309 message(ParserMessages::attributeSpecNameTokenExpected);
313 markup->addDelim(Syntax::dVI);
314 result = AttributeParameter::vi;
322 void Parser::extendUnquotedAttributeValue()
324 InputSource *in = currentInput();
325 size_t length = in->currentTokenLength();
326 const Syntax &syn = syntax();
328 Xchar c = in->tokenChar(messenger());
330 || !syn.isSgmlChar(c)
331 || c == InputSource::eE
332 || c == syn.delimGeneral(Syntax::dTAGC)[0])
336 in->endToken(length);
339 Boolean Parser::parseAttributeValueLiteral(Boolean lita, Text &text)
341 size_t maxLength = (syntax().litlen() > syntax().normsep()
342 ? syntax().litlen() - syntax().normsep()
344 if (parseLiteral(lita ? alitaMode : alitMode, aliteMode,
346 ParserMessages::attributeValueLength,
347 (wantMarkup() ? unsigned(literalDelimInfo) : 0),
350 && syntax().normsep() > syntax().litlen())
351 message(ParserMessages::attributeValueLengthNeg,
352 NumberMessageArg(syntax().normsep() - syntax().litlen()));
359 Boolean Parser::parseTokenizedAttributeValueLiteral(Boolean lita, Text &text)
361 size_t maxLength = (syntax().litlen() > syntax().normsep()
362 ? syntax().litlen() - syntax().normsep()
364 if (parseLiteral(lita ? talitaMode : talitMode, taliteMode,
366 ParserMessages::tokenizedAttributeValueLength,
368 | (wantMarkup() ? unsigned(literalDelimInfo) : 0),
371 && syntax().normsep() > syntax().litlen())
372 message(ParserMessages::tokenizedAttributeValueLengthNeg,
373 NumberMessageArg(syntax().normsep() - syntax().litlen()));
381 Boolean Parser::skipAttributeSpec()
383 AttributeParameter::Type parm;
385 if (!parseAttributeParameter(0, 0, parm, netEnabling))
387 while (parm != AttributeParameter::end) {
388 if (parm == AttributeParameter::name) {
389 size_t nameMarkupIndex = 0;
391 nameMarkupIndex = currentMarkup()->size() - 1;
392 if (!parseAttributeParameter(0, 1, parm, netEnabling))
394 if (parm == AttributeParameter::vi) {
395 Token token = getToken(tagMode);
396 while (token == tokenS) {
398 currentMarkup()->addS(currentChar());
399 token = getToken(tagMode);
402 case tokenUnrecognized:
403 if (!reportNonSgmlCharacter())
404 message(ParserMessages::attributeSpecCharacter,
405 StringMessageArg(currentToken()));
408 message(ParserMessages::attributeSpecEntityEnd);
416 message(ParserMessages::attributeValueExpected);
420 case tokenLcUcNmchar:
421 if (!sd().shorttag())
422 message(ParserMessages::attributeValueShorttag);
423 extendNameToken(syntax().litlen() >= syntax().normsep()
424 ? syntax().litlen() - syntax().normsep()
426 ParserMessages::attributeValueLength);
428 currentMarkup()->addAttributeValue(currentInput());
434 if (!parseLiteral(token == tokenLita ? talitaMode : talitMode,
437 ParserMessages::tokenizedAttributeValueLength,
438 (currentMarkup() ? literalDelimInfo : 0)
443 currentMarkup()->addLiteral(text);
449 if (!parseAttributeParameter(0, 0, parm, netEnabling))
454 currentMarkup()->changeToAttributeValue(nameMarkupIndex);
455 if (!sd().shorttag())
456 message(ParserMessages::attributeNameShorttag);
460 // It's a name token.
461 if (!parseAttributeParameter(0, 0, parm, netEnabling))
463 if (!sd().shorttag())
464 message(ParserMessages::attributeNameShorttag);
468 message(ParserMessages::startTagGroupNet);