summaryrefslogtreecommitdiff
diff options
authorMartin Quinson <mquinson@debian.org>2006-09-16 00:44:05 +0200
committergit-ubuntu importer <ubuntu-devel-discuss@lists.ubuntu.com>2006-11-08 08:03:05 +0000
commit36cf2640230d902a3fcea52df5a81be46bfc7761 (patch)
tree15846901f66328ba9ef61159fcbda33ff41394bd
parent9ee068e3d78ff23ca29089f3b8f481d507b57441 (diff)
parent77afe1cb483c1750ec235404549d32d3f4c017af (diff)
Imported using git-ubuntu import.
-rw-r--r--EnlargeFlex.patch92
-rw-r--r--Makefile14
-rw-r--r--Makefile.defs3
-rw-r--r--NOTES4
-rw-r--r--README7
-rw-r--r--TODO6
-rw-r--r--debian/changelog62
-rw-r--r--debian/compat2
-rw-r--r--debian/docs1
-rwxr-xr-xdebian/rules2
-rw-r--r--examples/FleXML.xml4
-rw-r--r--examples/Makefile16
-rw-r--r--examples/xhtml1-transitional.dtd1201
-rw-r--r--flexml-act-bootstrap.c5
-rw-r--r--flexml-act.dtd6
-rwxr-xr-xflexml.pl398
-rw-r--r--paper.html6
-rw-r--r--skel171
-rw-r--r--testbed/.#Makefile.1.1138
-rwxr-xr-xtestbed/CompareOut.pl84
-rw-r--r--testbed/Makefile200
-rw-r--r--testbed/biparser-one.dtd2
-rw-r--r--testbed/biparser-one.in2
-rw-r--r--testbed/biparser-two.dtd3
-rw-r--r--testbed/biparser-two.in2
-rw-r--r--testbed/biparser.precious.c69
-rw-r--r--testbed/biparser.stdout.expected6
-rw-r--r--testbed/corebin0 -> 303104 bytes
-rw-r--r--testbed/init_header.act27
-rw-r--r--testbed/init_header.dtd4
-rw-r--r--testbed/init_header.h3
-rw-r--r--testbed/init_header.in2
-rw-r--r--testbed/init_header.stdout.expected4
-rw-r--r--testbed/missing-att.act32
-rw-r--r--testbed/missing-att.dtd4
-rw-r--r--testbed/missing-att.in2
-rw-r--r--testbed/missing-att.stderr.expected1
-rw-r--r--testbed/missing-att.stdout.expected1
-rw-r--r--testbed/mixed-enumatt.act53
-rw-r--r--testbed/mixed-enumatt.dtd8
-rw-r--r--testbed/mixed-enumatt.in8
-rw-r--r--testbed/mixed-enumatt.stdout.expected18
-rw-r--r--testbed/mixed-enumatt2.act47
-rw-r--r--testbed/mixed-enumatt2.dtd8
-rw-r--r--testbed/mixed-enumatt2.in8
-rw-r--r--testbed/mixed-enumatt2.stdout.expected18
-rw-r--r--testbed/mixed-stratt-def.act33
-rw-r--r--testbed/mixed-stratt-def.dtd7
-rw-r--r--testbed/mixed-stratt-def.in6
-rw-r--r--testbed/mixed-stratt-def.stdout.expected12
-rw-r--r--testbed/mixed-stratt.act32
-rw-r--r--testbed/mixed-stratt.dtd4
-rw-r--r--testbed/mixed-stratt.in2
-rw-r--r--testbed/mixed-stratt.stdout.expected4
-rw-r--r--testbed/mixed1.act27
-rw-r--r--testbed/mixed1.dtd4
-rw-r--r--testbed/mixed1.in2
-rw-r--r--testbed/mixed1.stdout.expected3
-rw-r--r--testbed/multi-parser-run.act38
-rw-r--r--testbed/multi-parser-run.dtd7
-rw-r--r--testbed/multi-parser-run.in2
-rw-r--r--testbed/multi-parser-run.stdout.expected9
62 files changed, 2614 insertions, 332 deletions
diff --git a/EnlargeFlex.patch b/EnlargeFlex.patch
deleted file mode 100644
index e665d5a..0000000
--- a/EnlargeFlex.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-This patch, relative to the flex-2.5.4a sources, permits really large
-NFA and DFAs when flex is passed the -Ca option (since in that case it
-does not affect performance in any way).
-
-Note: The patch is ALREADY applied in the Debian GNU/Linux package
-since flex-2.5.4a-6.
-
-$Id: EnlargeFlex.patch,v 1.2 1999/12/13 15:57:18 krisrose Exp $
-Copyright � 1999 Kristoffer Rose; placed in the public domain.
-
-diff -ur flex-2.5.4a/MISC/texinfo/flex.texi.orig flex-2.5.4a/MISC/texinfo/flex.texi
---- flex-2.5.4a/MISC/texinfo/flex.texi.orig Sun Jul 27 04:47:21 1997
-+++ flex-2.5.4a/MISC/texinfo/flex.texi Fri Dec 3 18:59:51 1999
-@@ -2152,8 +2152,10 @@
- aligned for memory access and computation. On some
- RISC architectures, fetching and manipulating
- long-words is more efficient than with smaller-sized
--units such as shortwords. This option can double
--the size of the tables used by your scanner.
-+units such as shortwords. This option can quadruple
-+the size of the tables used by your scanner. It has the
-+side effect of permitting much larger scanners, however,
-+if you need this.
-
- @samp{-Ce} directs @code{flex} to construct @dfn{equivalence classes},
- i.e., sets of characters which have identical
-diff -ur flex-2.5.4a/flexdef.h.orig flex-2.5.4a/flexdef.h
---- flex-2.5.4a/flexdef.h.orig Sun Jul 27 04:42:50 1997
-+++ flex-2.5.4a/flexdef.h Fri Dec 3 18:46:36 1999
-@@ -214,11 +214,12 @@
-
- /* Maximum number of NFA states. */
- #define MAXIMUM_MNS 31999
-+#define MAXIMUM_MNS_LONG 3999999
-
- /* Enough so that if it's subtracted from an NFA state number, the result
- * is guaranteed to be negative.
- */
--#define MARKER_DIFFERENCE (MAXIMUM_MNS+2)
-+#define MARKER_DIFFERENCE (maximum_mns+2)
-
- /* Maximum number of nxt/chk pairs for non-templates. */
- #define INITIAL_MAX_XPAIRS 2000
-@@ -457,6 +458,7 @@
-
-
- /* Variables for nfa machine data:
-+ * maximum_mns - maximal number of NFA states supported by tables
- * current_mns - current maximum on number of NFA states
- * num_rules - number of the last accepting state; also is number of
- * rules created so far
-@@ -485,7 +487,7 @@
- * rule_useful - true if we've determined that the rule can be matched
- */
-
--extern int current_mns, current_max_rules;
-+extern int maximum_mns, current_mns, current_max_rules;
- extern int num_rules, num_eof_rules, default_rule, lastnfa;
- extern int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2;
- extern int *accptnum, *assoc_rule, *state_type;
-diff -ur flex-2.5.4a/main.c.orig flex-2.5.4a/main.c
---- flex-2.5.4a/main.c.orig Sun Jul 27 04:32:19 1997
-+++ flex-2.5.4a/main.c Fri Dec 3 18:57:27 1999
-@@ -70,7 +70,7 @@
- int do_stdinit, use_stdout;
- int onestate[ONE_STACK_SIZE], onesym[ONE_STACK_SIZE];
- int onenext[ONE_STACK_SIZE], onedef[ONE_STACK_SIZE], onesp;
--int current_mns, current_max_rules;
-+int maximum_mns, current_mns, current_max_rules;
- int num_rules, num_eof_rules, default_rule, lastnfa;
- int *firstst, *lastst, *finalst, *transchar, *trans1, *trans2;
- int *accptnum, *assoc_rule, *state_type;
-@@ -1056,6 +1056,7 @@
-
- void set_up_initial_allocations()
- {
-+ maximum_mns = (long_align ? MAXIMUM_MNS_LONG : MAXIMUM_MNS);
- current_mns = INITIAL_MNS;
- firstst = allocate_integer_array( current_mns );
- lastst = allocate_integer_array( current_mns );
-diff -ur flex-2.5.4a/nfa.c.orig flex-2.5.4a/nfa.c
---- flex-2.5.4a/nfa.c.orig Sun Jul 27 04:32:19 1997
-+++ flex-2.5.4a/nfa.c Fri Dec 3 18:44:33 1999
-@@ -595,7 +595,7 @@
- {
- if ( ++lastnfa >= current_mns )
- {
-- if ( (current_mns += MNS_INCREMENT) >= MAXIMUM_MNS )
-+ if ( (current_mns += MNS_INCREMENT) >= maximum_mns )
- lerrif(
- _( "input rules are too complicated (>= %d NFA states)" ),
- current_mns );
diff --git a/Makefile b/Makefile
index 7268278..f322977 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
# Make(1) rules for FleXML XML processor generator system.
-# Copyright � 1999 Kristoffer Rose. All rights reserved.
+# Copyright (c) 1999 Kristoffer Rose. All rights reserved.
#
# This file is part of the FleXML XML processor generator system.
-# Copyright � 1999 Kristoffer Rose. All rights reserved.
+# Copyright (c) 1999 Kristoffer Rose. All rights reserved.
#
# 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
@@ -18,7 +18,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-# $Id: Makefile,v 1.39 2006/03/21 13:16:08 mquinson Exp $
+# $Id: Makefile,v 1.42 2006/08/23 16:23:59 mquinson Exp $
# SUFF (defined in Makefile.defs) is the versioning suffix added to binaries and
# resource files. To get rid of it (and do a non-versioned install,
@@ -34,7 +34,7 @@ BINS = $(FLEXML)
LIBS = $(FLEXML_ACT)
DATA = skel
MANS = flexml.1
-DOCS = README NOTES TODO flexml-act.dtd EnlargeFlex.patch
+DOCS = README NOTES TODO flexml-act.dtd
HTMLS = FleXML.html paper.html
SRC = $(STUFF) $(DATA) $(DOCS) $(HTMLS)
@@ -70,7 +70,7 @@ dist: clean
mkdir $(FLEXML_DISTDIR)
cp $(STUFF) $(DATA) $(DOCS) $(HTMLS) flexml-act-bootstrap.c \
$(FLEXML_DISTDIR)
- cp -r examples $(FLEXML_DISTDIR)
+ cp -r examples testbed $(FLEXML_DISTDIR)
find $(FLEXML_DISTDIR) -name CVS | xargs rm -rf
find $(FLEXML_DISTDIR) -name .cvsignore | xargs rm -rf
tar cvfz $(FLEXML_DISTDIR).tar.gz $(FLEXML_DISTDIR)
@@ -131,8 +131,8 @@ index.html: FleXML.html
# TESTS.
-clean::; make -C examples $@
-test::; make -C examples $@
+clean::; make -C examples $@; make -C testbed $@
+test::; make -C examples $@; make -C testbed $@
# END.
diff --git a/Makefile.defs b/Makefile.defs
index 7d4ce78..5e15481 100644
--- a/Makefile.defs
+++ b/Makefile.defs
@@ -6,7 +6,7 @@
#SUFF ?=-$(VER)
SUFF ?=
-VER = 1.4.1
+VER = 1.7
# SETUP.
@@ -38,6 +38,7 @@ POD2MAN = $(PERL_DIR)/pod2man
POD2HTML = $(PERL_DIR)/pod2html
FLEX = /usr/bin/flex
+SYMLINK = ln -s
# Build compilation setup.
CC = gcc -Wall -ansi -pedantic
diff --git a/NOTES b/NOTES
index 4ebb349..c3e42e0 100644
--- a/NOTES
+++ b/NOTES
@@ -1,5 +1,5 @@
# FleXML fast XML scanner framework
-# Copyright � 1999 Kristoffer Rose. All rights reserved.
+# Copyright (c) 1999 Kristoffer Rose. All rights reserved.
#
# Description: Notes for FleXML scanner generator
# Author: Kristoffer Rose
@@ -20,7 +20,7 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-# $Id: NOTES,v 1.2 1999/11/22 18:41:48 krisrose Exp $
+# $Id: NOTES,v 1.3 2006/07/18 18:21:13 mquinson Exp $
GUIDELINES FOR WRITING A flex(1) SCANNER FOR SIMPLE XML FORMATS.
diff --git a/README b/README
index 3faccf4..5a6fa40 100644
--- a/README
+++ b/README
@@ -13,11 +13,8 @@ change the setup; similarly you will probably have to change
executable.
The toolkit produces scanners for flex(1) which you should thus
-install. In order to be able to handle large DTDs (such as XHTML) you
-will have to apply `EnlargeFlex.patch' (and use the -Ca option).
-
-Note: Debian flex has this patch applied since version 2.5.4a-6.
+install.
Enjoy,
- Kristoffer H�gsbro Rose
+ Kristoffer Rose
pgp f-p: A4D3 5BD7 3EC5 7CA2 924E D21D 126B B8E0 <krisrose@debian.org>
diff --git a/TODO b/TODO
index 432d2e0..f9c40cc 100644
--- a/TODO
+++ b/TODO
@@ -1,7 +1,7 @@
-1. Make text buffer dynamically allocated.
+1. -- this space intentionally left blank --
2. Rework scanner to get rid of *all* flex dummy rule fallbacks.
3. ID type attributes should be validated for uniqueness.
4. IDREF and IDREFS attributes should be validated.
-5. ENTITY and ENTITIES attribute types should be supported.
+5. ENTITY and ENTITIES attribute types should be validated.
6. The xml:spaces pragma attrbute should be supported.
-7. Make the pcdata buffer act more like a traditional parser stack.
+
diff --git a/debian/changelog b/debian/changelog
index d202770..eb802aa 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,69 @@
+flexml (1.7-1) unstable; urgency=low
+
+ [William Dowling]
+ * Change the static buffstack into two dynamically allocated stacks.
+ This get rids of any stack size limitation;
+ This also solves #1529930 (parsing mixed content fails on sparc/solaris,
+ which were caused by misaligned pointers)
+ * Fix #1538171: Only display the stacknames when they are defined (they
+ are not in the prolog)
+ * Fix a bufferstack memleak. This fixes both leaks of attributes and leaks
+ of pcdata. People using large XML files shouldn't have to use insane
+ buffsizes anymore.
+ * Fix bug #1558023 'REQUIRED attributes not validated correctly'.
+ * Add -i command-line param to #include given file in output .l.
+ * Add a proper regression testing infrastructure and some test cases.
+
+ -- Martin Quinson <mquinson@debian.org> Sat, 16 Sep 2006 00:44:05 +0200
+
+flexml (1.5.3-1) unstable; urgency=low
+
+ * New option: --sysid to override the system id
+ * Kill any non ascii char from the distrib. They were latin1, I use utf8
+ so they annoyed me for not much benefit. I could have switched to utf8,
+ but it would have annoyed other people, I'm sure.
+ * Kill the EnlargeFlex.patch: was integrated into flex a few ages ago.
+
+ -- Martin Quinson <mquinson@debian.org> Tue, 18 Jul 2006 19:40:36 +0200
+
+flexml (1.5.2-1) unstable; urgency=low
+
+ * Bug fix: do find the skeleton file in installed distributions
+
+ -- Martin Quinson <mquinson@debian.org> Tue, 18 Jul 2006 14:06:50 +0200
+
+flexml (1.5.1-1) unstable; urgency=low
+
+ * Tests used to rely on wget to fetch a dtd. Include this in the tarball
+ instead.
+
+ -- Martin Quinson <mquinson@debian.org> Thu, 13 Jul 2006 21:47:45 +0200
+
+flexml (1.5-1) unstable; urgency=low
+
+ [William Dowling]
+ * Fix bug 1498401 "Parser loops on empty entity expansion" (l. 251);
+ * Fix bug 1498407 "Cannot have ELEMENT with same name as ATTLIST" (ll. 674-5);
+ * Fix bug 1498418 "ENTITY attribute type unimplemented." (ll. 842-51).
+
+ [Martin Quinson]
+ (upstream)
+ * Switch to Getopt::Long (I hope I didn't break anything)
+ * Add long version of each command line option
+ * Allow to override the scanner, header, application names using an
+ optionnal argument along to -S -H -A options.
+ (debian package)
+ * Switch to debhelper level 5 (at least try to, change seem to be ignored)
+ * Run the test suite in the process of package building
+
+ -- Martin Quinson <mquinson@debian.org> Thu, 13 Jul 2006 20:27:50 +0200
+
flexml (1.4.1-1) unstable; urgency=low
* More fixes to get several parsers in the same C code:
- pass bufferstack to static too
- prefix the pcdata variable (WARNING: go fix your code using it)
- Interesingly enough, this seems to be needed on Mac OSX somehow
+ This seems to be needed with gcc 4.x
-- Martin Quinson <mquinson@debian.org> Sat, 22 Apr 2006 01:29:23 +0200
diff --git a/debian/compat b/debian/compat
index b8626c4..7ed6ff8 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-4
+5
diff --git a/debian/docs b/debian/docs
index 1f1fe8c..10ce222 100644
--- a/debian/docs
+++ b/debian/docs
@@ -1,4 +1,3 @@
README
-EnlargeFlex.patch
NOTES
TODO
diff --git a/debian/rules b/debian/rules
index c03982b..5b956ec 100755
--- a/debian/rules
+++ b/debian/rules
@@ -12,6 +12,7 @@ build: build-stamp
build-stamp:
dh_testdir
$(MAKE) SUFF=
+ $(MAKE) test SUFF=
touch build-stamp
clean:
@@ -27,7 +28,6 @@ install: build
dh_clean -k
dh_installdirs
$(MAKE) install DESTDIR=`pwd`/debian/tmp SUFF=
- rm debian/tmp/usr/share/doc/flexml/EnlargeFlex.patch
touch install-stamp
# Build architecture-independent files here.
diff --git a/examples/FleXML.xml b/examples/FleXML.xml
index 3fd8357..88ba334 100644
--- a/examples/FleXML.xml
+++ b/examples/FleXML.xml
@@ -1,6 +1,6 @@
<!DOCTYPE html PUBLIC "-//IETF//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
-<!--$Id: FleXML.xml,v 1.1 2005/03/18 22:02:50 wdowling Exp $-->
+<!--$Id: FleXML.xml,v 1.2 2006/07/18 18:21:13 mquinson Exp $-->
<html>
<head>
<title>FleXML - XML Processor Generator</title>
@@ -175,7 +175,7 @@
`copyleft').
</p>
<hr />
- <address>Copyright �
+ <address>Copyright (c)
<a href="mailto:Kristoffer.Rose@ens-lyon.fr">Kristoffer Rose</a>.
<!-- Created: Thu Dec 9 08:09:41 CET 1999 -->
<!-- hhmts start -->
diff --git a/examples/Makefile b/examples/Makefile
index 42148db..0606531 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,8 +1,8 @@
# Make(1) rules for FleXML XML processor generator system.
-# Copyright � 1999 Kristoffer Rose. All rights reserved.
+# Copyright (c) 1999 Kristoffer Rose. All rights reserved.
#
# This file is part of the FleXML XML processor generator system.
-# Copyright � 1999 Kristoffer Rose. All rights reserved.
+# Copyright (c) 1999 Kristoffer Rose. All rights reserved.
#
# 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
@@ -18,7 +18,7 @@
# with this program; if not, write to the Free Software Foundation, Inc., 59
# Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-# $Id: Makefile,v 1.5 2006/03/21 13:11:27 mquinson Exp $
+# $Id: Makefile,v 1.8 2006/08/28 20:50:38 wdowling Exp $
# FILES.
@@ -30,7 +30,7 @@ ACT=../flexml-act
SAMPS = my.dtd my-show.act my-joke.xml my-joke2.xml my-joke3.xml \
tricky.dtd tricky.act tricky.xml \
- test.html
+ test.html xhtml1-transitional.dtd
SRC = $(SAMPS)
ALL = $(SAMPS)
@@ -115,9 +115,6 @@ clean::; $(RM) tricky.[lco] tricky
# Complex example: application to print XHTML <a href=...> values.
-xhtml1-transitional.dtd:
- wget 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'
-
xhtml1-transitional.l xhtml1-transitional.h: xhtml1-transitional.dtd
$(FLEXML_PROG) -rhtml \
-p "-//IETF//DTD XHTML 1.0 Transitional//EN" \
@@ -127,6 +124,9 @@ xhtml1-transitional.l xhtml1-transitional.h: xhtml1-transitional.dtd
xhtml1-transitional.c: xhtml1-transitional.l
$(FLEX) -B -s -v -Ca -oxhtml1-transitional.c xhtml1-transitional.l
+# turn off the -O2 when building this -- it takes too long to run
+xhtml1-transitional.o: CFLAGS = -g
+
xhtml1-transitional.o: xhtml1-transitional.c xhtml1-transitional.h
xhtml-href.c: xhtml-href.act xhtml1-transitional.dtd
@@ -138,7 +138,7 @@ test:: xhtml-href FleXML.xml
if ./xhtml-href <test.html ; then echo "TEST PASSED"; else echo "TEST FAILED"; fi
if ./xhtml-href < FleXML.xml ; then echo "TEST PASSED"; else echo "TEST FAILED"; fi
-clean::; $(RM) xhtml1-*.dtd xhtml1-*.[lhco] xhtml-href.[co] xhtml-href
+clean::; $(RM) xhtml1-*.[lhco] xhtml-href.[co] xhtml-href
# END.
diff --git a/examples/xhtml1-transitional.dtd b/examples/xhtml1-transitional.dtd
new file mode 100644
index 0000000..9448c25
--- /dev/null
+++ b/examples/xhtml1-transitional.dtd
@@ -0,0 +1,1201 @@
+<!--
+ Extensible HTML version 1.0 Transitional DTD
+
+ This is the same as HTML 4 Transitional except for
+ changes due to the differences between XML and SGML.
+
+ Namespace = http://www.w3.org/1999/xhtml
+
+ For further information, see: http://www.w3.org/TR/xhtml1
+
+ Copyright (c) 1998-2002 W3C (MIT, INRIA, Keio),
+ All Rights Reserved.
+
+ This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ SYSTEM "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
+
+ $Revision: 1.1 $
+ $Date: 2006/07/13 19:57:04 $
+
+-->
+
+<!--================ Character mnemonic entities =========================-->
+
+<!ENTITY % HTMLlat1 PUBLIC
+ "-//W3C//ENTITIES Latin 1 for XHTML//EN"
+ "xhtml-lat1.ent">
+%HTMLlat1;
+
+<!ENTITY % HTMLsymbol PUBLIC
+ "-//W3C//ENTITIES Symbols for XHTML//EN"
+ "xhtml-symbol.ent">
+%HTMLsymbol;
+
+<!ENTITY % HTMLspecial PUBLIC
+ "-//W3C//ENTITIES Special for XHTML//EN"
+ "xhtml-special.ent">
+%HTMLspecial;
+
+<!--================== Imported Names ====================================-->
+
+<!ENTITY % ContentType "CDATA">
+ <!-- media type, as per [RFC2045] -->
+
+<!ENTITY % ContentTypes "CDATA">
+ <!-- comma-separated list of media types, as per [RFC2045] -->
+
+<!ENTITY % Charset "CDATA">
+ <!-- a character encoding, as per [RFC2045] -->
+
+<!ENTITY % Charsets "CDATA">
+ <!-- a space separated list of character encodings, as per [RFC2045] -->
+
+<!ENTITY % LanguageCode "NMTOKEN">
+ <!-- a language code, as per [RFC3066] -->
+
+<!ENTITY % Character "CDATA">
+ <!-- a single character, as per section 2.2 of [XML] -->
+
+<!ENTITY % Number "CDATA">
+ <!-- one or more digits -->
+
+<!ENTITY % LinkTypes "CDATA">
+ <!-- space-separated list of link types -->
+
+<!ENTITY % MediaDesc "CDATA">
+ <!-- single or comma-separated list of media descriptors -->
+
+<!ENTITY % URI "CDATA">
+ <!-- a Uniform Resource Identifier, see [RFC2396] -->
+
+<!ENTITY % UriList "CDATA">
+ <!-- a space separated list of Uniform Resource Identifiers -->
+
+<!ENTITY % Datetime "CDATA">
+ <!-- date and time information. ISO date format -->
+
+<!ENTITY % Script "CDATA">
+ <!-- script expression -->
+
+<!ENTITY % StyleSheet "CDATA">
+ <!-- style sheet data -->
+
+<!ENTITY % Text "CDATA">
+ <!-- used for titles etc. -->
+
+<!ENTITY % FrameTarget "NMTOKEN">
+ <!-- render in this frame -->
+
+<!ENTITY % Length "CDATA">
+ <!-- nn for pixels or nn% for percentage length -->
+
+<!ENTITY % MultiLength "CDATA">
+ <!-- pixel, percentage, or relative -->
+
+<!ENTITY % Pixels "CDATA">
+ <!-- integer representing length in pixels -->
+
+<!-- these are used for image maps -->
+
+<!ENTITY % Shape "(rect|circle|poly|default)">
+
+<!ENTITY % Coords "CDATA">
+ <!-- comma separated list of lengths -->
+
+<!-- used for object, applet, img, input and iframe -->
+<!ENTITY % ImgAlign "(top|middle|bottom|left|right)">
+
+<!-- a color using sRGB: #RRGGBB as Hex values -->
+<!ENTITY % Color "CDATA">
+
+<!-- There are also 16 widely known color names with their sRGB values:
+
+ Black = #000000 Green = #008000
+ Silver = #C0C0C0 Lime = #00FF00
+ Gray = #808080 Olive = #808000
+ White = #FFFFFF Yellow = #FFFF00
+ Maroon = #800000 Navy = #000080
+ Red = #FF0000 Blue = #0000FF
+ Purple = #800080 Teal = #008080
+ Fuchsia= #FF00FF Aqua = #00FFFF
+-->
+
+<!--=================== Generic Attributes ===============================-->
+
+<!-- core attributes common to most elements
+ id document-wide unique id
+ class space separated list of classes
+ style associated style info
+ title advisory title/amplification
+-->
+<!ENTITY % coreattrs
+ "id ID #IMPLIED
+ class CDATA #IMPLIED
+ style %StyleSheet; #IMPLIED
+ title %Text; #IMPLIED"
+ >
+
+<!-- internationalization attributes
+ lang language code (backwards compatible)
+ xml:lang language code (as per XML 1.0 spec)
+ dir direction for weak/neutral text
+-->
+<!ENTITY % i18n
+ "lang %LanguageCode; #IMPLIED
+ xml:lang %LanguageCode; #IMPLIED
+ dir (ltr|rtl) #IMPLIED"
+ >
+
+<!-- attributes for common UI events
+ onclick a pointer button was clicked
+ ondblclick a pointer button was double clicked
+ onmousedown a pointer button was pressed down
+ onmouseup a pointer button was released
+ onmousemove a pointer was moved onto the element
+ onmouseout a pointer was moved away from the element
+ onkeypress a key was pressed and released
+ onkeydown a key was pressed down
+ onkeyup a key was released
+-->
+<!ENTITY % events
+ "onclick %Script; #IMPLIED
+ ondblclick %Script; #IMPLIED
+ onmousedown %Script; #IMPLIED
+ onmouseup %Script; #IMPLIED
+ onmouseover %Script; #IMPLIED
+ onmousemove %Script; #IMPLIED
+ onmouseout %Script; #IMPLIED
+ onkeypress %Script; #IMPLIED
+ onkeydown %Script; #IMPLIED
+ onkeyup %Script; #IMPLIED"
+ >
+
+<!-- attributes for elements that can get the focus
+ accesskey accessibility key character
+ tabindex position in tabbing order
+ onfocus the element got the focus
+ onblur the element lost the focus
+-->
+<!ENTITY % focus
+ "accesskey %Character; #IMPLIED
+ tabindex %Number; #IMPLIED
+ onfocus %Script; #IMPLIED
+ onblur %Script; #IMPLIED"
+ >
+
+<!ENTITY % attrs "%coreattrs; %i18n; %events;">
+
+<!-- text alignment for p, div, h1-h6. The default is
+ align="left" for ltr headings, "right" for rtl -->
+
+<!ENTITY % TextAlign "align (left|center|right|justify) #IMPLIED">
+
+<!--=================== Text Elements ====================================-->
+
+<!ENTITY % special.extra
+ "object | applet | img | map | iframe">
+
+<!ENTITY % special.basic
+ "br | span | bdo">
+
+<!ENTITY % special
+ "%special.basic; | %special.extra;">
+
+<!ENTITY % fontstyle.extra "big | small | font | basefont">
+
+<!ENTITY % fontstyle.basic "tt | i | b | u
+ | s | strike ">
+
+<!ENTITY % fontstyle "%fontstyle.basic; | %fontstyle.extra;">
+
+<!ENTITY % phrase.extra "sub | sup">
+<!ENTITY % phrase.basic "em | strong | dfn | code | q |
+ samp | kbd | var | cite | abbr | acronym">
+
+<!ENTITY % phrase "%phrase.basic; | %phrase.extra;">
+
+<!ENTITY % inline.forms "input | select | textarea | label | button">
+
+<!-- these can occur at block or inline level -->
+<!ENTITY % misc.inline "ins | del | script">
+
+<!-- these can only occur at block level -->
+<!ENTITY % misc "noscript | %misc.inline;">
+
+<!ENTITY % inline "a | %special; | %fontstyle; | %phrase; | %inline.forms;">
+
+<!-- %Inline; covers inline or "text-level" elements -->
+<!ENTITY % Inline "(#PCDATA | %inline; | %misc.inline;)*">
+
+<!--================== Block level elements ==============================-->
+
+<!ENTITY % heading "h1|h2|h3|h4|h5|h6">
+<!ENTITY % lists "ul | ol | dl | menu | dir">
+<!ENTITY % blocktext "pre | hr | blockquote | address | center | noframes">
+
+<!ENTITY % block
+ "p | %heading; | div | %lists; | %blocktext; | isindex |fieldset | table">
+
+<!-- %Flow; mixes block and inline and is used for list items etc. -->
+<!ENTITY % Flow "(#PCDATA | %block; | form | %inline; | %misc;)*">
+
+<!--================== Content models for exclusions =====================-->
+
+<!-- a elements use %Inline; excluding a -->
+
+<!ENTITY % a.content
+ "(#PCDATA | %special; | %fontstyle; | %phrase; | %inline.forms; | %misc.inline;)*">
+
+<!-- pre uses %Inline excluding img, object, applet, big, small,
+ font, or basefont -->
+
+<!ENTITY % pre.content
+ "(#PCDATA | a | %special.basic; | %fontstyle.basic; | %phrase.basic; |
+ %inline.forms; | %misc.inline;)*">
+
+<!-- form uses %Flow; excluding form -->
+
+<!ENTITY % form.content "(#PCDATA | %block; | %inline; | %misc;)*">
+
+<!-- button uses %Flow; but excludes a, form, form controls, iframe -->
+
+<!ENTITY % button.content
+ "(#PCDATA | p | %heading; | div | %lists; | %blocktext; |
+ table | br | span | bdo | object | applet | img | map |
+ %fontstyle; | %phrase; | %misc;)*">
+
+<!--================ Document Structure ==================================-->
+
+<!-- the namespace URI designates the document profile -->
+
+<!ELEMENT html (head, body)>
+<!ATTLIST html
+ %i18n;
+ id ID #IMPLIED
+ xmlns %URI; #FIXED 'http://www.w3.org/1999/xhtml'
+ >
+
+<!--================ Document Head =======================================-->
+
+<!ENTITY % head.misc "(script|style|meta|link|object|isindex)*">
+
+<!-- content model is %head.misc; combined with a single
+ title and an optional base element in any order -->
+
+<!ELEMENT head (%head.misc;,
+ ((title, %head.misc;, (base, %head.misc;)?) |
+ (base, %head.misc;, (title, %head.misc;))))>
+
+<!ATTLIST head
+ %i18n;
+ id ID #IMPLIED
+ profile %URI; #IMPLIED
+ >
+
+<!-- The title element is not considered part of the flow of text.
+ It should be displayed, for example as the page header or
+ window title. Exactly one title is required per document.
+ -->
+<!ELEMENT title (#PCDATA)>
+<!ATTLIST title
+ %i18n;
+ id ID #IMPLIED
+ >
+
+<!-- document base URI -->
+
+<!ELEMENT base EMPTY>
+<!ATTLIST base
+ id ID #IMPLIED
+ href %URI; #IMPLIED
+ target %FrameTarget; #IMPLIED
+ >
+
+<!-- generic metainformation -->
+<!ELEMENT meta EMPTY>
+<!ATTLIST meta
+ %i18n;
+ id ID #IMPLIED
+ http-equiv CDATA #IMPLIED
+ name CDATA #IMPLIED
+ content CDATA #REQUIRED
+ scheme CDATA #IMPLIED
+ >
+
+<!--
+ Relationship values can be used in principle:
+
+ a) for document specific toolbars/menus when used
+ with the link element in document head e.g.
+ start, contents, previous, next, index, end, help
+ b) to link to a separate style sheet (rel="stylesheet")
+ c) to make a link to a script (rel="script")
+ d) by stylesheets to control how collections of
+ html nodes are rendered into printed documents
+ e) to make a link to a printable version of this document
+ e.g. a PostScript or PDF version (rel="alternate" media="print")
+-->
+
+<!ELEMENT link EMPTY>
+<!ATTLIST link
+ %attrs;
+ charset %Charset; #IMPLIED
+ href %URI; #IMPLIED
+ hreflang %LanguageCode; #IMPLIED
+ type %ContentType; #IMPLIED
+ rel %LinkTypes; #IMPLIED
+ rev %LinkTypes; #IMPLIED
+ media %MediaDesc; #IMPLIED
+ target %FrameTarget; #IMPLIED
+ >
+
+<!-- style info, which may include CDATA sections -->
+<!ELEMENT style (#PCDATA)>
+<!ATTLIST style
+ %i18n;
+ id ID #IMPLIED
+ type %ContentType; #REQUIRED
+ media %MediaDesc; #IMPLIED
+ title %Text; #IMPLIED
+ xml:space (preserve) #FIXED 'preserve'
+ >
+
+<!-- script statements, which may include CDATA sections -->
+<!ELEMENT script (#PCDATA)>
+<!ATTLIST script
+ id ID #IMPLIED
+ charset %Charset; #IMPLIED
+ type %ContentType; #REQUIRED
+ language CDATA #IMPLIED
+ src %URI; #IMPLIED
+ defer (defer) #IMPLIED
+ xml:space (preserve) #FIXED 'preserve'
+ >
+
+<!-- alternate content container for non script-based rendering -->
+
+<!ELEMENT noscript %Flow;>
+<!ATTLIST noscript
+ %attrs;
+ >
+
+<!--======================= Frames =======================================-->
+
+<!-- inline subwindow -->
+
+<!ELEMENT iframe %Flow;>
+<!ATTLIST iframe
+ %coreattrs;
+ longdesc %URI; #IMPLIED
+ name NMTOKEN #IMPLIED
+ src %URI; #IMPLIED
+ frameborder (1|0) "1"
+ marginwidth %Pixels; #IMPLIED
+ marginheight %Pixels; #IMPLIED
+ scrolling (yes|no|auto) "auto"
+ align %ImgAlign; #IMPLIED
+ height %Length; #IMPLIED
+ width %Length; #IMPLIED
+ >
+
+<!-- alternate content container for non frame-based rendering -->
+
+<!ELEMENT noframes %Flow;>
+<!ATTLIST noframes
+ %attrs;
+ >
+
+<!--=================== Document Body ====================================-->
+
+<!ELEMENT body %Flow;>
+<!ATTLIST body
+ %attrs;
+ onload %Script; #IMPLIED
+ onunload %Script; #IMPLIED
+ background %URI; #IMPLIED
+ bgcolor %Color; #IMPLIED
+ text %Color; #IMPLIED
+ link %Color; #IMPLIED
+ vlink %Color; #IMPLIED
+ alink %Color; #IMPLIED
+ >
+
+<!ELEMENT div %Flow;> <!-- generic language/style container -->
+<!ATTLIST div
+ %attrs;
+ %TextAlign;
+ >
+
+<!--=================== Paragraphs =======================================-->
+
+<!ELEMENT p %Inline;>
+<!ATTLIST p
+ %attrs;
+ %TextAlign;
+ >
+
+<!--=================== Headings =========================================-->
+
+<!--
+ There are six levels of headings from h1 (the most important)
+ to h6 (the least important).
+-->
+
+<!ELEMENT h1 %Inline;>
+<!ATTLIST h1
+ %attrs;
+ %TextAlign;
+ >
+
+<!ELEMENT h2 %Inline;>
+<!ATTLIST h2
+ %attrs;
+ %TextAlign;
+ >
+
+<!ELEMENT h3 %Inline;>
+<!ATTLIST h3
+ %attrs;
+ %TextAlign;
+ >
+
+<!ELEMENT h4 %Inline;>
+<!ATTLIST h4
+ %attrs;
+ %TextAlign;
+ >
+
+<!ELEMENT h5 %Inline;>
+<!ATTLIST h5
+ %attrs;
+ %TextAlign;
+ >
+
+<!ELEMENT h6 %Inline;>
+<!ATTLIST h6
+ %attrs;
+ %TextAlign;
+ >
+
+<!--=================== Lists ============================================-->
+
+<!-- Unordered list bullet styles -->
+
+<!ENTITY % ULStyle "(disc|square|circle)">
+
+<!-- Unordered list -->
+
+<!ELEMENT ul (li)+>
+<!ATTLIST ul
+ %attrs;
+ type %ULStyle; #IMPLIED
+ compact (compact) #IMPLIED
+ >
+
+<!-- Ordered list numbering style
+
+ 1 arabic numbers 1, 2, 3, ...
+ a lower alpha a, b, c, ...
+ A upper alpha A, B, C, ...
+ i lower roman i, ii, iii, ...
+ I upper roman I, II, III, ...
+
+ The style is applied to the sequence number which by default
+ is reset to 1 for the first list item in an ordered list.
+-->
+<!ENTITY % OLStyle "CDATA">
+
+<!-- Ordered (numbered) list -->
+
+<!ELEMENT ol (li)+>
+<!ATTLIST ol
+ %attrs;
+ type %OLStyle; #IMPLIED
+ compact (compact) #IMPLIED
+ start %Number; #IMPLIED
+ >
+
+<!-- single column list (DEPRECATED) -->
+<!ELEMENT menu (li)+>
+<!ATTLIST menu
+ %attrs;
+ compact (compact) #IMPLIED
+ >
+
+<!-- multiple column list (DEPRECATED) -->
+<!ELEMENT dir (li)+>
+<!ATTLIST dir
+ %attrs;
+ compact (compact) #IMPLIED
+ >
+
+<!-- LIStyle is constrained to: "(%ULStyle;|%OLStyle;)" -->
+<!ENTITY % LIStyle "CDATA">
+
+<!-- list item -->
+
+<!ELEMENT li %Flow;>
+<!ATTLIST li
+ %attrs;
+ type %LIStyle; #IMPLIED
+ value %Number; #IMPLIED
+ >
+
+<!-- definition lists - dt for term, dd for its definition -->
+
+<!ELEMENT dl (dt|dd)+>
+<!ATTLIST dl
+ %attrs;
+ compact (compact) #IMPLIED
+ >
+
+<!ELEMENT dt %Inline;>
+<!ATTLIST dt
+ %attrs;
+ >
+
+<!ELEMENT dd %Flow;>
+<!ATTLIST dd
+ %attrs;
+ >
+
+<!--=================== Address ==========================================-->
+
+<!-- information on author -->
+
+<!ELEMENT address (#PCDATA | %inline; | %misc.inline; | p)*>
+<!ATTLIST address
+ %attrs;
+ >
+
+<!--=================== Horizontal Rule ==================================-->
+
+<!ELEMENT hr EMPTY>
+<!ATTLIST hr
+ %attrs;
+ align (left|center|right) #IMPLIED
+ noshade (noshade) #IMPLIED
+ size %Pixels; #IMPLIED
+ width %Length; #IMPLIED
+ >
+
+<!--=================== Preformatted Text ================================-->
+
+<!-- content is %Inline; excluding
+ "img|object|applet|big|small|sub|sup|font|basefont" -->
+
+<!ELEMENT pre %pre.content;>
+<!ATTLIST pre
+ %attrs;
+ width %Number; #IMPLIED
+ xml:space (preserve) #FIXED 'preserve'
+ >
+
+<!--=================== Block-like Quotes ================================-->
+
+<!ELEMENT blockquote %Flow;>
+<!ATTLIST blockquote
+ %attrs;
+ cite %URI; #IMPLIED
+ >
+
+<!--=================== Text alignment ===================================-->
+
+<!-- center content -->
+<!ELEMENT center %Flow;>
+<!ATTLIST center
+ %attrs;
+ >
+
+<!--=================== Inserted/Deleted Text ============================-->
+
+<!--
+ ins/del are allowed in block and inline content, but its
+ inappropriate to include block content within an ins element
+ occurring in inline content.
+-->
+<!ELEMENT ins %Flow;>
+<!ATTLIST ins
+ %attrs;
+ cite %URI; #IMPLIED
+ datetime %Datetime; #IMPLIED
+ >
+
+<!ELEMENT del %Flow;>
+<!ATTLIST del
+ %attrs;
+ cite %URI; #IMPLIED
+ datetime %Datetime; #IMPLIED
+ >
+
+<!--================== The Anchor Element ================================-->
+
+<!-- content is %Inline; except that anchors shouldn't be nested -->
+
+<!ELEMENT a %a.content;>
+<!ATTLIST a
+ %attrs;
+ %focus;
+ charset %Charset; #IMPLIED
+ type %ContentType; #IMPLIED
+ name NMTOKEN #IMPLIED
+ href %URI; #IMPLIED
+ hreflang %LanguageCode; #IMPLIED
+ rel %LinkTypes; #IMPLIED
+ rev %LinkTypes; #IMPLIED
+ shape %Shape; "rect"
+ coords %Coords; #IMPLIED
+ target %FrameTarget; #IMPLIED
+ >
+
+<!--===================== Inline Elements ================================-->
+
+<!ELEMENT span %Inline;> <!-- generic language/style container -->
+<!ATTLIST span
+ %attrs;
+ >
+
+<!ELEMENT bdo %Inline;> <!-- I18N BiDi over-ride -->
+<!ATTLIST bdo
+ %coreattrs;
+ %events;
+ lang %LanguageCode; #IMPLIED
+ xml:lang %LanguageCode; #IMPLIED
+ dir (ltr|rtl) #REQUIRED
+ >
+
+<!ELEMENT br EMPTY> <!-- forced line break -->
+<!ATTLIST br
+ %coreattrs;
+ clear (left|all|right|none) "none"
+ >
+
+<!ELEMENT em %Inline;> <!-- emphasis -->
+<!ATTLIST em %attrs;>
+
+<!ELEMENT strong %Inline;> <!-- strong emphasis -->
+<!ATTLIST strong %attrs;>
+
+<!ELEMENT dfn %Inline;> <!-- definitional -->
+<!ATTLIST dfn %attrs;>
+
+<!ELEMENT code %Inline;> <!-- program code -->
+<!ATTLIST code %attrs;>
+
+<!ELEMENT samp %Inline;> <!-- sample -->
+<!ATTLIST samp %attrs;>
+
+<!ELEMENT kbd %Inline;> <!-- something user would type -->
+<!ATTLIST kbd %attrs;>
+
+<!ELEMENT var %Inline;> <!-- variable -->
+<!ATTLIST var %attrs;>
+
+<!ELEMENT cite %Inline;> <!-- citation -->
+<!ATTLIST cite %attrs;>
+
+<!ELEMENT abbr %Inline;> <!-- abbreviation -->
+<!ATTLIST abbr %attrs;>
+
+<!ELEMENT acronym %Inline;> <!-- acronym -->
+<!ATTLIST acronym %attrs;>
+
+<!ELEMENT q %Inline;> <!-- inlined quote -->
+<!ATTLIST q
+ %attrs;
+ cite %URI; #IMPLIED
+ >
+
+<!ELEMENT sub %Inline;> <!-- subscript -->
+<!ATTLIST sub %attrs;>
+
+<!ELEMENT sup %Inline;> <!-- superscript -->
+<!ATTLIST sup %attrs;>
+
+<!ELEMENT tt %Inline;> <!-- fixed pitch font -->
+<!ATTLIST tt %attrs;>
+
+<!ELEMENT i %Inline;> <!-- italic font -->
+<!ATTLIST i %attrs;>
+
+<!ELEMENT b %Inline;> <!-- bold font -->
+<!ATTLIST b %attrs;>
+
+<!ELEMENT big %Inline;> <!-- bigger font -->
+<!ATTLIST big %attrs;>
+
+<!ELEMENT small %Inline;> <!-- smaller font -->
+<!ATTLIST small %attrs;>
+
+<!ELEMENT u %Inline;> <!-- underline -->
+<!ATTLIST u %attrs;>
+
+<!ELEMENT s %Inline;> <!-- strike-through -->
+<!ATTLIST s %attrs;>
+
+<!ELEMENT strike %Inline;> <!-- strike-through -->
+<!ATTLIST strike %attrs;>
+
+<!ELEMENT basefont EMPTY> <!-- base font size -->
+<!ATTLIST basefont
+ id ID #IMPLIED
+ size CDATA #REQUIRED
+ color %Color; #IMPLIED
+ face CDATA #IMPLIED
+ >
+
+<!ELEMENT font %Inline;> <!-- local change to font -->
+<!ATTLIST font
+ %coreattrs;
+ %i18n;
+ size CDATA #IMPLIED
+ color %Color; #IMPLIED
+ face CDATA #IMPLIED
+ >
+
+<!--==================== Object ======================================-->
+<!--
+ object is used to embed objects as part of HTML pages.
+ param elements should precede other content. Parameters
+ can also be expressed as attribute/value pairs on the
+ object element itself when brevity is desired.
+-->
+
+<!ELEMENT object (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST object
+ %attrs;
+ declare (declare) #IMPLIED
+ classid %URI; #IMPLIED
+ codebase %URI; #IMPLIED
+ data %URI; #IMPLIED
+ type %ContentType; #IMPLIED
+ codetype %ContentType; #IMPLIED
+ archive %UriList; #IMPLIED
+ standby %Text; #IMPLIED
+ height %Length; #IMPLIED
+ width %Length; #IMPLIED
+ usemap %URI; #IMPLIED
+ name NMTOKEN #IMPLIED
+ tabindex %Number; #IMPLIED
+ align %ImgAlign; #IMPLIED
+ border %Pixels; #IMPLIED
+ hspace %Pixels; #IMPLIED
+ vspace %Pixels; #IMPLIED
+ >
+
+<!--
+ param is used to supply a named property value.
+ In XML it would seem natural to follow RDF and support an
+ abbreviated syntax where the param elements are replaced
+ by attribute value pairs on the object start tag.
+-->
+<!ELEMENT param EMPTY>
+<!ATTLIST param
+ id ID #IMPLIED
+ name CDATA #REQUIRED
+ value CDATA #IMPLIED
+ valuetype (data|ref|object) "data"
+ type %ContentType; #IMPLIED
+ >
+
+<!--=================== Java applet ==================================-->
+<!--
+ One of code or object attributes must be present.
+ Place param elements before other content.
+-->
+<!ELEMENT applet (#PCDATA | param | %block; | form | %inline; | %misc;)*>
+<!ATTLIST applet
+ %coreattrs;
+ codebase %URI; #IMPLIED
+ archive CDATA #IMPLIED
+ code CDATA #IMPLIED
+ object CDATA #IMPLIED
+ alt %Text; #IMPLIED
+ name NMTOKEN #IMPLIED
+ width %Length; #REQUIRED
+ height %Length; #REQUIRED
+ align %ImgAlign; #IMPLIED
+ hspace %Pixels; #IMPLIED
+ vspace %Pixels; #IMPLIED
+ >
+
+<!--=================== Images ===========================================-->
+
+<!--
+ To avoid accessibility problems for people who aren't
+ able to see the image, you should provide a text
+ description using the alt and longdesc attributes.
+ In addition, avoid the use of server-side image maps.
+-->
+
+<!ELEMENT img EMPTY>
+<!ATTLIST img
+ %attrs;
+ src %URI; #REQUIRED
+ alt %Text; #REQUIRED
+ name NMTOKEN #IMPLIED
+ longdesc %URI; #IMPLIED
+ height %Length; #IMPLIED
+ width %Length; #IMPLIED
+ usemap %URI; #IMPLIED
+ ismap (ismap) #IMPLIED
+ align %ImgAlign; #IMPLIED
+ border %Length; #IMPLIED
+ hspace %Pixels; #IMPLIED
+ vspace %Pixels; #IMPLIED
+ >
+
+<!-- usemap points to a map element which may be in this document
+ or an external document, although the latter is not widely supported -->
+
+<!--================== Client-side image maps ============================-->
+
+<!-- These can be placed in the same document or grouped in a
+ separate document although this isn't yet widely supported -->
+
+<!ELEMENT map ((%block; | form | %misc;)+ | area+)>
+<!ATTLIST map
+ %i18n;
+ %events;
+ id ID #REQUIRED
+ class CDATA #IMPLIED
+ style %StyleSheet; #IMPLIED
+ title %Text; #IMPLIED
+ name CDATA #IMPLIED
+ >
+
+<!ELEMENT area EMPTY>
+<!ATTLIST area
+ %attrs;
+ %focus;
+ shape %Shape; "rect"
+ coords %Coords; #IMPLIED
+ href %URI; #IMPLIED
+ nohref (nohref) #IMPLIED
+ alt %Text; #REQUIRED
+ target %FrameTarget; #IMPLIED
+ >
+
+<!--================ Forms ===============================================-->
+
+<!ELEMENT form %form.content;> <!-- forms shouldn't be nested -->
+
+<!ATTLIST form
+ %attrs;
+ action %URI; #REQUIRED
+ method (get|post) "get"
+ name NMTOKEN #IMPLIED
+ enctype %ContentType; "application/x-www-form-urlencoded"
+ onsubmit %Script; #IMPLIED
+ onreset %Script; #IMPLIED
+ accept %ContentTypes; #IMPLIED
+ accept-charset %Charsets; #IMPLIED
+ target %FrameTarget; #IMPLIED
+ >
+
+<!--
+ Each label must not contain more than ONE field
+ Label elements shouldn't be nested.
+-->
+<!ELEMENT label %Inline;>
+<!ATTLIST label
+ %attrs;
+ for IDREF #IMPLIED
+ accesskey %Character; #IMPLIED
+ onfocus %Script; #IMPLIED
+ onblur %Script; #IMPLIED
+ >
+
+<!ENTITY % InputType
+ "(text | password | checkbox |
+ radio | submit | reset |
+ file | hidden | image | button)"
+ >
+
+<!-- the name attribute is required for all but submit & reset -->
+
+<!ELEMENT input EMPTY> <!-- form control -->
+<!ATTLIST input
+ %attrs;
+ %focus;
+ type %InputType; "text"
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED
+ checked (checked) #IMPLIED
+ disabled (disabled) #IMPLIED
+ readonly (readonly) #IMPLIED
+ size CDATA #IMPLIED
+ maxlength %Number; #IMPLIED
+ src %URI; #IMPLIED
+ alt CDATA #IMPLIED
+ usemap %URI; #IMPLIED
+ onselect %Script; #IMPLIED
+ onchange %Script; #IMPLIED
+ accept %ContentTypes; #IMPLIED
+ align %ImgAlign; #IMPLIED
+ >
+
+<!ELEMENT select (optgroup|option)+> <!-- option selector -->
+<!ATTLIST select
+ %attrs;
+ name CDATA #IMPLIED
+ size %Number; #IMPLIED
+ multiple (multiple) #IMPLIED
+ disabled (disabled) #IMPLIED
+ tabindex %Number; #IMPLIED
+ onfocus %Script; #IMPLIED
+ onblur %Script; #IMPLIED
+ onchange %Script; #IMPLIED
+ >
+
+<!ELEMENT optgroup (option)+> <!-- option group -->
+<!ATTLIST optgroup
+ %attrs;
+ disabled (disabled) #IMPLIED
+ label %Text; #REQUIRED
+ >
+
+<!ELEMENT option (#PCDATA)> <!-- selectable choice -->
+<!ATTLIST option
+ %attrs;
+ selected (selected) #IMPLIED
+ disabled (disabled) #IMPLIED
+ label %Text; #IMPLIED
+ value CDATA #IMPLIED
+ >
+
+<!ELEMENT textarea (#PCDATA)> <!-- multi-line text field -->
+<!ATTLIST textarea
+ %attrs;
+ %focus;
+ name CDATA #IMPLIED
+ rows %Number; #REQUIRED
+ cols %Number; #REQUIRED
+ disabled (disabled) #IMPLIED
+ readonly (readonly) #IMPLIED
+ onselect %Script; #IMPLIED
+ onchange %Script; #IMPLIED
+ >
+
+<!--
+ The fieldset element is used to group form fields.
+ Only one legend element should occur in the content
+ and if present should only be preceded by whitespace.
+-->
+<!ELEMENT fieldset (#PCDATA | legend | %block; | form | %inline; | %misc;)*>
+<!ATTLIST fieldset
+ %attrs;
+ >
+
+<!ENTITY % LAlign "(top|bottom|left|right)">
+
+<!ELEMENT legend %Inline;> <!-- fieldset label -->
+<!ATTLIST legend
+ %attrs;
+ accesskey %Character; #IMPLIED
+ align %LAlign; #IMPLIED
+ >
+
+<!--
+ Content is %Flow; excluding a, form, form controls, iframe
+-->
+<!ELEMENT button %button.content;> <!-- push button -->
+<!ATTLIST button
+ %attrs;
+ %focus;
+ name CDATA #IMPLIED
+ value CDATA #IMPLIED
+ type (button|submit|reset) "submit"
+ disabled (disabled) #IMPLIED
+ >
+
+<!-- single-line text input control (DEPRECATED) -->
+<!ELEMENT isindex EMPTY>
+<!ATTLIST isindex
+ %coreattrs;
+ %i18n;
+ prompt %Text; #IMPLIED
+ >
+
+<!--======================= Tables =======================================-->
+
+<!-- Derived from IETF HTML table standard, see [RFC1942] -->
+
+<!--
+ The border attribute sets the thickness of the frame around the
+ table. The default units are screen pixels.
+
+ The frame attribute specifies which parts of the frame around
+ the table should be rendered. The values are not the same as
+ CALS to avoid a name clash with the valign attribute.
+-->
+<!ENTITY % TFrame "(void|above|below|hsides|lhs|rhs|vsides|box|border)">
+
+<!--
+ The rules attribute defines which rules to draw between cells:
+
+ If rules is absent then assume:
+ "none" if border is absent or border="0" otherwise "all"
+-->
+
+<!ENTITY % TRules "(none | groups | rows | cols | all)">
+
+<!-- horizontal placement of table relative to document -->
+<!ENTITY % TAlign "(left|center|right)">
+
+<!-- horizontal alignment attributes for cell contents
+
+ char alignment char, e.g. char=':'
+ charoff offset for alignment char
+-->
+<!ENTITY % cellhalign
+ "align (left|center|right|justify|char) #IMPLIED
+ char %Character; #IMPLIED
+ charoff %Length; #IMPLIED"
+ >
+
+<!-- vertical alignment attributes for cell contents -->
+<!ENTITY % cellvalign
+ "valign (top|middle|bottom|baseline) #IMPLIED"
+ >
+
+<!ELEMENT table
+ (caption?, (col*|colgroup*), thead?, tfoot?, (tbody+|tr+))>
+<!ELEMENT caption %Inline;>
+<!ELEMENT thead (tr)+>
+<!ELEMENT tfoot (tr)+>
+<!ELEMENT tbody (tr)+>
+<!ELEMENT colgroup (col)*>
+<!ELEMENT col EMPTY>
+<!ELEMENT tr (th|td)+>
+<!ELEMENT th %Flow;>
+<!ELEMENT td %Flow;>
+
+<!ATTLIST table
+ %attrs;
+ summary %Text; #IMPLIED
+ width %Length; #IMPLIED
+ border %Pixels; #IMPLIED
+ frame %TFrame; #IMPLIED
+ rules %TRules; #IMPLIED
+ cellspacing %Length; #IMPLIED
+ cellpadding %Length; #IMPLIED
+ align %TAlign; #IMPLIED
+ bgcolor %Color; #IMPLIED
+ >
+
+<!ENTITY % CAlign "(top|bottom|left|right)">
+
+<!ATTLIST caption
+ %attrs;
+ align %CAlign; #IMPLIED
+ >
+
+<!--
+colgroup groups a set of col elements. It allows you to group
+several semantically related columns together.
+-->
+<!ATTLIST colgroup
+ %attrs;
+ span %Number; "1"
+ width %MultiLength; #IMPLIED
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!--
+ col elements define the alignment properties for cells in
+ one or more columns.
+
+ The width attribute specifies the width of the columns, e.g.
+
+ width=64 width in screen pixels
+ width=0.5* relative width of 0.5
+
+ The span attribute causes the attributes of one
+ col element to apply to more than one column.
+-->
+<!ATTLIST col
+ %attrs;
+ span %Number; "1"
+ width %MultiLength; #IMPLIED
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!--
+ Use thead to duplicate headers when breaking table
+ across page boundaries, or for static headers when
+ tbody sections are rendered in scrolling panel.
+
+ Use tfoot to duplicate footers when breaking table
+ across page boundaries, or for static footers when
+ tbody sections are rendered in scrolling panel.
+
+ Use multiple tbody sections when rules are needed
+ between groups of table rows.
+-->
+<!ATTLIST thead
+ %attrs;
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!ATTLIST tfoot
+ %attrs;
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!ATTLIST tbody
+ %attrs;
+ %cellhalign;
+ %cellvalign;
+ >
+
+<!ATTLIST tr
+ %attrs;
+ %cellhalign;
+ %cellvalign;
+ bgcolor %Color; #IMPLIED
+ >
+
+<!-- Scope is simpler than headers attribute for common tables -->
+<!ENTITY % Scope "(row|col|rowgroup|colgroup)">
+
+<!-- th is for headers, td for data and for cells acting as both -->
+
+<!ATTLIST th
+ %attrs;
+ abbr %Text; #IMPLIED
+ axis CDATA #IMPLIED
+ headers IDREFS #IMPLIED
+ scope %Scope; #IMPLIED
+ rowspan %Number; "1"
+ colspan %Number; "1"
+ %cellhalign;
+ %cellvalign;
+ nowrap (nowrap) #IMPLIED
+ bgcolor %Color; #IMPLIED
+ width %Length; #IMPLIED
+ height %Length; #IMPLIED
+ >
+
+<!ATTLIST td
+ %attrs;
+ abbr %Text; #IMPLIED
+ axis CDATA #IMPLIED
+ headers IDREFS #IMPLIED
+ scope %Scope; #IMPLIED
+ rowspan %Number; "1"
+ colspan %Number; "1"
+ %cellhalign;
+ %cellvalign;
+ nowrap (nowrap) #IMPLIED
+ bgcolor %Color; #IMPLIED
+ width %Length; #IMPLIED
+ height %Length; #IMPLIED
+ >
+
diff --git a/flexml-act-bootstrap.c b/flexml-act-bootstrap.c
index 963d0b0..e1a8584 100644
--- a/flexml-act-bootstrap.c
+++ b/flexml-act-bootstrap.c
@@ -1,8 +1,8 @@
/* Flex(1) XML processor action language application.
- * Copyright � 1999 Kristoffer Rose. All rights reserved.
+ * Copyright (c) 1999 Kristoffer Rose. All rights reserved.
*
* This file is part of the FleXML XML processor generator system.
- * Copyright � 1999 Kristoffer Rose. All rights reserved.
+ * Copyright (c) 1999 Kristoffer Rose. All rights reserved.
*
* 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
@@ -24,6 +24,7 @@
#include <unistd.h>
#include "flexml-act.h"
+extern char *bufferstack;
extern FILE* yyin;
extern int yylineno;
extern int yylex(void);
diff --git a/flexml-act.dtd b/flexml-act.dtd
index 54aeb5f..a65a696 100644
--- a/flexml-act.dtd
+++ b/flexml-act.dtd
@@ -1,9 +1,9 @@
<!-- Flex(1) XML processor action file DTD.
- $Id: flexml-act.dtd,v 1.7 1999/11/30 18:28:23 krisrose Exp $
- Copyright � 1999 Kristoffer Rose. All rights reserved.
+ $Id: flexml-act.dtd,v 1.8 2006/07/18 18:21:13 mquinson Exp $
+ Copyright (c) 1999 Kristoffer Rose. All rights reserved.
This file is part of the FleXML XML processor generator system.
- Copyright � 1999 Kristoffer Rose. All rights reserved.
+ Copyright (c) 1999 Kristoffer Rose. All rights reserved.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
diff --git a/flexml.pl b/flexml.pl
index 9ae4cff..11561b4 100755
--- a/flexml.pl
+++ b/flexml.pl
@@ -1,10 +1,11 @@
#!/usr/bin/env perl
# Flex(1) XML processor scanner generator.
-# Copyright � 1999 Kristoffer Rose. All rights reserved.
+# Copyright (C) 1999 Kristoffer Rose. All rights reserved.
#
# This file is part of the FleXML XML processor generator system.
-# Copyright � 1999 Kristoffer Rose. All rights reserved.
+# Copyright (C) 1999 Kristoffer Rose. All rights reserved.
+# Copyright (C) 2003-2006 Martin Quinson. All rights reserved.
#
# 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
@@ -22,12 +23,12 @@
use warnings;
-my $Id = '$Id: flexml.pl,v 1.48 2006/03/21 13:09:12 mquinson Exp $ ';
+my $Id = '$Id: flexml.pl,v 1.61 2006/09/13 16:34:33 wdowling Exp $ ';
$Id =~ s/\s*\$\s*//go;
# IMPORTS.
-use Getopt::Std;
+use Getopt::Long;
use LWP::UserAgent;
use Carp qw/cluck confess/;
@@ -41,10 +42,11 @@ use vars qw/ $HEADER /; # generated XML processor API header
use vars qw/ $ACTIONS /; # the actions file
use vars qw/ $APPLICATION /; # generated XML application
+$SKELETON = "./skel"; # default value
+
# OPTIONS (and other globals).
my $Use; # usage string
-my %opt = (); # options
my $debug; # -d option flag
my $verbose; # -v option flag
@@ -53,9 +55,19 @@ my $nofail; # -X option flag
my $quiet_parser; # -q option flag
my $uri; # -u option uri
my $pubid; # -p option string
-my $stacksize; # -b option flag
-my $tagprefix; # -P option flag
-my $actbin; # -T option content
+my $sysid; # --sysid option string
+my $stacksize=100000; # -b option flag
+my $tagprefix=""; # -P option flag
+my $actbin="./flexml-act"; # -T option content
+my $init_header=""; # -i option string
+
+my $header; # -H option flag/content
+my $dummy; # -D option flag/content
+my $standalone; # -A option flag/content
+my $scanner; # -S option flag/content
+my $actions; # -a option content
+
+my $dryrun; # -n option flag
my $dtd; # DTD file name (or URI)
my $dtdrevision; # DTD version pruned from file
@@ -166,7 +178,8 @@ sub redistribute { # Print C comment with generated file "license".
my ($pre) = @_;
print <<EOT;
$pre This program was generated with the FleXML XML processor generator.
-$pre FleXML is Copyright � 1999-2005 Kristoffer Rose. All rights reserved.
+$pre FleXML is Copyright (C) 1999-2005 Kristoffer Rose. All rights reserved.
+$pre FleXML is Copyright (C) 2003-2006 Martin Quinson. All rights reserved.
$pre ($Id).
$pre
$pre There are two, intertwined parts to this program, part A and part B.
@@ -175,8 +188,8 @@ $pre Part A
$pre ------
$pre
$pre Some parts, here collectively called "Part A", are found in the
-$pre FleXML package. They are Copyright � 1999-2005 Kristoffer Rose.
-$pre All rights reserved.
+$pre FleXML package. They are Copyright (C) 1999-2005 Kristoffer Rose
+$pre and Copyright (C) 2003-2006 Martin Quinson. All rights reserved.
$pre
$pre You can redistribute, use, perform, display and/or modify "Part A"
$pre provided the following two conditions hold:
@@ -234,12 +247,22 @@ sub api_types { # Print XML application interface types.
sub api_data { # Print XML application interface parameters.
- my ($pre) = @_;
+ my ($pre) = @_; # pre should be a storage class spec like 'static' or 'extern'
print "/* FleXML-provided data. */\n";
- print $pre . "const char* ${tagprefix}pcdata;\n";
+ print $pre . "int ${tagprefix}pcdata_ix;\n";
+ print "extern char *${tagprefix}bufferstack;\n";
+ print "#define ${tagprefix}pcdata (${tagprefix}bufferstack + ${tagprefix}pcdata_ix)\n";
+
for (keys %atttype) {
if (m.($Nmtoken)[/]($Nmtoken).xo) {
- print $pre . "AT_${tagprefix}$ctag{$1}_$catt{$2} A_${tagprefix}$ctag{$1}_$catt{$2};\n";
+ print $pre . "AT_${tagprefix}$ctag{$1}_$catt{$2} AX_${tagprefix}$ctag{$1}_$catt{$2};\n";
+ print "#define A_${tagprefix}$ctag{$1}_$catt{$2} ";
+ if ($enumtype{$_}) {
+ print "AX_${tagprefix}$ctag{$1}_$catt{$2}\n";
+ }
+ else {
+ print "(${tagprefix}bufferstack + AX_${tagprefix}$ctag{$1}_$catt{$2})\n";
+ }
}
}
}
@@ -248,7 +271,7 @@ sub api_data { # Print XML application interface parameters.
sub expandparametersat { # Expand parameter entities in $_ at $place.
my ($place) = @_;
while ( m/$place\s*%($Name);/ ) {
- if ($parameter{$1}) {
+ if (defined $parameter{$1}) {
s/$place(\s*)%($Name);/ ' '. $1 . $parameter{$2} . ' ' /xe;
}
}
@@ -300,6 +323,16 @@ sub geturl { # Insert contents of URL into input stream at current point
# }
}
+# add attribute to list of all default attributes
+my @default_attributes;
+my $next_att_loc = 1;
+sub add_def_att {
+ my ($att) = @_;
+ my $retval = $next_att_loc;
+ push @default_attributes, ($att);
+ $next_att_loc += length($att) + 1;
+ return $retval;
+}
sub nextline { # return one input line
@@ -487,49 +520,71 @@ sub analysechildren { # Analyse DTD children specification; return
# Parse options.
-$Use = "Usage: flexml [-ASHDvdqnLXV] [-s skel] [-T actbin] [-p pubid] [-u uri]\n"
- . " [-b stack_size] [-r roottags] [-a actions] [-P prefix] name[.dtd]";
-
-getopts('ASHDvdnLXVqp:b:P:s:T:u:r:a:', \%opt);
+$Use = "Usage: flexml [-ASHDvdqnLXV] [-s skel] [-T actbin] [--sysid sysid] "
+ . "[-p pubid] [-u uri] [-i init_header]\n"
+ . " [-b stack_increment] [-r roottags] [-a actions] [-P prefix] name[.dtd]";
-# Version!
-print "FleXML version $Id.\n" if $opt{V} or $opt{v};
-exit 0 if $opt{V};
+sub show_version {
-# Debugging?
-$debug = $opt{d};
-$verbose = $opt{v};
+ exit 0;
+}
+
+Getopt::Long::Configure ("bundling");
+GetOptions(
+ # Debugging and verbosity
+ "debug|d" => \$debug,
+ "verbose|v" => \$verbose,
+ "quiet|q" => \$quiet_parser,
+
+ # Version!
+ "version|V" => sub { print "FleXML version $Id.\n"; exit 0; },
-# Line numbers?
-$lineno = $opt{L};
+ # dry-run ?
+ "dry-run|n" => \$dryrun,
-# Quiet parser?
-$quiet_parser = $opt{q};
+ # Line numbers?
+ "lineno|L" => \$lineno,
-# Exit without fail message?
-$nofail = $opt{X};
+ # Exit without fail message?
+ "nofail|X" => \$nofail,
-# Specific root tags?
-if ($opt{r}) {
- for (split ',',$opt{r}) { $roottags{$_} = 'true'; }
-}
+ # Specific root tags?
+ "root-tags|r=s" => sub {
+ for (split ',',$_[1]) { $roottags{$_} = 'true'; }
+ },
-# Specific stack size?
-$stacksize = ($opt{'b'} ? $opt{'b'} : 100000);
+ # Specific stack size?
+ "stack-increment|b=s" => \$stacksize,
+
+ # Specific tagprefix?
+ "tag-prefix|P=s" => sub { $tagprefix = $_[1]."_" },
+
+ # Specific actbin? (internal use)
+ "act-bin|T=s" => \$actbin,
+
+ # Set skeleton scanner file name and check it is readable (if needed).
+ "skel|s=s" => sub {
+ $SKELETON = $_[1];
+ die "$0: No skeleton file $SKELETON.\n" if not -r $SKELETON and $_[1];
+ },
+
+ # Set document type URI and PUBID.
+ "uri|u=s" => \$uri,
+ "pubid|p=s" => \$pubid,
+ "sysid=s" => \$sysid,
-# Specific tagprefix?
-$tagprefix = ($opt{'P'} ? $opt{'P'}."_" : "");
+ # name of header file to be included in initial section of generated .l file
+ "init_header|i=s" => \$init_header,
-# Specific actbin?
-$actbin = ($opt{'T'} ? $opt{'T'} : "./flexml-act");
-
-# Set skeleton scanner file name and check it is readable (if needed).
-$SKELETON = ($opt{'s'} ? $opt{'s'} : './skel');
-die "$0: No skeleton file $SKELETON.\n" if not -r $SKELETON and $opt{S};
+ # What to generate
+ "header|H:s" => sub { $header = $_[1] || 'true' },
+ "dummy|D:s" => sub { $dummy = $_[1] || 'true' },
+ "stand-alone|A" => \$standalone,
+ "scanner|S:s" => sub { $scanner = $_[1] || 'true' },
+ "actions|a=s" => \$actions
+ );
-# Set document type URI and PUBID.
-$uri = $opt{u} if $opt{u};
-$pubid = $opt{p} if $opt{p};
+print "FleXML version $Id.\n" if $verbose;
# Set DTD file name...and extract prefix for later
my $prefix = $ARGV[0];
@@ -546,30 +601,30 @@ else {
# Selection options: If none of -SHDA specified then default to -SH.
# Furthermore -a implies -D.
-$opt{S} = $opt{H} = 'true' unless ($opt{S} or $opt{H} or $opt{D} or $opt{A});
-$opt{D} ||= $opt{a} unless $opt{A};
+$scanner = $header = 'true' unless ($scanner or $header or $dummy or $standalone);
+$dummy ||= $actions unless $standalone;
# Set default (DTD-based) output file names.
-$SCANNER = "$prefix.l";
-$HEADER = "$prefix.h";
-$APPLICATION = "$prefix-dummy.c";
+$SCANNER = (!defined($scanner)) || $scanner eq 'true' ? "$prefix.l" : $scanner;
+$HEADER = (!defined($header)) || $header eq 'true' ? "$prefix.h" : $header;
+$APPLICATION = (!defined($dummy)) || $dummy eq 'true' ? "$prefix-dummy.c" : $dummy;
# Set actions=based output file names, if any.
-if ($ACTIONS = $opt{a}) {
- $opt{a} =~ s/\.[a-z]+$//;
- $APPLICATION = "$opt{a}.c";
+if ($ACTIONS = $actions) {
+ $actions =~ s/\.[a-z]+$//;
+ $APPLICATION = "$actions.c";
}
# Stand-alone applications...
-if ($opt{A}) {
- die "$0: -A conflicts with -SHD.\n" if ($opt{S} or $opt{H} or $opt{D});
+if ($standalone) {
+ die "$0: -A conflicts with -SHD.\n" if ($scanner or $header or $dummy);
$SCANNER = $APPLICATION;
$SCANNER =~ s/\.c$/.l/;
}
# Dry-run?
-if ($opt{n}) {
- $opt{A} = $opt{S} = $opt{H} = $opt{D} = undef;
+if ($dryrun) {
+ $standalone = $scanner = $header = $dummy = undef;
}
@@ -672,11 +727,12 @@ while (@inputs) { # While there are lines...
# strip off the matched code from the beginning of $_
$_ = $'; #'
+ # place the newly found tag into the list of tags @tags
+ die place()."Repeated element $tag.\n" if exists $source{$tag};
+
# ????? - most of the time $orig is undef
$source{$tag} = "$orig";
- # place the newly found tag into the list of tags @tags
- die place()."Repeated element $tag.\n" if $ctag{$tag};
push @tags, $tag;
# Create C-friendly tag names.
@@ -815,12 +871,12 @@ while (@inputs) { # While there are lines...
}
# ...and string/token types.
else {
- $typeof{"$tag/$attribute"} = 'const char*';
+ $typeof{"$tag/$attribute"} = 'int';
if ($default) {
- $initof{"$tag/$attribute"} = "\"$default\"";
+ $initof{"$tag/$attribute"} = add_def_att($default);
}
else {
- $initof{"$tag/$attribute"} = 'NULL';
+ $initof{"$tag/$attribute"} = '0';
}
# Special treatment of token types.
@@ -839,10 +895,15 @@ while (@inputs) { # While there are lines...
$literaltype{"$tag/$attribute"} = '{Nmtokens}';
}
elsif ( $type eq 'ENTITY' ) {
- die place()."ENTITY attribute type unimplemented.\n";
+ #die place()."ENTITY attribute type unimplemented.\n";
+ $literaltype{"$tag/$attribute"} = '{Name}';
+ print STDERR place()."Warning: attribute type `$type' not validated.\n";
}
elsif ( $type eq 'ENTITIES' ) {
- die place()."ENTITIES attribute type unimplemented.\n";
+ #die place()."ENTITIES attribute type unimplemented.\n";
+ $literaltype{"$tag/$attribute"} = '{Names}';
+ print STDERR place()."Warning: attribute type `$type' not validated.\n";
+
}
elsif ( $type ne 'CDATA' ) {
die place()."Unknown AttType `$type'.\n";
@@ -980,7 +1041,7 @@ if (not %roottags) {
}
# Handling prefix
-if($opt{P}) {
+if(length($tagprefix)) {
my($h,$k);
my(@hashlist) = (\%states,\%emptytrans,\%instates,\%startstate,
\%endstates,\%exittrans);
@@ -1016,7 +1077,32 @@ if ($debug) {
return $out;
}
- print '%opt = (' . printhash(\%opt) . ")\n";
+ # display the options we got
+ print "debug=".($debug||'undef')."\n";
+ print "verbose=".($verbose||'undef')."\n";
+ print "quiet=".($quiet_parser||'undef')."\n";
+
+ print "dry-run=".($dryrun||'undef')."\n";
+ print "lineno=".($lineno||'undef')."\n";
+
+ print "nofail=".($nofail||'undef')."\n";
+
+ print "stack-increment=".($stacksize||'undef')."\n";
+ print "tag-prefix=".($tagprefix||'undef')."\n";
+
+ print "act-bin=".($actbin||'undef')."\n";
+
+ print "skel=".($SKELETON||'undef')."\n";
+
+ print "uri=".($uri||'undef')."\n";
+ print "pubid=".($pubid||'undef')."\n\n";
+ print "sysid=".($sysid||'undef')."\n\n";
+
+ print "header=".($header||'undef')."\n";
+ print "dummy=".($dummy||'undef')."\n";
+ print "stand-alone=".($standalone||'undef')."\n";
+ print "scanner=".($scanner||'undef')."\n";
+ print "actions=".($actions||'undef')."\n\n";
print '%source = (' . printhash(\%source) . ")\n";
print "\n";
@@ -1065,7 +1151,7 @@ if ($debug) {
# WRITE API HEADER (if requested).
-if ($opt{H}) {
+if ($header) {
print STDOUT "Generating XML processor header in `$HEADER'.\n" if $verbose;
@@ -1112,10 +1198,10 @@ if ($opt{H}) {
# WRITE XML PROCESSOR (if requested).
-if ($opt{S} or $opt{A}) {
+if ($scanner or $standalone) {
print STDOUT "Writing XML processor"
- . ($opt{a} || $opt{A} ? " and application" : "")
+ . ($actions || $standalone ? " and application" : "")
. " onto `$SCANNER'.\n" if $verbose;
open SCANNER, "+>$SCANNER"|| die "$0: cannot write $SCANNER: $!\n";
@@ -1154,11 +1240,14 @@ if ($opt{S} or $opt{A}) {
print "#define FLEXML_yylineno\n" if $lineno;
print "#define FLEXML_NOFAIL\n" if $nofail;
print "#define FLEXML_quiet_parser\n" if $quiet_parser;
- print "#define FLEXML_HasMixed\n" if %inmixed;
+ print "#ifndef FLEXML_BUFFERSTACKSIZE\n";
print "#define FLEXML_BUFFERSTACKSIZE $stacksize\n";
+ print "#endif\n";
+ print "#define FLEXML_NEED_BUFFERLIT\n"
+ if (scalar(%literaltype) or ($#default_attributes >= 0));
print "\n";
- if ($opt{A}) {
+ if ($standalone) {
api_functions('static ',';');
print "\n";
api_types();
@@ -1168,11 +1257,18 @@ if ($opt{S} or $opt{A}) {
else {
print "/* XML processor api. */\n";
print "#include \"$HEADER\"\n\n"
- if ($opt{H});
+ if ($header);
api_data('');
}
}
+ elsif ( /^FLEXML_INCLUDE_INIT_HEADER$/ ) {
+ if ($init_header) {
+ print "/* User-supplied header */\n";
+ print "#include \"$init_header\"\n";
+ }
+ }
+
elsif ( /^FLEXML_FLEX_OPTIONS$/ ) {
print "%option yylineno\n" if $lineno;
@@ -1203,7 +1299,10 @@ if ($opt{S} or $opt{A}) {
my ($state, $tag);
print " /* FleXML_init */\n";
- print " next = bufferstack;\n";
+ print " bnext = inext = 1;\n";
+ for my $att (@default_attributes) {
+ print " ${tagprefix}bufferliteral('\\0', &bnext, \"$att\");\n";
+ }
print " if(!${tagprefix}statenames) {${tagprefix}statenames= (const char **)calloc(IMPOSSIBLE,sizeof(char*));\n";
for ('PROLOG','DOCTYPE','EPILOG','INCOMMENT','INPI','VALUE1','VALUE2','CDATA') {
print " ${tagprefix}statenames[$_] = NULL;\n";
@@ -1220,8 +1319,9 @@ if ($opt{S} or $opt{A}) {
}
elsif ( /^FLEXML_DOCTYPES$/ ) {
- my $sysid = ( $uri ? "(\"'$uri'\"|\"\\\"$uri\\\"\")"
- : "(\"'$dtd'\"|\"\\\"$dtd\\\"\")" );
+ $sysid = $sysid ? "(\"'$sysid'\"|\"\\\"$sysid\\\"\")"
+ : ( $uri ? "(\"'$uri'\"|\"\\\"$uri\\\"\")"
+ : "(\"'$dtd'\"|\"\\\"$dtd\\\"\")" );
for (keys %roottags) {
my $c = $ctag{$_};
@@ -1268,11 +1368,6 @@ if ($opt{S} or $opt{A}) {
}
$exitswitch .= " }\n";
}
-
-
-
-
-
# Start or empty tag: initialise attribute list.
print "\n";
@@ -1288,9 +1383,9 @@ if ($opt{S} or $opt{A}) {
print ">\"<$tag\"{s} {\n";
for my $attribute (@myattributes) {
- print " A_${tagprefix}${myctag}_$catt{$attribute} = " . $initof{"$tag/$attribute"} . ";\n";
+ print " AX_${tagprefix}${myctag}_$catt{$attribute} = " . $initof{"$tag/$attribute"} . ";\n";
}
- print " ENTER(AL_${tagprefix}$myctag);\n";
+ print " ENTER(AL_${tagprefix}$myctag); pushbuffer(0);\n";
print " }\n";
# print " . FAIL(\"Unexpected character `%c': `<$tag' expected.\",yytext[0]);\n";
@@ -1333,23 +1428,23 @@ if ($opt{S} or $opt{A}) {
print " \"$attribute\"{Eq}\"'" . $attdef{"$tag/$attribute"} . "'\""
. " |\n"
. " \"$attribute\"{Eq}\"\\\"" . $attdef{"$tag/$attribute"} . "\\\"\""
- . " A_${tagprefix}${myctag}_$catt{$attribute}"
+ . " AX_${tagprefix}${myctag}_$catt{$attribute}"
. " = " . $initof{"$tag/$attribute"} . ";\n";
}
elsif ($type = $literaltype{"$tag/$attribute"}) {
# - (non-fixed) literal-type attribute: scan literal string directly, or
- print " \"$attribute\"{Eq}\'$type\' BUFFERLITERAL('\\\'',A_${tagprefix}${myctag}_$catt{$attribute});\n";
+ print " \"$attribute\"{Eq}\'$type\' BUFFERLITERAL('\\\'',AX_${tagprefix}${myctag}_$catt{$attribute});\n";
- print " \"$attribute\"{Eq}\\\"$type\\\" BUFFERLITERAL('\"',A_${tagprefix}${myctag}_$catt{$attribute});\n";
+ print " \"$attribute\"{Eq}\\\"$type\\\" BUFFERLITERAL('\"',AX_${tagprefix}${myctag}_$catt{$attribute});\n";
}
else {
# - (non-fixed non-literal) attribute: scan string with entity expansion.
- print " \"$attribute\"{Eq}\\' ENTER(VALUE1); BUFFERSET(A_${tagprefix}${myctag}_$catt{$attribute});\n";
- print " \"$attribute\"{Eq}\\\" ENTER(VALUE2); BUFFERSET(A_${tagprefix}${myctag}_$catt{$attribute});\n";
+ print " \"$attribute\"{Eq}\\' ENTER(VALUE1); BUFFERSET(AX_${tagprefix}${myctag}_$catt{$attribute});\n";
+ print " \"$attribute\"{Eq}\\\" ENTER(VALUE2); BUFFERSET(AX_${tagprefix}${myctag}_$catt{$attribute});\n";
}
print "\n";
@@ -1360,13 +1455,13 @@ if ($opt{S} or $opt{A}) {
print " \">\" {\n";
for my $attribute (@myattributes) {
if ($required{"$tag/$attribute"}) {
- print " if (!A_${tagprefix}$ctag{$tag}_" . variablify($attribute) . ")"
+ print " if (!AX_${tagprefix}$ctag{$tag}_" . variablify($attribute) . ")"
. " FAIL(\"Required attribute `$attribute' not set for `$tag' element.\");\n";
}
}
print " LEAVE; STag_${tagprefix}$myctag();"
- . (%inmixed ? ' pushbuffer('."${tagprefix}".'pcdata);' : '')
- . ($mixed{$tag} ? 'BUFFERSET('."${tagprefix}".'pcdata)' : "${tagprefix}".'pcdata = NULL'). ";"
+ . (%inmixed ? ' pushbuffer('."${tagprefix}".'pcdata_ix);' : '')
+ . ($mixed{$tag} ? 'pushbuffer('."${tagprefix}".'pcdata_ix); BUFFERSET('."${tagprefix}".'pcdata_ix);' : "${tagprefix}".'pcdata_ix = 0'). ";"
. " ENTER($startstate{$tag});\n";
print " }\n";
#
@@ -1375,16 +1470,16 @@ if ($opt{S} or $opt{A}) {
print " \"/>\" {\n";
for my $attribute (@myattributes) {
if ($required{"$tag/$attribute"}) {
- print " if (!A_${tagprefix}$ctag{$tag}_" . variablify($attribute) . ")"
+ print " if (!AX_${tagprefix}$ctag{$tag}_" . variablify($attribute) . ")"
. " FAIL(\"Required attribute `$attribute' not set for `$tag' element.\");\n";
}
}
print " LEAVE; STag_${tagprefix}$myctag();"
- . (%inmixed ? ' pushbuffer('."${tagprefix}".'pcdata);' : '')
- . " ${tagprefix}".'pcdata = ' . ($mixed{$tag} ? '""' : 'NULL') . ';'
+ . (%inmixed ? ' pushbuffer('."${tagprefix}".'pcdata_ix);' : '')
+ . " ${tagprefix}".'pcdata_ix = 0;'
. " ETag_${tagprefix}$myctag();"
- . (%inmixed ? " ${tagprefix}".'pcdata = popbuffer();' : '')
- . "\n";
+ . (%inmixed ? " ${tagprefix}".'pcdata_ix = popbuffer();' : '')
+ . " popbuffer(); /* attribute */\n";
#
print $exitswitch;
print " }\n";
@@ -1408,7 +1503,9 @@ if ($opt{S} or $opt{A}) {
print " LEAVE;\n";
print " BUFFERDONE;\n" if $mixed{$tag};
print " ETag_${tagprefix}$myctag();\n";
- print " ${tagprefix}pcdata = popbuffer();\n" if %inmixed;
+ print " ${tagprefix}pcdata_ix = popbuffer();\n" if $mixed{$tag};
+ print " ${tagprefix}pcdata_ix = popbuffer();\n" if %inmixed;
+ print " popbuffer(); /* attribute */\n";
print $exitswitch;
print " }\n";
@@ -1505,13 +1602,15 @@ if ($opt{S} or $opt{A}) {
s/element_context/${tagprefix}element_context/g;
s/parse_err_msg/${tagprefix}parse_err_msg/g;
s/rcs_flexml_skeleton/rcs_${tagprefix}flexml_skeleton/g;
+ s/bufferliteral/${tagprefix}bufferliteral/g;
+ s/bufferstack/${tagprefix}bufferstack/g;
print;
}
}
close SKELETON || die "$0: Cannot close $SKELETON: $!\n";
- unless ($opt{A}) {
+ unless ($standalone) {
close SCANNER || die "$0: Cannot close $SCANNER: $!\n";
}
}
@@ -1521,10 +1620,10 @@ if ($opt{S} or $opt{A}) {
# WRITE APPLICATION.
-if ($opt{D}) {
+if ($dummy) {
print STDOUT "Writing XML"
- . ($opt{a} ? "" : " dummy")
+ . ($actions ? "" : " dummy")
. " application onto `$APPLICATION'.\n" if $verbose;
open APPLICATION, "+>$APPLICATION" || die "$0: Cannot write $APPLICATION: $!\n";
@@ -1546,7 +1645,7 @@ if ($opt{D}) {
}
-if ($opt{D} or $opt{A}) {
+if ($dummy or $standalone) {
# Get requested actions.
if ($ACTIONS) {
@@ -1589,23 +1688,17 @@ if ($opt{D} or $opt{A}) {
if ($tag) {
while ( s/\{($Name)\}/A_${tagprefix}$ctag{$tag}_$catt{$1}/x ) {
- die "\"$ACTIONS\", line $lineno: Attributes only allowed in start tag.\n"
- if not $isstart;
die "\"$ACTIONS\", line $lineno: Unknown attribute `$1' for <$tag>.\n"
if not $atttype{"$tag/$1"};
}
while ( s/\{[!]($Name)\}/AU_${tagprefix}$ctag{$tag}_$catt{$1}/x ) {
- die "\"$ACTIONS\", line $lineno: Attributes only allowed in start tag.\n"
- if not $isstart;
die "\"$ACTIONS\", line $lineno: Unknown attribute `$1' for <$tag>.\n"
if not $atttype{"$tag/$1"};
}
while ( s|\{($Name)=($Name)\}|
"A_${tagprefix}$ctag{$tag}_$catt{$1}_" . variablify($2); |xe ) {
- die "\"$ACTIONS\", line $lineno: Attributes only allowed in start tag.\n"
- if not $isstart;
my ($att,$elt) = ($1,$2);
die "\"$ACTIONS\", line $lineno: Unknown attribute $1 for <$tag>.\n"
if not $atttype{"$tag/$1"};
@@ -1623,6 +1716,7 @@ if ($opt{D} or $opt{A}) {
die "\"$ACTIONS\", line $lineno: Malformed annotation `$&' in <$tag> action.\n"
if m|\{[^;\s]+\}|o;
}
+ print STDERR "Action: $_" if $debug;
print $_;
}
@@ -1635,10 +1729,10 @@ if ($opt{D} or $opt{A}) {
}
-if ($opt{D}) {
+if ($dummy) {
close APPLICATION || die "$0: Cannot close $APPLICATION: $!\n";
}
-elsif ($opt{A}) {
+elsif ($standalone) {
close SCANNER || die "$0: Cannot close $SCANNER: $!\n";
}
@@ -1656,6 +1750,7 @@ B<flexml>
[B<-ASHDvdnLXV>]
[B<-s>I<skel>]
[B<-p>I<pubid>]
+[B<-i>I<init_header>]
[B<-u>I<uri>]
[B<-r>I<rootags>]
[B<-a>I<actions>]
@@ -1700,102 +1795,114 @@ I<Flexml> takes the following options.
=over 4
-=item B<-A>
+=item B<--stand-alone>, B<-A>
Generate a I<stand-alone> scanner application. If combined with
B<-a>I<actions> then the application will be named as I<actions> with
the extension replaced by F<.l>, otherwise it will be in I<name>F<.l>.
Conflicts with B<-S>, B<-H>, and B<-D>.
-=item B<-a> I<actions>
+=item B<--actions> I<actions>, B<-a> I<actions>
Uses the I<actions> file to produce an XML application in the file
with the same name as I<actions> after replacing the extension with
F<.c>. If combined with B<-A> then instead the stand-alone
application will include the action functions.
-=item B<-D>
+=item B<--dummy> B<[>I<app_name>B<]>, B<-D> B<[>I<app_name>B<]>
-Generate a dummy application I<name>F<-dummy.c> with just empty
-functions to be called by the XML processor. If combined with
-B<-a>I<actions> then the application will insert the specified
-actions and be named as I<actions> with the extension replaced by
-F<.c>. Conflicts with B<-A>; implied by B<-a> unless either of
-B<-SHD> is specified.
+Generate a dummy application with just empty functions to be called by the
+XML processor. If I<app_name> is not specified on the command line, it
+defaults to I<name>F<-dummy.c>. If combined with B<-a> I<actions> then the
+application will insert the specified actions and be named as I<actions>
+with the extension replaced by F<.c>. Conflicts with B<-A>; implied by
+B<-a> unless either of B<-SHD> is specified.
-=item B<-d>
+=item B<--debug>, B<-d>
Turns on debug mode in the flex scanner and also prints out the
details of the DTD analysis performed by I<flexml>.
-=item B<-H>
+=item B<--header> B<[>I<header_name>B<]>, B<-H> B<[>I<header_name>B<]>
-Generate the header file I<name>F<.h>. Conflicts with B<-A>; on by
+Generate the header file. If the I<header_name> is not specified on the
+command line, defaults to I<name>F<.h>. Conflicts with B<-A>; on by
default if none of B<-SHD> specified.
-=item B<-L>
+=item B<--lineno>, B<-L>
Makes the XML processor (as produced by I<flex>(1)) count the lines in
the input and keep it available to XML application actions in the
integer C<yylineno>. (This is off by default as the performance
overhead is significant.)
-=item B<-q>
+=item B<--quiet>, B<-q>
Prevents the XML processor (as produced by I<flex>(1)) from reporting
the error it runs into on stderr. Instead, users will have to pool for
error messages with the parse_err_msg() function.
By default, error messages are written on stderr.
-=item B<-n>
+=item B<--dry-run>, B<-n>
"Dry-run": do not produce any of the output files.
-=item B<-p> I<pubid>
+=item B<--pubid> I<pubid>, B<-p> I<pubid>
Sets the document type to be C<PUBLIC> with the identifier I<pubid>
instead of C<SYSTEM>, the default.
-=item B<-r> I<roottags>
+=item B<--init_header> I<init_header>, B<-i> I<init_header>
+
+Puts a line containing C<#include "init_header"> in the C<%{...%}> section
+at the top of the generated .l file. This may be useful for making various
+flex C<#define>s, for example C<YY_INPUT> or C<YY_DECL>.
+
+=item B<--sysid>=I<sysid>
+
+Overrides the C<SYSTEM> id of the accepted DTD. Sometimes usefull when your
+dtd is placed in a subdirectory.
+
+=item B<--root-tags> I<roottags>, B<-r> I<roottags>
Restricts the XML processor to validate only documents with one of the
root elements listed in the comma-separated I<roottags>.
-=item B<-S>
+=item B<--scanner> B<[>I<scanner_name>B<]>, B<-S> B<[>I<scanner_name>B<]>
-Generate the scanner I<name>F<.l>. Conflicts with B<-A>; on by
-default if none of B<-SHD> specified.
+Generate the scanner. If I<scanner_name> is not given on command line, it
+defaults to I<name>F<.l>. Conflicts with B<-A>; on by default if none of
+B<-SHD> specified.
-=item B<-s> I<skel>
+=item B<--skel> I<skel>, B<-s> I<skel>
Use the skeleton scanner I<skel> instead of the default.
-=item B<-T> I<flexml-act>
+=item B<--act-bin> I<flexml-act>, B<-T> I<flexml-act>
This is an internal option mainly used to test versions of flexml not
installed yet.
-=item B<-b> I<stack_size>
+=item B<--stack-increment> I<stack_increment>, B<-b> I<stack_increment>
-Sets the FLEXML_BUFFERSTACKSIZE to stack_size (100000 by default). Use
-this option when you get an error like "Assertion `next<limit'
-failed".
+Sets the FLEXML_BUFFERSTACKSIZE to stack_increment (100000 by default). This
+controls how much the data stack grows in each realloc().
-=item B<-p> I<STRING>
+=item B<--tag-prefix> I<STRING>, B<-O> I<STRING>
Use STRING to differentiate multiple versions of flexml in the same C
-code.
+code, just like the -P flex argument.
-=item B<-u> I<uri>
+=item B<--uri> I<uri>, B<-u> I<uri>
Sets the URI of the DTD, used in the C<DOCTYPE> header, to the
specified I<uri> (the default is the DTD name).
-=item B<-v>
+=item B<--verbose>, B<-v>
Be verbose: echo each DTD declaration (after parameter expansion).
-=item B<-V>
+=item B<--version>, B<-V>
Print the version of I<flexml> and exit.
@@ -1946,11 +2053,6 @@ in particular C<xml:spaces> should be supported.
=item *
-The XML processor currently uses a fixed-size buffer to read
-C<pcdata>. It should not.
-
-=item *
-
The DTD parser is presently a perl hack so it may parse some DTDs
badly; in particular the expansion of parameter entities may not
conform fully to the XML specification.
@@ -1984,7 +2086,7 @@ REC-xml-1998-0210).
=head1 AUTHOR
-I<Flexml> was written by Kristoffer H�gsbro Rose,
+I<Flexml> was written by Kristoffer Rose,
E<lt>C<krisrose@debian.org>E<gt>.
=head1 COPYRIGHT
diff --git a/paper.html b/paper.html
index 7897c2d..0ab73bd 100644
--- a/paper.html
+++ b/paper.html
@@ -4,7 +4,7 @@
<html>
<head>
<title>Generating Fast Validating XML Processors</title>
- <!--$Id: paper.html,v 1.12 2005/04/06 10:12:27 mquinson Exp $-->
+ <!--$Id: paper.html,v 1.13 2006/07/18 18:21:13 mquinson Exp $-->
<style type="text/css">
<!--
BODY { BACKGROUND-COLOR: #ffffff; FONT-FAMILY: arial, times new roman, sans-serif; }
@@ -385,7 +385,7 @@ gcc -Wall -ansi -pedantic xhtml-href.o xhtml1-transitional.o -o xhtml-href
<p>
This is useful for XML applications that are meant to process a
large number of documents in a fixed format. One such
- application is the NTSys �-payment transaction server which is
+ application is the NTSys u-payment transaction server which is
implemented as an Apache module where performance is of premium
importance. Using FleXML permits a highly modular development
of modules for the various transaction types based on a common
@@ -445,7 +445,7 @@ gcc -Wall -ansi -pedantic xhtml-href.o xhtml1-transitional.o -o xhtml-href
</dl>
<hr>
- <address>Copyright �
+ <address>Copyright (c)
<a href="mailto:krisrose@debian.org">Kristoffer Rose</a>.
<!-- Created: Thu Dec 9 08:09:41 CET 1999 -->
<!-- hhmts start -->Last modified: Tue Feb 11 13:56:40 EST 2003 <!-- hhmts end -->
diff --git a/skel b/skel
index 6d926b7..de4db60 100644
--- a/skel
+++ b/skel
@@ -1,8 +1,8 @@
/* Flex(1) XML processor skeleton scanner (in -*-C-*-).
- * Copyright � 1999 Kristoffer Rose. All rights reserved.
+ * Copyright (C) 1999 Kristoffer Rose. All rights reserved.
*
* This file is part of the FleXML XML processor generator system.
- * Copyright � 1999 Kristoffer Rose. All rights reserved.
+ * Copyright (C) 1999 Kristoffer Rose. All rights reserved.
*
* 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
@@ -25,7 +25,7 @@
/* Version strings. */
const char rcs_flexml_skeleton[] =
- "$Id: skel,v 1.28 2006/03/21 12:04:13 legranda Exp $";
+ "$Id: skel,v 1.38 2006/09/12 18:05:45 wdowling Exp $";
FLEXML_VERSION
/* ANSI headers. */
@@ -36,6 +36,10 @@ FLEXML_VERSION
#include <stdarg.h>
#include <ctype.h>
+#ifndef FLEXML_INDEXSTACKSIZE
+#define FLEXML_INDEXSTACKSIZE 1000
+#endif
+
/* Generated definitions. */
FLEXML_DEFINITIONS
@@ -59,64 +63,99 @@ FLEXML_DEFINITIONS
#define FAIL return fail
static int fail(const char*, ...);
-const char * parse_err_msg(void);
+
+enum {flexml_max_err_msg_size = 512};
+static char flexml_err_msg[flexml_max_err_msg_size];
+const char * parse_err_msg()
+{
+ return flexml_err_msg;
+}
+static void reset_parse_err_msg()
+{
+ flexml_err_msg[0] = '\0';
+}
/* Cleanup */
static void cleanup(void);
#define CLEANUP cleanup()
/* Text buffer stack handling. */
-static char bufferstack[FLEXML_BUFFERSTACKSIZE];
-static char* limit = bufferstack + FLEXML_BUFFERSTACKSIZE;
-typedef struct BufferLast_s {
- struct BufferLast_s *old; char* saved; char new1[1];
-} BufferLast;
-#ifdef FLEXML_HasMixed
-static BufferLast* last = (BufferLast*)0;
-#endif
-static char* next = bufferstack;
+char *bufferstack = NULL;
+static int blimit = FLEXML_BUFFERSTACKSIZE;
+static int bnext = 1;
+
+static int *indexstack = NULL;
+static int ilimit = FLEXML_INDEXSTACKSIZE;
+static int inext = 1;
-#define BUFFERSET(P) (P = next)
-#define BUFFERPUTC(C) (assert(next<limit), *(next++) = (C))
+#define BUFFERSET(P) (P = bnext)
+#define BUFFERPUTC(C) (ck_blimit(), bufferstack[bnext++] = (C))
#define BUFFERDONE (BUFFERPUTC('\0'))
-#define BUFFERLITERAL(C,P) bufferliteral(C,&(P),yytext)
-static void bufferliteral(char c, const char** pp, char* text)
+#define BUFFERLITERAL(C, P) bufferliteral(C, &(P), yytext)
+
+/* after this is called, there are at least 2 slots left in the stack */
+static int ck_blimit()
+{
+ if (bnext >= blimit) {
+ blimit += FLEXML_BUFFERSTACKSIZE + 2;
+ {
+ char *temp = (char *) realloc(bufferstack, blimit);
+ assert(temp);
+ bufferstack = temp;
+ }
+ }
+ return 0;
+}
+
+/* after this is called, there are at least 2 slots left in the stack */
+static int ck_ilimit()
+{
+ if (inext >= ilimit) {
+ ilimit += FLEXML_INDEXSTACKSIZE + 2;
+ {
+ int *temp = (int *) realloc(indexstack, ilimit);
+ assert(temp);
+ indexstack = temp;
+ }
+ }
+ return 0;
+}
+
+#ifdef FLEXML_NEED_BUFFERLIT
+static void bufferliteral(char c, int* pp, const char* text)
{
- char *s = strchr(text,c), *e = strrchr(text,c);
+ const char *s = (c ? strchr(text,c) : text-1), *e = strrchr(text,c);
assert(s <= e); BUFFERSET(*pp);
while (++s<e) {
- if (isspace(*s)) { BUFFERPUTC(' '); while (isspace(*s)) ++s; }
+ if (isspace(*s) && c) { BUFFERPUTC(' '); while (isspace(*s)) ++s; }
else BUFFERPUTC(*s);
}
BUFFERDONE;
}
+#endif
-#ifdef FLEXML_HasMixed
-static void pushbuffer(char* p)
+static void pushbuffer(int p)
{
- BufferLast* l = (BufferLast*)next;
- assert(next < limit);
- l->old = last;
- l->saved = p;
- next = l->new1;
- last = l;
+ ck_ilimit();
+ indexstack[inext++] = p;
+ indexstack[inext++] = bnext;
}
-static char* popbuffer(void)
+static int popbuffer(void)
{
- BufferLast* l = last;
- assert(last != (BufferLast*)0);
- last = l->old;
- next = (char*)l;
- return l->saved;
+ assert(inext >= 2);
+ bnext = indexstack[--inext];
+ return indexstack[--inext];
}
-#endif
/* General internal entities are `unput' back onto the input stream... */
#define ENTITYTEXT(T) \
{ char *s = (T), *e = s+strlen(s);\
while (--e >= s) { unput(*e); }}
+
+FLEXML_INCLUDE_INIT_HEADER
+
%}
/* Flex standard options. */
@@ -173,6 +212,22 @@ FLEXML_EXTRA_DEFINITIONS
/* Bypass Flex's default INITIAL state and begin by parsing the XML prolog. */
SET(PROLOG);
+ reset_parse_err_msg();
+ bufferstack = (char *) malloc(FLEXML_BUFFERSTACKSIZE);
+ assert(bufferstack);
+ #ifdef FLEX_DEBUG
+ {
+ int i;
+ for (i = 0; i < blimit; i++) {
+ bufferstack[i] = '\377';
+ }
+ }
+ #endif
+ bufferstack[0] = '\0';
+ indexstack = (int *) malloc(FLEXML_INDEXSTACKSIZE * sizeof(int));
+ assert(indexstack);
+ indexstack[0] = 0;
+
FLEXML_EXTRA_DEFINITIONS_INIT
/* COMMENTS and PIs: handled uniformly for efficiency. */
@@ -289,19 +344,39 @@ void print_yy_stack(char* fmt, ...)
{
int i = 0; va_list ap; va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
- for (i=1; i<yy_start_stack_ptr; i++)
- fprintf(stderr, "%s/", statenames[yy_start_stack[i] ]);
- fprintf(stderr,"%s\n", statenames[YY_START]);
+ if (statenames) {
+ for (i=1; i<yy_start_stack_ptr; i++) {
+ fprintf(stderr, "%s/", statenames[yy_start_stack[i] ]);
+ }
+ fprintf(stderr,"%s\n", statenames[YY_START]);
+ }
va_end(ap);
}
+void print_bufferstack()
+{
+ int i;
+ fputs("Buffer: ", stderr);
+ for (i = 0; i < blimit; i++) {
+ if ( bufferstack[i] == '\377' ) break;
+ putc(bufferstack[i], stderr);
+ }
+ putc('\n', stderr);
+}
+
static void debug_enter(int state, const char* statename) {
yy_push_state(state);
- if (yy_flex_debug) print_yy_stack("--ENTER(%s) : ",statename);
+ if (yy_flex_debug) {
+ print_yy_stack("--ENTER(%s) : ",statename);
+ print_bufferstack();
+ }
}
static void debug_leave(void) {
- if (yy_flex_debug) print_yy_stack("--LEAVE : ");
+ if (yy_flex_debug) {
+ print_yy_stack("--LEAVE : ");
+ print_bufferstack();
+ }
yy_pop_state();
}
@@ -311,19 +386,6 @@ static void debug_set(int state, const char* statename) {
}
#endif
-enum {flexml_max_err_msg_size = 512};
-
-static char flexml_err_msg[flexml_max_err_msg_size];
-const char * parse_err_msg()
-{
- return flexml_err_msg;
-}
-
-static void reset_parse_err_msg()
-{
- flexml_err_msg[0] = '\0';
-}
-
static void cleanup(void)
{
@@ -331,6 +393,11 @@ static void cleanup(void)
free(statenames);
statenames = NULL;
}
+ free(bufferstack);
+ bufferstack = NULL;
+
+ free(indexstack);
+ indexstack = NULL;
}
diff --git a/testbed/.#Makefile.1.1 b/testbed/.#Makefile.1.1
new file mode 100644
index 0000000..39d4539
--- /dev/null
+++ b/testbed/.#Makefile.1.1
@@ -0,0 +1,138 @@
+# $Source: /cvsroot/flexml/flexml/testbed/Makefile,v $
+
+# regression testbed Makefile
+
+#####################################################
+# Fixed definitions -- do not modify for new tests
+#####################################################
+
+include ../Makefile.defs
+
+MAKEUTILS_DIR = .
+
+# If UNIT_TESTS is test_foo
+# and test_foo_out is bar baz
+# Then the created files (that need to be deleted by 'make clean'
+# will be
+# test_foo foo.std{err,out} foo.std{err,out}.diff bar baz bar.diff baz.diff
+TEST_INTERMEDIATES = \
+ $(UNIT_TESTS) \
+ $(UNIT_TESTS:test_%=%.stdout) $(UNIT_TESTS:test_%=%.stdout.diff) \
+ $(UNIT_TESTS:test_%=.test_%.stdout.expected) \
+ $(UNIT_TESTS:test_%=%.stderr) $(UNIT_TESTS:test_%=%.stderr.diff) \
+ $(UNIT_TESTS:test_%=.test_%.stderr.expected) \
+ $(foreach var,$(UNIT_TESTS:%=%_out),$(foreach o,$($(var)),$o $(o).diff))
+
+# Compares test.out.std[out,err] with expected values
+COMPARE_OUT = $(MAKEUTILS_DIR)/CompareOut.pl
+
+CC = /usr/bin/gcc-3.3 -Wall -ansi
+CFLAGS = -O2 -g
+#FLEXDEBUG = -d
+
+FLEXML = /proj/flexml/flexml-from-cvs-20060821/flexml -s /proj/flexml/flexml-from-cvs-20060821/skel
+
+.PHONY : test
+.PHONY : clean
+
+#####################################################
+# test definitions -- add new tests here
+#####################################################
+
+EXES = mixed1 mixed-stratt
+INTERMEDIATES = $(EXES) $(EXES:%=%.c) $(EXES:%=%.l)
+
+UNIT_TESTS = \
+ test_mixed1 \
+ test_mixed-stratt
+
+
+test : $(UNIT_TESTS)
+
+# Test mixed1
+test_mixed1_cmd = ./mixed1 < mixed1.in
+test_mixed1_deps = mixed1 mixed1.in
+
+# Test mixed-stratt (mixed content + string attribute)
+test_mixed-stratt_cmd = ./mixed-stratt < mixed-stratt.in
+test_mixed-stratt_deps = mixed-stratt mixed-stratt.in
+
+#####################################################
+# test build rules -- add new build rules here
+#####################################################
+
+
+mixed1: mixed1.dtd mixed1.act
+ $(FLEXML) -b 1000 -A -amixed1.act mixed1.dtd
+ $(FLEX) -s -L -t mixed1.l > mixed1.c
+ $(CC) $(CFLAGS) -o $@ mixed1.c
+
+mixed-stratt: mixed-stratt.dtd mixed-stratt.act
+ $(FLEXML) -b 1000 -A -amixed-stratt.act mixed-stratt.dtd
+ $(FLEX) -s -L -t mixed-stratt.l > mixed-stratt.c
+ $(CC) $(CFLAGS) -o $@ mixed-stratt.c
+
+
+#####################################################
+# test infrastructure -- do not modify for new tests
+#####################################################
+
+clean :
+ rm -f $(TEST_INTERMEDIATES) $(INTERMEDIATES)
+
+# When we are building test_foo, the variable $(TEST_BASE) is "foo"
+test_% : TEST_BASE = $(@:test_%=%)
+
+ifndef distribute_deps
+# This will take a target and dependency list, and evaluate each dependency
+# individually. This only needs to be used on dependency lists that are to
+# be in an $(eval ...) function. This is a work-around for a bug in GNU Make
+# 3.80, which fails when $(eval)'ing dependency lists longer than about 160
+# characters.
+# 1. target
+# 2. dependency list
+define distribute_deps
+$(foreach dep,$(2),$(eval $(1) : $(dep)))
+endef
+endif
+
+define unit_test_deps_t
+$(1) : .$(1).stdout.expected
+$(1) : .$(1).stderr.expected
+$$(call distribute_deps,$(1),$($(1)_deps))
+endef
+
+$(foreach test,$(UNIT_TESTS),$(eval $(call unit_test_deps_t,$(test))))
+
+
+# To build .test_foo.std{err,out}.expected --
+# If foo.std{err,out}.expected exists, symlink to it
+# Else, .test_foo.std{err,out}.expected is a new empty file
+# These rules are invoked from rules in the Extradeps section.
+# They must be two separate rules (else 'make test' not idempotent
+# -- see bug #105)
+.test_%.stderr.expected:
+ @if [ -f $(@:.test_%=%) ]; \
+ then $(SYMLINK) $(@:.test_%=%) $@; \
+ else touch $@; \
+ fi
+.test_%.stdout.expected:
+ @if [ -f $(@:.test_%=%) ]; \
+ then $(SYMLINK) $(@:.test_%=%) $@; \
+ else touch $@; \
+ fi
+
+
+# Unit test rule. Expects:
+# UNIT_TESTS = test_foo test_bar (test_ prefix is necessary)
+# test_foo_cmd = command to run
+# test_foo_deps = dependencies (i.e. inputs to the test, and the executable)
+# test_foo_out = files and directories created by running the command
+# with corresponding .expected files for comparison
+
+$(UNIT_TESTS) :
+ @$(test_$(@:test_%=%)_cmd) > $(@:test_%=%).stdout \
+ 2>$(@:test_%=%).stderr || true
+ @$(PERL) $(COMPARE_OUT) -p '$($(@)_diff_prog)' -- \
+ $($(@)_diff_opts) $(@:test_%=%) $($(@)_out) | tee $@
+
diff --git a/testbed/CompareOut.pl b/testbed/CompareOut.pl
new file mode 100755
index 0000000..a30da20
--- /dev/null
+++ b/testbed/CompareOut.pl
@@ -0,0 +1,84 @@
+#!/usr/bin/env perl
+
+# Assume ARGV is ($basename @REST). Print "passed" or "failed" based on the
+# following comparisons:
+
+# Compare $basename.stderr with $basename.stderr.expected
+# pass if no difference or
+# $basename.stderr is empty and $basename.stderr.expected doesn't exist;
+# Compare $basename.stdout with $basename.stdout.expected
+# pass if no difference or
+# $basename.stdout is empty and $basename.stdout.expected doesn't exist;
+# For each file $foo in @REST
+# Compare $foo with $foo.expected
+# pass if no difference;
+
+
+# Print "passed" if all tests pass, otherwise print
+# "failed <file-that-failed>"
+
+# NOTES
+# In order to compare directories, GNU diff must be used. There
+# should probably be a test to ensure this.
+
+# $Id: CompareOut.pl,v 1.2 2006/08/21 17:33:13 wdowling Exp $
+# $Source: /cvsroot/flexml/flexml/testbed/CompareOut.pl,v $
+
+use strict;
+use Getopt::Std;
+
+my %args;
+getopts('p:', \%args);
+
+my $diff_prog = $args{'p'} || 'diff';
+
+my $diff_opt = "";
+if ($ARGV[0] =~ /^-/) {
+ $diff_opt = shift;
+}
+
+my $basename = shift;
+
+my $diff_cmd = "$diff_prog $diff_opt";
+
+my $retcode;
+my $fail_file;
+my $made_stdout = 0;
+my $made_stderr = 0;
+
+# Compare basename.stderr to basename.stderr.expected
+if (! -f "$basename.stderr.expected") {
+ system("touch $basename.stderr.expected");
+ $made_stderr = 1;
+}
+
+$retcode =
+ system("$diff_cmd $basename.stderr $basename.stderr.expected " .
+ "> $basename.stderr.diff 2>/dev/null");
+system("rm -f $basename.stderr.expected") if $made_stderr;
+
+$fail_file = "$basename.stderr" if $retcode;
+
+# Compare basename.stdout to basename.stdout.expected
+if ($retcode == 0) {
+ if (! -f "$basename.stdout.expected") {
+ system("touch $basename.stdout.expected");
+ $made_stdout = 1;
+ }
+
+ $retcode =
+ system("$diff_cmd $basename.stdout $basename.stdout.expected " .
+ "> $basename.stdout.diff 2>/dev/null");
+ system("rm -f $basename.stdout.expected") if $made_stdout;
+
+ $fail_file = "$basename.stdout" if $retcode;
+}
+
+while (($retcode == 0) && @ARGV) {
+ my $file = shift;
+ # compare file with file.expected
+ $retcode = system("$diff_cmd $file $file.expected >$file.diff 2>/dev/null");
+ $fail_file = $file if $retcode;
+}
+
+print ($retcode ? "failed $fail_file\n" : "passed $basename\n");
diff --git a/testbed/Makefile b/testbed/Makefile
new file mode 100644
index 0000000..9410be0
--- /dev/null
+++ b/testbed/Makefile
@@ -0,0 +1,200 @@
+# $Source: /cvsroot/flexml/flexml/testbed/Makefile,v $
+
+# regression testbed Makefile
+
+#####################################################
+# Fixed definitions -- do not modify for new tests
+#####################################################
+
+include ../Makefile.defs
+
+MAKEUTILS_DIR = .
+
+# If UNIT_TESTS is test_foo
+# and test_foo_out is bar baz
+# Then the created files (that need to be deleted by 'make clean'
+# will be
+# test_foo foo.std{err,out} foo.std{err,out}.diff bar baz bar.diff baz.diff
+TEST_INTERMEDIATES = \
+ $(UNIT_TESTS) \
+ $(UNIT_TESTS:test_%=%.stdout) $(UNIT_TESTS:test_%=%.stdout.diff) \
+ $(UNIT_TESTS:test_%=.test_%.stdout.expected) \
+ $(UNIT_TESTS:test_%=%.stderr) $(UNIT_TESTS:test_%=%.stderr.diff) \
+ $(UNIT_TESTS:test_%=.test_%.stderr.expected) \
+ $(foreach var,$(UNIT_TESTS:%=%_out),$(foreach o,$($(var)),$o $(o).diff))
+
+# Compares test.out.std[out,err] with expected values
+COMPARE_OUT = $(MAKEUTILS_DIR)/CompareOut.pl
+
+#CC = /usr/bin/gcc-3.3 -Wall
+#CFLAGS = -O2 -g
+#FLEXDEBUG = -d
+
+FLEXML = ../flexml -s ../skel -T../flexml-act
+
+.PHONY : test
+.PHONY : clean
+
+#####################################################
+# test definitions -- add new tests here
+#####################################################
+
+EXES = \
+ biparser \
+ init_header \
+ missing-att \
+ mixed-enumatt \
+ mixed-enumatt2 \
+ mixed-stratt \
+ mixed-stratt-def \
+ mixed1 \
+ multi-parser-run
+
+
+INTERMEDIATES = $(EXES) $(EXES:%=%.c) $(EXES:%=%.l)
+
+# leave this alphabetically sorted for easy scanning
+UNIT_TESTS = \
+ test_biparser \
+ test_init_header \
+ test_missing-att \
+ test_mixed-enumatt \
+ test_mixed-enumatt2 \
+ test_mixed-stratt \
+ test_mixed-stratt-def \
+ test_mixed1 \
+ test_multi-parser-run
+
+test : $(UNIT_TESTS)
+
+# Test init_header
+test_init_header_cmd = ./init_header < init_header.in
+test_init_header_deps = init_header init_header.in
+
+# Test missing REQUIRED attribute
+test_missing-att_cmd = ./missing-att < missing-att.in
+test_missing-att_deps = missing-att missing-att.in
+
+# Test mixed1
+test_mixed1_cmd = ./mixed1 < mixed1.in
+test_mixed1_deps = mixed1 mixed1.in
+
+# Test mixed-enumatt (mixed content + enumerated attribute)
+test_mixed-enumatt_cmd = ./mixed-enumatt < mixed-enumatt.in
+test_mixed-enumatt_deps = mixed-enumatt mixed-enumatt.in
+
+# Test mixed-enumatt2 (mixed content + enumerated attribute, eval'ed in end tag)
+test_mixed-enumatt2_cmd = ./mixed-enumatt2 < mixed-enumatt2.in
+test_mixed-enumatt2_deps = mixed-enumatt2 mixed-enumatt2.in
+
+# Test mixed-stratt (mixed content + string attribute)
+test_mixed-stratt_cmd = ./mixed-stratt < mixed-stratt.in
+test_mixed-stratt_deps = mixed-stratt mixed-stratt.in
+
+# Test mixed-stratt (mixed content + default string attribute)
+test_mixed-stratt-def_cmd = ./mixed-stratt-def < mixed-stratt-def.in
+test_mixed-stratt-def_deps = mixed-stratt-def mixed-stratt-def.in
+
+# Test multi-parser-run (Run the parser several times on "different" files)
+test_multi-parser-run_cmd = ./multi-parser-run multi-parser-run.in
+test_multi-parser-run_deps = multi-parser-run multi-parser-run.in
+
+# Test biparser (Have two parsers in the same code)
+test_biparser_cmd = ./biparser biparser-one.in biparser-two.in
+test_biparser_deps = biparser biparser-one.in biparser-two.in
+
+biparser: biparser-one.dtd biparser-two.dtd biparser.precious.c
+ for n in one two ; do \
+ $(FLEXML) -P$$n -H biparser-$$n.h -L biparser-$$n.dtd; \
+ $(FLEXML) -P$$n -S biparser-$$n.l -L biparser-$$n.dtd; \
+ $(FLEX) -s -L -P$${n}_ -obiparser-$$n.c biparser-$$n.l; \
+ done
+ $(CC) $(CFLAGS) -o biparser \
+ biparser-one.c biparser-two.c \
+ biparser.precious.c
+CLEANFILES+= biparser-one.h biparser-one.l biparser-one.c \
+ biparser-two.h biparser-two.l biparser-two.c
+
+init_header : init_header.act init_header.dtd init_header.h
+ $(FLEXML) -b 1000 -A -i$@.h -a$@.act $@.dtd
+ $(FLEX) -s -L -o$@.c $@.l
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+% : %.dtd %.act
+ $(FLEXML) -b 1000 -A -a$@.act $@.dtd
+ $(FLEX) -s -L -o$@.c $@.l
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+##############################################################
+# test build rules -- add override build rules here if needed
+##############################################################
+
+#mixed1: mixed1.dtd mixed1.act
+# $(FLEXML) -b 500 -A -amixed1.act mixed1.dtd
+# $(FLEX) -s -L -o mixed1.c mixed1.l > mixed1.c
+# $(CC) $(CFLAGS) -o $@ mixed1.c
+
+
+#####################################################
+# test infrastructure -- do not modify for new tests
+#####################################################
+
+clean :
+ rm -f $(TEST_INTERMEDIATES) $(INTERMEDIATES) $(CLEANFILES)
+
+# When we are building test_foo, the variable $(TEST_BASE) is "foo"
+test_% : TEST_BASE = $(@:test_%=%)
+
+ifndef distribute_deps
+# This will take a target and dependency list, and evaluate each dependency
+# individually. This only needs to be used on dependency lists that are to
+# be in an $(eval ...) function. This is a work-around for a bug in GNU Make
+# 3.80, which fails when $(eval)'ing dependency lists longer than about 160
+# characters.
+# 1. target
+# 2. dependency list
+define distribute_deps
+$(foreach dep,$(2),$(eval $(1) : $(dep)))
+endef
+endif
+
+define unit_test_deps_t
+$(1) : .$(1).stdout.expected
+$(1) : .$(1).stderr.expected
+$$(call distribute_deps,$(1),$($(1)_deps))
+endef
+
+$(foreach test,$(UNIT_TESTS),$(eval $(call unit_test_deps_t,$(test))))
+
+
+# To build .test_foo.std{err,out}.expected --
+# If foo.std{err,out}.expected exists, symlink to it
+# Else, .test_foo.std{err,out}.expected is a new empty file
+# These rules are invoked from rules in the Extradeps section.
+# They must be two separate rules (else 'make test' not idempotent
+# -- see bug #105)
+.test_%.stderr.expected:
+ @if [ -f $(@:.test_%=%) ]; \
+ then $(SYMLINK) $(@:.test_%=%) $@; \
+ else touch $@; \
+ fi
+.test_%.stdout.expected:
+ @if [ -f $(@:.test_%=%) ]; \
+ then $(SYMLINK) $(@:.test_%=%) $@; \
+ else touch $@; \
+ fi
+
+
+# Unit test rule. Expects:
+# UNIT_TESTS = test_foo test_bar (test_ prefix is necessary)
+# test_foo_cmd = command to run
+# test_foo_deps = dependencies (i.e. inputs to the test, and the executable)
+# test_foo_out = files and directories created by running the command
+# with corresponding .expected files for comparison
+
+$(UNIT_TESTS) :
+ @$(test_$(@:test_%=%)_cmd) > $(@:test_%=%).stdout \
+ 2>$(@:test_%=%).stderr || true
+ @$(PERL) $(COMPARE_OUT) -p '$($(@)_diff_prog)' -- \
+ $($(@)_diff_opts) $(@:test_%=%) $($(@)_out) | tee $@
+
diff --git a/testbed/biparser-one.dtd b/testbed/biparser-one.dtd
new file mode 100644
index 0000000..abf24ac
--- /dev/null
+++ b/testbed/biparser-one.dtd
@@ -0,0 +1,2 @@
+<!ELEMENT foo (#PCDATA|bar)*>
+<!ELEMENT bar (#PCDATA)>
diff --git a/testbed/biparser-one.in b/testbed/biparser-one.in
new file mode 100644
index 0000000..1cfc6b8
--- /dev/null
+++ b/testbed/biparser-one.in
@@ -0,0 +1,2 @@
+<!DOCTYPE foo SYSTEM "biparser-one.dtd">
+<foo>012<bar>456789ab</bar>cdefghijklmn</foo>
diff --git a/testbed/biparser-two.dtd b/testbed/biparser-two.dtd
new file mode 100644
index 0000000..9d2bfab
--- /dev/null
+++ b/testbed/biparser-two.dtd
@@ -0,0 +1,3 @@
+<!ELEMENT toto (#PCDATA|tutu)*>
+<!ELEMENT tutu (#PCDATA)>
+
diff --git a/testbed/biparser-two.in b/testbed/biparser-two.in
new file mode 100644
index 0000000..37b210b
--- /dev/null
+++ b/testbed/biparser-two.in
@@ -0,0 +1,2 @@
+<!DOCTYPE toto SYSTEM "biparser-two.dtd">
+<toto>012<tutu>456789ab</tutu>cdefghijklmn</toto>
diff --git a/testbed/biparser.precious.c b/testbed/biparser.precious.c
new file mode 100644
index 0000000..6a0cc3f
--- /dev/null
+++ b/testbed/biparser.precious.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+
+#include "biparser-one.h"
+#include "biparser-two.h"
+
+/* XML application entry points.
+ Should be generated from two action files, but I wasn't succesfull in that area yet [Mt] */
+void STag_one_foo(void) {}
+void ETag_one_foo(void) {printf("foo pcdata: %s\n", one_pcdata);}
+void STag_one_bar(void) {}
+void ETag_one_bar(void) {printf("bar pcdata: %s\n", one_pcdata);}
+
+void STag_two_toto(void) {}
+void ETag_two_toto(void) {printf("toto pcdata: %s\n", two_pcdata);}
+void STag_two_tutu(void) {}
+void ETag_two_tutu(void) {printf("tutu pcdata: %s\n", two_pcdata);}
+
+/* Parsers control.
+ Should probably be added to the .h */
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int one_lex (void);
+extern void one_restart (FILE *input_file );
+extern void one__switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE one__create_buffer (FILE *file,int size );
+extern void one__delete_buffer (YY_BUFFER_STATE b );
+extern void one__flush_buffer (YY_BUFFER_STATE b );
+extern void one_push_buffer_state (YY_BUFFER_STATE new_buffer );
+extern void one_pop_buffer_state (void );
+
+extern int two_lex (void);
+extern void two_restart (FILE *input_file );
+extern void two__switch_to_buffer (YY_BUFFER_STATE new_buffer );
+extern YY_BUFFER_STATE two__create_buffer (FILE *file,int size );
+extern void two__delete_buffer (YY_BUFFER_STATE b );
+extern void two__flush_buffer (YY_BUFFER_STATE b );
+extern void two_push_buffer_state (YY_BUFFER_STATE new_buffer );
+extern void two_pop_buffer_state (void );
+
+
+int main(int argc, char **argv) {
+ FILE *infile;
+ YY_BUFFER_STATE buff;
+ int retval;
+
+ printf("Parse biparser-one.in\n");
+ infile=fopen("biparser-one.in","r");
+ buff=one__create_buffer(infile,10);
+ one__switch_to_buffer(buff);
+ retval = one_lex();
+ one__delete_buffer(buff);
+ fclose(infile);
+
+ printf("Parse biparser-two.in\n");
+ infile=fopen("biparser-two.in","r");
+ buff=two__create_buffer(infile,10);
+ two__switch_to_buffer(buff);
+ retval = two_lex() || retval;
+ two__delete_buffer(buff);
+ fclose(infile);
+
+ return retval;
+}
+
+
+
diff --git a/testbed/biparser.stdout.expected b/testbed/biparser.stdout.expected
new file mode 100644
index 0000000..d0efb8b
--- /dev/null
+++ b/testbed/biparser.stdout.expected
@@ -0,0 +1,6 @@
+Parse biparser-one.in
+bar pcdata: 456789ab
+foo pcdata: 012cdefghijklmn
+Parse biparser-two.in
+tutu pcdata: 456789ab
+toto pcdata: 012cdefghijklmn
diff --git a/testbed/core b/testbed/core
new file mode 100644
index 0000000..c6d2199
--- /dev/null
+++ b/testbed/core
Binary files differ
diff --git a/testbed/init_header.act b/testbed/init_header.act
new file mode 100644
index 0000000..ae0855c
--- /dev/null
+++ b/testbed/init_header.act
@@ -0,0 +1,27 @@
+<!DOCTYPE actions SYSTEM "flexml-act.dtd">
+<actions>
+
+<top><![CDATA[
+#include <stdio.h>
+]]></top>
+
+<end tag='bar'><![CDATA[
+ printf("bar pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<end tag='foo'><![CDATA[
+ printf("foo pcdata: %s\nparam was %d\n", {#PCDATA}, static_lexer_param);
+]]></end>
+
+
+<main><![CDATA[
+int main(int argc, char **argv)
+{
+ int retval = lexer(7);
+ printf("retval = %d\n", retval);
+ return retval;
+}
+]]></main>
+
+</actions>
diff --git a/testbed/init_header.dtd b/testbed/init_header.dtd
new file mode 100644
index 0000000..dd51f3b
--- /dev/null
+++ b/testbed/init_header.dtd
@@ -0,0 +1,4 @@
+
+<!ELEMENT foo (#PCDATA|bar)*>
+<!ELEMENT bar (#PCDATA)>
+<!-- <!ATTLIST bar batt CDATA #REQUIRED> -->
diff --git a/testbed/init_header.h b/testbed/init_header.h
new file mode 100644
index 0000000..80beccf
--- /dev/null
+++ b/testbed/init_header.h
@@ -0,0 +1,3 @@
+/* header file to be included at end of generated %{ ... %} section */
+#define YY_DECL static int static_lexer_param; int lexer(int lexer_param)
+#define YY_USER_INIT static_lexer_param = lexer_param;
diff --git a/testbed/init_header.in b/testbed/init_header.in
new file mode 100644
index 0000000..051a356
--- /dev/null
+++ b/testbed/init_header.in
@@ -0,0 +1,2 @@
+<!DOCTYPE foo SYSTEM "init_header.dtd">
+<foo>012<bar>456789ab</bar>cdefghijklmn</foo>
diff --git a/testbed/init_header.stdout.expected b/testbed/init_header.stdout.expected
new file mode 100644
index 0000000..7d60070
--- /dev/null
+++ b/testbed/init_header.stdout.expected
@@ -0,0 +1,4 @@
+bar pcdata: 456789ab
+foo pcdata: 012cdefghijklmn
+param was 7
+retval = 0
diff --git a/testbed/missing-att.act b/testbed/missing-att.act
new file mode 100644
index 0000000..0afbd24
--- /dev/null
+++ b/testbed/missing-att.act
@@ -0,0 +1,32 @@
+<!DOCTYPE actions SYSTEM "flexml-act.dtd">
+<actions>
+
+<top><![CDATA[
+#include <stdio.h>
+]]></top>
+
+<start tag='bar'><![CDATA[
+ printf("bar att: %s\n", {batt});
+]]></start>
+
+
+<end tag='bar'><![CDATA[
+ printf("bar pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<end tag='foo'><![CDATA[
+ printf("foo pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<main><![CDATA[
+int main(int argc, char **argv)
+{
+ int retval = yylex();
+ printf("retval = %d\n", retval);
+ return retval;
+}
+]]></main>
+
+</actions>
diff --git a/testbed/missing-att.dtd b/testbed/missing-att.dtd
new file mode 100644
index 0000000..2ec03fa
--- /dev/null
+++ b/testbed/missing-att.dtd
@@ -0,0 +1,4 @@
+<!-- test mixed content elements with string sttributes -->
+<!ELEMENT foo (#PCDATA|bar)*>
+<!ELEMENT bar (#PCDATA)>
+<!ATTLIST bar batt CDATA #REQUIRED>
diff --git a/testbed/missing-att.in b/testbed/missing-att.in
new file mode 100644
index 0000000..970ec5f
--- /dev/null
+++ b/testbed/missing-att.in
@@ -0,0 +1,2 @@
+<!DOCTYPE foo SYSTEM "missing-att.dtd">
+<foo>012<bar>456789ab</bar>cdefghijklmn</foo>
diff --git a/testbed/missing-att.stderr.expected b/testbed/missing-att.stderr.expected
new file mode 100644
index 0000000..05a0230
--- /dev/null
+++ b/testbed/missing-att.stderr.expected
@@ -0,0 +1 @@
+Invalid XML (state 13): Required attribute `batt' not set for `bar' element.
diff --git a/testbed/missing-att.stdout.expected b/testbed/missing-att.stdout.expected
new file mode 100644
index 0000000..a086c81
--- /dev/null
+++ b/testbed/missing-att.stdout.expected
@@ -0,0 +1 @@
+retval = 1
diff --git a/testbed/mixed-enumatt.act b/testbed/mixed-enumatt.act
new file mode 100644
index 0000000..5b22569
--- /dev/null
+++ b/testbed/mixed-enumatt.act
@@ -0,0 +1,53 @@
+<!DOCTYPE actions SYSTEM "flexml-act.dtd">
+<actions>
+
+<top><![CDATA[
+#include <stdio.h>
+]]></top>
+
+<start tag='reqatt'><![CDATA[
+ printf("reqatt att: (%s)\n",
+ {att} == {att=val1} ? "val1" :
+ {att} == {att=val2} ? "val2" :
+ {att} == {!att} ? "no att given" : "error in attribute");
+]]></start>
+<start tag='defatt'><![CDATA[
+ printf("defatt att: (%s)\n",
+ {att} == {att=val1} ? "val1" :
+ {att} == {att=val2} ? "val2" :
+ {att} == {!att} ? "no att given" : "error in attribute");
+]]></start>
+<start tag='optatt'><![CDATA[
+ printf("optatt att: (%s)\n",
+ {att} == {att=val1} ? "val1" :
+ {att} == {att=val2} ? "val2" :
+ {att} == {!att} ? "no att given" : "error in attribute");
+]]></start>
+
+
+<end tag='reqatt'><![CDATA[
+ printf("reqatt pcdata: %s\n", {#PCDATA});
+]]></end>
+<end tag='defatt'><![CDATA[
+ printf("defatt pcdata: %s\n", {#PCDATA});
+]]></end>
+<end tag='optatt'><![CDATA[
+ printf("optatt pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<end tag='foo'><![CDATA[
+ printf("foo pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<main><![CDATA[
+int main(int argc, char **argv)
+{
+ int retval = yylex();
+ printf("retval = %d\n", retval);
+ return retval;
+}
+]]></main>
+
+</actions>
diff --git a/testbed/mixed-enumatt.dtd b/testbed/mixed-enumatt.dtd
new file mode 100644
index 0000000..c82c098
--- /dev/null
+++ b/testbed/mixed-enumatt.dtd
@@ -0,0 +1,8 @@
+
+<!ELEMENT foo (#PCDATA|reqatt|defatt|optatt)*>
+<!ELEMENT reqatt (#PCDATA)>
+<!ATTLIST reqatt att (val1 | val2 ) #REQUIRED>
+<!ELEMENT defatt (#PCDATA)>
+<!ATTLIST defatt att (val1 | val2 ) 'val2'>
+<!ELEMENT optatt (#PCDATA)>
+<!ATTLIST optatt att (val1 | val2 ) #IMPLIED>
diff --git a/testbed/mixed-enumatt.in b/testbed/mixed-enumatt.in
new file mode 100644
index 0000000..51f55b4
--- /dev/null
+++ b/testbed/mixed-enumatt.in
@@ -0,0 +1,8 @@
+<!DOCTYPE foo SYSTEM "mixed-enumatt.dtd">
+<foo>foo start data
+ <reqatt att="val1">reqatt data</reqatt>
+ <defatt att="val1">defatt data</defatt>
+ <defatt>defatt data</defatt>
+ <optatt att="val1">optatt data</optatt>
+ <optatt>optatt data</optatt>
+foo end data.</foo>
diff --git a/testbed/mixed-enumatt.stdout.expected b/testbed/mixed-enumatt.stdout.expected
new file mode 100644
index 0000000..db43a9d
--- /dev/null
+++ b/testbed/mixed-enumatt.stdout.expected
@@ -0,0 +1,18 @@
+reqatt att: (val1)
+reqatt pcdata: reqatt data
+defatt att: (val1)
+defatt pcdata: defatt data
+defatt att: (val2)
+defatt pcdata: defatt data
+optatt att: (val1)
+optatt pcdata: optatt data
+optatt att: (no att given)
+optatt pcdata: optatt data
+foo pcdata: foo start data
+
+
+
+
+
+foo end data.
+retval = 0
diff --git a/testbed/mixed-enumatt2.act b/testbed/mixed-enumatt2.act
new file mode 100644
index 0000000..6ec197d
--- /dev/null
+++ b/testbed/mixed-enumatt2.act
@@ -0,0 +1,47 @@
+<!DOCTYPE actions SYSTEM "flexml-act.dtd">
+<actions>
+
+<top><![CDATA[
+#include <stdio.h>
+]]></top>
+
+<end tag='reqatt'><![CDATA[
+ printf("reqatt pcdata: %s\n", {#PCDATA});
+ printf("reqatt att: (%s)\n",
+ {att} == {att=val1} ? "val1" :
+ {att} == {att=val2} ? "val2" :
+ {att} == {!att} ? "no att given" : "error in attribute");
+]]></end>
+<end tag='defatt'><![CDATA[
+ printf("defatt pcdata: %s\n", {#PCDATA});
+ printf("defatt att: (%s)\n",
+ {att} == {att=val1} ? "val1" :
+ {att} == {att=val2} ? "val2" :
+ {att} == {!att} ? "no att given" : "error in attribute");
+
+]]></end>
+<end tag='optatt'><![CDATA[
+ printf("optatt pcdata: %s\n", {#PCDATA});
+ printf("optatt att: (%s)\n",
+ {att} == {att=val1} ? "val1" :
+ {att} == {att=val2} ? "val2" :
+ {att} == {!att} ? "no att given" : "error in attribute");
+
+]]></end>
+
+
+<end tag='foo'><![CDATA[
+ printf("foo pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<main><![CDATA[
+int main(int argc, char **argv)
+{
+ int retval = yylex();
+ printf("retval = %d\n", retval);
+ return retval;
+}
+]]></main>
+
+</actions>
diff --git a/testbed/mixed-enumatt2.dtd b/testbed/mixed-enumatt2.dtd
new file mode 100644
index 0000000..c82c098
--- /dev/null
+++ b/testbed/mixed-enumatt2.dtd
@@ -0,0 +1,8 @@
+
+<!ELEMENT foo (#PCDATA|reqatt|defatt|optatt)*>
+<!ELEMENT reqatt (#PCDATA)>
+<!ATTLIST reqatt att (val1 | val2 ) #REQUIRED>
+<!ELEMENT defatt (#PCDATA)>
+<!ATTLIST defatt att (val1 | val2 ) 'val2'>
+<!ELEMENT optatt (#PCDATA)>
+<!ATTLIST optatt att (val1 | val2 ) #IMPLIED>
diff --git a/testbed/mixed-enumatt2.in b/testbed/mixed-enumatt2.in
new file mode 100644
index 0000000..fd90810
--- /dev/null
+++ b/testbed/mixed-enumatt2.in
@@ -0,0 +1,8 @@
+<!DOCTYPE foo SYSTEM "mixed-enumatt2.dtd">
+<foo>foo start data
+ <reqatt att="val1">reqatt data</reqatt>
+ <defatt att="val1">defatt data</defatt>
+ <defatt>defatt data</defatt>
+ <optatt att="val1">optatt data</optatt>
+ <optatt>optatt data</optatt>
+foo end data.</foo>
diff --git a/testbed/mixed-enumatt2.stdout.expected b/testbed/mixed-enumatt2.stdout.expected
new file mode 100644
index 0000000..0e5c5b5
--- /dev/null
+++ b/testbed/mixed-enumatt2.stdout.expected
@@ -0,0 +1,18 @@
+reqatt pcdata: reqatt data
+reqatt att: (val1)
+defatt pcdata: defatt data
+defatt att: (val1)
+defatt pcdata: defatt data
+defatt att: (val2)
+optatt pcdata: optatt data
+optatt att: (val1)
+optatt pcdata: optatt data
+optatt att: (no att given)
+foo pcdata: foo start data
+
+
+
+
+
+foo end data.
+retval = 0
diff --git a/testbed/mixed-stratt-def.act b/testbed/mixed-stratt-def.act
new file mode 100644
index 0000000..2f6a9ea
--- /dev/null
+++ b/testbed/mixed-stratt-def.act
@@ -0,0 +1,33 @@
+<!DOCTYPE actions SYSTEM "flexml-act.dtd">
+<actions>
+
+<top><![CDATA[
+#include <stdio.h>
+]]></top>
+
+<start tag='bar'><![CDATA[
+ printf("bar batt: (%s) batt2: (%s) batt3: (%s)\n",
+ {batt}, {batt2}, {batt3});
+]]></start>
+
+
+<end tag='bar'><![CDATA[
+ printf("bar pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<end tag='foo'><![CDATA[
+ printf("foo pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<main><![CDATA[
+int main(int argc, char **argv)
+{
+ int retval = yylex();
+ printf("retval = %d\n", retval);
+ return retval;
+}
+]]></main>
+
+</actions>
diff --git a/testbed/mixed-stratt-def.dtd b/testbed/mixed-stratt-def.dtd
new file mode 100644
index 0000000..55b67c7
--- /dev/null
+++ b/testbed/mixed-stratt-def.dtd
@@ -0,0 +1,7 @@
+<!-- test mixed content elements with default string sttributes -->
+<!ELEMENT foo (#PCDATA|bar)*>
+<!ELEMENT bar (#PCDATA)>
+<!ATTLIST bar batt CDATA 'default value'
+ batt2 CDATA 'second default value'
+ batt3 CDATA 'third default value'
+>
diff --git a/testbed/mixed-stratt-def.in b/testbed/mixed-stratt-def.in
new file mode 100644
index 0000000..9f5846d
--- /dev/null
+++ b/testbed/mixed-stratt-def.in
@@ -0,0 +1,6 @@
+<!DOCTYPE foo SYSTEM "mixed-stratt-def.dtd">
+<foo>012
+ <bar>bar data 1</bar>
+ <bar batt2=' non-default 2'>bar data 2</bar>
+ <bar batt3 = "non-default with single-quote(')">bar data 3</bar>
+ cdefghijklmn</foo>
diff --git a/testbed/mixed-stratt-def.stdout.expected b/testbed/mixed-stratt-def.stdout.expected
new file mode 100644
index 0000000..17e021b
--- /dev/null
+++ b/testbed/mixed-stratt-def.stdout.expected
@@ -0,0 +1,12 @@
+bar batt: (default value) batt2: (second default value) batt3: (third default value)
+bar pcdata: bar data 1
+bar batt: (default value) batt2: ( non-default 2) batt3: (third default value)
+bar pcdata: bar data 2
+bar batt: (default value) batt2: (second default value) batt3: (non-default with single-quote('))
+bar pcdata: bar data 3
+foo pcdata: 012
+
+
+
+ cdefghijklmn
+retval = 0
diff --git a/testbed/mixed-stratt.act b/testbed/mixed-stratt.act
new file mode 100644
index 0000000..0afbd24
--- /dev/null
+++ b/testbed/mixed-stratt.act
@@ -0,0 +1,32 @@
+<!DOCTYPE actions SYSTEM "flexml-act.dtd">
+<actions>
+
+<top><![CDATA[
+#include <stdio.h>
+]]></top>
+
+<start tag='bar'><![CDATA[
+ printf("bar att: %s\n", {batt});
+]]></start>
+
+
+<end tag='bar'><![CDATA[
+ printf("bar pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<end tag='foo'><![CDATA[
+ printf("foo pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<main><![CDATA[
+int main(int argc, char **argv)
+{
+ int retval = yylex();
+ printf("retval = %d\n", retval);
+ return retval;
+}
+]]></main>
+
+</actions>
diff --git a/testbed/mixed-stratt.dtd b/testbed/mixed-stratt.dtd
new file mode 100644
index 0000000..2ec03fa
--- /dev/null
+++ b/testbed/mixed-stratt.dtd
@@ -0,0 +1,4 @@
+<!-- test mixed content elements with string sttributes -->
+<!ELEMENT foo (#PCDATA|bar)*>
+<!ELEMENT bar (#PCDATA)>
+<!ATTLIST bar batt CDATA #REQUIRED>
diff --git a/testbed/mixed-stratt.in b/testbed/mixed-stratt.in
new file mode 100644
index 0000000..22d9e90
--- /dev/null
+++ b/testbed/mixed-stratt.in
@@ -0,0 +1,2 @@
+<!DOCTYPE foo SYSTEM "mixed-stratt.dtd">
+<foo>012<bar batt="batt1">456789ab</bar>cdefghijklmn</foo>
diff --git a/testbed/mixed-stratt.stdout.expected b/testbed/mixed-stratt.stdout.expected
new file mode 100644
index 0000000..a476ed7
--- /dev/null
+++ b/testbed/mixed-stratt.stdout.expected
@@ -0,0 +1,4 @@
+bar att: batt1
+bar pcdata: 456789ab
+foo pcdata: 012cdefghijklmn
+retval = 0
diff --git a/testbed/mixed1.act b/testbed/mixed1.act
new file mode 100644
index 0000000..7cafafa
--- /dev/null
+++ b/testbed/mixed1.act
@@ -0,0 +1,27 @@
+<!DOCTYPE actions SYSTEM "flexml-act.dtd">
+<actions>
+
+<top><![CDATA[
+#include <stdio.h>
+]]></top>
+
+<end tag='bar'><![CDATA[
+ printf("bar pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<end tag='foo'><![CDATA[
+ printf("foo pcdata: %s\n", {#PCDATA});
+]]></end>
+
+
+<main><![CDATA[
+int main(int argc, char **argv)
+{
+ int retval = yylex();
+ printf("retval = %d\n", retval);
+ return retval;
+}
+]]></main>
+
+</actions>
diff --git a/testbed/mixed1.dtd b/testbed/mixed1.dtd
new file mode 100644
index 0000000..dd51f3b
--- /dev/null
+++ b/testbed/mixed1.dtd
@@ -0,0 +1,4 @@
+
+<!ELEMENT foo (#PCDATA|bar)*>
+<!ELEMENT bar (#PCDATA)>
+<!-- <!ATTLIST bar batt CDATA #REQUIRED> -->
diff --git a/testbed/mixed1.in b/testbed/mixed1.in
new file mode 100644
index 0000000..c9045bc
--- /dev/null
+++ b/testbed/mixed1.in
@@ -0,0 +1,2 @@
+<!DOCTYPE foo SYSTEM "mixed1.dtd">
+<foo>012<bar>456789ab</bar>cdefghijklmn</foo>
diff --git a/testbed/mixed1.stdout.expected b/testbed/mixed1.stdout.expected
new file mode 100644
index 0000000..1c29c6a
--- /dev/null
+++ b/testbed/mixed1.stdout.expected
@@ -0,0 +1,3 @@
+bar pcdata: 456789ab
+foo pcdata: 012cdefghijklmn
+retval = 0
diff --git a/testbed/multi-parser-run.act b/testbed/multi-parser-run.act
new file mode 100644
index 0000000..7e71408
--- /dev/null
+++ b/testbed/multi-parser-run.act
@@ -0,0 +1,38 @@
+<!DOCTYPE actions SYSTEM "flexml-act.dtd">
+<actions>
+
+<top><![CDATA[
+#include <stdio.h>
+]]></top>
+
+<start tag='foo'><![CDATA[
+ printf("foo attributes name='%s' toz='%s' gaz='%s'\n", {name}, {toz}, {gaz});
+]]></start>
+
+<start tag='bar'><![CDATA[
+ printf("bar attributes name='%s'\n", {name});
+]]></start>
+
+<main><![CDATA[
+int main(int argc, char **argv) {
+ FILE *infile;
+ YY_BUFFER_STATE buff;
+ int retval;
+
+ int i;
+
+ for (i=0; i<3; i++) {
+ printf("Run %d\n",i);
+ infile=fopen(argv[1],"r");
+ buff=yy_create_buffer(infile,10);
+ yy_switch_to_buffer(buff);
+ retval = yylex();
+ yy_delete_buffer(buff);
+ fclose(infile);
+ }
+
+ return retval;
+}
+]]></main>
+
+</actions>
diff --git a/testbed/multi-parser-run.dtd b/testbed/multi-parser-run.dtd
new file mode 100644
index 0000000..a97c9a3
--- /dev/null
+++ b/testbed/multi-parser-run.dtd
@@ -0,0 +1,7 @@
+<!ELEMENT foo (bar)*>
+<!ATTLIST foo name CDATA #REQUIRED>
+<!ATTLIST foo toz CDATA "0.0">
+<!ATTLIST foo gaz CDATA "0.0">
+
+<!ELEMENT bar EMPTY>
+<!ATTLIST bar name CDATA #REQUIRED>
diff --git a/testbed/multi-parser-run.in b/testbed/multi-parser-run.in
new file mode 100644
index 0000000..ede99c0
--- /dev/null
+++ b/testbed/multi-parser-run.in
@@ -0,0 +1,2 @@
+<!DOCTYPE foo SYSTEM "multi-parser-run.dtd">
+<foo name="toto"><bar name="tutu"/> </foo>
diff --git a/testbed/multi-parser-run.stdout.expected b/testbed/multi-parser-run.stdout.expected
new file mode 100644
index 0000000..3b16573
--- /dev/null
+++ b/testbed/multi-parser-run.stdout.expected
@@ -0,0 +1,9 @@
+Run 0
+foo attributes name='toto' toz='0.0' gaz='0.0'
+bar attributes name='tutu'
+Run 1
+foo attributes name='toto' toz='0.0' gaz='0.0'
+bar attributes name='tutu'
+Run 2
+foo attributes name='toto' toz='0.0' gaz='0.0'
+bar attributes name='tutu'