Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
automatic updates
[simgrid.git] / src / surf / surfxml.l
index 1c69a55..b2ca27a 100644 (file)
@@ -1,12 +1,21 @@
 /* Validating XML processor for surfxml.dtd.
- * Generated 2005/01/05 14:22:05.
+ * Generated 2005/06/21 12:23:56.
  *
- * This program was generated with the FleXML XML processor generator,
- * (Id: flexml.pl,v 1.35 2005/01/05 06:29:58 legranda Exp).
- * Copyright © 1999 Kristoffer Rose.  All rights reserved.
+ * This program was generated with the FleXML XML processor generator.
+ * FleXML is Copyright © 1999-2005 Kristoffer Rose.  All rights reserved.
+ * (Id: flexml.pl,v 1.44 2005/02/23 23:08:16 mquinson Exp).
+ * 
+ * There are two, intertwined parts to this program, part A and part B.
  *
- * You can redistribute and/or modify this program provided the following
- * two conditions hold:
+ * Part A
+ * ------
+ * 
+ * Some parts, here collectively called "Part A", are found in the 
+ * FleXML package.  They are Copyright © 1999-2005 Kristoffer Rose. 
+ * All rights reserved.
+ *
+ * You can redistribute, use, perform, display and/or modify "Part A"
+ * provided the following two conditions hold:
  *
  * 1. The program is distributed WITHOUT ANY WARRANTY from the author of
  *    FleXML; without even the implied warranty of MERCHANTABILITY or
  * Notice that these are explicit rights granted to you for files
  * generated by the FleXML system.  For your rights in connection with
  * the FleXML system itself please consult the GNU General Public License.
+ * 
+ * Part B
+ * ------
+ * 
+ * The other parts, here collectively called "Part B", and which came 
+ * from the DTD used by FleXML to generate this program, can be 
+ * distributed (or not, as the case may be) under the terms of whoever
+ * wrote them, provided these terms respect and obey the two conditions 
+ * above under the heading "Part A".
+ *
+ * The author of and contributors to FleXML specifically disclaim
+ * any copyright interest in "Part B", unless "Part B" was written 
+ * by the author of or contributors to FleXML.
+ * 
  */
 
 %{
 
 /* Version strings. */
 const char rcs_flexml_skeleton[] =
- "$" "Id: skel,v 1.19 2005/01/05 18:49:27 legranda Exp $";
+ "$" "Id: skel,v 1.26 2005/02/23 22:22:20 wdowling Exp $";
 const char rcs_flexml[] =
- "$" "Id: flexml.pl,v 1.35 2005/01/05 06:29:58 legranda Exp $";
+ "$" "Id: flexml.pl,v 1.44 2005/02/23 23:08:16 mquinson Exp $";
 
 /* ANSI headers. */
 #include <unistd.h>
@@ -39,31 +62,40 @@ const char rcs_flexml[] =
 
 /* Generated definitions. */
 #define FLEXML_yylineno
-#define FLEXML_BUFFERSTACKSIZE 10000000
+#define FLEXML_BUFFERSTACKSIZE 1000000
 
 /* XML processor api. */
-#include "surfxml.h"
-
 /* FleXML-provided data. */
 const char* pcdata;
 AT_network_link_bandwidth A_network_link_bandwidth;
 AT_cpu_name A_cpu_name;
+AT_process_kill_time A_process_kill_time;
 AT_network_link_state A_network_link_state;
 AT_argument_value A_argument_value;
 AT_cpu_availability_file A_cpu_availability_file;
 AT_process_host A_process_host;
+AT_route_impact_on_src A_route_impact_on_src;
 AT_route_src A_route_src;
 AT_network_link_latency_file A_network_link_latency_file;
+AT_cpu_max_outgoing_rate A_cpu_max_outgoing_rate;
+AT_route_impact_on_dst_with_other_send A_route_impact_on_dst_with_other_send;
+AT_cpu_interference_send_recv A_cpu_interference_send_recv;
 AT_cpu_availability A_cpu_availability;
+AT_route_impact_on_dst A_route_impact_on_dst;
+AT_cpu_interference_recv A_cpu_interference_recv;
+AT_route_impact_on_src_with_other_recv A_route_impact_on_src_with_other_recv;
 AT_network_link_name A_network_link_name;
 AT_route_element_name A_route_element_name;
 AT_cpu_power A_cpu_power;
+AT_process_start_time A_process_start_time;
+AT_include_file A_include_file;
 AT_process_function A_process_function;
-AT_cpu_state A_cpu_state;
 AT_route_dst A_route_dst;
+AT_cpu_state A_cpu_state;
 AT_network_link_latency A_network_link_latency;
-AT_cpu_state_file A_cpu_state_file;
 AT_network_link_state_file A_network_link_state_file;
+AT_cpu_interference_send A_cpu_interference_send;
+AT_cpu_state_file A_cpu_state_file;
 AT_network_link_bandwidth_file A_network_link_bandwidth_file;
 
 /* XML state. */
@@ -82,16 +114,21 @@ AT_network_link_bandwidth_file A_network_link_bandwidth_file;
 
 /* Generic actions. */
 #define SKIP   /*skip*/
-#define SUCCEED        return 0
+#define SUCCEED        CLEANUP; return 0
 
 #define FAIL   return fail
 static int fail(const char*, ...);
+const char * parse_err_msg(void);
+
+/* Cleanup */
+static void cleanup(void);
+#define CLEANUP  cleanup()
 
 /* Text buffer stack handling. */
 char bufferstack[FLEXML_BUFFERSTACKSIZE];
 char* limit = bufferstack + FLEXML_BUFFERSTACKSIZE;
 typedef struct BufferLast_s {
-  struct BufferLast_s *old; char* saved; char new[1];
+  struct BufferLast_s *old; char* saved; char new1[1];
 } BufferLast;
 BufferLast* last = (BufferLast*)0;
 char* next = bufferstack;
@@ -108,7 +145,7 @@ static void bufferliteral(char c, const char** pp, char* text)
   while (++s<e) {
     if (isspace(*s)) { BUFFERPUTC(' '); while (isspace(*s)) ++s; }
     else BUFFERPUTC(*s);
-  } 
+  }
   BUFFERDONE;
 }
 
@@ -119,7 +156,7 @@ static void pushbuffer(char* p)
   assert(next < limit);
   l->old = last;
   l->saved = p;
-  next = l->new;
+  next = l->new1;
   last = l;
 }
 
@@ -186,6 +223,7 @@ Literal             \'[^'']*\'|\"[^""]*\"
  */
 %x PROLOG DOCTYPE EPILOG INCOMMENT INPI VALUE1 VALUE2 CDATA
 %x ROOT_platform_description AL_platform_description S_platform_description S_platform_description_1 S_platform_description_2 E_platform_description
+%x ROOT_include AL_include S_include S_include_1 S_include_2 E_include
 %x ROOT_cpu AL_cpu E_cpu
 %x ROOT_network_link AL_network_link E_network_link
 %x ROOT_route AL_route S_route S_route_1 S_route_2 E_route
@@ -202,9 +240,10 @@ const char* *statenames=NULL;
 %%
 
  /* Bypass Flex's default INITIAL state and begin by parsing the XML prolog. */
- SET(PROLOG); 
+ SET(PROLOG);
   /* FleXML_init */
-  if(!statenames) statenames=calloc(IMPOSSIBLE,sizeof(char*));
+  next = bufferstack;
+  if(!statenames) {statenames= (const char **)calloc(IMPOSSIBLE,sizeof(char*));
   statenames[PROLOG] = NULL;
   statenames[DOCTYPE] = NULL;
   statenames[EPILOG] = NULL;
@@ -219,6 +258,12 @@ const char* *statenames=NULL;
   statenames[S_platform_description_1] = "platform_description";
   statenames[S_platform_description_2] = "platform_description";
   statenames[E_platform_description] = "platform_description";
+  statenames[ROOT_include] = NULL;
+  statenames[AL_include] = NULL;
+  statenames[S_include] = "include";
+  statenames[S_include_1] = "include";
+  statenames[S_include_2] = "include";
+  statenames[E_include] = "include";
   statenames[ROOT_cpu] = NULL;
   statenames[AL_cpu] = NULL;
   statenames[E_cpu] = "cpu";
@@ -243,10 +288,11 @@ const char* *statenames=NULL;
   statenames[ROOT_argument] = NULL;
   statenames[AL_argument] = NULL;
   statenames[E_argument] = "argument";
+  }
 
  /* COMMENTS and PIs: handled uniformly for efficiency. */
 
-<ROOT_platform_description,AL_platform_description,S_platform_description,S_platform_description_1,S_platform_description_2,E_platform_description,ROOT_cpu,AL_cpu,E_cpu,ROOT_network_link,AL_network_link,E_network_link,ROOT_route,AL_route,S_route,S_route_1,S_route_2,E_route,ROOT_route_element,AL_route_element,E_route_element,ROOT_process,AL_process,S_process,S_process_1,S_process_2,E_process,ROOT_argument,AL_argument,E_argument,PROLOG,DOCTYPE,EPILOG>{
+<ROOT_platform_description,AL_platform_description,S_platform_description,S_platform_description_1,S_platform_description_2,E_platform_description,ROOT_include,AL_include,S_include,S_include_1,S_include_2,E_include,ROOT_cpu,AL_cpu,E_cpu,ROOT_network_link,AL_network_link,E_network_link,ROOT_route,AL_route,S_route,S_route_1,S_route_2,E_route,ROOT_route_element,AL_route_element,E_route_element,ROOT_process,AL_process,S_process,S_process_1,S_process_2,E_process,ROOT_argument,AL_argument,E_argument,PROLOG,DOCTYPE,EPILOG>{
  "<!--" ENTER(INCOMMENT);
  "<?" ENTER(INPI);
 }
@@ -266,12 +312,12 @@ const char* *statenames=NULL;
 
  /* SPACES: skipped uniformly */
 
-<ROOT_platform_description,AL_platform_description,S_platform_description,S_platform_description_1,S_platform_description_2,E_platform_description,ROOT_cpu,AL_cpu,E_cpu,ROOT_network_link,AL_network_link,E_network_link,ROOT_route,AL_route,S_route,S_route_1,S_route_2,E_route,ROOT_route_element,AL_route_element,E_route_element,ROOT_process,AL_process,S_process,S_process_1,S_process_2,E_process,ROOT_argument,AL_argument,E_argument,PROLOG,DOCTYPE,EPILOG>{S} SKIP;
+<ROOT_platform_description,AL_platform_description,S_platform_description,S_platform_description_1,S_platform_description_2,E_platform_description,ROOT_include,AL_include,S_include,S_include_1,S_include_2,E_include,ROOT_cpu,AL_cpu,E_cpu,ROOT_network_link,AL_network_link,E_network_link,ROOT_route,AL_route,S_route,S_route_1,S_route_2,E_route,ROOT_route_element,AL_route_element,E_route_element,ROOT_process,AL_process,S_process,S_process_1,S_process_2,E_process,ROOT_argument,AL_argument,E_argument,PROLOG,DOCTYPE,EPILOG>{S} SKIP;
 
  /* PROLOG: determine root element and process it. */
 
 <PROLOG>{
- "<?xml"({S}version{Eq}(\'{VersionNum}\'|\"{VersionNum}\"))?"?>" SET(DOCTYPE);
+ "<?xml"({S}version{Eq}(\'{VersionNum}\'|\"{VersionNum}\"))?({S}encoding{Eq}(\'[^']*\'|\"[^"]*\"))?"?>" SET(DOCTYPE); 
  "<?xml"[^>]*">" FAIL("Bad declaration %s.",yytext);
 }
 
@@ -279,6 +325,7 @@ const char* *statenames=NULL;
  "<!DOCTYPE"{S}"argument"{S}SYSTEM{S}("'surfxml.dtd'"|"\"surfxml.dtd\""){s}">" SET(ROOT_argument);
  "<!DOCTYPE"{S}"route_element"{S}SYSTEM{S}("'surfxml.dtd'"|"\"surfxml.dtd\""){s}">" SET(ROOT_route_element);
  "<!DOCTYPE"{S}"cpu"{S}SYSTEM{S}("'surfxml.dtd'"|"\"surfxml.dtd\""){s}">" SET(ROOT_cpu);
+ "<!DOCTYPE"{S}"include"{S}SYSTEM{S}("'surfxml.dtd'"|"\"surfxml.dtd\""){s}">" SET(ROOT_include);
  "<!DOCTYPE"{S}"route"{S}SYSTEM{S}("'surfxml.dtd'"|"\"surfxml.dtd\""){s}">" SET(ROOT_route);
  "<!DOCTYPE"{S}"platform_description"{S}SYSTEM{S}("'surfxml.dtd'"|"\"surfxml.dtd\""){s}">" SET(ROOT_platform_description);
  "<!DOCTYPE"{S}"network_link"{S}SYSTEM{S}("'surfxml.dtd'"|"\"surfxml.dtd\""){s}">" SET(ROOT_network_link);
@@ -324,13 +371,59 @@ const char* *statenames=NULL;
  <<EOF>> FAIL("Premature EOF: `</platform_description>' expected.");
 }
 
-<ROOT_cpu,S_platform_description_2,S_platform_description_1,S_platform_description>"<cpu"{s} {
+<ROOT_include,S_platform_description_2,S_include,S_include_2,S_platform_description_1,S_include_1,S_platform_description>"<include"{s} {
+  A_include_file = NULL;
+  ENTER(AL_include);
+  }
+
+<AL_include>{
+ "file"{Eq}\' ENTER(VALUE1); BUFFERSET(A_include_file);
+ "file"{Eq}\" ENTER(VALUE2); BUFFERSET(A_include_file);
+
+ ">" {
+  if (!A_include_file) FAIL("Required attribute `file' not set for `include' element.");
+  LEAVE; STag_include();pcdata = NULL; ENTER(S_include);
+ }
+ "/>" {
+  if (!A_include_file) FAIL("Required attribute `file' not set for `include' element.");
+  LEAVE; STag_include(); pcdata = NULL; ETag_include();
+  switch (YY_START) {
+   case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
+   case ROOT_include: SET(EPILOG); break;
+  }
+ }
+ .       FAIL("Unexpected character `%c' in attribute list of include element.", yytext[0]);
+ {Name} FAIL("Bad attribute `%s' in `include' element start tag.",yytext);
+ <<EOF>> FAIL("EOF in attribute list of `include' element.");
+}
+
+<E_include,S_include,S_include_2>{
+ "</include"{s}">" {
+  LEAVE;
+  ETag_include();
+  switch (YY_START) {
+   case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
+   case ROOT_include: SET(EPILOG); break;
+  }
+ }
+ "</"{Name}{s}">" FAIL("Unexpected end-tag `%s': `</include>' expected.",yytext);
+ .       FAIL("Unexpected character `%c': `</include>' expected.",yytext[0]);
+ <<EOF>> FAIL("Premature EOF: `</include>' expected.");
+}
+
+<ROOT_cpu,S_platform_description_2,S_include,S_include_2,S_platform_description_1,S_include_1,S_platform_description>"<cpu"{s} {
   A_cpu_name = NULL;
   A_cpu_power = NULL;
   A_cpu_availability = "1.0";
   A_cpu_availability_file = NULL;
   A_cpu_state = A_cpu_state_ON;
   A_cpu_state_file = NULL;
+  A_cpu_interference_send = "1.0";
+  A_cpu_interference_recv = "1.0";
+  A_cpu_interference_send_recv = "1.0";
+  A_cpu_max_outgoing_rate = "-1.0";
   ENTER(AL_cpu);
   }
 
@@ -355,6 +448,18 @@ const char* *statenames=NULL;
  "state_file"{Eq}\' ENTER(VALUE1); BUFFERSET(A_cpu_state_file);
  "state_file"{Eq}\" ENTER(VALUE2); BUFFERSET(A_cpu_state_file);
 
+ "interference_send"{Eq}\' ENTER(VALUE1); BUFFERSET(A_cpu_interference_send);
+ "interference_send"{Eq}\" ENTER(VALUE2); BUFFERSET(A_cpu_interference_send);
+
+ "interference_recv"{Eq}\' ENTER(VALUE1); BUFFERSET(A_cpu_interference_recv);
+ "interference_recv"{Eq}\" ENTER(VALUE2); BUFFERSET(A_cpu_interference_recv);
+
+ "interference_send_recv"{Eq}\' ENTER(VALUE1); BUFFERSET(A_cpu_interference_send_recv);
+ "interference_send_recv"{Eq}\" ENTER(VALUE2); BUFFERSET(A_cpu_interference_send_recv);
+
+ "max_outgoing_rate"{Eq}\' ENTER(VALUE1); BUFFERSET(A_cpu_max_outgoing_rate);
+ "max_outgoing_rate"{Eq}\" ENTER(VALUE2); BUFFERSET(A_cpu_max_outgoing_rate);
+
  ">" {
   if (!A_cpu_name) FAIL("Required attribute `name' not set for `cpu' element.");
   if (!A_cpu_power) FAIL("Required attribute `power' not set for `cpu' element.");
@@ -366,6 +471,7 @@ const char* *statenames=NULL;
   LEAVE; STag_cpu(); pcdata = NULL; ETag_cpu();
   switch (YY_START) {
    case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
    case ROOT_cpu: SET(EPILOG); break;
   }
  }
@@ -380,6 +486,7 @@ const char* *statenames=NULL;
   ETag_cpu();
   switch (YY_START) {
    case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
    case ROOT_cpu: SET(EPILOG); break;
   }
  }
@@ -388,11 +495,11 @@ const char* *statenames=NULL;
  <<EOF>> FAIL("Premature EOF: `</cpu>' expected.");
 }
 
-<ROOT_network_link,S_platform_description_2,S_platform_description_1,S_platform_description>"<network_link"{s} {
+<ROOT_network_link,S_platform_description_2,S_include,S_include_2,S_platform_description_1,S_include_1,S_platform_description>"<network_link"{s} {
   A_network_link_name = NULL;
   A_network_link_bandwidth = NULL;
   A_network_link_bandwidth_file = NULL;
-  A_network_link_latency = "0.001";
+  A_network_link_latency = "0.0";
   A_network_link_latency_file = NULL;
   A_network_link_state = A_network_link_state_ON;
   A_network_link_state_file = NULL;
@@ -434,6 +541,7 @@ const char* *statenames=NULL;
   LEAVE; STag_network_link(); pcdata = NULL; ETag_network_link();
   switch (YY_START) {
    case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
    case ROOT_network_link: SET(EPILOG); break;
   }
  }
@@ -448,6 +556,7 @@ const char* *statenames=NULL;
   ETag_network_link();
   switch (YY_START) {
    case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
    case ROOT_network_link: SET(EPILOG); break;
   }
  }
@@ -456,9 +565,13 @@ const char* *statenames=NULL;
  <<EOF>> FAIL("Premature EOF: `</network_link>' expected.");
 }
 
-<ROOT_route,S_platform_description_2,S_platform_description_1,S_platform_description>"<route"{s} {
+<ROOT_route,S_platform_description_2,S_include,S_include_2,S_platform_description_1,S_include_1,S_platform_description>"<route"{s} {
   A_route_src = NULL;
   A_route_dst = NULL;
+  A_route_impact_on_src = "0.0";
+  A_route_impact_on_dst = "0.0";
+  A_route_impact_on_src_with_other_recv = "0.0";
+  A_route_impact_on_dst_with_other_send = "0.0";
   ENTER(AL_route);
   }
 
@@ -469,6 +582,18 @@ const char* *statenames=NULL;
  "dst"{Eq}\' ENTER(VALUE1); BUFFERSET(A_route_dst);
  "dst"{Eq}\" ENTER(VALUE2); BUFFERSET(A_route_dst);
 
+ "impact_on_src"{Eq}\' ENTER(VALUE1); BUFFERSET(A_route_impact_on_src);
+ "impact_on_src"{Eq}\" ENTER(VALUE2); BUFFERSET(A_route_impact_on_src);
+
+ "impact_on_dst"{Eq}\' ENTER(VALUE1); BUFFERSET(A_route_impact_on_dst);
+ "impact_on_dst"{Eq}\" ENTER(VALUE2); BUFFERSET(A_route_impact_on_dst);
+
+ "impact_on_src_with_other_recv"{Eq}\' ENTER(VALUE1); BUFFERSET(A_route_impact_on_src_with_other_recv);
+ "impact_on_src_with_other_recv"{Eq}\" ENTER(VALUE2); BUFFERSET(A_route_impact_on_src_with_other_recv);
+
+ "impact_on_dst_with_other_send"{Eq}\' ENTER(VALUE1); BUFFERSET(A_route_impact_on_dst_with_other_send);
+ "impact_on_dst_with_other_send"{Eq}\" ENTER(VALUE2); BUFFERSET(A_route_impact_on_dst_with_other_send);
+
  ">" {
   if (!A_route_src) FAIL("Required attribute `src' not set for `route' element.");
   if (!A_route_dst) FAIL("Required attribute `dst' not set for `route' element.");
@@ -480,6 +605,7 @@ const char* *statenames=NULL;
   LEAVE; STag_route(); pcdata = NULL; ETag_route();
   switch (YY_START) {
    case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
    case ROOT_route: SET(EPILOG); break;
   }
  }
@@ -494,6 +620,7 @@ const char* *statenames=NULL;
   ETag_route();
   switch (YY_START) {
    case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
    case ROOT_route: SET(EPILOG); break;
   }
  }
@@ -542,9 +669,11 @@ const char* *statenames=NULL;
  <<EOF>> FAIL("Premature EOF: `</route_element>' expected.");
 }
 
-<ROOT_process,S_platform_description_2,S_platform_description_1,S_platform_description>"<process"{s} {
+<ROOT_process,S_platform_description_2,S_include,S_include_2,S_platform_description_1,S_include_1,S_platform_description>"<process"{s} {
   A_process_host = NULL;
   A_process_function = NULL;
+  A_process_start_time = "-1.0";
+  A_process_kill_time = "-1.0";
   ENTER(AL_process);
   }
 
@@ -555,6 +684,12 @@ const char* *statenames=NULL;
  "function"{Eq}\' ENTER(VALUE1); BUFFERSET(A_process_function);
  "function"{Eq}\" ENTER(VALUE2); BUFFERSET(A_process_function);
 
+ "start_time"{Eq}\' ENTER(VALUE1); BUFFERSET(A_process_start_time);
+ "start_time"{Eq}\" ENTER(VALUE2); BUFFERSET(A_process_start_time);
+
+ "kill_time"{Eq}\' ENTER(VALUE1); BUFFERSET(A_process_kill_time);
+ "kill_time"{Eq}\" ENTER(VALUE2); BUFFERSET(A_process_kill_time);
+
  ">" {
   if (!A_process_host) FAIL("Required attribute `host' not set for `process' element.");
   if (!A_process_function) FAIL("Required attribute `function' not set for `process' element.");
@@ -566,6 +701,7 @@ const char* *statenames=NULL;
   LEAVE; STag_process(); pcdata = NULL; ETag_process();
   switch (YY_START) {
    case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
    case ROOT_process: SET(EPILOG); break;
   }
  }
@@ -580,6 +716,7 @@ const char* *statenames=NULL;
   ETag_process();
   switch (YY_START) {
    case S_platform_description_2: case S_platform_description_1: case S_platform_description: SET(S_platform_description_2); break;
+   case S_include: case S_include_2: case S_include_1: SET(S_include_2); break;
    case ROOT_process: SET(EPILOG); break;
   }
  }
@@ -631,7 +768,7 @@ const char* *statenames=NULL;
  /* EPILOG: after the root element. */
 
 <EPILOG>{
- .             FAIL("Unexpected character `%c' after document.", yytext[0]);
+ . {SET(PROLOG); yyless(0); CLEANUP; return -1;}
  <<EOF>>       SUCCEED;
 }
 
@@ -679,15 +816,16 @@ const char* *statenames=NULL;
 
 <CDATA>{
  "]""]>"               LEAVE;
- "]""]"                BUFFERPUTC(yytext[0]); BUFFERPUTC(yytext[1]);
+ /* "]""]"             BUFFERPUTC(yytext[0]); BUFFERPUTC(yytext[1]); */
  .             BUFFERPUTC(yytext[0]);
  <<EOF>>       FAIL("EOF in CDATA section.");
 }
 
  /* Impossible rules to avoid warnings from flex(1). */
-
-<INITIAL,IMPOSSIBLE>{
- .|[\n] FAIL("The Impossible Happened: INITIAL or IMPOSSIBLE state entered?");
+ /* Ideally, this should be replaced by code in flexml.pl that
+    generates just the states not covered by other rules. */
+<*>{
+ .|[\n] FAIL("Syntax error on character `%c'.", yytext[0]);
 }
 
 %%
@@ -727,17 +865,53 @@ 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)
+{
+    if (statenames) {
+        free(statenames);
+       statenames = NULL;
+    }
+}
+
 
 static int fail(const char* fmt, ...)
 {
-  va_list ap; va_start(ap, fmt);
+    int chars_left, used;
+    va_list ap; va_start(ap, fmt);
 #ifdef FLEXML_yylineno
-  fprintf(stderr, "Invalid XML (XML input line %d, state %d): ", yylineno, YY_START);
+    used = sprintf(flexml_err_msg,
+                  "Invalid XML (XML input line %d, state %d): ",
+                  yylineno, YY_START);
 #else
-  fprintf(stderr, "Invalid XML (state %d): ",YY_START);
+    used = sprintf(flexml_err_msg,
+                  "Invalid XML (state %d): ",
+                  YY_START);
 #endif
-  vfprintf(stderr, fmt, ap);
-  fprintf(stderr, "\n");
-  va_end(ap);
-  return 1;
+    chars_left = flexml_max_err_msg_size - used - 1;
+    vsnprintf(flexml_err_msg + used, chars_left, fmt, ap);
+    va_end(ap);
+
+#ifndef FLEXML_quiet_parser
+    /* print directly to sdterr */
+    fprintf(stderr, "%s\n", flexml_err_msg);
+    flexml_err_msg[0] = '\0';
+#endif
+
+    cleanup();
+
+    return 1;
 }