summaryrefslogtreecommitdiff
path: root/gprofng/src/SAXParserFactory.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng/src/SAXParserFactory.cc')
-rw-r--r--gprofng/src/SAXParserFactory.cc666
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 &lt; &gt;
+ 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 &amp;
+ 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 &apos; &quot;
+ 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));
+ }
+}