* XML XInclude support
@ 2007-01-29 21:32 Daniel Jacobowitz
2007-01-31 18:33 ` Daniel Jacobowitz
2007-02-02 18:53 ` Eli Zaretskii
0 siblings, 2 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2007-01-29 21:32 UTC (permalink / raw)
To: gdb-patches; +Cc: Eli Zaretskii
This patch adds support for a limited subset (I confess, very limited)
of XInclude to GDB's target description parser. It's a simple textual
transform. A file that looks like this:
<target>
<xi:include href="other.xml"/>
</target>
is expanded to include the contents of other.xml instead of the
xi:include element, before parsing it as a target description.
For "set tdesc filename" other.xml should be in the same directory
as the original description. For qXfer:features, other.xml is
a new annex to read from the target.
This is really handy, because it allows descriptions to be broken up
into pieces. One place where we use it is when most of a description
is static, but part is determined at runtime by the remote debug stub -
it can include the correct elements for e.g. a target with or without
floating point registers once it knows which one it's got. This limits
the amount of XML the debug stub has to know about or generate.
It's also handy for reuseable bits of descriptions, like separating
the bit that describes architecture core registers from the bit that
describes whatever motivated you to write an XML description in the
first place.
Also included are documentation and test cases. I've tested this on
arm-none-linux-gnueabi and x86_64-pc-linux-gnu. The patch is pretty
uninteresting; if the documentation is OK, I plan to apply it when
the next couple of things I'm posting are ready.
Oh, if anyone has a better portable way to convert a blob of text into
a C array than my shell/awk hybrid, do let me know, thanks :-)
--
Daniel Jacobowitz
CodeSourcery
2007-01-29 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (XMLFILES): New.
(COMMON_OBS): Add xml-builtin.o.
(xml-builtin.c, stamp-xml): New rules.
(xml-tdesc.o): Update.
* features/feature_to_c.sh: New file.
* xml-support.c (MAX_XINCLUDE_DEPTH): Define.
(struct gdb_xml_parser): Add dtd_name and is_xinclude.
(gdb_xml_start_element): Initialize scope after possibly reallocating
scopes. Move cleanup later. Handle the XInclude description
specially.
(gdb_xml_end_element): Only parse the body if there is a current element.
Call XML_DefaultCurrent if there is no element.
(gdb_xml_fetch_external_entity, gdb_xml_use_dtd): New.
(struct xinclude_parsing_data, xinclude_start_include)
(xinclude_end_include, xml_xinclude_default)
(xml_xinclude_start_doctype, xml_xinclude_end_doctype)
(xml_xinclude_xml_decl, xml_xinclude_cleanup, xinclude_attributes)
(xinclude_elements, xml_process_xincludes, fetch_xml_builtin): New.
* xml-support.h (xml_fetch_another, xml_process_xincludes)
(fetch_xml_builtin, xml_builtin, gdb_xml_use_dtd): New declarations.
* xml-tdesc.c (tdesc_parse_xml): Add fetcher_baton argument. Expand
XInclude directives. Use the compiled in DTD.
(fetch_xml_from_file): Add baton argument. Treat it as a containing
directory name. Do not warn here.
(file_read_description_xml): Update call. Warn here instead. Pass
a dirname as baton.
(fetch_available_features_from_target): New.
(target_read_description_xml): Use it.
* features/gdb-target.dtd: Add copyright notice. Use xinclude.dtd
to handle XInclude.
* features/xinclude.dtd: New file.
* gdb.xml/bad-include.xml, gdb.xml/inc-2.xml, gdb.xml/inc-body.xml,
gdb.xml/includes.xml, gdb.xml/tdesc-xinclude.exp: New files.
* gdb.texinfo (Target Description Format): Add section on XInclude.
---
gdb/Makefile.in | 20 +
gdb/doc/gdb.texinfo | 21 +
gdb/features/feature_to_c.sh | 77 ++++++
gdb/features/gdb-target.dtd | 11
gdb/features/xinclude.dtd | 13 +
gdb/testsuite/gdb.xml/bad-include.xml | 1
gdb/testsuite/gdb.xml/inc-2.xml | 1
gdb/testsuite/gdb.xml/inc-body.xml | 1
gdb/testsuite/gdb.xml/includes.xml | 3
gdb/testsuite/gdb.xml/tdesc-xinclude.exp | 54 ++++
gdb/xml-support.c | 372 +++++++++++++++++++++++++++++--
gdb/xml-support.h | 34 ++
gdb/xml-tdesc.c | 98 ++++++--
13 files changed, 661 insertions(+), 45 deletions(-)
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in 2007-01-29 12:37:14.000000000 -0500
+++ src/gdb/Makefile.in 2007-01-29 12:39:10.000000000 -0500
@@ -400,6 +400,9 @@ LINTFLAGS= $(GDB_CFLAGS) $(OPCODES_CFLAG
RUNTEST = runtest
RUNTESTFLAGS=
+# XML files to build in to GDB.
+XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd
+
# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
# interface to the serial port. Hopefully if get ported to OS/2, VMS,
# etc., then there will be (as part of the C library or perhaps as
@@ -972,7 +975,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
tramp-frame.o \
solib.o solib-null.o \
prologue-value.o memory-map.o xml-support.o \
- target-descriptions.o target-memory.o xml-tdesc.o
+ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
TSOBS = inflow.o
@@ -1681,6 +1684,19 @@ po/$(PACKAGE).pot: force
.PRECIOUS: objc-exp.c
.PRECIOUS: p-exp.c
+# XML rules
+
+xml-builtin.c: stamp-xml; @true
+stamp-xml: $(srcdir)/features/feature_to_c.sh Makefile $(XMLFILES)
+ rm -f xml-builtin.tmp
+ AWK="$(AWK)" \
+ $(SHELL) $(srcdir)/features/feature_to_c.sh \
+ xml-builtin.tmp $(XMLFILES)
+ $(SHELL) $(srcdir)/../move-if-change xml-builtin.tmp xml-builtin.c
+ echo stamp > stamp-xml
+
+.PRECIOUS: xml-builtin.c
+
#
# gdb/ dependencies
#
@@ -2876,7 +2892,7 @@ xcoffread.o: xcoffread.c $(defs_h) $(bfd
xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \
$(gdbcmd_h) $(symfile_h) $(frame_h) $(gdb_regex_h)
xml-tdesc.o: xml-tdesc.c $(defs_h) $(target_h) $(target_descriptions_h) \
- $(xml_tdesc_h) $(xml_support_h) $(gdb_assert_h)
+ $(xml_tdesc_h) $(xml_support_h) $(filenames_h) $(gdb_assert_h)
xml-support.o: xml-support.c $(defs_h) $(xml_support_h) $(exceptions_h) \
$(gdbcmd_h) $(gdb_string_h) $(gdb_expat_h) $(safe_ctype_h)
xstormy16-tdep.o: xstormy16-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \
Index: src/gdb/features/feature_to_c.sh
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/features/feature_to_c.sh 2007-01-29 12:39:10.000000000 -0500
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+# Convert text files to compilable C arrays.
+#
+# Copyright (C) 2007 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# 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 2 of the License, 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, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+output=$1
+shift
+
+if test -z "$output" || test -z "$1"; then
+ echo "Usage: $0 OUTPUTFILE INPUTFILE..."
+ exit 1
+fi
+
+if test -e "$output"; then
+ echo "Output file \"$output\" already exists; refusing to overwrite."
+ exit 1
+fi
+
+for input; do
+ arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
+
+ ${AWK:-awk} 'BEGIN { n = 0
+ print "static const char '$arrayname'[] = {"
+ for (i = 0; i < 255; i++)
+ _ord_[sprintf("%c", i)] = i
+ } {
+ split($0, line, "");
+ printf " "
+ for (i = 1; i <= length($0); i++) {
+ c = line[i]
+ if (c == "'\''") {
+ printf "'\''\\'\'''\'', "
+ } else if (c == "\\") {
+ printf "'\''\\\\'\'', "
+ } else if (_ord_[c] >= 32 && _ord_[c] < 127) {
+ printf "'\''" c "'\'', "
+ } else {
+ printf "'\''\\%03o'\'', ", _ord_[c]
+ }
+ if (i % 10 == 0)
+ printf "\n "
+ }
+ printf "'\''\\n'\'', \n"
+ } END {
+ print " 0 };"
+ }' < $input >> $output
+done
+
+echo >> $output
+echo "const char *const xml_builtin[][2] = {" >> $output
+
+for input; do
+ basename=`echo $input | sed 's,.*/,,'`
+ arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
+ echo " { \"$basename\", $arrayname }," >> $output
+done
+
+echo " { 0, 0 }" >> $output
+echo "};" >> $output
Index: src/gdb/xml-support.c
===================================================================
--- src.orig/gdb/xml-support.c 2007-01-29 12:37:14.000000000 -0500
+++ src/gdb/xml-support.c 2007-01-29 12:39:10.000000000 -0500
@@ -36,6 +36,10 @@ static int debug_xml;
#include "gdb_string.h"
#include "safe-ctype.h"
+/* The maximum depth of <xi:include> nesting. No need to be miserly,
+ we just want to avoid running out of stack on loops. */
+#define MAX_XINCLUDE_DEPTH 30
+
/* A parsing level -- used to keep track of the current element
nesting. */
struct scope_level
@@ -68,6 +72,10 @@ struct gdb_xml_parser
struct gdb_exception error; /* A thrown error, if any. */
int last_line; /* The line of the thrown error, or 0. */
+
+ const char *dtd_name; /* The name of the expected / default DTD,
+ if specified. */
+ int is_xinclude; /* Are we the special <xi:include> parser? */
};
/* Process some body text. We accumulate the text for later use; it's
@@ -152,7 +160,7 @@ gdb_xml_start_element (void *data, const
const XML_Char **attrs)
{
struct gdb_xml_parser *parser = data;
- struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
+ struct scope_level *scope;
struct scope_level new_scope;
const struct gdb_xml_element *element;
const struct gdb_xml_attribute *attribute;
@@ -160,13 +168,13 @@ gdb_xml_start_element (void *data, const
unsigned int seen;
struct cleanup *back_to;
- back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
-
/* Push an error scope. If we return or throw an exception before
filling this in, it will tell us to ignore children of this
element. */
+ VEC_reserve (scope_level_s, parser->scopes, 1);
+ scope = VEC_last (scope_level_s, parser->scopes);
memset (&new_scope, 0, sizeof (new_scope));
- VEC_safe_push (scope_level_s, parser->scopes, &new_scope);
+ VEC_quick_push (scope_level_s, parser->scopes, &new_scope);
gdb_xml_debug (parser, _("Entering element <%s>"), name);
@@ -181,8 +189,21 @@ gdb_xml_start_element (void *data, const
if (element == NULL || element->name == NULL)
{
+ /* If we're working on XInclude, <xi:include> can be the child
+ of absolutely anything. Copy the previous scope's element
+ list into the new scope even if there was no match. */
+ if (parser->is_xinclude)
+ {
+ struct scope_level *unknown_scope;
+
+ XML_DefaultCurrent (parser->expat_parser);
+
+ unknown_scope = VEC_last (scope_level_s, parser->scopes);
+ unknown_scope->elements = scope->elements;
+ return;
+ }
+
gdb_xml_debug (parser, _("Element <%s> unknown"), name);
- do_cleanups (back_to);
return;
}
@@ -191,6 +212,8 @@ gdb_xml_start_element (void *data, const
scope->seen |= seen;
+ back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
+
for (attribute = element->attributes;
attribute != NULL && attribute->name != NULL;
attribute++)
@@ -304,7 +327,6 @@ gdb_xml_end_element (void *data, const X
struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
const struct gdb_xml_element *element;
unsigned int seen;
- char *body;
gdb_xml_debug (parser, _("Leaving element <%s>"), name);
@@ -317,26 +339,32 @@ gdb_xml_end_element (void *data, const X
element->name);
/* Call the element processor. */
- if (scope->body == NULL)
- body = "";
- else
+ if (scope->element != NULL && scope->element->end_handler)
{
- int length;
+ char *body;
- length = obstack_object_size (scope->body);
- obstack_1grow (scope->body, '\0');
- body = obstack_finish (scope->body);
-
- /* Strip leading and trailing whitespace. */
- while (length > 0 && ISSPACE (body[length-1]))
- body[--length] = '\0';
- while (*body && ISSPACE (*body))
- body++;
- }
+ if (scope->body == NULL)
+ body = "";
+ else
+ {
+ int length;
- if (scope->element != NULL && scope->element->end_handler)
- scope->element->end_handler (parser, scope->element, parser->user_data,
- body);
+ length = obstack_object_size (scope->body);
+ obstack_1grow (scope->body, '\0');
+ body = obstack_finish (scope->body);
+
+ /* Strip leading and trailing whitespace. */
+ while (length > 0 && ISSPACE (body[length-1]))
+ body[--length] = '\0';
+ while (*body && ISSPACE (*body))
+ body++;
+ }
+
+ scope->element->end_handler (parser, scope->element, parser->user_data,
+ body);
+ }
+ else if (scope->element == NULL)
+ XML_DefaultCurrent (parser->expat_parser);
/* Pop the scope level. */
if (scope->body)
@@ -435,6 +463,74 @@ gdb_xml_create_parser_and_cleanup (const
return parser;
}
+/* External entity handler. The only external entities we support
+ are those compiled into GDB (we do not fetch entities from the
+ target). */
+
+static int XMLCALL
+gdb_xml_fetch_external_entity (XML_Parser expat_parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ struct gdb_xml_parser *parser = XML_GetUserData (expat_parser);
+ XML_Parser entity_parser;
+ const char *text;
+ enum XML_Status status;
+
+ if (systemId == NULL)
+ {
+ text = fetch_xml_builtin (parser->dtd_name);
+ if (text == NULL)
+ internal_error (__FILE__, __LINE__, "could not locate built-in DTD %s",
+ parser->dtd_name);
+ }
+ else
+ {
+ text = fetch_xml_builtin (systemId);
+ if (text == NULL)
+ return XML_STATUS_ERROR;
+ }
+
+ entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL);
+
+ /* Don't use our handlers for the contents of the DTD. Just let expat
+ process it. */
+ XML_SetElementHandler (entity_parser, NULL, NULL);
+ XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
+ XML_SetXmlDeclHandler (entity_parser, NULL);
+ XML_SetDefaultHandler (entity_parser, NULL);
+ XML_SetUserData (entity_parser, NULL);
+
+ status = XML_Parse (entity_parser, text, strlen (text), 1);
+
+ XML_ParserFree (entity_parser);
+ return status;
+}
+
+/* Associate DTD_NAME, which must be the name of a compiled-in DTD,
+ with PARSER. */
+
+void
+gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name)
+{
+ enum XML_Error err;
+
+ parser->dtd_name = dtd_name;
+
+ XML_SetParamEntityParsing (parser->expat_parser,
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
+ XML_SetExternalEntityRefHandler (parser->expat_parser,
+ gdb_xml_fetch_external_entity);
+
+ /* Even if no DTD is provided, use the built-in DTD anyway. */
+ err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE);
+ if (err != XML_ERROR_NONE)
+ internal_error (__FILE__, __LINE__,
+ "XML_UseForeignDTD failed: %s", XML_ErrorString (err));
+}
+
/* Invoke PARSER on BUFFER. BUFFER is the data to parse, which
should be NUL-terminated.
@@ -560,6 +656,236 @@ gdb_xml_parse_attr_enum (struct gdb_xml_
memcpy (ret, &enums->value, sizeof (enums->value));
return ret;
}
+\f
+
+/* XInclude processing. This is done as a separate step from actually
+ parsing the document, so that we can produce a single combined XML
+ document - e.g. to hand to a front end or to simplify comparing two
+ documents. We make extensive use of XML_DefaultCurrent, to pass
+ input text directly into the output without reformatting or
+ requoting it.
+
+ We output the DOCTYPE declaration for the first document unchanged,
+ if present, and discard DOCTYPEs from included documents. Only the
+ one we pass through here is used when we feed the result back to
+ expat. The XInclude standard explicitly does not discuss
+ validation of the result; we choose to apply the same DTD applied
+ to the outermost document.
+
+ We can not simply include the external DTD subset in the document
+ as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
+ only in external subsets. But if we do not pass the DTD into the
+ output at all, default values will not be filled in.
+
+ We don't pass through any <?xml> declaration because we generate
+ UTF-8, not whatever the input encoding was. */
+
+struct xinclude_parsing_data
+{
+ /* The obstack to build the output in. */
+ struct obstack obstack;
+
+ /* A count indicating whether we are in an element whose
+ children should not be copied to the output, and if so,
+ how deep we are nested. This is used for anything inside
+ an xi:include, and for the DTD. */
+ int skip_depth;
+
+ /* The number of <xi:include> elements currently being processed,
+ to detect loops. */
+ int include_depth;
+
+ /* A function to call to obtain additional features, and its
+ baton. */
+ xml_fetch_another fetcher;
+ void *fetcher_baton;
+};
+
+static void
+xinclude_start_include (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+ struct xinclude_parsing_data *data = user_data;
+ char *href = VEC_index (gdb_xml_value_s, attributes, 0)->value;
+ struct cleanup *back_to;
+ char *text, *output;
+ int ret;
+
+ gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
+
+ if (data->include_depth > MAX_XINCLUDE_DEPTH)
+ gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
+ MAX_XINCLUDE_DEPTH);
+
+ text = data->fetcher (href, data->fetcher_baton);
+ if (text == NULL)
+ gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
+ back_to = make_cleanup (xfree, text);
+
+ output = xml_process_xincludes (parser->name, text, data->fetcher,
+ data->fetcher_baton,
+ data->include_depth + 1);
+ if (output == NULL)
+ gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
+
+ obstack_grow (&data->obstack, output, strlen (output));
+ xfree (output);
+
+ do_cleanups (back_to);
+
+ data->skip_depth++;
+}
+
+static void
+xinclude_end_include (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, const char *body_text)
+{
+ struct xinclude_parsing_data *data = user_data;
+
+ data->skip_depth--;
+}
+
+static void XMLCALL
+xml_xinclude_default (void *data_, const XML_Char *s, int len)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ /* If we are inside of e.g. xi:include or the DTD, don't save this
+ string. */
+ if (data->skip_depth)
+ return;
+
+ /* Otherwise just add it to the end of the document we're building
+ up. */
+ obstack_grow (&data->obstack, s, len);
+}
+
+static void XMLCALL
+xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
+ const XML_Char *sysid, const XML_Char *pubid,
+ int has_internal_subset)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ /* Don't print out the doctype, or the contents of the DTD internal
+ subset, if any. */
+ data->skip_depth++;
+}
+
+static void XMLCALL
+xml_xinclude_end_doctype (void *data_)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ data->skip_depth--;
+}
+
+static void XMLCALL
+xml_xinclude_xml_decl (void *data_, const XML_Char *version,
+ const XML_Char *encoding, int standalone)
+{
+ /* Do nothing - this function prevents the default handler from
+ being called, thus suppressing the XML declaration from the
+ output. */
+}
+
+static void
+xml_xinclude_cleanup (void *data_)
+{
+ struct xinclude_parsing_data *data = data_;
+
+ obstack_free (&data->obstack, NULL);
+ xfree (data);
+}
+
+const struct gdb_xml_attribute xinclude_attributes[] = {
+ { "href", GDB_XML_AF_NONE, NULL, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element xinclude_elements[] = {
+ { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
+ GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
+ xinclude_start_include, xinclude_end_include },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+/* The main entry point for <xi:include> processing. */
+
+char *
+xml_process_xincludes (const char *name, const char *text,
+ xml_fetch_another fetcher, void *fetcher_baton,
+ int depth)
+{
+ enum XML_Error err;
+ struct gdb_xml_parser *parser;
+ struct xinclude_parsing_data *data;
+ struct cleanup *back_to;
+ char *result = NULL;
+
+ data = XZALLOC (struct xinclude_parsing_data);
+ obstack_init (&data->obstack);
+ back_to = make_cleanup (xml_xinclude_cleanup, data);
+
+ parser = gdb_xml_create_parser_and_cleanup (name, xinclude_elements, data);
+ parser->is_xinclude = 1;
+
+ data->include_depth = depth;
+ data->fetcher = fetcher;
+ data->fetcher_baton = fetcher_baton;
+
+ XML_SetCharacterDataHandler (parser->expat_parser, NULL);
+ XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
+
+ /* Always discard the XML version declarations; the only important
+ thing this provides is encoding, and our result will have been
+ converted to UTF-8. */
+ XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
+
+ if (depth > 0)
+ /* Discard the doctype for included documents. */
+ XML_SetDoctypeDeclHandler (parser->expat_parser,
+ xml_xinclude_start_doctype,
+ xml_xinclude_end_doctype);
+
+ gdb_xml_use_dtd (parser, "xinclude.dtd");
+
+ if (gdb_xml_parse (parser, text) == 0)
+ {
+ obstack_1grow (&data->obstack, '\0');
+ result = xstrdup (obstack_finish (&data->obstack));
+
+ if (depth == 0)
+ gdb_xml_debug (parser, _("XInclude processing succeeded:\n%s"),
+ result);
+ }
+ else
+ result = NULL;
+
+ do_cleanups (back_to);
+ return result;
+}
+\f
+
+/* Return an XML document which was compiled into GDB, from
+ the given FILENAME, or NULL if the file was not compiled in. */
+
+const char *
+fetch_xml_builtin (const char *filename)
+{
+ const char *(*p)[2];
+
+ for (p = xml_builtin; (*p)[0]; p++)
+ if (strcmp ((*p)[0], filename) == 0)
+ return (*p)[1];
+
+ return NULL;
+}
#endif /* HAVE_LIBEXPAT */
Index: src/gdb/xml-support.h
===================================================================
--- src.orig/gdb/xml-support.h 2007-01-29 12:37:14.000000000 -0500
+++ src/gdb/xml-support.h 2007-01-29 12:39:10.000000000 -0500
@@ -30,6 +30,35 @@ struct gdb_xml_parser;
struct gdb_xml_element;
struct gdb_xml_attribute;
+/* Support for XInclude. */
+
+/* Callback to fetch a new XML file, based on the provided HREF. */
+
+typedef char *(*xml_fetch_another) (const char *href, void *baton);
+
+/* Return a new string which is the expansion of TEXT after processing
+ <xi:include> tags. FETCHER will be called (with FETCHER_BATON) to
+ retrieve any new files. DEPTH should be zero on the initial call.
+
+ On failure, this function uses NAME in a warning and returns NULL.
+ It may throw an exception, but does not for XML parsing
+ problems. */
+
+char *xml_process_xincludes (const char *name, const char *text,
+ xml_fetch_another fetcher, void *fetcher_baton,
+ int depth);
+
+/* Return an XML document which was compiled into GDB, from
+ the given FILENAME, or NULL if the file was not compiled in. */
+
+const char *fetch_xml_builtin (const char *filename);
+
+/* The text of compiled-in XML documents, from xml-builtin.c
+ (generated). */
+extern const char *xml_builtin[][2];
+
+/* Simplified XML parser infrastructure. */
+
/* A name and value pair, used to record parsed attributes. */
struct gdb_xml_value
@@ -140,6 +169,11 @@ struct gdb_xml_parser *gdb_xml_create_pa
(const char *name, const struct gdb_xml_element *elements,
void *user_data);
+/* Associate DTD_NAME, which must be the name of a compiled-in DTD,
+ with PARSER. */
+
+void gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name);
+
/* Invoke PARSER on BUFFER. BUFFER is the data to parse, which
should be NUL-terminated.
Index: src/gdb/xml-tdesc.c
===================================================================
--- src.orig/gdb/xml-tdesc.c 2007-01-29 12:37:14.000000000 -0500
+++ src/gdb/xml-tdesc.c 2007-01-29 12:39:10.000000000 -0500
@@ -28,6 +28,8 @@
#include "xml-support.h"
#include "xml-tdesc.h"
+#include "filenames.h"
+
#include "gdb_assert.h"
#if !defined(HAVE_LIBEXPAT)
@@ -36,7 +38,8 @@
an XML parser. */
static struct target_desc *
-tdesc_parse_xml (const char *document)
+tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
+ void *fetcher_baton)
{
static int have_warned;
@@ -94,22 +97,33 @@ const struct gdb_xml_element tdesc_eleme
/* Parse DOCUMENT into a target description and return it. */
static struct target_desc *
-tdesc_parse_xml (const char *document)
+tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
+ void *fetcher_baton)
{
struct cleanup *back_to, *result_cleanup;
struct gdb_xml_parser *parser;
struct tdesc_parsing_data data;
+ char *expanded_text;
- memset (&data, 0, sizeof (struct tdesc_parsing_data));
+ /* Expand all XInclude directives. */
+ expanded_text = xml_process_xincludes (_("target description"),
+ document, fetcher, fetcher_baton, 0);
+ if (expanded_text == NULL)
+ {
+ warning (_("Could not load XML target description; ignoring"));
+ return NULL;
+ }
+ back_to = make_cleanup (xfree, expanded_text);
- back_to = make_cleanup (null_cleanup, NULL);
parser = gdb_xml_create_parser_and_cleanup (_("target description"),
tdesc_elements, &data);
+ gdb_xml_use_dtd (parser, "gdb-target.dtd");
+ memset (&data, 0, sizeof (struct tdesc_parsing_data));
data.tdesc = allocate_target_description ();
result_cleanup = make_cleanup_free_target_description (data.tdesc);
- if (gdb_xml_parse (parser, document) == 0)
+ if (gdb_xml_parse (parser, expanded_text) == 0)
{
/* Parsed successfully. */
discard_cleanups (result_cleanup);
@@ -123,7 +137,6 @@ tdesc_parse_xml (const char *document)
return NULL;
}
}
-
#endif /* HAVE_LIBEXPAT */
\f
@@ -139,19 +152,28 @@ do_cleanup_fclose (void *file)
the text. If something goes wrong, return NULL and warn. */
static char *
-fetch_xml_from_file (const char *filename)
+fetch_xml_from_file (const char *filename, void *baton)
{
+ const char *dirname = baton;
FILE *file;
struct cleanup *back_to;
char *text;
size_t len, offset;
- file = fopen (filename, FOPEN_RT);
- if (file == NULL)
+ if (dirname && *dirname)
{
- warning (_("Could not open \"%s\""), filename);
- return NULL;
+ char *fullname = concat (dirname, "/", filename, NULL);
+ if (fullname == NULL)
+ nomem (0);
+ file = fopen (fullname, FOPEN_RT);
+ xfree (fullname);
}
+ else
+ file = fopen (filename, FOPEN_RT);
+
+ if (file == NULL)
+ return NULL;
+
back_to = make_cleanup (do_cleanup_fclose, file);
/* Read in the whole file, one chunk at a time. */
@@ -198,18 +220,59 @@ file_read_description_xml (const char *f
struct target_desc *tdesc;
char *tdesc_str;
struct cleanup *back_to;
+ const char *base;
+ char *dirname;
- tdesc_str = fetch_xml_from_file (filename);
+ tdesc_str = fetch_xml_from_file (filename, NULL);
if (tdesc_str == NULL)
- return NULL;
+ {
+ warning (_("Could not open \"%s\""), filename);
+ return NULL;
+ }
back_to = make_cleanup (xfree, tdesc_str);
- tdesc = tdesc_parse_xml (tdesc_str);
+
+ /* Simple, portable version of dirname that does not modify its
+ argument. */
+ base = lbasename (filename);
+ while (base > filename && IS_DIR_SEPARATOR (base[-1]))
+ --base;
+ if (base > filename)
+ {
+ dirname = xmalloc (base - filename + 1);
+ memcpy (dirname, filename, base - filename);
+ dirname[base - filename] = '\0';
+ make_cleanup (xfree, dirname);
+ }
+ else
+ dirname = NULL;
+
+ tdesc = tdesc_parse_xml (tdesc_str, fetch_xml_from_file, dirname);
do_cleanups (back_to);
return tdesc;
}
+/* Read a string representation of available features from the target,
+ using TARGET_OBJECT_AVAILABLE_FEATURES. The returned string is
+ malloc allocated and NUL-terminated. NAME should be a non-NULL
+ string identifying the XML document we want; the top level document
+ is "target.xml". Other calls may be performed for the DTD or
+ for <xi:include>. */
+
+static char *
+fetch_available_features_from_target (const char *name, void *baton_)
+{
+ struct target_ops *ops = baton_;
+
+ /* Read this object as a string. This ensures that a NUL
+ terminator is added. */
+ return target_read_stralloc (ops,
+ TARGET_OBJECT_AVAILABLE_FEATURES,
+ name);
+}
+\f
+
/* Read an XML target description using OPS. Parse it, and return the
parsed description. */
@@ -220,13 +283,14 @@ target_read_description_xml (struct targ
char *tdesc_str;
struct cleanup *back_to;
- tdesc_str = target_read_stralloc (ops, TARGET_OBJECT_AVAILABLE_FEATURES,
- "target.xml");
+ tdesc_str = fetch_available_features_from_target ("target.xml", ops);
if (tdesc_str == NULL)
return NULL;
back_to = make_cleanup (xfree, tdesc_str);
- tdesc = tdesc_parse_xml (tdesc_str);
+ tdesc = tdesc_parse_xml (tdesc_str,
+ fetch_available_features_from_target,
+ ops);
do_cleanups (back_to);
return tdesc;
Index: src/gdb/features/gdb-target.dtd
===================================================================
--- src.orig/gdb/features/gdb-target.dtd 2007-01-29 12:37:14.000000000 -0500
+++ src/gdb/features/gdb-target.dtd 2007-01-29 12:39:10.000000000 -0500
@@ -1,9 +1,14 @@
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
<!-- The root element of a GDB target description is <target>. -->
<!ELEMENT target (architecture?)>
-<!ATTLIST target
- xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
<!ELEMENT architecture (#PCDATA)>
-
+<!ENTITY % xinclude SYSTEM "xinclude.dtd">
+%xinclude;
Index: src/gdb/features/xinclude.dtd
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/features/xinclude.dtd 2007-01-29 12:39:10.000000000 -0500
@@ -0,0 +1,13 @@
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!-- GDB supports a subset of XInclude. Only whole documents can
+ be included, and only as XML. -->
+
+<!ELEMENT xi:include (EMPTY)>
+<!ATTLIST xi:include
+ xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
+ href CDATA #REQUIRED>
Index: src/gdb/testsuite/gdb.xml/bad-include.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/bad-include.xml 2007-01-29 12:39:10.000000000 -0500
@@ -0,0 +1 @@
+<xi:include href="nonexistant.xml"/>
Index: src/gdb/testsuite/gdb.xml/inc-2.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/inc-2.xml 2007-01-29 12:39:10.000000000 -0500
@@ -0,0 +1 @@
+<xi:include href="inc-body.xml"/>
Index: src/gdb/testsuite/gdb.xml/inc-body.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/inc-body.xml 2007-01-29 12:39:10.000000000 -0500
@@ -0,0 +1 @@
+<architecture>invalid-body</architecture>
Index: src/gdb/testsuite/gdb.xml/includes.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/includes.xml 2007-01-29 12:39:10.000000000 -0500
@@ -0,0 +1,3 @@
+<target>
+ <xi:include href="inc-2.xml"/>
+</target>
Index: src/gdb/testsuite/gdb.xml/tdesc-xinclude.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/tdesc-xinclude.exp 2007-01-29 12:39:10.000000000 -0500
@@ -0,0 +1,54 @@
+# Copyright 2007 Free Software Foundation, Inc.
+
+# 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 2 of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+if {[gdb_skip_xml_test]} {
+ unsupported "tdesc-errors.exp"
+ return -1
+}
+
+gdb_start
+
+proc set_arch { srcfile errmsg } {
+ global gdb_prompt
+ global srcdir
+ global subdir
+
+ # Anchor the test output, so that error messages are detected.
+ set cmd "set tdesc filename $srcdir/$subdir/$srcfile"
+ set msg $cmd
+ set cmd_regex [string_to_regexp $cmd]
+ gdb_test_multiple $cmd $msg {
+ -re "^$cmd_regex\r\n$errmsg$gdb_prompt $" {
+ pass $msg
+ }
+ }
+}
+
+set common_warn "\r\nwarning: Could not load XML target description; ignoring\r\n"
+
+# This file is valid, but specifies an unknown architecture.
+# We should get a warning, if we process the includes correctly.
+set_arch "includes.xml" \
+ "warning:.*specified unknown architecture.* \"invalid-body\"$common_warn"
+
+# This file contains a missing include. We should warn the user about
+# it.
+set_arch "bad-include.xml" \
+ "warning:.*Could not load XML document \"nonexistant.xml\"$common_warn"
+
+# Make sure we detect infinite loops, eventually.
+set_arch "loop.xml" \
+ "warning:.*Maximum XInclude depth.*$common_warn"
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo 2007-01-29 12:37:52.000000000 -0500
+++ src/gdb/doc/gdb.texinfo 2007-01-29 12:39:10.000000000 -0500
@@ -25781,6 +25781,27 @@ The content of the @samp{<architecture>}
name, from the same selection accepted by @code{set architecture}
(@pxref{Targets, ,Specifying a Debugging Target}).
+@subsection Inclusion
+
+It can sometimes be valuable to split a target description up into
+several different annexes, either for organizational purposes, or to
+share files between different possible target descriptions. You can
+divide a description into multiple files by replacing any element of
+the target description with an inclusion directive of the form:
+
+@example
+<xi:include href="@var{name}"/>
+@end example
+
+@noindent
+When @value{GDBN} encounters an element of this form, it will retrieve
+the XML document named @var{name}, and replace the inclusion directive
+with the contents of that annex. If the current description was read
+using @samp{qXfer}, then the new document will be also, using
+@var{name} as the annex. If the current description was read from a
+file, @value{GDBN} will look for a file named @var{name} in the same
+directory as the original file.
+
@include gpl.texi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-01-29 21:32 XML XInclude support Daniel Jacobowitz
@ 2007-01-31 18:33 ` Daniel Jacobowitz
2007-02-02 18:53 ` Eli Zaretskii
1 sibling, 0 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2007-01-31 18:33 UTC (permalink / raw)
To: gdb-patches; +Cc: Eli Zaretskii
On Mon, Jan 29, 2007 at 04:32:30PM -0500, Daniel Jacobowitz wrote:
> 2007-01-29 Daniel Jacobowitz <dan@codesourcery.com>
Whoops. Noticed today that I'd left one of the new test supporting
files out of this patch - here's a complete version.
--
Daniel Jacobowitz
CodeSourcery
2007-01-29 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (XMLFILES): New.
(COMMON_OBS): Add xml-builtin.o.
(xml-builtin.c, stamp-xml): New rules.
(xml-tdesc.o): Update.
* features/feature_to_c.sh: New file.
* xml-support.c (MAX_XINCLUDE_DEPTH): Define.
(struct gdb_xml_parser): Add dtd_name and is_xinclude.
(gdb_xml_start_element): Initialize scope after possibly reallocating
scopes. Move cleanup later. Handle the XInclude description
specially.
(gdb_xml_end_element): Only parse the body if there is a current element.
Call XML_DefaultCurrent if there is no element.
(gdb_xml_fetch_external_entity, gdb_xml_use_dtd): New.
(struct xinclude_parsing_data, xinclude_start_include)
(xinclude_end_include, xml_xinclude_default)
(xml_xinclude_start_doctype, xml_xinclude_end_doctype)
(xml_xinclude_xml_decl, xml_xinclude_cleanup, xinclude_attributes)
(xinclude_elements, xml_process_xincludes, fetch_xml_builtin): New.
* xml-support.h (xml_fetch_another, xml_process_xincludes)
(fetch_xml_builtin, xml_builtin, gdb_xml_use_dtd): New declarations.
* xml-tdesc.c (tdesc_parse_xml): Add fetcher_baton argument. Expand
XInclude directives. Use the compiled in DTD.
(fetch_xml_from_file): Add baton argument. Treat it as a containing
directory name. Do not warn here.
(file_read_description_xml): Update call. Warn here instead. Pass
a dirname as baton.
(fetch_available_features_from_target): New.
(target_read_description_xml): Use it.
* features/gdb-target.dtd: Add copyright notice. Use xinclude.dtd
to handle XInclude.
* features/xinclude.dtd: New file.
* gdb.xml/bad-include.xml, gdb.xml/inc-2.xml, gdb.xml/inc-body.xml,
gdb.xml/includes.xml, gdb.xml/loop.xml,
gdb.xml/tdesc-xinclude.exp: New files.
* gdb.texinfo (Target Description Format): Add section on XInclude.
---
gdb/Makefile.in | 20 +
gdb/doc/gdb.texinfo | 21 +
gdb/features/feature_to_c.sh | 77 ++++++
gdb/features/gdb-target.dtd | 11
gdb/features/xinclude.dtd | 13 +
gdb/testsuite/gdb.xml/bad-include.xml | 1
gdb/testsuite/gdb.xml/inc-2.xml | 1
gdb/testsuite/gdb.xml/inc-body.xml | 1
gdb/testsuite/gdb.xml/includes.xml | 3
gdb/testsuite/gdb.xml/loop.xml | 1
gdb/testsuite/gdb.xml/tdesc-xinclude.exp | 54 ++++
gdb/xml-support.c | 372 +++++++++++++++++++++++++++++--
gdb/xml-support.h | 34 ++
gdb/xml-tdesc.c | 98 ++++++--
14 files changed, 662 insertions(+), 45 deletions(-)
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in 2007-01-31 13:31:22.000000000 -0500
+++ src/gdb/Makefile.in 2007-01-31 13:31:55.000000000 -0500
@@ -400,6 +400,9 @@ LINTFLAGS= $(GDB_CFLAGS) $(OPCODES_CFLAG
RUNTEST = runtest
RUNTESTFLAGS=
+# XML files to build in to GDB.
+XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd
+
# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
# interface to the serial port. Hopefully if get ported to OS/2, VMS,
# etc., then there will be (as part of the C library or perhaps as
@@ -972,7 +975,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
tramp-frame.o \
solib.o solib-null.o \
prologue-value.o memory-map.o xml-support.o \
- target-descriptions.o target-memory.o xml-tdesc.o
+ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
TSOBS = inflow.o
@@ -1681,6 +1684,19 @@ po/$(PACKAGE).pot: force
.PRECIOUS: objc-exp.c
.PRECIOUS: p-exp.c
+# XML rules
+
+xml-builtin.c: stamp-xml; @true
+stamp-xml: $(srcdir)/features/feature_to_c.sh Makefile $(XMLFILES)
+ rm -f xml-builtin.tmp
+ AWK="$(AWK)" \
+ $(SHELL) $(srcdir)/features/feature_to_c.sh \
+ xml-builtin.tmp $(XMLFILES)
+ $(SHELL) $(srcdir)/../move-if-change xml-builtin.tmp xml-builtin.c
+ echo stamp > stamp-xml
+
+.PRECIOUS: xml-builtin.c
+
#
# gdb/ dependencies
#
@@ -2876,7 +2892,7 @@ xcoffread.o: xcoffread.c $(defs_h) $(bfd
xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \
$(gdbcmd_h) $(symfile_h) $(frame_h) $(gdb_regex_h)
xml-tdesc.o: xml-tdesc.c $(defs_h) $(target_h) $(target_descriptions_h) \
- $(xml_tdesc_h) $(xml_support_h) $(gdb_assert_h)
+ $(xml_tdesc_h) $(xml_support_h) $(filenames_h) $(gdb_assert_h)
xml-support.o: xml-support.c $(defs_h) $(xml_support_h) $(exceptions_h) \
$(gdbcmd_h) $(gdb_string_h) $(gdb_expat_h) $(safe_ctype_h)
xstormy16-tdep.o: xstormy16-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \
Index: src/gdb/features/feature_to_c.sh
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/features/feature_to_c.sh 2007-01-31 13:31:55.000000000 -0500
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+# Convert text files to compilable C arrays.
+#
+# Copyright (C) 2007 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# 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 2 of the License, 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, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+output=$1
+shift
+
+if test -z "$output" || test -z "$1"; then
+ echo "Usage: $0 OUTPUTFILE INPUTFILE..."
+ exit 1
+fi
+
+if test -e "$output"; then
+ echo "Output file \"$output\" already exists; refusing to overwrite."
+ exit 1
+fi
+
+for input; do
+ arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
+
+ ${AWK:-awk} 'BEGIN { n = 0
+ print "static const char '$arrayname'[] = {"
+ for (i = 0; i < 255; i++)
+ _ord_[sprintf("%c", i)] = i
+ } {
+ split($0, line, "");
+ printf " "
+ for (i = 1; i <= length($0); i++) {
+ c = line[i]
+ if (c == "'\''") {
+ printf "'\''\\'\'''\'', "
+ } else if (c == "\\") {
+ printf "'\''\\\\'\'', "
+ } else if (_ord_[c] >= 32 && _ord_[c] < 127) {
+ printf "'\''" c "'\'', "
+ } else {
+ printf "'\''\\%03o'\'', ", _ord_[c]
+ }
+ if (i % 10 == 0)
+ printf "\n "
+ }
+ printf "'\''\\n'\'', \n"
+ } END {
+ print " 0 };"
+ }' < $input >> $output
+done
+
+echo >> $output
+echo "const char *const xml_builtin[][2] = {" >> $output
+
+for input; do
+ basename=`echo $input | sed 's,.*/,,'`
+ arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
+ echo " { \"$basename\", $arrayname }," >> $output
+done
+
+echo " { 0, 0 }" >> $output
+echo "};" >> $output
Index: src/gdb/xml-support.c
===================================================================
--- src.orig/gdb/xml-support.c 2007-01-31 13:31:22.000000000 -0500
+++ src/gdb/xml-support.c 2007-01-31 13:31:55.000000000 -0500
@@ -36,6 +36,10 @@ static int debug_xml;
#include "gdb_string.h"
#include "safe-ctype.h"
+/* The maximum depth of <xi:include> nesting. No need to be miserly,
+ we just want to avoid running out of stack on loops. */
+#define MAX_XINCLUDE_DEPTH 30
+
/* A parsing level -- used to keep track of the current element
nesting. */
struct scope_level
@@ -68,6 +72,10 @@ struct gdb_xml_parser
struct gdb_exception error; /* A thrown error, if any. */
int last_line; /* The line of the thrown error, or 0. */
+
+ const char *dtd_name; /* The name of the expected / default DTD,
+ if specified. */
+ int is_xinclude; /* Are we the special <xi:include> parser? */
};
/* Process some body text. We accumulate the text for later use; it's
@@ -152,7 +160,7 @@ gdb_xml_start_element (void *data, const
const XML_Char **attrs)
{
struct gdb_xml_parser *parser = data;
- struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
+ struct scope_level *scope;
struct scope_level new_scope;
const struct gdb_xml_element *element;
const struct gdb_xml_attribute *attribute;
@@ -160,13 +168,13 @@ gdb_xml_start_element (void *data, const
unsigned int seen;
struct cleanup *back_to;
- back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
-
/* Push an error scope. If we return or throw an exception before
filling this in, it will tell us to ignore children of this
element. */
+ VEC_reserve (scope_level_s, parser->scopes, 1);
+ scope = VEC_last (scope_level_s, parser->scopes);
memset (&new_scope, 0, sizeof (new_scope));
- VEC_safe_push (scope_level_s, parser->scopes, &new_scope);
+ VEC_quick_push (scope_level_s, parser->scopes, &new_scope);
gdb_xml_debug (parser, _("Entering element <%s>"), name);
@@ -181,8 +189,21 @@ gdb_xml_start_element (void *data, const
if (element == NULL || element->name == NULL)
{
+ /* If we're working on XInclude, <xi:include> can be the child
+ of absolutely anything. Copy the previous scope's element
+ list into the new scope even if there was no match. */
+ if (parser->is_xinclude)
+ {
+ struct scope_level *unknown_scope;
+
+ XML_DefaultCurrent (parser->expat_parser);
+
+ unknown_scope = VEC_last (scope_level_s, parser->scopes);
+ unknown_scope->elements = scope->elements;
+ return;
+ }
+
gdb_xml_debug (parser, _("Element <%s> unknown"), name);
- do_cleanups (back_to);
return;
}
@@ -191,6 +212,8 @@ gdb_xml_start_element (void *data, const
scope->seen |= seen;
+ back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
+
for (attribute = element->attributes;
attribute != NULL && attribute->name != NULL;
attribute++)
@@ -304,7 +327,6 @@ gdb_xml_end_element (void *data, const X
struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
const struct gdb_xml_element *element;
unsigned int seen;
- char *body;
gdb_xml_debug (parser, _("Leaving element <%s>"), name);
@@ -317,26 +339,32 @@ gdb_xml_end_element (void *data, const X
element->name);
/* Call the element processor. */
- if (scope->body == NULL)
- body = "";
- else
+ if (scope->element != NULL && scope->element->end_handler)
{
- int length;
+ char *body;
- length = obstack_object_size (scope->body);
- obstack_1grow (scope->body, '\0');
- body = obstack_finish (scope->body);
-
- /* Strip leading and trailing whitespace. */
- while (length > 0 && ISSPACE (body[length-1]))
- body[--length] = '\0';
- while (*body && ISSPACE (*body))
- body++;
- }
+ if (scope->body == NULL)
+ body = "";
+ else
+ {
+ int length;
- if (scope->element != NULL && scope->element->end_handler)
- scope->element->end_handler (parser, scope->element, parser->user_data,
- body);
+ length = obstack_object_size (scope->body);
+ obstack_1grow (scope->body, '\0');
+ body = obstack_finish (scope->body);
+
+ /* Strip leading and trailing whitespace. */
+ while (length > 0 && ISSPACE (body[length-1]))
+ body[--length] = '\0';
+ while (*body && ISSPACE (*body))
+ body++;
+ }
+
+ scope->element->end_handler (parser, scope->element, parser->user_data,
+ body);
+ }
+ else if (scope->element == NULL)
+ XML_DefaultCurrent (parser->expat_parser);
/* Pop the scope level. */
if (scope->body)
@@ -435,6 +463,74 @@ gdb_xml_create_parser_and_cleanup (const
return parser;
}
+/* External entity handler. The only external entities we support
+ are those compiled into GDB (we do not fetch entities from the
+ target). */
+
+static int XMLCALL
+gdb_xml_fetch_external_entity (XML_Parser expat_parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ struct gdb_xml_parser *parser = XML_GetUserData (expat_parser);
+ XML_Parser entity_parser;
+ const char *text;
+ enum XML_Status status;
+
+ if (systemId == NULL)
+ {
+ text = fetch_xml_builtin (parser->dtd_name);
+ if (text == NULL)
+ internal_error (__FILE__, __LINE__, "could not locate built-in DTD %s",
+ parser->dtd_name);
+ }
+ else
+ {
+ text = fetch_xml_builtin (systemId);
+ if (text == NULL)
+ return XML_STATUS_ERROR;
+ }
+
+ entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL);
+
+ /* Don't use our handlers for the contents of the DTD. Just let expat
+ process it. */
+ XML_SetElementHandler (entity_parser, NULL, NULL);
+ XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
+ XML_SetXmlDeclHandler (entity_parser, NULL);
+ XML_SetDefaultHandler (entity_parser, NULL);
+ XML_SetUserData (entity_parser, NULL);
+
+ status = XML_Parse (entity_parser, text, strlen (text), 1);
+
+ XML_ParserFree (entity_parser);
+ return status;
+}
+
+/* Associate DTD_NAME, which must be the name of a compiled-in DTD,
+ with PARSER. */
+
+void
+gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name)
+{
+ enum XML_Error err;
+
+ parser->dtd_name = dtd_name;
+
+ XML_SetParamEntityParsing (parser->expat_parser,
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
+ XML_SetExternalEntityRefHandler (parser->expat_parser,
+ gdb_xml_fetch_external_entity);
+
+ /* Even if no DTD is provided, use the built-in DTD anyway. */
+ err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE);
+ if (err != XML_ERROR_NONE)
+ internal_error (__FILE__, __LINE__,
+ "XML_UseForeignDTD failed: %s", XML_ErrorString (err));
+}
+
/* Invoke PARSER on BUFFER. BUFFER is the data to parse, which
should be NUL-terminated.
@@ -560,6 +656,236 @@ gdb_xml_parse_attr_enum (struct gdb_xml_
memcpy (ret, &enums->value, sizeof (enums->value));
return ret;
}
+\f
+
+/* XInclude processing. This is done as a separate step from actually
+ parsing the document, so that we can produce a single combined XML
+ document - e.g. to hand to a front end or to simplify comparing two
+ documents. We make extensive use of XML_DefaultCurrent, to pass
+ input text directly into the output without reformatting or
+ requoting it.
+
+ We output the DOCTYPE declaration for the first document unchanged,
+ if present, and discard DOCTYPEs from included documents. Only the
+ one we pass through here is used when we feed the result back to
+ expat. The XInclude standard explicitly does not discuss
+ validation of the result; we choose to apply the same DTD applied
+ to the outermost document.
+
+ We can not simply include the external DTD subset in the document
+ as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
+ only in external subsets. But if we do not pass the DTD into the
+ output at all, default values will not be filled in.
+
+ We don't pass through any <?xml> declaration because we generate
+ UTF-8, not whatever the input encoding was. */
+
+struct xinclude_parsing_data
+{
+ /* The obstack to build the output in. */
+ struct obstack obstack;
+
+ /* A count indicating whether we are in an element whose
+ children should not be copied to the output, and if so,
+ how deep we are nested. This is used for anything inside
+ an xi:include, and for the DTD. */
+ int skip_depth;
+
+ /* The number of <xi:include> elements currently being processed,
+ to detect loops. */
+ int include_depth;
+
+ /* A function to call to obtain additional features, and its
+ baton. */
+ xml_fetch_another fetcher;
+ void *fetcher_baton;
+};
+
+static void
+xinclude_start_include (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+ struct xinclude_parsing_data *data = user_data;
+ char *href = VEC_index (gdb_xml_value_s, attributes, 0)->value;
+ struct cleanup *back_to;
+ char *text, *output;
+ int ret;
+
+ gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
+
+ if (data->include_depth > MAX_XINCLUDE_DEPTH)
+ gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
+ MAX_XINCLUDE_DEPTH);
+
+ text = data->fetcher (href, data->fetcher_baton);
+ if (text == NULL)
+ gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
+ back_to = make_cleanup (xfree, text);
+
+ output = xml_process_xincludes (parser->name, text, data->fetcher,
+ data->fetcher_baton,
+ data->include_depth + 1);
+ if (output == NULL)
+ gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
+
+ obstack_grow (&data->obstack, output, strlen (output));
+ xfree (output);
+
+ do_cleanups (back_to);
+
+ data->skip_depth++;
+}
+
+static void
+xinclude_end_include (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, const char *body_text)
+{
+ struct xinclude_parsing_data *data = user_data;
+
+ data->skip_depth--;
+}
+
+static void XMLCALL
+xml_xinclude_default (void *data_, const XML_Char *s, int len)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ /* If we are inside of e.g. xi:include or the DTD, don't save this
+ string. */
+ if (data->skip_depth)
+ return;
+
+ /* Otherwise just add it to the end of the document we're building
+ up. */
+ obstack_grow (&data->obstack, s, len);
+}
+
+static void XMLCALL
+xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
+ const XML_Char *sysid, const XML_Char *pubid,
+ int has_internal_subset)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ /* Don't print out the doctype, or the contents of the DTD internal
+ subset, if any. */
+ data->skip_depth++;
+}
+
+static void XMLCALL
+xml_xinclude_end_doctype (void *data_)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ data->skip_depth--;
+}
+
+static void XMLCALL
+xml_xinclude_xml_decl (void *data_, const XML_Char *version,
+ const XML_Char *encoding, int standalone)
+{
+ /* Do nothing - this function prevents the default handler from
+ being called, thus suppressing the XML declaration from the
+ output. */
+}
+
+static void
+xml_xinclude_cleanup (void *data_)
+{
+ struct xinclude_parsing_data *data = data_;
+
+ obstack_free (&data->obstack, NULL);
+ xfree (data);
+}
+
+const struct gdb_xml_attribute xinclude_attributes[] = {
+ { "href", GDB_XML_AF_NONE, NULL, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element xinclude_elements[] = {
+ { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
+ GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
+ xinclude_start_include, xinclude_end_include },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+/* The main entry point for <xi:include> processing. */
+
+char *
+xml_process_xincludes (const char *name, const char *text,
+ xml_fetch_another fetcher, void *fetcher_baton,
+ int depth)
+{
+ enum XML_Error err;
+ struct gdb_xml_parser *parser;
+ struct xinclude_parsing_data *data;
+ struct cleanup *back_to;
+ char *result = NULL;
+
+ data = XZALLOC (struct xinclude_parsing_data);
+ obstack_init (&data->obstack);
+ back_to = make_cleanup (xml_xinclude_cleanup, data);
+
+ parser = gdb_xml_create_parser_and_cleanup (name, xinclude_elements, data);
+ parser->is_xinclude = 1;
+
+ data->include_depth = depth;
+ data->fetcher = fetcher;
+ data->fetcher_baton = fetcher_baton;
+
+ XML_SetCharacterDataHandler (parser->expat_parser, NULL);
+ XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
+
+ /* Always discard the XML version declarations; the only important
+ thing this provides is encoding, and our result will have been
+ converted to UTF-8. */
+ XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
+
+ if (depth > 0)
+ /* Discard the doctype for included documents. */
+ XML_SetDoctypeDeclHandler (parser->expat_parser,
+ xml_xinclude_start_doctype,
+ xml_xinclude_end_doctype);
+
+ gdb_xml_use_dtd (parser, "xinclude.dtd");
+
+ if (gdb_xml_parse (parser, text) == 0)
+ {
+ obstack_1grow (&data->obstack, '\0');
+ result = xstrdup (obstack_finish (&data->obstack));
+
+ if (depth == 0)
+ gdb_xml_debug (parser, _("XInclude processing succeeded:\n%s"),
+ result);
+ }
+ else
+ result = NULL;
+
+ do_cleanups (back_to);
+ return result;
+}
+\f
+
+/* Return an XML document which was compiled into GDB, from
+ the given FILENAME, or NULL if the file was not compiled in. */
+
+const char *
+fetch_xml_builtin (const char *filename)
+{
+ const char *(*p)[2];
+
+ for (p = xml_builtin; (*p)[0]; p++)
+ if (strcmp ((*p)[0], filename) == 0)
+ return (*p)[1];
+
+ return NULL;
+}
#endif /* HAVE_LIBEXPAT */
Index: src/gdb/xml-support.h
===================================================================
--- src.orig/gdb/xml-support.h 2007-01-31 13:31:22.000000000 -0500
+++ src/gdb/xml-support.h 2007-01-31 13:31:55.000000000 -0500
@@ -30,6 +30,35 @@ struct gdb_xml_parser;
struct gdb_xml_element;
struct gdb_xml_attribute;
+/* Support for XInclude. */
+
+/* Callback to fetch a new XML file, based on the provided HREF. */
+
+typedef char *(*xml_fetch_another) (const char *href, void *baton);
+
+/* Return a new string which is the expansion of TEXT after processing
+ <xi:include> tags. FETCHER will be called (with FETCHER_BATON) to
+ retrieve any new files. DEPTH should be zero on the initial call.
+
+ On failure, this function uses NAME in a warning and returns NULL.
+ It may throw an exception, but does not for XML parsing
+ problems. */
+
+char *xml_process_xincludes (const char *name, const char *text,
+ xml_fetch_another fetcher, void *fetcher_baton,
+ int depth);
+
+/* Return an XML document which was compiled into GDB, from
+ the given FILENAME, or NULL if the file was not compiled in. */
+
+const char *fetch_xml_builtin (const char *filename);
+
+/* The text of compiled-in XML documents, from xml-builtin.c
+ (generated). */
+extern const char *xml_builtin[][2];
+
+/* Simplified XML parser infrastructure. */
+
/* A name and value pair, used to record parsed attributes. */
struct gdb_xml_value
@@ -140,6 +169,11 @@ struct gdb_xml_parser *gdb_xml_create_pa
(const char *name, const struct gdb_xml_element *elements,
void *user_data);
+/* Associate DTD_NAME, which must be the name of a compiled-in DTD,
+ with PARSER. */
+
+void gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name);
+
/* Invoke PARSER on BUFFER. BUFFER is the data to parse, which
should be NUL-terminated.
Index: src/gdb/xml-tdesc.c
===================================================================
--- src.orig/gdb/xml-tdesc.c 2007-01-31 13:31:22.000000000 -0500
+++ src/gdb/xml-tdesc.c 2007-01-31 13:31:55.000000000 -0500
@@ -28,6 +28,8 @@
#include "xml-support.h"
#include "xml-tdesc.h"
+#include "filenames.h"
+
#include "gdb_assert.h"
#if !defined(HAVE_LIBEXPAT)
@@ -36,7 +38,8 @@
an XML parser. */
static struct target_desc *
-tdesc_parse_xml (const char *document)
+tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
+ void *fetcher_baton)
{
static int have_warned;
@@ -94,22 +97,33 @@ const struct gdb_xml_element tdesc_eleme
/* Parse DOCUMENT into a target description and return it. */
static struct target_desc *
-tdesc_parse_xml (const char *document)
+tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
+ void *fetcher_baton)
{
struct cleanup *back_to, *result_cleanup;
struct gdb_xml_parser *parser;
struct tdesc_parsing_data data;
+ char *expanded_text;
- memset (&data, 0, sizeof (struct tdesc_parsing_data));
+ /* Expand all XInclude directives. */
+ expanded_text = xml_process_xincludes (_("target description"),
+ document, fetcher, fetcher_baton, 0);
+ if (expanded_text == NULL)
+ {
+ warning (_("Could not load XML target description; ignoring"));
+ return NULL;
+ }
+ back_to = make_cleanup (xfree, expanded_text);
- back_to = make_cleanup (null_cleanup, NULL);
parser = gdb_xml_create_parser_and_cleanup (_("target description"),
tdesc_elements, &data);
+ gdb_xml_use_dtd (parser, "gdb-target.dtd");
+ memset (&data, 0, sizeof (struct tdesc_parsing_data));
data.tdesc = allocate_target_description ();
result_cleanup = make_cleanup_free_target_description (data.tdesc);
- if (gdb_xml_parse (parser, document) == 0)
+ if (gdb_xml_parse (parser, expanded_text) == 0)
{
/* Parsed successfully. */
discard_cleanups (result_cleanup);
@@ -123,7 +137,6 @@ tdesc_parse_xml (const char *document)
return NULL;
}
}
-
#endif /* HAVE_LIBEXPAT */
\f
@@ -139,19 +152,28 @@ do_cleanup_fclose (void *file)
the text. If something goes wrong, return NULL and warn. */
static char *
-fetch_xml_from_file (const char *filename)
+fetch_xml_from_file (const char *filename, void *baton)
{
+ const char *dirname = baton;
FILE *file;
struct cleanup *back_to;
char *text;
size_t len, offset;
- file = fopen (filename, FOPEN_RT);
- if (file == NULL)
+ if (dirname && *dirname)
{
- warning (_("Could not open \"%s\""), filename);
- return NULL;
+ char *fullname = concat (dirname, "/", filename, NULL);
+ if (fullname == NULL)
+ nomem (0);
+ file = fopen (fullname, FOPEN_RT);
+ xfree (fullname);
}
+ else
+ file = fopen (filename, FOPEN_RT);
+
+ if (file == NULL)
+ return NULL;
+
back_to = make_cleanup (do_cleanup_fclose, file);
/* Read in the whole file, one chunk at a time. */
@@ -198,18 +220,59 @@ file_read_description_xml (const char *f
struct target_desc *tdesc;
char *tdesc_str;
struct cleanup *back_to;
+ const char *base;
+ char *dirname;
- tdesc_str = fetch_xml_from_file (filename);
+ tdesc_str = fetch_xml_from_file (filename, NULL);
if (tdesc_str == NULL)
- return NULL;
+ {
+ warning (_("Could not open \"%s\""), filename);
+ return NULL;
+ }
back_to = make_cleanup (xfree, tdesc_str);
- tdesc = tdesc_parse_xml (tdesc_str);
+
+ /* Simple, portable version of dirname that does not modify its
+ argument. */
+ base = lbasename (filename);
+ while (base > filename && IS_DIR_SEPARATOR (base[-1]))
+ --base;
+ if (base > filename)
+ {
+ dirname = xmalloc (base - filename + 1);
+ memcpy (dirname, filename, base - filename);
+ dirname[base - filename] = '\0';
+ make_cleanup (xfree, dirname);
+ }
+ else
+ dirname = NULL;
+
+ tdesc = tdesc_parse_xml (tdesc_str, fetch_xml_from_file, dirname);
do_cleanups (back_to);
return tdesc;
}
+/* Read a string representation of available features from the target,
+ using TARGET_OBJECT_AVAILABLE_FEATURES. The returned string is
+ malloc allocated and NUL-terminated. NAME should be a non-NULL
+ string identifying the XML document we want; the top level document
+ is "target.xml". Other calls may be performed for the DTD or
+ for <xi:include>. */
+
+static char *
+fetch_available_features_from_target (const char *name, void *baton_)
+{
+ struct target_ops *ops = baton_;
+
+ /* Read this object as a string. This ensures that a NUL
+ terminator is added. */
+ return target_read_stralloc (ops,
+ TARGET_OBJECT_AVAILABLE_FEATURES,
+ name);
+}
+\f
+
/* Read an XML target description using OPS. Parse it, and return the
parsed description. */
@@ -220,13 +283,14 @@ target_read_description_xml (struct targ
char *tdesc_str;
struct cleanup *back_to;
- tdesc_str = target_read_stralloc (ops, TARGET_OBJECT_AVAILABLE_FEATURES,
- "target.xml");
+ tdesc_str = fetch_available_features_from_target ("target.xml", ops);
if (tdesc_str == NULL)
return NULL;
back_to = make_cleanup (xfree, tdesc_str);
- tdesc = tdesc_parse_xml (tdesc_str);
+ tdesc = tdesc_parse_xml (tdesc_str,
+ fetch_available_features_from_target,
+ ops);
do_cleanups (back_to);
return tdesc;
Index: src/gdb/features/gdb-target.dtd
===================================================================
--- src.orig/gdb/features/gdb-target.dtd 2007-01-31 13:31:22.000000000 -0500
+++ src/gdb/features/gdb-target.dtd 2007-01-31 13:31:55.000000000 -0500
@@ -1,9 +1,14 @@
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
<!-- The root element of a GDB target description is <target>. -->
<!ELEMENT target (architecture?)>
-<!ATTLIST target
- xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
<!ELEMENT architecture (#PCDATA)>
-
+<!ENTITY % xinclude SYSTEM "xinclude.dtd">
+%xinclude;
Index: src/gdb/features/xinclude.dtd
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/features/xinclude.dtd 2007-01-31 13:31:55.000000000 -0500
@@ -0,0 +1,13 @@
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!-- GDB supports a subset of XInclude. Only whole documents can
+ be included, and only as XML. -->
+
+<!ELEMENT xi:include (EMPTY)>
+<!ATTLIST xi:include
+ xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
+ href CDATA #REQUIRED>
Index: src/gdb/testsuite/gdb.xml/bad-include.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/bad-include.xml 2007-01-31 13:31:55.000000000 -0500
@@ -0,0 +1 @@
+<xi:include href="nonexistant.xml"/>
Index: src/gdb/testsuite/gdb.xml/inc-2.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/inc-2.xml 2007-01-31 13:31:55.000000000 -0500
@@ -0,0 +1 @@
+<xi:include href="inc-body.xml"/>
Index: src/gdb/testsuite/gdb.xml/inc-body.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/inc-body.xml 2007-01-31 13:31:55.000000000 -0500
@@ -0,0 +1 @@
+<architecture>invalid-body</architecture>
Index: src/gdb/testsuite/gdb.xml/includes.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/includes.xml 2007-01-31 13:31:55.000000000 -0500
@@ -0,0 +1,3 @@
+<target>
+ <xi:include href="inc-2.xml"/>
+</target>
Index: src/gdb/testsuite/gdb.xml/tdesc-xinclude.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/tdesc-xinclude.exp 2007-01-31 13:31:55.000000000 -0500
@@ -0,0 +1,54 @@
+# Copyright 2007 Free Software Foundation, Inc.
+
+# 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 2 of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+if {[gdb_skip_xml_test]} {
+ unsupported "tdesc-errors.exp"
+ return -1
+}
+
+gdb_start
+
+proc set_arch { srcfile errmsg } {
+ global gdb_prompt
+ global srcdir
+ global subdir
+
+ # Anchor the test output, so that error messages are detected.
+ set cmd "set tdesc filename $srcdir/$subdir/$srcfile"
+ set msg $cmd
+ set cmd_regex [string_to_regexp $cmd]
+ gdb_test_multiple $cmd $msg {
+ -re "^$cmd_regex\r\n$errmsg$gdb_prompt $" {
+ pass $msg
+ }
+ }
+}
+
+set common_warn "\r\nwarning: Could not load XML target description; ignoring\r\n"
+
+# This file is valid, but specifies an unknown architecture.
+# We should get a warning, if we process the includes correctly.
+set_arch "includes.xml" \
+ "warning:.*specified unknown architecture.* \"invalid-body\"$common_warn"
+
+# This file contains a missing include. We should warn the user about
+# it.
+set_arch "bad-include.xml" \
+ "warning:.*Could not load XML document \"nonexistant.xml\"$common_warn"
+
+# Make sure we detect infinite loops, eventually.
+set_arch "loop.xml" \
+ "warning:.*Maximum XInclude depth.*$common_warn"
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo 2007-01-31 13:31:22.000000000 -0500
+++ src/gdb/doc/gdb.texinfo 2007-01-31 13:31:55.000000000 -0500
@@ -25781,6 +25781,27 @@ The content of the @samp{<architecture>}
name, from the same selection accepted by @code{set architecture}
(@pxref{Targets, ,Specifying a Debugging Target}).
+@subsection Inclusion
+
+It can sometimes be valuable to split a target description up into
+several different annexes, either for organizational purposes, or to
+share files between different possible target descriptions. You can
+divide a description into multiple files by replacing any element of
+the target description with an inclusion directive of the form:
+
+@example
+<xi:include href="@var{name}"/>
+@end example
+
+@noindent
+When @value{GDBN} encounters an element of this form, it will retrieve
+the XML document named @var{name}, and replace the inclusion directive
+with the contents of that annex. If the current description was read
+using @samp{qXfer}, then the new document will be also, using
+@var{name} as the annex. If the current description was read from a
+file, @value{GDBN} will look for a file named @var{name} in the same
+directory as the original file.
+
@include gpl.texi
Index: src/gdb/testsuite/gdb.xml/loop.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/loop.xml 2007-01-11 16:28:03.000000000 -0500
@@ -0,0 +1 @@
+<xi:include href="loop.xml"/>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-01-29 21:32 XML XInclude support Daniel Jacobowitz
2007-01-31 18:33 ` Daniel Jacobowitz
@ 2007-02-02 18:53 ` Eli Zaretskii
2007-02-06 12:49 ` Daniel Jacobowitz
2007-02-06 13:03 ` Daniel Jacobowitz
1 sibling, 2 replies; 14+ messages in thread
From: Eli Zaretskii @ 2007-02-02 18:53 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
> Date: Mon, 29 Jan 2007 16:32:30 -0500
> From: Daniel Jacobowitz <drow@false.org>
> Cc: Eli Zaretskii <eliz@gnu.org>
>
> This patch adds support for a limited subset (I confess, very limited)
> of XInclude to GDB's target description parser. It's a simple textual
> transform. A file that looks like this:
>
> <target>
> <xi:include href="other.xml"/>
> </target>
>
> is expanded to include the contents of other.xml instead of the
> xi:include element, before parsing it as a target description.
> For "set tdesc filename" other.xml should be in the same directory
> as the original description. For qXfer:features, other.xml is
> a new annex to read from the target.
Thanks.
> + /* Simple, portable version of dirname that does not modify its
> + argument. */
> + base = lbasename (filename);
> + while (base > filename && IS_DIR_SEPARATOR (base[-1]))
> + --base;
I'm glad to see portable file-name handling, but this loop needs a
small extra to not fail in the case of "d:foo".
> +@example
> +<xi:include href="@var{name}"/>
> +@end example
> +
> +@noindent
> +When @value{GDBN} encounters an element of this form, it will retrieve
> +the XML document named @var{name}, and replace the inclusion directive
> +with the contents of that annex.
I'd suggest to use @var{document} instead of @var{name}, and reword
the last sentence like this:
When @value{GDBN} encounters an element of this form, it will retrieve
the named XML @var{document} ...
> If the current description was read
> +using @samp{qXfer}, then the new document will be also
This "the new document will be also" is a bit confusing, I think. How
about this instead:
If the current description was read using @samp{qXfer}, then so will
be the included @var{document}; the description's name will be
interpreted as the name of an annex.
> If the current description was read from a
> +file, @value{GDBN} will look for a file named @var{name} in the same
> +directory as the original file.
If the current description was read from a
file, @value{GDBN} will look for @var{document} as a file in the same
directory where it found the original description.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-02 18:53 ` Eli Zaretskii
@ 2007-02-06 12:49 ` Daniel Jacobowitz
2007-02-07 18:16 ` Eli Zaretskii
2007-02-06 13:03 ` Daniel Jacobowitz
1 sibling, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2007-02-06 12:49 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On Fri, Feb 02, 2007 at 08:53:32PM +0200, Eli Zaretskii wrote:
> > + /* Simple, portable version of dirname that does not modify its
> > + argument. */
> > + base = lbasename (filename);
> > + while (base > filename && IS_DIR_SEPARATOR (base[-1]))
> > + --base;
>
> I'm glad to see portable file-name handling, but this loop needs a
> small extra to not fail in the case of "d:foo".
Does it? lbasename ("d:foo") will return a pointer to the 'f'. At
that point base > filename is true, but IS_DIR_SEPARATOR is false,
so we use "d:" as the directory name. If that's wrong, I don't know
enough about DOS based filesystems to know why.
> I'd suggest to use @var{document} instead of @var{name}, and reword
> the last sentence like this:
Is this better?
@noindent
When @value{GDBN} encounters an element of this form, it will retrieve
the named XML @var{document}, and replace the inclusion directive with
the contents of that document. If the current description was read
using @samp{qXfer}, then so will be the included document;
@var{document} will be interpreted as the name of an annex. If the
current description was read from a file, @value{GDBN} will look for
@var{document} as a file in the same directory where it found the
original description.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-02 18:53 ` Eli Zaretskii
2007-02-06 12:49 ` Daniel Jacobowitz
@ 2007-02-06 13:03 ` Daniel Jacobowitz
2007-02-07 18:20 ` Eli Zaretskii
1 sibling, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2007-02-06 13:03 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
I wanted to index this as:
@subsection Inclusion
+@cindex target descriptions, inclusion
+@cindex XInclude
+@cindex <xi:include>
That doesn't work in info, because the info browser tries to interpret
the colon. But the colon is a syntactic element here, and this is what
I would look for. Plus it works in the PDF, or in print. What do you
think - should I leave the somewhat broken @cindex, since it's more
useful than not?
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-06 12:49 ` Daniel Jacobowitz
@ 2007-02-07 18:16 ` Eli Zaretskii
2007-02-07 18:37 ` Daniel Jacobowitz
0 siblings, 1 reply; 14+ messages in thread
From: Eli Zaretskii @ 2007-02-07 18:16 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
> Date: Tue, 6 Feb 2007 07:49:10 -0500
> From: Daniel Jacobowitz <drow@false.org>
> Cc: gdb-patches@sourceware.org
>
> On Fri, Feb 02, 2007 at 08:53:32PM +0200, Eli Zaretskii wrote:
> > > + /* Simple, portable version of dirname that does not modify its
> > > + argument. */
> > > + base = lbasename (filename);
> > > + while (base > filename && IS_DIR_SEPARATOR (base[-1]))
> > > + --base;
> >
> > I'm glad to see portable file-name handling, but this loop needs a
> > small extra to not fail in the case of "d:foo".
>
> Does it? lbasename ("d:foo") will return a pointer to the 'f'. At
> that point base > filename is true, but IS_DIR_SEPARATOR is false,
> so we use "d:" as the directory name. If that's wrong, I don't know
> enough about DOS based filesystems to know why.
"d:" is wrong because when you use it to construct a file name, you
will get "d:/bar", which is generally not in the same directory as
"d:foo".
What you need is to produce "d:." from "d:foo", not "d:".
> > I'd suggest to use @var{document} instead of @var{name}, and reword
> > the last sentence like this:
>
> Is this better?
>
> @noindent
> When @value{GDBN} encounters an element of this form, it will retrieve
> the named XML @var{document}, and replace the inclusion directive with
> the contents of that document. If the current description was read
> using @samp{qXfer}, then so will be the included document;
> @var{document} will be interpreted as the name of an annex. If the
> current description was read from a file, @value{GDBN} will look for
> @var{document} as a file in the same directory where it found the
> original description.
Yes, this is much better.
Thanks.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-06 13:03 ` Daniel Jacobowitz
@ 2007-02-07 18:20 ` Eli Zaretskii
0 siblings, 0 replies; 14+ messages in thread
From: Eli Zaretskii @ 2007-02-07 18:20 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: gdb-patches
> Date: Tue, 6 Feb 2007 08:03:30 -0500
> From: Daniel Jacobowitz <drow@false.org>
> Cc: gdb-patches@sourceware.org
>
> I wanted to index this as:
>
> @subsection Inclusion
> +@cindex target descriptions, inclusion
> +@cindex XInclude
> +@cindex <xi:include>
>
> That doesn't work in info, because the info browser tries to interpret
> the colon.
Yes, colons shouldn't appear in index entries (see the Texinfo
manual).
> But the colon is a syntactic element here, and this is what
> I would look for. Plus it works in the PDF, or in print. What do you
> think - should I leave the somewhat broken @cindex, since it's more
> useful than not?
I think you can condition it on the output format, like so:
@ifnotinfo
@cindex <xi:include>
@end ifnotinfo
Btw, isn't it better to use "@cindex xi:include", without the
brackets? If I were looking for this, I'd probably omitted the
brackets; wouldn't you?
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-07 18:16 ` Eli Zaretskii
@ 2007-02-07 18:37 ` Daniel Jacobowitz
2007-02-07 18:45 ` Daniel Jacobowitz
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2007-02-07 18:37 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: gdb-patches
On Wed, Feb 07, 2007 at 08:15:59PM +0200, Eli Zaretskii wrote:
> "d:" is wrong because when you use it to construct a file name, you
> will get "d:/bar", which is generally not in the same directory as
> "d:foo".
>
> What you need is to produce "d:." from "d:foo", not "d:".
Thank you for explaining! I've added this, and some notes so that
I can remember why.
On Wed, Feb 07, 2007 at 08:20:13PM +0200, Eli Zaretskii wrote:
> > But the colon is a syntactic element here, and this is what
> > I would look for. Plus it works in the PDF, or in print. What do you
> > think - should I leave the somewhat broken @cindex, since it's more
> > useful than not?
>
> I think you can condition it on the output format, like so:
>
> @ifnotinfo
> @cindex <xi:include>
> @end ifnotinfo
Thanks - I'll use that.
> Btw, isn't it better to use "@cindex xi:include", without the
> brackets? If I were looking for this, I'd probably omitted the
> brackets; wouldn't you?
For this case, I've added xi:include too, since that's reasonable with
or without the brackets. But in general, no, I wouldn't. Especially
not since "reg" and "architecture" are very ambiguous index entries,
but "<reg>" and "<architecture>" are quite clear. So I didn't
add a matching @cindex reg.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-07 18:37 ` Daniel Jacobowitz
@ 2007-02-07 18:45 ` Daniel Jacobowitz
2007-02-07 22:49 ` Daniel Jacobowitz
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2007-02-07 18:45 UTC (permalink / raw)
To: Eli Zaretskii, gdb-patches
On Wed, Feb 07, 2007 at 01:36:56PM -0500, Daniel Jacobowitz wrote:
> For this case, I've added xi:include too, since that's reasonable with
> or without the brackets.
That was silly. xi:include won't work for the same reason <xi:include>
won't. Fortunately right where it would sit in the index is the entry
for XInclude, so that should be OK.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-07 18:45 ` Daniel Jacobowitz
@ 2007-02-07 22:49 ` Daniel Jacobowitz
2007-02-08 13:06 ` Mark Kettenis
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2007-02-07 22:49 UTC (permalink / raw)
To: gdb-patches; +Cc: Eli Zaretskii
On Wed, Feb 07, 2007 at 01:44:58PM -0500, Daniel Jacobowitz wrote:
> On Wed, Feb 07, 2007 at 01:36:56PM -0500, Daniel Jacobowitz wrote:
> > For this case, I've added xi:include too, since that's reasonable with
> > or without the brackets.
>
> That was silly. xi:include won't work for the same reason <xi:include>
> won't. Fortunately right where it would sit in the index is the entry
> for XInclude, so that should be OK.
Here's the version I committed.
--
Daniel Jacobowitz
CodeSourcery
2007-02-07 Daniel Jacobowitz <dan@codesourcery.com>
* Makefile.in (XMLFILES): New.
(COMMON_OBS): Add xml-builtin.o.
(xml-builtin.c, stamp-xml): New rules.
(xml-tdesc.o): Update.
* features/feature_to_c.sh: New file.
* xml-support.c (MAX_XINCLUDE_DEPTH): Define.
(struct gdb_xml_parser): Add dtd_name and is_xinclude.
(gdb_xml_start_element): Initialize scope after possibly reallocating
scopes. Move cleanup later. Handle the XInclude description
specially.
(gdb_xml_end_element): Only parse the body if there is a current element.
Call XML_DefaultCurrent if there is no element.
(gdb_xml_fetch_external_entity, gdb_xml_use_dtd): New.
(struct xinclude_parsing_data, xinclude_start_include)
(xinclude_end_include, xml_xinclude_default)
(xml_xinclude_start_doctype, xml_xinclude_end_doctype)
(xml_xinclude_xml_decl, xml_xinclude_cleanup, xinclude_attributes)
(xinclude_elements, xml_process_xincludes, fetch_xml_builtin): New.
* xml-support.h (xml_fetch_another, xml_process_xincludes)
(fetch_xml_builtin, xml_builtin, gdb_xml_use_dtd): New declarations.
* xml-tdesc.c (tdesc_parse_xml): Add fetcher_baton argument. Expand
XInclude directives. Use the compiled in DTD.
(fetch_xml_from_file): Add baton argument. Treat it as a containing
directory name. Do not warn here.
(file_read_description_xml): Update call. Warn here instead. Pass
a dirname as baton.
(fetch_available_features_from_target): New.
(target_read_description_xml): Use it.
* features/gdb-target.dtd: Add copyright notice. Use xinclude.dtd
to handle XInclude.
* features/xinclude.dtd: New file.
2007-02-07 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.xml/bad-include.xml, gdb.xml/inc-2.xml, gdb.xml/inc-body.xml,
gdb.xml/includes.xml, gdb.xml/tdesc-xinclude.exp: New files.
2007-02-07 Daniel Jacobowitz <dan@codesourcery.com>
* gdb.texinfo (Target Description Format): Add section on XInclude.
---
gdb/Makefile.in | 20 +
gdb/doc/gdb.texinfo | 27 ++
gdb/features/feature_to_c.sh | 77 ++++++
gdb/features/gdb-target.dtd | 11
gdb/features/xinclude.dtd | 13 +
gdb/testsuite/gdb.xml/bad-include.xml | 1
gdb/testsuite/gdb.xml/inc-2.xml | 1
gdb/testsuite/gdb.xml/inc-body.xml | 1
gdb/testsuite/gdb.xml/includes.xml | 3
gdb/testsuite/gdb.xml/loop.xml | 1
gdb/testsuite/gdb.xml/tdesc-xinclude.exp | 54 ++++
gdb/xml-support.c | 372 +++++++++++++++++++++++++++++--
gdb/xml-support.h | 34 ++
gdb/xml-tdesc.c | 106 +++++++-
14 files changed, 676 insertions(+), 45 deletions(-)
Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in 2007-02-06 07:35:36.000000000 -0500
+++ src/gdb/Makefile.in 2007-02-07 13:27:11.000000000 -0500
@@ -400,6 +400,9 @@ LINTFLAGS= $(GDB_CFLAGS) $(OPCODES_CFLAG
RUNTEST = runtest
RUNTESTFLAGS=
+# XML files to build in to GDB.
+XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd
+
# This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
# interface to the serial port. Hopefully if get ported to OS/2, VMS,
# etc., then there will be (as part of the C library or perhaps as
@@ -972,7 +975,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
tramp-frame.o \
solib.o solib-null.o \
prologue-value.o memory-map.o xml-support.o \
- target-descriptions.o target-memory.o xml-tdesc.o
+ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o
TSOBS = inflow.o
@@ -1681,6 +1684,19 @@ po/$(PACKAGE).pot: force
.PRECIOUS: objc-exp.c
.PRECIOUS: p-exp.c
+# XML rules
+
+xml-builtin.c: stamp-xml; @true
+stamp-xml: $(srcdir)/features/feature_to_c.sh Makefile $(XMLFILES)
+ rm -f xml-builtin.tmp
+ AWK="$(AWK)" \
+ $(SHELL) $(srcdir)/features/feature_to_c.sh \
+ xml-builtin.tmp $(XMLFILES)
+ $(SHELL) $(srcdir)/../move-if-change xml-builtin.tmp xml-builtin.c
+ echo stamp > stamp-xml
+
+.PRECIOUS: xml-builtin.c
+
#
# gdb/ dependencies
#
@@ -2876,7 +2892,7 @@ xcoffread.o: xcoffread.c $(defs_h) $(bfd
xcoffsolib.o: xcoffsolib.c $(defs_h) $(bfd_h) $(xcoffsolib_h) $(inferior_h) \
$(gdbcmd_h) $(symfile_h) $(frame_h) $(gdb_regex_h)
xml-tdesc.o: xml-tdesc.c $(defs_h) $(target_h) $(target_descriptions_h) \
- $(xml_tdesc_h) $(xml_support_h) $(gdb_assert_h)
+ $(xml_tdesc_h) $(xml_support_h) $(filenames_h) $(gdb_assert_h)
xml-support.o: xml-support.c $(defs_h) $(xml_support_h) $(exceptions_h) \
$(gdbcmd_h) $(gdb_string_h) $(gdb_expat_h) $(safe_ctype_h)
xstormy16-tdep.o: xstormy16-tdep.c $(defs_h) $(frame_h) $(frame_base_h) \
Index: src/gdb/features/feature_to_c.sh
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/features/feature_to_c.sh 2007-02-06 07:37:40.000000000 -0500
@@ -0,0 +1,77 @@
+#!/bin/sh
+
+# Convert text files to compilable C arrays.
+#
+# Copyright (C) 2007 Free Software Foundation, Inc.
+#
+# This file is part of GDB.
+#
+# 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 2 of the License, 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, Inc., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+
+output=$1
+shift
+
+if test -z "$output" || test -z "$1"; then
+ echo "Usage: $0 OUTPUTFILE INPUTFILE..."
+ exit 1
+fi
+
+if test -e "$output"; then
+ echo "Output file \"$output\" already exists; refusing to overwrite."
+ exit 1
+fi
+
+for input; do
+ arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
+
+ ${AWK:-awk} 'BEGIN { n = 0
+ print "static const char '$arrayname'[] = {"
+ for (i = 0; i < 255; i++)
+ _ord_[sprintf("%c", i)] = i
+ } {
+ split($0, line, "");
+ printf " "
+ for (i = 1; i <= length($0); i++) {
+ c = line[i]
+ if (c == "'\''") {
+ printf "'\''\\'\'''\'', "
+ } else if (c == "\\") {
+ printf "'\''\\\\'\'', "
+ } else if (_ord_[c] >= 32 && _ord_[c] < 127) {
+ printf "'\''" c "'\'', "
+ } else {
+ printf "'\''\\%03o'\'', ", _ord_[c]
+ }
+ if (i % 10 == 0)
+ printf "\n "
+ }
+ printf "'\''\\n'\'', \n"
+ } END {
+ print " 0 };"
+ }' < $input >> $output
+done
+
+echo >> $output
+echo "const char *const xml_builtin[][2] = {" >> $output
+
+for input; do
+ basename=`echo $input | sed 's,.*/,,'`
+ arrayname=xml_feature_`echo $input | sed 's,.*/,,; s/[-.]/_/g'`
+ echo " { \"$basename\", $arrayname }," >> $output
+done
+
+echo " { 0, 0 }" >> $output
+echo "};" >> $output
Index: src/gdb/xml-support.c
===================================================================
--- src.orig/gdb/xml-support.c 2007-02-06 07:35:36.000000000 -0500
+++ src/gdb/xml-support.c 2007-02-07 13:27:11.000000000 -0500
@@ -36,6 +36,10 @@ static int debug_xml;
#include "gdb_string.h"
#include "safe-ctype.h"
+/* The maximum depth of <xi:include> nesting. No need to be miserly,
+ we just want to avoid running out of stack on loops. */
+#define MAX_XINCLUDE_DEPTH 30
+
/* A parsing level -- used to keep track of the current element
nesting. */
struct scope_level
@@ -68,6 +72,10 @@ struct gdb_xml_parser
struct gdb_exception error; /* A thrown error, if any. */
int last_line; /* The line of the thrown error, or 0. */
+
+ const char *dtd_name; /* The name of the expected / default DTD,
+ if specified. */
+ int is_xinclude; /* Are we the special <xi:include> parser? */
};
/* Process some body text. We accumulate the text for later use; it's
@@ -152,7 +160,7 @@ gdb_xml_start_element (void *data, const
const XML_Char **attrs)
{
struct gdb_xml_parser *parser = data;
- struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
+ struct scope_level *scope;
struct scope_level new_scope;
const struct gdb_xml_element *element;
const struct gdb_xml_attribute *attribute;
@@ -160,13 +168,13 @@ gdb_xml_start_element (void *data, const
unsigned int seen;
struct cleanup *back_to;
- back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
-
/* Push an error scope. If we return or throw an exception before
filling this in, it will tell us to ignore children of this
element. */
+ VEC_reserve (scope_level_s, parser->scopes, 1);
+ scope = VEC_last (scope_level_s, parser->scopes);
memset (&new_scope, 0, sizeof (new_scope));
- VEC_safe_push (scope_level_s, parser->scopes, &new_scope);
+ VEC_quick_push (scope_level_s, parser->scopes, &new_scope);
gdb_xml_debug (parser, _("Entering element <%s>"), name);
@@ -181,8 +189,21 @@ gdb_xml_start_element (void *data, const
if (element == NULL || element->name == NULL)
{
+ /* If we're working on XInclude, <xi:include> can be the child
+ of absolutely anything. Copy the previous scope's element
+ list into the new scope even if there was no match. */
+ if (parser->is_xinclude)
+ {
+ struct scope_level *unknown_scope;
+
+ XML_DefaultCurrent (parser->expat_parser);
+
+ unknown_scope = VEC_last (scope_level_s, parser->scopes);
+ unknown_scope->elements = scope->elements;
+ return;
+ }
+
gdb_xml_debug (parser, _("Element <%s> unknown"), name);
- do_cleanups (back_to);
return;
}
@@ -191,6 +212,8 @@ gdb_xml_start_element (void *data, const
scope->seen |= seen;
+ back_to = make_cleanup (gdb_xml_values_cleanup, &attributes);
+
for (attribute = element->attributes;
attribute != NULL && attribute->name != NULL;
attribute++)
@@ -304,7 +327,6 @@ gdb_xml_end_element (void *data, const X
struct scope_level *scope = VEC_last (scope_level_s, parser->scopes);
const struct gdb_xml_element *element;
unsigned int seen;
- char *body;
gdb_xml_debug (parser, _("Leaving element <%s>"), name);
@@ -317,26 +339,32 @@ gdb_xml_end_element (void *data, const X
element->name);
/* Call the element processor. */
- if (scope->body == NULL)
- body = "";
- else
+ if (scope->element != NULL && scope->element->end_handler)
{
- int length;
+ char *body;
- length = obstack_object_size (scope->body);
- obstack_1grow (scope->body, '\0');
- body = obstack_finish (scope->body);
-
- /* Strip leading and trailing whitespace. */
- while (length > 0 && ISSPACE (body[length-1]))
- body[--length] = '\0';
- while (*body && ISSPACE (*body))
- body++;
- }
+ if (scope->body == NULL)
+ body = "";
+ else
+ {
+ int length;
- if (scope->element != NULL && scope->element->end_handler)
- scope->element->end_handler (parser, scope->element, parser->user_data,
- body);
+ length = obstack_object_size (scope->body);
+ obstack_1grow (scope->body, '\0');
+ body = obstack_finish (scope->body);
+
+ /* Strip leading and trailing whitespace. */
+ while (length > 0 && ISSPACE (body[length-1]))
+ body[--length] = '\0';
+ while (*body && ISSPACE (*body))
+ body++;
+ }
+
+ scope->element->end_handler (parser, scope->element, parser->user_data,
+ body);
+ }
+ else if (scope->element == NULL)
+ XML_DefaultCurrent (parser->expat_parser);
/* Pop the scope level. */
if (scope->body)
@@ -435,6 +463,74 @@ gdb_xml_create_parser_and_cleanup (const
return parser;
}
+/* External entity handler. The only external entities we support
+ are those compiled into GDB (we do not fetch entities from the
+ target). */
+
+static int XMLCALL
+gdb_xml_fetch_external_entity (XML_Parser expat_parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId)
+{
+ struct gdb_xml_parser *parser = XML_GetUserData (expat_parser);
+ XML_Parser entity_parser;
+ const char *text;
+ enum XML_Status status;
+
+ if (systemId == NULL)
+ {
+ text = fetch_xml_builtin (parser->dtd_name);
+ if (text == NULL)
+ internal_error (__FILE__, __LINE__, "could not locate built-in DTD %s",
+ parser->dtd_name);
+ }
+ else
+ {
+ text = fetch_xml_builtin (systemId);
+ if (text == NULL)
+ return XML_STATUS_ERROR;
+ }
+
+ entity_parser = XML_ExternalEntityParserCreate (expat_parser, context, NULL);
+
+ /* Don't use our handlers for the contents of the DTD. Just let expat
+ process it. */
+ XML_SetElementHandler (entity_parser, NULL, NULL);
+ XML_SetDoctypeDeclHandler (entity_parser, NULL, NULL);
+ XML_SetXmlDeclHandler (entity_parser, NULL);
+ XML_SetDefaultHandler (entity_parser, NULL);
+ XML_SetUserData (entity_parser, NULL);
+
+ status = XML_Parse (entity_parser, text, strlen (text), 1);
+
+ XML_ParserFree (entity_parser);
+ return status;
+}
+
+/* Associate DTD_NAME, which must be the name of a compiled-in DTD,
+ with PARSER. */
+
+void
+gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name)
+{
+ enum XML_Error err;
+
+ parser->dtd_name = dtd_name;
+
+ XML_SetParamEntityParsing (parser->expat_parser,
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE);
+ XML_SetExternalEntityRefHandler (parser->expat_parser,
+ gdb_xml_fetch_external_entity);
+
+ /* Even if no DTD is provided, use the built-in DTD anyway. */
+ err = XML_UseForeignDTD (parser->expat_parser, XML_TRUE);
+ if (err != XML_ERROR_NONE)
+ internal_error (__FILE__, __LINE__,
+ "XML_UseForeignDTD failed: %s", XML_ErrorString (err));
+}
+
/* Invoke PARSER on BUFFER. BUFFER is the data to parse, which
should be NUL-terminated.
@@ -560,6 +656,236 @@ gdb_xml_parse_attr_enum (struct gdb_xml_
memcpy (ret, &enums->value, sizeof (enums->value));
return ret;
}
+\f
+
+/* XInclude processing. This is done as a separate step from actually
+ parsing the document, so that we can produce a single combined XML
+ document - e.g. to hand to a front end or to simplify comparing two
+ documents. We make extensive use of XML_DefaultCurrent, to pass
+ input text directly into the output without reformatting or
+ requoting it.
+
+ We output the DOCTYPE declaration for the first document unchanged,
+ if present, and discard DOCTYPEs from included documents. Only the
+ one we pass through here is used when we feed the result back to
+ expat. The XInclude standard explicitly does not discuss
+ validation of the result; we choose to apply the same DTD applied
+ to the outermost document.
+
+ We can not simply include the external DTD subset in the document
+ as an internal subset, because <!IGNORE> and <!INCLUDE> are valid
+ only in external subsets. But if we do not pass the DTD into the
+ output at all, default values will not be filled in.
+
+ We don't pass through any <?xml> declaration because we generate
+ UTF-8, not whatever the input encoding was. */
+
+struct xinclude_parsing_data
+{
+ /* The obstack to build the output in. */
+ struct obstack obstack;
+
+ /* A count indicating whether we are in an element whose
+ children should not be copied to the output, and if so,
+ how deep we are nested. This is used for anything inside
+ an xi:include, and for the DTD. */
+ int skip_depth;
+
+ /* The number of <xi:include> elements currently being processed,
+ to detect loops. */
+ int include_depth;
+
+ /* A function to call to obtain additional features, and its
+ baton. */
+ xml_fetch_another fetcher;
+ void *fetcher_baton;
+};
+
+static void
+xinclude_start_include (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+ struct xinclude_parsing_data *data = user_data;
+ char *href = VEC_index (gdb_xml_value_s, attributes, 0)->value;
+ struct cleanup *back_to;
+ char *text, *output;
+ int ret;
+
+ gdb_xml_debug (parser, _("Processing XInclude of \"%s\""), href);
+
+ if (data->include_depth > MAX_XINCLUDE_DEPTH)
+ gdb_xml_error (parser, _("Maximum XInclude depth (%d) exceeded"),
+ MAX_XINCLUDE_DEPTH);
+
+ text = data->fetcher (href, data->fetcher_baton);
+ if (text == NULL)
+ gdb_xml_error (parser, _("Could not load XML document \"%s\""), href);
+ back_to = make_cleanup (xfree, text);
+
+ output = xml_process_xincludes (parser->name, text, data->fetcher,
+ data->fetcher_baton,
+ data->include_depth + 1);
+ if (output == NULL)
+ gdb_xml_error (parser, _("Parsing \"%s\" failed"), href);
+
+ obstack_grow (&data->obstack, output, strlen (output));
+ xfree (output);
+
+ do_cleanups (back_to);
+
+ data->skip_depth++;
+}
+
+static void
+xinclude_end_include (struct gdb_xml_parser *parser,
+ const struct gdb_xml_element *element,
+ void *user_data, const char *body_text)
+{
+ struct xinclude_parsing_data *data = user_data;
+
+ data->skip_depth--;
+}
+
+static void XMLCALL
+xml_xinclude_default (void *data_, const XML_Char *s, int len)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ /* If we are inside of e.g. xi:include or the DTD, don't save this
+ string. */
+ if (data->skip_depth)
+ return;
+
+ /* Otherwise just add it to the end of the document we're building
+ up. */
+ obstack_grow (&data->obstack, s, len);
+}
+
+static void XMLCALL
+xml_xinclude_start_doctype (void *data_, const XML_Char *doctypeName,
+ const XML_Char *sysid, const XML_Char *pubid,
+ int has_internal_subset)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ /* Don't print out the doctype, or the contents of the DTD internal
+ subset, if any. */
+ data->skip_depth++;
+}
+
+static void XMLCALL
+xml_xinclude_end_doctype (void *data_)
+{
+ struct gdb_xml_parser *parser = data_;
+ struct xinclude_parsing_data *data = parser->user_data;
+
+ data->skip_depth--;
+}
+
+static void XMLCALL
+xml_xinclude_xml_decl (void *data_, const XML_Char *version,
+ const XML_Char *encoding, int standalone)
+{
+ /* Do nothing - this function prevents the default handler from
+ being called, thus suppressing the XML declaration from the
+ output. */
+}
+
+static void
+xml_xinclude_cleanup (void *data_)
+{
+ struct xinclude_parsing_data *data = data_;
+
+ obstack_free (&data->obstack, NULL);
+ xfree (data);
+}
+
+const struct gdb_xml_attribute xinclude_attributes[] = {
+ { "href", GDB_XML_AF_NONE, NULL, NULL },
+ { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element xinclude_elements[] = {
+ { "http://www.w3.org/2001/XInclude!include", xinclude_attributes, NULL,
+ GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
+ xinclude_start_include, xinclude_end_include },
+ { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+/* The main entry point for <xi:include> processing. */
+
+char *
+xml_process_xincludes (const char *name, const char *text,
+ xml_fetch_another fetcher, void *fetcher_baton,
+ int depth)
+{
+ enum XML_Error err;
+ struct gdb_xml_parser *parser;
+ struct xinclude_parsing_data *data;
+ struct cleanup *back_to;
+ char *result = NULL;
+
+ data = XZALLOC (struct xinclude_parsing_data);
+ obstack_init (&data->obstack);
+ back_to = make_cleanup (xml_xinclude_cleanup, data);
+
+ parser = gdb_xml_create_parser_and_cleanup (name, xinclude_elements, data);
+ parser->is_xinclude = 1;
+
+ data->include_depth = depth;
+ data->fetcher = fetcher;
+ data->fetcher_baton = fetcher_baton;
+
+ XML_SetCharacterDataHandler (parser->expat_parser, NULL);
+ XML_SetDefaultHandler (parser->expat_parser, xml_xinclude_default);
+
+ /* Always discard the XML version declarations; the only important
+ thing this provides is encoding, and our result will have been
+ converted to UTF-8. */
+ XML_SetXmlDeclHandler (parser->expat_parser, xml_xinclude_xml_decl);
+
+ if (depth > 0)
+ /* Discard the doctype for included documents. */
+ XML_SetDoctypeDeclHandler (parser->expat_parser,
+ xml_xinclude_start_doctype,
+ xml_xinclude_end_doctype);
+
+ gdb_xml_use_dtd (parser, "xinclude.dtd");
+
+ if (gdb_xml_parse (parser, text) == 0)
+ {
+ obstack_1grow (&data->obstack, '\0');
+ result = xstrdup (obstack_finish (&data->obstack));
+
+ if (depth == 0)
+ gdb_xml_debug (parser, _("XInclude processing succeeded:\n%s"),
+ result);
+ }
+ else
+ result = NULL;
+
+ do_cleanups (back_to);
+ return result;
+}
+\f
+
+/* Return an XML document which was compiled into GDB, from
+ the given FILENAME, or NULL if the file was not compiled in. */
+
+const char *
+fetch_xml_builtin (const char *filename)
+{
+ const char *(*p)[2];
+
+ for (p = xml_builtin; (*p)[0]; p++)
+ if (strcmp ((*p)[0], filename) == 0)
+ return (*p)[1];
+
+ return NULL;
+}
#endif /* HAVE_LIBEXPAT */
Index: src/gdb/xml-support.h
===================================================================
--- src.orig/gdb/xml-support.h 2007-02-06 07:35:36.000000000 -0500
+++ src/gdb/xml-support.h 2007-02-07 13:27:11.000000000 -0500
@@ -30,6 +30,35 @@ struct gdb_xml_parser;
struct gdb_xml_element;
struct gdb_xml_attribute;
+/* Support for XInclude. */
+
+/* Callback to fetch a new XML file, based on the provided HREF. */
+
+typedef char *(*xml_fetch_another) (const char *href, void *baton);
+
+/* Return a new string which is the expansion of TEXT after processing
+ <xi:include> tags. FETCHER will be called (with FETCHER_BATON) to
+ retrieve any new files. DEPTH should be zero on the initial call.
+
+ On failure, this function uses NAME in a warning and returns NULL.
+ It may throw an exception, but does not for XML parsing
+ problems. */
+
+char *xml_process_xincludes (const char *name, const char *text,
+ xml_fetch_another fetcher, void *fetcher_baton,
+ int depth);
+
+/* Return an XML document which was compiled into GDB, from
+ the given FILENAME, or NULL if the file was not compiled in. */
+
+const char *fetch_xml_builtin (const char *filename);
+
+/* The text of compiled-in XML documents, from xml-builtin.c
+ (generated). */
+extern const char *xml_builtin[][2];
+
+/* Simplified XML parser infrastructure. */
+
/* A name and value pair, used to record parsed attributes. */
struct gdb_xml_value
@@ -140,6 +169,11 @@ struct gdb_xml_parser *gdb_xml_create_pa
(const char *name, const struct gdb_xml_element *elements,
void *user_data);
+/* Associate DTD_NAME, which must be the name of a compiled-in DTD,
+ with PARSER. */
+
+void gdb_xml_use_dtd (struct gdb_xml_parser *parser, const char *dtd_name);
+
/* Invoke PARSER on BUFFER. BUFFER is the data to parse, which
should be NUL-terminated.
Index: src/gdb/xml-tdesc.c
===================================================================
--- src.orig/gdb/xml-tdesc.c 2007-02-06 07:35:36.000000000 -0500
+++ src/gdb/xml-tdesc.c 2007-02-07 13:31:47.000000000 -0500
@@ -28,6 +28,8 @@
#include "xml-support.h"
#include "xml-tdesc.h"
+#include "filenames.h"
+
#include "gdb_assert.h"
#if !defined(HAVE_LIBEXPAT)
@@ -36,7 +38,8 @@
an XML parser. */
static struct target_desc *
-tdesc_parse_xml (const char *document)
+tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
+ void *fetcher_baton)
{
static int have_warned;
@@ -94,22 +97,33 @@ const struct gdb_xml_element tdesc_eleme
/* Parse DOCUMENT into a target description and return it. */
static struct target_desc *
-tdesc_parse_xml (const char *document)
+tdesc_parse_xml (const char *document, xml_fetch_another fetcher,
+ void *fetcher_baton)
{
struct cleanup *back_to, *result_cleanup;
struct gdb_xml_parser *parser;
struct tdesc_parsing_data data;
+ char *expanded_text;
- memset (&data, 0, sizeof (struct tdesc_parsing_data));
+ /* Expand all XInclude directives. */
+ expanded_text = xml_process_xincludes (_("target description"),
+ document, fetcher, fetcher_baton, 0);
+ if (expanded_text == NULL)
+ {
+ warning (_("Could not load XML target description; ignoring"));
+ return NULL;
+ }
+ back_to = make_cleanup (xfree, expanded_text);
- back_to = make_cleanup (null_cleanup, NULL);
parser = gdb_xml_create_parser_and_cleanup (_("target description"),
tdesc_elements, &data);
+ gdb_xml_use_dtd (parser, "gdb-target.dtd");
+ memset (&data, 0, sizeof (struct tdesc_parsing_data));
data.tdesc = allocate_target_description ();
result_cleanup = make_cleanup_free_target_description (data.tdesc);
- if (gdb_xml_parse (parser, document) == 0)
+ if (gdb_xml_parse (parser, expanded_text) == 0)
{
/* Parsed successfully. */
discard_cleanups (result_cleanup);
@@ -123,7 +137,6 @@ tdesc_parse_xml (const char *document)
return NULL;
}
}
-
#endif /* HAVE_LIBEXPAT */
\f
@@ -139,19 +152,28 @@ do_cleanup_fclose (void *file)
the text. If something goes wrong, return NULL and warn. */
static char *
-fetch_xml_from_file (const char *filename)
+fetch_xml_from_file (const char *filename, void *baton)
{
+ const char *dirname = baton;
FILE *file;
struct cleanup *back_to;
char *text;
size_t len, offset;
- file = fopen (filename, FOPEN_RT);
- if (file == NULL)
+ if (dirname && *dirname)
{
- warning (_("Could not open \"%s\""), filename);
- return NULL;
+ char *fullname = concat (dirname, "/", filename, NULL);
+ if (fullname == NULL)
+ nomem (0);
+ file = fopen (fullname, FOPEN_RT);
+ xfree (fullname);
}
+ else
+ file = fopen (filename, FOPEN_RT);
+
+ if (file == NULL)
+ return NULL;
+
back_to = make_cleanup (do_cleanup_fclose, file);
/* Read in the whole file, one chunk at a time. */
@@ -198,18 +220,67 @@ file_read_description_xml (const char *f
struct target_desc *tdesc;
char *tdesc_str;
struct cleanup *back_to;
+ const char *base;
+ char *dirname;
- tdesc_str = fetch_xml_from_file (filename);
+ tdesc_str = fetch_xml_from_file (filename, NULL);
if (tdesc_str == NULL)
- return NULL;
+ {
+ warning (_("Could not open \"%s\""), filename);
+ return NULL;
+ }
back_to = make_cleanup (xfree, tdesc_str);
- tdesc = tdesc_parse_xml (tdesc_str);
+
+ /* Simple, portable version of dirname that does not modify its
+ argument. */
+ base = lbasename (filename);
+ while (base > filename && IS_DIR_SEPARATOR (base[-1]))
+ --base;
+ if (base > filename)
+ {
+ dirname = xmalloc (base - filename + 2);
+ memcpy (dirname, filename, base - filename);
+
+ /* On DOS based file systems, convert "d:foo" to "d:.", so that
+ we create "d:./bar" later instead of the (different)
+ "d:/bar". */
+ if (base - filename == 2 && IS_ABSOLUTE_PATH (base)
+ && !IS_DIR_SEPARATOR (filename[0]))
+ dirname[base++ - filename] = '.';
+
+ dirname[base - filename] = '\0';
+ make_cleanup (xfree, dirname);
+ }
+ else
+ dirname = NULL;
+
+ tdesc = tdesc_parse_xml (tdesc_str, fetch_xml_from_file, dirname);
do_cleanups (back_to);
return tdesc;
}
+/* Read a string representation of available features from the target,
+ using TARGET_OBJECT_AVAILABLE_FEATURES. The returned string is
+ malloc allocated and NUL-terminated. NAME should be a non-NULL
+ string identifying the XML document we want; the top level document
+ is "target.xml". Other calls may be performed for the DTD or
+ for <xi:include>. */
+
+static char *
+fetch_available_features_from_target (const char *name, void *baton_)
+{
+ struct target_ops *ops = baton_;
+
+ /* Read this object as a string. This ensures that a NUL
+ terminator is added. */
+ return target_read_stralloc (ops,
+ TARGET_OBJECT_AVAILABLE_FEATURES,
+ name);
+}
+\f
+
/* Read an XML target description using OPS. Parse it, and return the
parsed description. */
@@ -220,13 +291,14 @@ target_read_description_xml (struct targ
char *tdesc_str;
struct cleanup *back_to;
- tdesc_str = target_read_stralloc (ops, TARGET_OBJECT_AVAILABLE_FEATURES,
- "target.xml");
+ tdesc_str = fetch_available_features_from_target ("target.xml", ops);
if (tdesc_str == NULL)
return NULL;
back_to = make_cleanup (xfree, tdesc_str);
- tdesc = tdesc_parse_xml (tdesc_str);
+ tdesc = tdesc_parse_xml (tdesc_str,
+ fetch_available_features_from_target,
+ ops);
do_cleanups (back_to);
return tdesc;
Index: src/gdb/features/gdb-target.dtd
===================================================================
--- src.orig/gdb/features/gdb-target.dtd 2007-02-06 07:35:36.000000000 -0500
+++ src/gdb/features/gdb-target.dtd 2007-02-07 13:27:11.000000000 -0500
@@ -1,9 +1,14 @@
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
<!-- The root element of a GDB target description is <target>. -->
<!ELEMENT target (architecture?)>
-<!ATTLIST target
- xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
<!ELEMENT architecture (#PCDATA)>
-
+<!ENTITY % xinclude SYSTEM "xinclude.dtd">
+%xinclude;
Index: src/gdb/features/xinclude.dtd
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/features/xinclude.dtd 2007-02-06 07:37:40.000000000 -0500
@@ -0,0 +1,13 @@
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!-- GDB supports a subset of XInclude. Only whole documents can
+ be included, and only as XML. -->
+
+<!ELEMENT xi:include (EMPTY)>
+<!ATTLIST xi:include
+ xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
+ href CDATA #REQUIRED>
Index: src/gdb/testsuite/gdb.xml/bad-include.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/bad-include.xml 2007-02-06 07:37:40.000000000 -0500
@@ -0,0 +1 @@
+<xi:include href="nonexistant.xml"/>
Index: src/gdb/testsuite/gdb.xml/inc-2.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/inc-2.xml 2007-02-06 07:37:40.000000000 -0500
@@ -0,0 +1 @@
+<xi:include href="inc-body.xml"/>
Index: src/gdb/testsuite/gdb.xml/inc-body.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/inc-body.xml 2007-02-06 07:37:40.000000000 -0500
@@ -0,0 +1 @@
+<architecture>invalid-body</architecture>
Index: src/gdb/testsuite/gdb.xml/includes.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/includes.xml 2007-02-06 07:37:40.000000000 -0500
@@ -0,0 +1,3 @@
+<target>
+ <xi:include href="inc-2.xml"/>
+</target>
Index: src/gdb/testsuite/gdb.xml/tdesc-xinclude.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/tdesc-xinclude.exp 2007-02-06 07:37:40.000000000 -0500
@@ -0,0 +1,54 @@
+# Copyright 2007 Free Software Foundation, Inc.
+
+# 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 2 of the License, 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, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+if {[gdb_skip_xml_test]} {
+ unsupported "tdesc-errors.exp"
+ return -1
+}
+
+gdb_start
+
+proc set_arch { srcfile errmsg } {
+ global gdb_prompt
+ global srcdir
+ global subdir
+
+ # Anchor the test output, so that error messages are detected.
+ set cmd "set tdesc filename $srcdir/$subdir/$srcfile"
+ set msg $cmd
+ set cmd_regex [string_to_regexp $cmd]
+ gdb_test_multiple $cmd $msg {
+ -re "^$cmd_regex\r\n$errmsg$gdb_prompt $" {
+ pass $msg
+ }
+ }
+}
+
+set common_warn "\r\nwarning: Could not load XML target description; ignoring\r\n"
+
+# This file is valid, but specifies an unknown architecture.
+# We should get a warning, if we process the includes correctly.
+set_arch "includes.xml" \
+ "warning:.*specified unknown architecture.* \"invalid-body\"$common_warn"
+
+# This file contains a missing include. We should warn the user about
+# it.
+set_arch "bad-include.xml" \
+ "warning:.*Could not load XML document \"nonexistant.xml\"$common_warn"
+
+# Make sure we detect infinite loops, eventually.
+set_arch "loop.xml" \
+ "warning:.*Maximum XInclude depth.*$common_warn"
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo 2007-02-06 07:36:13.000000000 -0500
+++ src/gdb/doc/gdb.texinfo 2007-02-07 13:44:01.000000000 -0500
@@ -25825,6 +25825,33 @@ The content of the @samp{<architecture>}
name, from the same selection accepted by @code{set architecture}
(@pxref{Targets, ,Specifying a Debugging Target}).
+@subsection Inclusion
+@cindex target descriptions, inclusion
+@cindex XInclude
+@ifnotinfo
+@cindex <xi:include>
+@end ifnotinfo
+
+It can sometimes be valuable to split a target description up into
+several different annexes, either for organizational purposes, or to
+share files between different possible target descriptions. You can
+divide a description into multiple files by replacing any element of
+the target description with an inclusion directive of the form:
+
+@example
+<xi:include href="@var{document}"/>
+@end example
+
+@noindent
+When @value{GDBN} encounters an element of this form, it will retrieve
+the named XML @var{document}, and replace the inclusion directive with
+the contents of that document. If the current description was read
+using @samp{qXfer}, then so will be the included document;
+@var{document} will be interpreted as the name of an annex. If the
+current description was read from a file, @value{GDBN} will look for
+@var{document} as a file in the same directory where it found the
+original description.
+
@include gpl.texi
Index: src/gdb/testsuite/gdb.xml/loop.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/testsuite/gdb.xml/loop.xml 2007-02-06 07:37:40.000000000 -0500
@@ -0,0 +1 @@
+<xi:include href="loop.xml"/>
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-07 22:49 ` Daniel Jacobowitz
@ 2007-02-08 13:06 ` Mark Kettenis
2007-02-08 13:14 ` Daniel Jacobowitz
0 siblings, 1 reply; 14+ messages in thread
From: Mark Kettenis @ 2007-02-08 13:06 UTC (permalink / raw)
To: drow; +Cc: gdb-patches, eliz
> Date: Wed, 7 Feb 2007 17:49:10 -0500
> From: Daniel Jacobowitz <drow@false.org>
>
> 2007-02-07 Daniel Jacobowitz <dan@codesourcery.com>
>
> * Makefile.in (XMLFILES): New.
> (COMMON_OBS): Add xml-builtin.o.
> (xml-builtin.c, stamp-xml): New rules.
> (xml-tdesc.o): Update.
> * features/feature_to_c.sh: New file.
> * xml-support.c (MAX_XINCLUDE_DEPTH): Define.
> (struct gdb_xml_parser): Add dtd_name and is_xinclude.
> (gdb_xml_start_element): Initialize scope after possibly reallocating
> scopes. Move cleanup later. Handle the XInclude description
> specially.
> (gdb_xml_end_element): Only parse the body if there is a current element.
> Call XML_DefaultCurrent if there is no element.
> (gdb_xml_fetch_external_entity, gdb_xml_use_dtd): New.
> (struct xinclude_parsing_data, xinclude_start_include)
> (xinclude_end_include, xml_xinclude_default)
> (xml_xinclude_start_doctype, xml_xinclude_end_doctype)
> (xml_xinclude_xml_decl, xml_xinclude_cleanup, xinclude_attributes)
> (xinclude_elements, xml_process_xincludes, fetch_xml_builtin): New.
> * xml-support.h (xml_fetch_another, xml_process_xincludes)
> (fetch_xml_builtin, xml_builtin, gdb_xml_use_dtd): New declarations.
> * xml-tdesc.c (tdesc_parse_xml): Add fetcher_baton argument. Expand
> XInclude directives. Use the compiled in DTD.
> (fetch_xml_from_file): Add baton argument. Treat it as a containing
> directory name. Do not warn here.
> (file_read_description_xml): Update call. Warn here instead. Pass
> a dirname as baton.
> (fetch_available_features_from_target): New.
> (target_read_description_xml): Use it.
> * features/gdb-target.dtd: Add copyright notice. Use xinclude.dtd
> to handle XInclude.
> * features/xinclude.dtd: New file.
>
> 2007-02-07 Daniel Jacobowitz <dan@codesourcery.com>
>
> * gdb.xml/bad-include.xml, gdb.xml/inc-2.xml, gdb.xml/inc-body.xml,
> gdb.xml/includes.xml, gdb.xml/tdesc-xinclude.exp: New files.
>
> 2007-02-07 Daniel Jacobowitz <dan@codesourcery.com>
>
> * gdb.texinfo (Target Description Format): Add section on XInclude.
Hi Daniel,
This broke my builds on OpenBSD :(. Here's the make output.
---
rm -f xml-builtin.tmp
AWK="nawk" /bin/sh ../../../src/gdb/gdb/features/feature_to_c.sh xml-builtin.tmp ../../../src/gdb/gdb/features/gdb-target.dtd ../../../src/gdb/gdb/features/xinclude.dtd
nawk: weird printf conversion %',
input record number 13, file
source line number 15
nawk: not enough args in printf('%', )
input record number 13, file
source line number 15
/bin/sh ../../../src/gdb/gdb/../move-if-change xml-builtin.tmp xml-builtin.c
echo stamp > stamp-xml
gcc -c -g -O2 -I. -I../../../src/gdb/gdb -I../../../src/gdb/gdb/config -DLOCALEDIR="\"/usr/local/share/locale\"" -DHAVE_CONFIG_H -I../../../src/gdb/gdb/../include/opcode -I../../../src/gdb/gdb/../readline/.. -I../bfd -I../../../src/gdb/gdb/../bfd -I../../../src/gdb/gdb/../include -DMI_OUT=1 -DTUI=1 -I/usr/local/include -Wall -Wpointer-arith -Wformat-nonliteral -Wno-unused -Wno-switch -Werror xml-builtin.c
xml-builtin.c:49: syntax error before `static'
xml-builtin.c:110: `xml_feature_xinclude_dtd' undeclared here (not in a function)
xml-builtin.c:110: initializer element is not constant
xml-builtin.c:110: (near initialization for `xml_builtin[1][1]')
*** Error code 1
Stop in /home/kettenis/obj/gdb/gdb.
*** Error code 1
Stop in /home/kettenis/obj/gdb (line 8486 of Makefile).
---
And here's the generated xml-builtin.c
---
static const char xml_feature_gdb_target_dtd[] = {
'<', '!', '-', '-', ' ', 'C', 'o', 'p', 'y', 'r',
'i', 'g', 'h', 't', ' ', '(', 'C', ')', ' ', '2',
'0', '0', '7', ' ', 'F', 'r', 'e', 'e', ' ', 'S',
'o', 'f', 't', 'w', 'a', 'r', 'e', ' ', 'F', 'o',
'u', 'n', 'd', 'a', 't', 'i', 'o', 'n', ',', ' ',
'I', 'n', 'c', '.', '\n',
'\n',
' ', ' ', ' ', ' ', ' ', 'C', 'o', 'p', 'y', 'i',
'n', 'g', ' ', 'a', 'n', 'd', ' ', 'd', 'i', 's',
't', 'r', 'i', 'b', 'u', 't', 'i', 'o', 'n', ' ',
'o', 'f', ' ', 't', 'h', 'i', 's', ' ', 'f', 'i',
'l', 'e', ',', ' ', 'w', 'i', 't', 'h', ' ', 'o',
'r', ' ', 'w', 'i', 't', 'h', 'o', 'u', 't', ' ',
'm', 'o', 'd', 'i', 'f', 'i', 'c', 'a', 't', 'i',
'o', 'n', ',', '\n',
' ', ' ', ' ', ' ', ' ', 'a', 'r', 'e', ' ', 'p',
'e', 'r', 'm', 'i', 't', 't', 'e', 'd', ' ', 'i',
'n', ' ', 'a', 'n', 'y', ' ', 'm', 'e', 'd', 'i',
'u', 'm', ' ', 'w', 'i', 't', 'h', 'o', 'u', 't',
' ', 'r', 'o', 'y', 'a', 'l', 't', 'y', ' ', 'p',
'r', 'o', 'v', 'i', 'd', 'e', 'd', ' ', 't', 'h',
'e', ' ', 'c', 'o', 'p', 'y', 'r', 'i', 'g', 'h',
't', '\n',
' ', ' ', ' ', ' ', ' ', 'n', 'o', 't', 'i', 'c',
'e', ' ', 'a', 'n', 'd', ' ', 't', 'h', 'i', 's',
' ', 'n', 'o', 't', 'i', 'c', 'e', ' ', 'a', 'r',
'e', ' ', 'p', 'r', 'e', 's', 'e', 'r', 'v', 'e',
'd', '.', ' ', ' ', '-', '-', '>', '\n',
'\n',
'<', '!', '-', '-', ' ', 'T', 'h', 'e', ' ', 'r',
'o', 'o', 't', ' ', 'e', 'l', 'e', 'm', 'e', 'n',
't', ' ', 'o', 'f', ' ', 'a', ' ', 'G', 'D', 'B',
' ', 't', 'a', 'r', 'g', 'e', 't', ' ', 'd', 'e',
's', 'c', 'r', 'i', 'p', 't', 'i', 'o', 'n', ' ',
'i', 's', ' ', '<', 't', 'a', 'r', 'g', 'e', 't',
'>', '.', ' ', ' ', '-', '-', '>', '\n',
'\n',
'<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T', ' ',
't', 'a', 'r', 'g', 'e', 't', '\011', '(', 'a', 'r',
'c', 'h', 'i', 't', 'e', 'c', 't', 'u', 'r', 'e',
'?', ')', '>', '\n',
'\n',
'<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T', ' ',
'a', 'r', 'c', 'h', 'i', 't', 'e', 'c', 't', 'u',
'r', 'e', '\011', '(', '#', 'P', 'C', 'D', 'A', 'T',
'A', ')', '>', '\n',
'\n',
'<', '!', 'E', 'N', 'T', 'I', 'T', 'Y', ' ', static const char xml_feature_xinclude_dtd[] = {
'<', '!', '-', '-', ' ', 'C', 'o', 'p', 'y', 'r',
'i', 'g', 'h', 't', ' ', '(', 'C', ')', ' ', '2',
'0', '0', '7', ' ', 'F', 'r', 'e', 'e', ' ', 'S',
'o', 'f', 't', 'w', 'a', 'r', 'e', ' ', 'F', 'o',
'u', 'n', 'd', 'a', 't', 'i', 'o', 'n', ',', ' ',
'I', 'n', 'c', '.', '\n',
'\n',
' ', ' ', ' ', ' ', ' ', 'C', 'o', 'p', 'y', 'i',
'n', 'g', ' ', 'a', 'n', 'd', ' ', 'd', 'i', 's',
't', 'r', 'i', 'b', 'u', 't', 'i', 'o', 'n', ' ',
'o', 'f', ' ', 't', 'h', 'i', 's', ' ', 'f', 'i',
'l', 'e', ',', ' ', 'w', 'i', 't', 'h', ' ', 'o',
'r', ' ', 'w', 'i', 't', 'h', 'o', 'u', 't', ' ',
'm', 'o', 'd', 'i', 'f', 'i', 'c', 'a', 't', 'i',
'o', 'n', ',', '\n',
' ', ' ', ' ', ' ', ' ', 'a', 'r', 'e', ' ', 'p',
'e', 'r', 'm', 'i', 't', 't', 'e', 'd', ' ', 'i',
'n', ' ', 'a', 'n', 'y', ' ', 'm', 'e', 'd', 'i',
'u', 'm', ' ', 'w', 'i', 't', 'h', 'o', 'u', 't',
' ', 'r', 'o', 'y', 'a', 'l', 't', 'y', ' ', 'p',
'r', 'o', 'v', 'i', 'd', 'e', 'd', ' ', 't', 'h',
'e', ' ', 'c', 'o', 'p', 'y', 'r', 'i', 'g', 'h',
't', '\n',
' ', ' ', ' ', ' ', ' ', 'n', 'o', 't', 'i', 'c',
'e', ' ', 'a', 'n', 'd', ' ', 't', 'h', 'i', 's',
' ', 'n', 'o', 't', 'i', 'c', 'e', ' ', 'a', 'r',
'e', ' ', 'p', 'r', 'e', 's', 'e', 'r', 'v', 'e',
'd', '.', ' ', ' ', '-', '-', '>', '\n',
'\n',
'<', '!', '-', '-', ' ', 'G', 'D', 'B', ' ', 's',
'u', 'p', 'p', 'o', 'r', 't', 's', ' ', 'a', ' ',
's', 'u', 'b', 's', 'e', 't', ' ', 'o', 'f', ' ',
'X', 'I', 'n', 'c', 'l', 'u', 'd', 'e', '.', ' ',
' ', 'O', 'n', 'l', 'y', ' ', 'w', 'h', 'o', 'l',
'e', ' ', 'd', 'o', 'c', 'u', 'm', 'e', 'n', 't',
's', ' ', 'c', 'a', 'n', '\n',
' ', ' ', ' ', ' ', ' ', 'b', 'e', ' ', 'i', 'n',
'c', 'l', 'u', 'd', 'e', 'd', ',', ' ', 'a', 'n',
'd', ' ', 'o', 'n', 'l', 'y', ' ', 'a', 's', ' ',
'X', 'M', 'L', '.', ' ', ' ', '-', '-', '>', '\n',
'\n',
'<', '!', 'E', 'L', 'E', 'M', 'E', 'N', 'T', ' ',
'x', 'i', ':', 'i', 'n', 'c', 'l', 'u', 'd', 'e',
'\011', '(', 'E', 'M', 'P', 'T', 'Y', ')', '>', '\n',
'<', '!', 'A', 'T', 'T', 'L', 'I', 'S', 'T', ' ',
'x', 'i', ':', 'i', 'n', 'c', 'l', 'u', 'd', 'e',
'\n',
'\011', 'x', 'm', 'l', 'n', 's', ':', 'x', 'i', '\011',
'C', 'D', 'A', 'T', 'A', '\011', '#', 'F', 'I', 'X',
'E', 'D', ' ', '"', 'h', 't', 't', 'p', ':', '/',
'/', 'w', 'w', 'w', '.', 'w', '3', '.', 'o', 'r',
'g', '/', '2', '0', '0', '1', '/', 'X', 'I', 'n',
'c', 'l', 'u', 'd', 'e', '"', '\n',
'\011', 'h', 'r', 'e', 'f', '\011', '\011', 'C', 'D', 'A',
'T', 'A', '\011', '#', 'R', 'E', 'Q', 'U', 'I', 'R',
'E', 'D', '>', '\n',
0 };
const char *const xml_builtin[][2] = {
{ "gdb-target.dtd", xml_feature_gdb_target_dtd },
{ "xinclude.dtd", xml_feature_xinclude_dtd },
{ 0, 0 }
};
---
which indeed isn't valid C code. Did yoy use some GNU-isms in the
bits of awk that are used to generate this code?
Mark
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-08 13:06 ` Mark Kettenis
@ 2007-02-08 13:14 ` Daniel Jacobowitz
2007-02-08 16:15 ` Mark Kettenis
0 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2007-02-08 13:14 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches, eliz
On Thu, Feb 08, 2007 at 02:06:02PM +0100, Mark Kettenis wrote:
> AWK="nawk" /bin/sh ../../../src/gdb/gdb/features/feature_to_c.sh xml-builtin.tmp ../../../src/gdb/gdb/features/gdb-target.dtd ../../../src/gdb/gdb/features/xinclude.dtd
> nawk: weird printf conversion %',
> input record number 13, file
> source line number 15
> nawk: not enough args in printf('%', )
> input record number 13, file
> source line number 15
I was afraid of the awk :-( I was very careful to try to avoid
GNU-ism; I tested with gawk, mawk, and gawk --posix. But apparently
all three of those let something through that nawk does not support.
That line is:
} else if (_ord_[c] >= 32 && _ord_[c] < 127) {
printf "'\''" c "'\'', "
We're inside single quotes here, so what gets passed to awk should be:
printf "'" c "', "
Could you try replacing that line with this, to avoid the % being
interpreted as a format specifier?
printf "'\''%c'\'', ", c
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-08 16:15 ` Mark Kettenis
@ 2007-02-08 13:57 ` Daniel Jacobowitz
0 siblings, 0 replies; 14+ messages in thread
From: Daniel Jacobowitz @ 2007-02-08 13:57 UTC (permalink / raw)
To: Mark Kettenis; +Cc: gdb-patches
On Thu, Feb 08, 2007 at 02:45:32PM +0100, Mark Kettenis wrote:
> > Could you try replacing that line with this, to avoid the % being
> > interpreted as a format specifier?
> >
> > printf "'\''%c'\'', ", c
>
> That seems to work, Thanks!
Oof - glad I checked; that's wrong. I've committed this instead,
which should still work for you, but not leave binary gunk in the file.
%c interprets 'a' as a character but '0' as an ASCII code.
Ever feel like I accomplish nothing except breaking your builds? :-)
--
Daniel Jacobowitz
CodeSourcery
2007-02-08 Daniel Jacobowitz <dan@codesourcery.com>
* features/feature_to_c.sh: Use %s to avoid problems with nawk.
Index: gdb/features/feature_to_c.sh
===================================================================
RCS file: /cvs/src/src/gdb/features/feature_to_c.sh,v
retrieving revision 1.2
diff -u -p -r1.2 feature_to_c.sh
--- gdb/features/feature_to_c.sh 7 Feb 2007 22:48:06 -0000 1.2
+++ gdb/features/feature_to_c.sh 8 Feb 2007 13:55:08 -0000
@@ -51,7 +51,7 @@ for input; do
} else if (c == "\\") {
printf "'\''\\\\'\'', "
} else if (_ord_[c] >= 32 && _ord_[c] < 127) {
- printf "'\''" c "'\'', "
+ printf "'\''%s'\'', ", c
} else {
printf "'\''\\%03o'\'', ", _ord_[c]
}
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: XML XInclude support
2007-02-08 13:14 ` Daniel Jacobowitz
@ 2007-02-08 16:15 ` Mark Kettenis
2007-02-08 13:57 ` Daniel Jacobowitz
0 siblings, 1 reply; 14+ messages in thread
From: Mark Kettenis @ 2007-02-08 16:15 UTC (permalink / raw)
To: drow; +Cc: gdb-patches
> Date: Thu, 8 Feb 2007 08:13:55 -0500
> From: Daniel Jacobowitz <drow@false.org>
>
> I was afraid of the awk :-( I was very careful to try to avoid
> GNU-ism; I tested with gawk, mawk, and gawk --posix. But apparently
> all three of those let something through that nawk does not support.
> That line is:
>
> } else if (_ord_[c] >= 32 && _ord_[c] < 127) {
> printf "'\''" c "'\'', "
>
> We're inside single quotes here, so what gets passed to awk should be:
>
> printf "'" c "', "
>
> Could you try replacing that line with this, to avoid the % being
> interpreted as a format specifier?
>
> printf "'\''%c'\'', ", c
That seems to work, Thanks!
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2007-02-08 16:15 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-01-29 21:32 XML XInclude support Daniel Jacobowitz
2007-01-31 18:33 ` Daniel Jacobowitz
2007-02-02 18:53 ` Eli Zaretskii
2007-02-06 12:49 ` Daniel Jacobowitz
2007-02-07 18:16 ` Eli Zaretskii
2007-02-07 18:37 ` Daniel Jacobowitz
2007-02-07 18:45 ` Daniel Jacobowitz
2007-02-07 22:49 ` Daniel Jacobowitz
2007-02-08 13:06 ` Mark Kettenis
2007-02-08 13:14 ` Daniel Jacobowitz
2007-02-08 16:15 ` Mark Kettenis
2007-02-08 13:57 ` Daniel Jacobowitz
2007-02-06 13:03 ` Daniel Jacobowitz
2007-02-07 18:20 ` Eli Zaretskii
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox