1 /* Copyright (C) 2021 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
26 #include "DefaultHandler.h"
27 #include "SAXParser.h"
28 #include "SAXParserFactory.h"
29 #include "StringBuilder.h"
32 * Private implementation of Attributes
34 class AttributesP : public Attributes
40 const char *getQName (int index);
41 const char *getValue (int index);
42 int getIndex (const char *qName);
43 const char *getValue (const char *qName);
44 void append (char *qName, char *value);
48 Vector<char*> *values;
51 AttributesP::AttributesP ()
53 names = new Vector<char*>;
54 values = new Vector<char*>;
57 AttributesP::~AttributesP ()
64 AttributesP::getLength ()
66 return names->size ();
70 AttributesP::getQName (int index)
72 if (index < 0 || index >= names->size ())
74 return names->fetch (index);
78 AttributesP::getValue (int index)
80 if (index < 0 || index >= values->size ())
82 return values->fetch (index);
86 AttributesP::getIndex (const char *qName)
88 for (int idx = 0; idx < names->size (); idx++)
89 if (strcmp (names->fetch (idx), qName) == 0)
95 AttributesP::getValue (const char *qName)
97 for (int idx = 0; idx < names->size (); idx++)
98 if (strcmp (names->fetch (idx), qName) == 0)
99 return values->fetch (idx);
104 AttributesP::append (char *qName, char *value)
106 names->append (qName);
107 values->append (value);
111 * Implementation of SAXException
113 SAXException::SAXException ()
115 message = strdup ("null");
118 SAXException::SAXException (const char *_message)
120 if (_message == NULL)
121 message = strdup ("null");
123 message = strdup (_message);
126 SAXException::~SAXException ()
132 SAXException::getMessage ()
140 SAXParseException::SAXParseException (char *message, int _lineNumber, int _columnNumber)
141 : SAXException (message == NULL ? GTXT ("XML parse error") : message)
143 lineNumber = _lineNumber;
144 columnNumber = _columnNumber;
148 * Private implementation of SAXParser
150 class SAXParserP : public SAXParser
156 void parse (File*, DefaultHandler*);
172 static const int CH_EOF = -1;
177 void scanString (const char *str);
179 char *parseString ();
180 char *decodeString (char *str);
181 Attributes *parseAttributes ();
183 void parseDocument ();
184 void parsePart (int idx);
196 SAXParserP::SAXParserP ()
200 buffer = (char*) malloc (bufsz);
207 SAXParserP::~SAXParserP ()
217 buffer = (char*) realloc (buffer, bufsz);
225 SAXParserP::parse (File *f, DefaultHandler *_dh)
230 FILE *file = (FILE*) f;
236 int n = (int) fread (buffer + cntsz, 1, rem, file);
237 if (ferror (file) || n <= 0)
245 int oldbufsz = bufsz;
246 bufsz = bufsz >= 0x100000 ? bufsz + 0x100000 : bufsz * 2;
247 buffer = (char*) realloc (buffer, bufsz);
248 rem = bufsz - oldbufsz;
258 if (c >= '0' && c <= '9')
260 else if (c >= 'a' && c <= 'f')
261 return 10 + (c - 'a');
266 SAXParserP::nextch ()
268 curch = idx >= cntsz ? CH_EOF : buffer[idx++];
279 SAXParserP::isWSpace ()
281 return curch == ' ' || curch == '\t' || curch == '\n' || curch == '\r';
285 SAXParserP::skipWSpaces ()
292 SAXParserP::scanString (const char *str)
294 if (str == NULL || *str == '\0')
300 else if (curch == *str)
318 SAXParserP::parseName ()
320 StringBuilder *name = new StringBuilder ();
322 if ((curch >= 'A' && curch <= 'Z') || (curch >= 'a' && curch <= 'z'))
324 name->append ((char) curch);
326 while (isalnum (curch) != 0 || curch == '_')
328 name->append ((char) curch);
333 char *res = name->toString ();
339 * Replaces encoded XML characters with original characters
340 * Attention: this method reuses the same string that is passed as the argument
345 SAXParserP::decodeString (char * str)
347 // Check if string has %22% and replace it with double quotes
348 // Also replace all other special combinations.
351 if (strstr (from, "%") || strstr (from, "&"))
353 int len = strlen (from);
354 for (int i = 0; i < len; i++)
357 // Process &...; combinations
358 if (nch == '&' && i + 3 < len)
360 if (from[i + 2] == 't' && from[i + 3] == ';')
363 if (from[i + 1] == 'l')
368 else if (from[i + 1] == 'g')
374 else if (i + 4 < len && from[i + 4] == ';')
377 if (from[i + 1] == 'a' && from[i + 2] == 'm' && from[i + 3] == 'p')
383 else if ((i + 5 < len) && (from[i + 5] == ';'))
385 // check ' "
386 if (from[i + 1] == 'a' && from[i + 2] == 'p'
387 && from[i + 3] == 'o' && from[i + 4] == 's')
392 if (from[i + 1] == 'q' && from[i + 2] == 'u' && from[i + 3] == 'o' && from[i + 4] == 't')
399 // Process %XX% combinations
400 if (nch == '%' && i + 3 < len && from[i + 3] == '%')
402 int ch = hex (from[i + 1]);
405 int ch2 = hex (from[i + 2]);
422 SAXParserP::parseString ()
424 StringBuilder *str = new StringBuilder ();
440 str->append ((char) curch);
444 char *res = str->toString ();
445 // Decode XML characters
446 res = decodeString (res);
452 SAXParserP::parseAttributes ()
454 AttributesP *attrs = new AttributesP ();
459 char *name = parseName ();
460 if (name == NULL || *name == '\0')
468 SAXParseException *e = new SAXParseException (NULL, line, column);
476 char *value = parseString ();
477 attrs->append (name, value);
483 SAXParserP::parseTag ()
487 char *name = parseName ();
488 if (name == NULL || *name == '\0')
490 SAXParseException *e = new SAXParseException (NULL, line, column);
497 Attributes *attrs = parseAttributes ();
508 SAXParseException *e = new SAXParseException (NULL, line, column);
518 dh->startElement (NULL, NULL, name, attrs);
521 dh->endElement (NULL, NULL, name);
527 StringBuilder *chars = new StringBuilder ();
533 else if (curch == '<')
535 if (chars->length () > 0)
537 char *str = chars->toString ();
538 // Decode XML characters
539 str = decodeString (str);
541 dh->ignorableWhitespace (str, 0, chars->length ());
543 dh->characters (str, 0, chars->length ());
545 chars->setLength (0);
552 char *ename = parseName ();
553 if (ename && *ename != '\0')
555 if (strcmp (name, ename) == 0)
561 dh->endElement (NULL, NULL, name);
565 SAXParseException *e = new SAXParseException (NULL, line, column);
570 SAXParseException *e = new SAXParseException (NULL, line, column);
584 chars->append ((char) curch);
596 SAXParserP::parseDocument ()
598 dh->startDocument ();
608 else if (curch == '!')
620 * Private implementation of SAXParserFactory
622 class SAXParserFactoryP : public SAXParserFactory
625 SAXParserFactoryP () { }
626 ~SAXParserFactoryP () { }
627 SAXParser *newSAXParser ();
630 setFeature (const char *, bool) { }
633 getFeature (const char *)
640 SAXParserFactoryP::newSAXParser ()
642 return new SAXParserP ();
648 const char *SAXParserFactory::DEFAULT_PROPERTY_NAME = "javax.xml.parsers.SAXParserFactory";
651 SAXParserFactory::newInstance ()
653 return new SAXParserFactoryP ();
657 DefaultHandler::dump_startElement (const char *qName, Attributes *attrs)
659 fprintf (stderr, NTXT ("DefaultHandler::startElement qName='%s'\n"), STR (qName));
660 for (int i = 0, sz = attrs ? attrs->getLength () : 0; i < sz; i++)
662 const char *qn = attrs->getQName (i);
663 const char *vl = attrs->getValue (i);
664 fprintf (stderr, NTXT (" %d '%s' = '%s'\n"), i, STR (qn), STR (vl));