diff options
Diffstat (limited to 'gprofng/src/SAXParserFactory.cc')
-rw-r--r-- | gprofng/src/SAXParserFactory.cc | 666 |
1 files changed, 666 insertions, 0 deletions
diff --git a/gprofng/src/SAXParserFactory.cc b/gprofng/src/SAXParserFactory.cc new file mode 100644 index 00000000000..7d9e8518494 --- /dev/null +++ b/gprofng/src/SAXParserFactory.cc @@ -0,0 +1,666 @@ +/* Copyright (C) 2021 Free Software Foundation, Inc. + Contributed by Oracle. + + This file is part of GNU Binutils. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "config.h" +#include <ctype.h> + +#include "util.h" +#include "vec.h" +#include "DefaultHandler.h" +#include "SAXParser.h" +#include "SAXParserFactory.h" +#include "StringBuilder.h" + +/* + * Private implementation of Attributes + */ +class AttributesP : public Attributes +{ +public: + AttributesP (); + ~AttributesP (); + int getLength (); + const char *getQName (int index); + const char *getValue (int index); + int getIndex (const char *qName); + const char *getValue (const char *qName); + void append (char *qName, char *value); + +private: + Vector<char*> *names; + Vector<char*> *values; +}; + +AttributesP::AttributesP () +{ + names = new Vector<char*>; + values = new Vector<char*>; +} + +AttributesP::~AttributesP () +{ + Destroy (names); + Destroy (values); +} + +int +AttributesP::getLength () +{ + return names->size (); +} + +const char * +AttributesP::getQName (int index) +{ + if (index < 0 || index >= names->size ()) + return NULL; + return names->fetch (index); +} + +const char * +AttributesP::getValue (int index) +{ + if (index < 0 || index >= values->size ()) + return NULL; + return values->fetch (index); +} + +int +AttributesP::getIndex (const char *qName) +{ + for (int idx = 0; idx < names->size (); idx++) + if (strcmp (names->fetch (idx), qName) == 0) + return idx; + return -1; +} + +const char * +AttributesP::getValue (const char *qName) +{ + for (int idx = 0; idx < names->size (); idx++) + if (strcmp (names->fetch (idx), qName) == 0) + return values->fetch (idx); + return NULL; +} + +void +AttributesP::append (char *qName, char *value) +{ + names->append (qName); + values->append (value); +} + +/* + * Implementation of SAXException + */ +SAXException::SAXException () +{ + message = strdup ("null"); +} + +SAXException::SAXException (const char *_message) +{ + if (_message == NULL) + message = strdup ("null"); + else + message = strdup (_message); +} + +SAXException::~SAXException () +{ + free (message); +} + +char * +SAXException::getMessage () +{ + return message; +} + +/* + * SAXParseException + */ +SAXParseException::SAXParseException (char *message, int _lineNumber, int _columnNumber) +: SAXException (message == NULL ? GTXT ("XML parse error") : message) +{ + lineNumber = _lineNumber; + columnNumber = _columnNumber; +} + +/* + * Private implementation of SAXParser + */ +class SAXParserP : public SAXParser +{ +public: + SAXParserP (); + ~SAXParserP (); + void reset (); + void parse (File*, DefaultHandler*); + + bool + isNamespaceAware () + { + return false; + } + + bool + isValidating () + { + return false; + } + +private: + + static const int CH_EOF = -1; + + void nextch (); + bool isWSpace (); + void skipWSpaces (); + void scanString (const char *str); + char *parseName (); + char *parseString (); + char *decodeString (char *str); + Attributes *parseAttributes (); + void parseTag (); + void parseDocument (); + void parsePart (int idx); + + DefaultHandler *dh; + int bufsz; + char *buffer; + int cntsz; + int idx; + int curch; + int line; + int column; +}; + +SAXParserP::SAXParserP () +{ + dh = NULL; + bufsz = 0x2000; + buffer = (char*) malloc (bufsz); + cntsz = 0; + idx = 0; + line = 1; + column = 0; +} + +SAXParserP::~SAXParserP () +{ + free (buffer); +} + +void +SAXParserP::reset () +{ + dh = NULL; + bufsz = 8192; + buffer = (char*) realloc (buffer, bufsz); + cntsz = 0; + idx = 0; + line = 1; + column = 0; +} + +void +SAXParserP::parse (File *f, DefaultHandler *_dh) +{ + if (_dh == NULL) + return; + dh = _dh; + FILE *file = (FILE*) f; + int rem = bufsz; + cntsz = 0; + idx = 0; + for (;;) + { + int n = (int) fread (buffer + cntsz, 1, rem, file); + if (ferror (file) || n <= 0) + break; + cntsz += n; + if (feof (file)) + break; + rem -= n; + if (rem == 0) + { + int oldbufsz = bufsz; + bufsz = bufsz >= 0x100000 ? bufsz + 0x100000 : bufsz * 2; + buffer = (char*) realloc (buffer, bufsz); + rem = bufsz - oldbufsz; + } + } + nextch (); + parseDocument (); +} + +static int +hex (char c) +{ + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= 'a' && c <= 'f') + return 10 + (c - 'a'); + return -1; +} + +void +SAXParserP::nextch () +{ + curch = idx >= cntsz ? CH_EOF : buffer[idx++]; + if (curch == '\n') + { + line += 1; + column = 0; + } + else + column += 1; +} + +bool +SAXParserP::isWSpace () +{ + return curch == ' ' || curch == '\t' || curch == '\n' || curch == '\r'; +} + +void +SAXParserP::skipWSpaces () +{ + while (isWSpace ()) + nextch (); +} + +void +SAXParserP::scanString (const char *str) +{ + if (str == NULL || *str == '\0') + return; + for (;;) + { + if (curch == CH_EOF) + break; + else if (curch == *str) + { + const char *p = str; + for (;;) + { + p += 1; + nextch (); + if (*p == '\0') + return; + if (curch != *p) + break; + } + } + nextch (); + } +} + +char * +SAXParserP::parseName () +{ + StringBuilder *name = new StringBuilder (); + + if ((curch >= 'A' && curch <= 'Z') || (curch >= 'a' && curch <= 'z')) + { + name->append ((char) curch); + nextch (); + while (isalnum (curch) != 0 || curch == '_') + { + name->append ((char) curch); + nextch (); + } + } + + char *res = name->toString (); + delete name; + return res; +} + +/** + * Replaces encoded XML characters with original characters + * Attention: this method reuses the same string that is passed as the argument + * @param str + * @return str + */ +char * +SAXParserP::decodeString (char * str) +{ + // Check if string has %22% and replace it with double quotes + // Also replace all other special combinations. + char *from = str; + char *to = str; + if (strstr (from, "%") || strstr (from, "&")) + { + int len = strlen (from); + for (int i = 0; i < len; i++) + { + int nch = from[i]; + // Process &...; combinations + if (nch == '&' && i + 3 < len) + { + if (from[i + 2] == 't' && from[i + 3] == ';') + { + // check < > + if (from[i + 1] == 'l') + { + nch = '<'; + i += 3; + } + else if (from[i + 1] == 'g') + { + nch = '>'; + i += 3; + } + } + else if (i + 4 < len && from[i + 4] == ';') + { + // check & + if (from[i + 1] == 'a' && from[i + 2] == 'm' && from[i + 3] == 'p') + { + nch = '&'; + i += 4; + } + } + else if ((i + 5 < len) && (from[i + 5] == ';')) + { + // check ' " + if (from[i + 1] == 'a' && from[i + 2] == 'p' + && from[i + 3] == 'o' && from[i + 4] == 's') + { + nch = '\''; + i += 5; + } + if (from[i + 1] == 'q' && from[i + 2] == 'u' && from[i + 3] == 'o' && from[i + 4] == 't') + { + nch = '"'; + i += 5; + } + } + } + // Process %XX% combinations + if (nch == '%' && i + 3 < len && from[i + 3] == '%') + { + int ch = hex (from[i + 1]); + if (ch >= 0) + { + int ch2 = hex (from[i + 2]); + if (ch2 >= 0) + { + ch = ch * 16 + ch2; + nch = ch; + i += 3; + } + } + } + *to++ = (char) nch; + } + *to = '\0'; + } + return str; +} + +char * +SAXParserP::parseString () +{ + StringBuilder *str = new StringBuilder (); + int quote = '>'; + if (curch == '"') + { + quote = curch; + nextch (); + } + for (;;) + { + if (curch == CH_EOF) + break; + if (curch == quote) + { + nextch (); + break; + } + str->append ((char) curch); + nextch (); + } + + char *res = str->toString (); + // Decode XML characters + res = decodeString (res); + delete str; + return res; +} + +Attributes * +SAXParserP::parseAttributes () +{ + AttributesP *attrs = new AttributesP (); + + for (;;) + { + skipWSpaces (); + char *name = parseName (); + if (name == NULL || *name == '\0') + { + free (name); + break; + } + skipWSpaces (); + if (curch != '=') + { + SAXParseException *e = new SAXParseException (NULL, line, column); + dh->error (e); + scanString (">"); + free (name); + return attrs; + } + nextch (); + skipWSpaces (); + char *value = parseString (); + attrs->append (name, value); + } + return attrs; +} + +void +SAXParserP::parseTag () +{ + skipWSpaces (); + bool empty = false; + char *name = parseName (); + if (name == NULL || *name == '\0') + { + SAXParseException *e = new SAXParseException (NULL, line, column); + dh->error (e); + scanString (">"); + free (name); + return; + } + + Attributes *attrs = parseAttributes (); + if (curch == '/') + { + nextch (); + empty = true; + } + if (curch == '>') + nextch (); + else + { + empty = false; + SAXParseException *e = new SAXParseException (NULL, line, column); + dh->error (e); + scanString (">"); + } + if (curch == CH_EOF) + { + free (name); + delete attrs; + return; + } + dh->startElement (NULL, NULL, name, attrs); + if (empty) + { + dh->endElement (NULL, NULL, name); + free (name); + delete attrs; + return; + } + + StringBuilder *chars = new StringBuilder (); + bool wspaces = true; + for (;;) + { + if (curch == CH_EOF) + break; + else if (curch == '<') + { + if (chars->length () > 0) + { + char *str = chars->toString (); + // Decode XML characters + str = decodeString (str); + if (wspaces) + dh->ignorableWhitespace (str, 0, chars->length ()); + else + dh->characters (str, 0, chars->length ()); + free (str); + chars->setLength (0); + wspaces = true; + } + nextch (); + if (curch == '/') + { + nextch (); + char *ename = parseName (); + if (ename && *ename != '\0') + { + if (strcmp (name, ename) == 0) + { + skipWSpaces (); + if (curch == '>') + { + nextch (); + dh->endElement (NULL, NULL, name); + free (ename); + break; + } + SAXParseException *e = new SAXParseException (NULL, line, column); + dh->error (e); + } + else + { + SAXParseException *e = new SAXParseException (NULL, line, column); + dh->error (e); + } + scanString (">"); + } + free (ename); + } + else + parseTag (); + } + else + { + if (!isWSpace ()) + wspaces = false; + chars->append ((char) curch); + nextch (); + } + } + + free (name); + delete attrs; + delete chars; + return; +} + +void +SAXParserP::parseDocument () +{ + dh->startDocument (); + for (;;) + { + if (curch == CH_EOF) + break; + if (curch == '<') + { + nextch (); + if (curch == '?') + scanString ("?>"); + else if (curch == '!') + scanString (">"); + else + parseTag (); + } + else + nextch (); + } + dh->endDocument (); +} + +/* + * Private implementation of SAXParserFactory + */ +class SAXParserFactoryP : public SAXParserFactory +{ +public: + SAXParserFactoryP () { } + ~SAXParserFactoryP () { } + SAXParser *newSAXParser (); + + void + setFeature (const char *, bool) { } + + bool + getFeature (const char *) + { + return false; + } +}; + +SAXParser * +SAXParserFactoryP::newSAXParser () +{ + return new SAXParserP (); +} + +/* + * SAXParserFactory + */ +const char *SAXParserFactory::DEFAULT_PROPERTY_NAME = "javax.xml.parsers.SAXParserFactory"; + +SAXParserFactory * +SAXParserFactory::newInstance () +{ + return new SAXParserFactoryP (); +} + +void +DefaultHandler::dump_startElement (const char *qName, Attributes *attrs) +{ + fprintf (stderr, NTXT ("DefaultHandler::startElement qName='%s'\n"), STR (qName)); + for (int i = 0, sz = attrs ? attrs->getLength () : 0; i < sz; i++) + { + const char *qn = attrs->getQName (i); + const char *vl = attrs->getValue (i); + fprintf (stderr, NTXT (" %d '%s' = '%s'\n"), i, STR (qn), STR (vl)); + } +} |