mirror of https://github.com/swig/swig
327 lines
8.6 KiB
C++
327 lines
8.6 KiB
C++
/* -----------------------------------------------------------------------------
|
|
* This file is part of SWIG, which is licensed as a whole under version 3
|
|
* (or any later version) of the GNU General Public License. Some additional
|
|
* terms also apply to certain portions of SWIG. The full details of the SWIG
|
|
* license and copyrights can be found in the LICENSE and COPYRIGHT files
|
|
* included with the SWIG source code as distributed by the SWIG developers
|
|
* and at https://www.swig.org/legal.html.
|
|
*
|
|
* xml.cxx
|
|
*
|
|
* An Xml parse tree generator.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
#include "swigmod.h"
|
|
|
|
static const char *usage = "\
|
|
XML Options (available with -xml)\n\
|
|
-xmllang <lang> - Typedef language\n\
|
|
-xmllite - More lightweight version of XML\n\
|
|
------\n\
|
|
deprecated (use -o): -xml <output.xml> - Use <output.xml> as output file (extension .xml mandatory)\n";
|
|
|
|
static File *out = 0;
|
|
static int xmllite = 0;
|
|
|
|
|
|
class XML:public Language {
|
|
public:
|
|
|
|
int indent_level;
|
|
long id;
|
|
|
|
XML() :indent_level(0) , id(0) {
|
|
}
|
|
|
|
virtual ~ XML() {
|
|
}
|
|
|
|
virtual void main(int argc, char *argv[]) {
|
|
SWIG_typemap_lang("xml");
|
|
for (int iX = 0; iX < argc; iX++) {
|
|
if (strcmp(argv[iX], "-xml") == 0) {
|
|
char *extension = 0;
|
|
if (iX + 1 >= argc)
|
|
continue;
|
|
extension = argv[iX + 1] + strlen(argv[iX + 1]) - 4;
|
|
if (strcmp(extension, ".xml"))
|
|
continue;
|
|
iX++;
|
|
Swig_mark_arg(iX);
|
|
String *outfile = NewString(argv[iX]);
|
|
out = NewFile(outfile, "w", SWIG_output_files());
|
|
if (!out) {
|
|
FileErrorDisplay(outfile);
|
|
Exit(EXIT_FAILURE);
|
|
}
|
|
continue;
|
|
}
|
|
if (strcmp(argv[iX], "-xmllang") == 0) {
|
|
Swig_mark_arg(iX);
|
|
iX++;
|
|
SWIG_typemap_lang(argv[iX]);
|
|
Swig_mark_arg(iX);
|
|
continue;
|
|
}
|
|
if (strcmp(argv[iX], "-help") == 0) {
|
|
fputs(usage, stdout);
|
|
}
|
|
if (strcmp(argv[iX], "-xmllite") == 0) {
|
|
Swig_mark_arg(iX);
|
|
xmllite = 1;
|
|
}
|
|
}
|
|
|
|
// Add a symbol to the parser for conditional compilation
|
|
Preprocessor_define("SWIGXML 1", 0);
|
|
}
|
|
|
|
/* Top of the parse tree */
|
|
|
|
virtual int top(Node *n) {
|
|
if (out == 0) {
|
|
String *outfile = Getattr(n, "outfile");
|
|
String *ext = Swig_file_extension(outfile);
|
|
// If there's an extension, ext will include the ".".
|
|
Delslice(outfile, Len(outfile) - Len(ext), DOH_END);
|
|
Delete(ext);
|
|
Append(outfile, ".xml");
|
|
out = NewFile(outfile, "w", SWIG_output_files());
|
|
if (!out) {
|
|
FileErrorDisplay(outfile);
|
|
Exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
Printf(out, "<?xml version=\"1.0\" ?> \n");
|
|
Xml_print_tree(n);
|
|
return SWIG_OK;
|
|
}
|
|
|
|
void print_indent(int l) {
|
|
int i;
|
|
for (i = 0; i < indent_level; i++) {
|
|
Printf(out, " ");
|
|
}
|
|
if (l) {
|
|
Printf(out, " ");
|
|
}
|
|
}
|
|
|
|
void Xml_print_tree(DOH *obj) {
|
|
while (obj) {
|
|
Xml_print_node(obj);
|
|
obj = nextSibling(obj);
|
|
}
|
|
}
|
|
|
|
void Xml_print_attributes(Node *obj) {
|
|
String *k;
|
|
indent_level += 4;
|
|
print_indent(0);
|
|
Printf(out, "<attributelist id=\"%ld\" addr=\"%p\" >\n", ++id, obj);
|
|
indent_level += 4;
|
|
Iterator ki;
|
|
ki = First(obj);
|
|
while (ki.key) {
|
|
k = ki.key;
|
|
if ((Cmp(k, "nodeType") == 0)
|
|
|| (Cmp(k, "firstChild") == 0)
|
|
|| (Cmp(k, "lastChild") == 0)
|
|
|| (Cmp(k, "parentNode") == 0)
|
|
|| (Cmp(k, "nextSibling") == 0)
|
|
|| (Cmp(k, "previousSibling") == 0)
|
|
|| (*(Char(k)) == '$')) {
|
|
/* Do nothing */
|
|
} else if (Cmp(k, "module") == 0) {
|
|
Xml_print_module(Getattr(obj, k));
|
|
} else if (Cmp(k, "baselist") == 0) {
|
|
Xml_print_baselist(Getattr(obj, k));
|
|
} else if (!xmllite && Cmp(k, "typescope") == 0) {
|
|
Xml_print_typescope(Getattr(obj, k));
|
|
} else if (!xmllite && Cmp(k, "typetab") == 0) {
|
|
Xml_print_typetab(Getattr(obj, k));
|
|
} else if (Cmp(k, "kwargs") == 0) {
|
|
Xml_print_kwargs(Getattr(obj, k));
|
|
} else if (Cmp(k, "parms") == 0 || Cmp(k, "pattern") == 0) {
|
|
Xml_print_parmlist(Getattr(obj, k));
|
|
} else if (Cmp(k, "catchlist") == 0 || Cmp(k, "templateparms") == 0) {
|
|
Xml_print_parmlist(Getattr(obj, k), Char(k));
|
|
} else {
|
|
DOH *o;
|
|
print_indent(0);
|
|
if (DohIsString(Getattr(obj, k))) {
|
|
String *ck = NewString(k);
|
|
o = Str(Getattr(obj, k));
|
|
Replaceall(ck, ":", "_");
|
|
Replaceall(ck, "<", "<");
|
|
/* Do first to avoid aliasing errors. */
|
|
Replaceall(o, "&", "&");
|
|
Replaceall(o, "<", "<");
|
|
Replaceall(o, "\"", """);
|
|
Replaceall(o, "\\", "\\\\");
|
|
Replaceall(o, "\n", " ");
|
|
Printf(out, "<attribute name=\"%s\" value=\"%s\" id=\"%ld\" addr=\"%p\" />\n", ck, o, ++id, o);
|
|
Delete(o);
|
|
Delete(ck);
|
|
} else {
|
|
o = Getattr(obj, k);
|
|
String *ck = NewString(k);
|
|
Replaceall(ck, ":", "_");
|
|
Printf(out, "<attribute name=\"%s\" value=\"%p\" id=\"%ld\" addr=\"%p\" />\n", ck, o, ++id, o);
|
|
Delete(ck);
|
|
}
|
|
}
|
|
ki = Next(ki);
|
|
}
|
|
indent_level -= 4;
|
|
print_indent(0);
|
|
Printf(out, "</attributelist >\n");
|
|
indent_level -= 4;
|
|
}
|
|
|
|
void Xml_print_node(Node *obj) {
|
|
Node *cobj;
|
|
|
|
print_indent(0);
|
|
Printf(out, "<%s id=\"%ld\" addr=\"%p\" >\n", nodeType(obj), ++id, obj);
|
|
Xml_print_attributes(obj);
|
|
cobj = firstChild(obj);
|
|
if (cobj) {
|
|
indent_level += 4;
|
|
Printf(out, "\n");
|
|
Xml_print_tree(cobj);
|
|
indent_level -= 4;
|
|
} else {
|
|
print_indent(1);
|
|
Printf(out, "\n");
|
|
}
|
|
print_indent(0);
|
|
Printf(out, "</%s >\n", nodeType(obj));
|
|
}
|
|
|
|
|
|
void Xml_print_parmlist(ParmList *p, const char* markup = "parmlist") {
|
|
|
|
print_indent(0);
|
|
Printf(out, "<%s id=\"%ld\" addr=\"%p\" >\n", markup, ++id, p);
|
|
indent_level += 4;
|
|
while (p) {
|
|
print_indent(0);
|
|
Printf(out, "<parm id=\"%ld\">\n", ++id);
|
|
Xml_print_attributes(p);
|
|
print_indent(0);
|
|
Printf(out, "</parm >\n");
|
|
p = nextSibling(p);
|
|
}
|
|
indent_level -= 4;
|
|
print_indent(0);
|
|
Printf(out, "</%s >\n", markup);
|
|
}
|
|
|
|
void Xml_print_baselist(List *p) {
|
|
|
|
print_indent(0);
|
|
Printf(out, "<baselist id=\"%ld\" addr=\"%p\" >\n", ++id, p);
|
|
indent_level += 4;
|
|
Iterator s;
|
|
for (s = First(p); s.item; s = Next(s)) {
|
|
print_indent(0);
|
|
String *item_name = Xml_escape_string(s.item);
|
|
Printf(out, "<base name=\"%s\" id=\"%ld\" addr=\"%p\" />\n", item_name, ++id, s.item);
|
|
Delete(item_name);
|
|
}
|
|
indent_level -= 4;
|
|
print_indent(0);
|
|
Printf(out, "</baselist >\n");
|
|
}
|
|
|
|
String *Xml_escape_string(String *str) {
|
|
String *escaped_str = 0;
|
|
if (str) {
|
|
escaped_str = NewString(str);
|
|
Replaceall(escaped_str, "&", "&");
|
|
Replaceall(escaped_str, "<", "<");
|
|
Replaceall(escaped_str, "\"", """);
|
|
Replaceall(escaped_str, "\\", "\\\\");
|
|
Replaceall(escaped_str, "\n", " ");
|
|
}
|
|
return escaped_str;
|
|
}
|
|
|
|
void Xml_print_module(Node *p) {
|
|
|
|
print_indent(0);
|
|
Printf(out, "<attribute name=\"module\" value=\"%s\" id=\"%ld\" addr=\"%p\" />\n", Getattr(p, "name"), ++id, p);
|
|
}
|
|
|
|
void Xml_print_kwargs(Hash *p) {
|
|
Xml_print_hash(p, "kwargs");
|
|
}
|
|
|
|
void Xml_print_typescope(Hash *p) {
|
|
|
|
Xml_print_hash(p, "typescope");
|
|
}
|
|
|
|
void Xml_print_typetab(Hash *p) {
|
|
|
|
Xml_print_hash(p, "typetab");
|
|
}
|
|
|
|
|
|
void Xml_print_hash(Hash *p, const char *markup) {
|
|
|
|
print_indent(0);
|
|
Printf(out, "<%s id=\"%ld\" addr=\"%p\" >\n", markup, ++id, p);
|
|
Xml_print_attributes(p);
|
|
indent_level += 4;
|
|
Iterator n = First(p);
|
|
while (n.key) {
|
|
print_indent(0);
|
|
Printf(out, "<%ssitem id=\"%ld\" addr=\"%p\" >\n", markup, ++id, n.item);
|
|
Xml_print_attributes(n.item);
|
|
print_indent(0);
|
|
Printf(out, "</%ssitem >\n", markup);
|
|
n = Next(n);
|
|
}
|
|
indent_level -= 4;
|
|
print_indent(0);
|
|
Printf(out, "</%s >\n", markup);
|
|
}
|
|
|
|
};
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* Swig_print_xml
|
|
*
|
|
* Dump an XML version of the parse tree. This is different from using the -xml
|
|
* language module normally as it allows the real language module to process the
|
|
* tree first, possibly stuffing in new attributes, so the XML that is output ends
|
|
* up being a post-processing version of the tree.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
void Swig_print_xml(DOH *obj, String *filename) {
|
|
XML xml;
|
|
xmllite = 1;
|
|
|
|
if (!filename) {
|
|
out = stdout;
|
|
} else {
|
|
out = NewFile(filename, "w", SWIG_output_files());
|
|
if (!out) {
|
|
FileErrorDisplay(filename);
|
|
Exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
|
|
Printf(out, "<?xml version=\"1.0\" ?> \n");
|
|
xml.Xml_print_tree(obj);
|
|
}
|
|
|
|
static Language *new_swig_xml() {
|
|
return new XML();
|
|
}
|
|
extern "C" Language *swig_xml(void) {
|
|
return new_swig_xml();
|
|
}
|