source: trunk/src/engine.c @ 196

Last change on this file since 196 was 196, checked in by lindanl, 11 years ago

Set text_or_markup_start in Parse_Prolog

File size: 72.9 KB
Line 
1/*  engine.c - Parabix XML parsing engine.
2    Copyright (c) 2007, 2008, Robert D. Cameron and Dan Lin.
3    Licensed to the public under the Open Software License 3.0.
4    Licensed to International Characters, Inc., under the Academic
5    Free License 3.0.
6*/
7
8#include "engine.h"
9#include "byteplex.h"
10#include "xmldecl.h"
11#include "bytelex.h"
12#include "bitlex.h"
13#include "contentmodel.h"
14#include "contentmodel.c"
15#include "xml_error.h"
16
17#include <assert.h>
18#include <stdlib.h>
19#include <errno.h>
20#include <string.h>
21#include <string>
22#include <iostream>
23using namespace std;
24       
25inline char * copy_string (unsigned char * s, int lgth){               
26        char * d = new char[lgth+1];
27        memcpy(d, (char *)s,lgth); 
28        d[lgth] = '\0'; 
29        return d;
30}
31
32inline char * cat_string (char * s1, char * s2, int lgth1, int lgth2){
33        char * s = new char[lgth1 + lgth2 + 1];
34        memcpy(s, s1,lgth1);
35        memcpy(&s[lgth1],s2,lgth2);
36        s[lgth1 + lgth2] = '\0';
37        return s;
38}
39       
40       
41       
42Parser_Interface * Parser_Interface::ParserFactory(char * filename) {
43       
44        int chars_read;
45        unsigned char signature[4];
46        FILE * infile;
47        infile = fopen(filename, "rb");
48        if (!infile) {
49                fprintf(stderr, "Error: cannot open %s for input.\n", filename);
50                exit(-1);
51        }
52        fread(signature,1,4,infile);
53        Entity_Info * e = new Entity_Info;
54        Model_Info * m = new Model_Info;
55        e->AnalyzeSignature(signature);
56        Byteplex * b = Byteplex::ByteplexFactory(e, infile);
57        b->InitializeBuffer(signature,4);
58        b->DoByteplex();
59        b->PreparePseudoASCII_Stream();
60       
61        if (e->code_unit_base == ASCII) {
62                XML_Decl_Parser<ASCII> decl_parser(b);
63                decl_parser.ReadXMLInfo(*e);
64                if (e->code_unit_size == SingleByte) {
65                        if (!(e->has_encoding_decl) || at_UTF_8(e->encoding))
66                                return new ParsingEngine< UTF8_Buffer>(e, m, b, false);         
67                        else return new ParsingEngine< X8_Buffer<ASCII> >(e, m, b, false);
68                }
69                else if (e->code_unit_size == DoubleByte) {
70                        return new ParsingEngine<U16_Buffer>(e, m, b, false);
71                }
72                else if (e->code_unit_size == QuadByte) {
73                        return new ParsingEngine<U32_Buffer>(e, m, b, false);
74                }
75        }
76        else /* if (e->code_unit_base == EBCDIC) */ {
77                XML_Decl_Parser<EBCDIC> decl_parser(b);
78                decl_parser.ReadXMLInfo(*e);
79                return new ParsingEngine< X8_Buffer<EBCDIC> >(e, m, b, false);
80        }       
81}
82
83Parser_Interface * Parser_Interface::ParserFactory(char * filename, Model_Info * m) {
84       
85        int chars_read;
86        unsigned char signature[4];
87        FILE * infile;
88        infile = fopen(filename, "rb");
89        if (!infile) {
90                fprintf(stderr, "Error: cannot open %s for input.\n", filename);
91                exit(-1);
92        }
93        fread(signature,1,4,infile);
94        Entity_Info * e = new Entity_Info;
95        e->AnalyzeSignature(signature);
96        Byteplex * b = Byteplex::ByteplexFactory(e, infile);
97        b->InitializeBuffer(signature,4);
98        b->DoByteplex();
99        b->PreparePseudoASCII_Stream();
100        if (e->code_unit_base == ASCII) {
101                XML_Decl_Parser<ASCII> decl_parser(b);
102                decl_parser.ReadXMLInfo(*e);
103                if (e->code_unit_size == SingleByte) {
104                        return new ParsingEngine< X8_Buffer<ASCII> >(e, m, b, true);
105                }
106                else if (e->code_unit_size == DoubleByte) {
107                        return new ParsingEngine<U16_Buffer>(e, m, b, true);
108                }
109                else if (e->code_unit_size == QuadByte) {
110                        return new ParsingEngine<U32_Buffer>(e, m, b, true);
111                }
112        }
113        else /* if (e->code_unit_base == EBCDIC) */ {
114                XML_Decl_Parser<EBCDIC> decl_parser(b);
115                decl_parser.ReadXMLInfo(*e);
116                return new ParsingEngine< X8_Buffer<EBCDIC> >(e, m, b, true);
117        }       
118}
119
120Parser_Interface * Parser_Interface::ParserFactory(char * byte_buffer, int byte_count, Entity_Info * e1, Model_Info * m){
121        Entity_Info * e = new Entity_Info;
122        e->BOM_units = 0;
123        e->code_unit_base=e1->code_unit_base;
124        e->code_unit_size=e1->code_unit_size;
125        e->version=e1->version;
126        e->encoding=e1->encoding;
127        e->content_start = 0;
128        Byteplex * b = Byteplex::ByteplexFactory(e, (unsigned char *) byte_buffer, byte_count);
129        b->DoByteplex();
130        b->PreparePseudoASCII_Stream();
131        if (e->code_unit_base == ASCII) {
132                if (e->code_unit_size == SingleByte) {
133                        return new ParsingEngine< X8_Buffer<ASCII> >(e, m, b, false);
134                }
135                else if (e->code_unit_size == DoubleByte) {
136                        return new ParsingEngine<U16_Buffer>(e, m, b, false);
137                }
138                else if (e->code_unit_size == QuadByte) {
139                        return new ParsingEngine<U32_Buffer>(e, m, b, false);
140                }
141        }
142        else /* if (e->code_unit_base == EBCDIC) */ {
143                return new ParsingEngine< X8_Buffer<EBCDIC> >(e, m, b, false);
144        }       
145}
146
147Parser_Interface::~Parser_Interface() {
148}
149
150
151bool Parser_Interface::has_ByteOrderMark() {
152        return entity_Info->BOM_units > 0;
153}
154
155XML_version Parser_Interface::get_version() {
156        return entity_Info->version;
157}
158
159XML_standalone Parser_Interface::standalone_status() {
160        return entity_Info->standalone;
161}
162
163bool Parser_Interface::has_EncodingDecl() {
164        return entity_Info->has_encoding_decl;
165}
166
167unsigned char * Parser_Interface::get_Encoding() {
168        return entity_Info->encoding;
169}
170
171template <class B>
172inline unsigned char * ParsingEngine<B>::GetCodeUnitPtr(int pos) {
173        int rel_pos = pos - buffer_base_pos;
174        return &((unsigned char *) (byteplex->src_buffer))[rel_pos * (int) B::Size];
175}
176
177template <>
178inline unsigned char * ParsingEngine<UTF8_Buffer>::GetCodeUnitPtr(int pos) {
179        int rel_pos = pos - buffer_base_pos;
180        return &((unsigned char *) (x8data))[rel_pos];
181}
182
183
184
185
186template <class B>
187ParsingEngine<B>::ParsingEngine(Entity_Info * e, Model_Info * m, Byteplex * b, bool is_external) : Parser_Interface () {
188        entity_Info = e;
189        model_info = m;
190        byteplex = b;
191
192//      m->symbol_table = new Symbol_Table();
193//      m->SimpleEntity("lt", "<");
194//      m->SimpleEntity("gt", ">");
195//      m->SimpleEntity("amp", "&");
196//      m->SimpleEntity("quot", "\"");
197//      m->SimpleEntity("apos", "'");   
198        m->symbol_table->version = e->version;
199
200        StrictWellFormedness=false;
201        LastAttOccurrence.assign(m->globalAttributeCount+1, 0);
202       
203       
204        bitplex = new Bitplex;
205        buf = (LexicalStreamSet *) simd_new(sizeof(LexicalStreamSet)/PACKSIZE);
206
207  /* Install sentinels for every lexical item stream*/
208#ifdef TEMPLATED_SIMD_LIB
209        BitBlock sentinel_value = simd<1>::constant<1>();
210#endif
211#ifndef TEMPLATED_SIMD_LIB
212        BitBlock sentinel_value = simd_const_1(1);
213#endif
214
215#ifdef OPTIMIZE_SHORT_SCAN
216        sentinel_value = sisd_sfli(sentinel_value, 8*sizeof(unsigned long));
217#endif
218
219        for (int j = minLexicalItem; j < LexicalItemCount; j++) {
220                buf->item_stream[j][BUFFER_BLOCKS] = sentinel_value;
221        }
222
223        buffer_base_pos = 0;
224        buffer_rel_pos = e->content_start;
225        buffer_limit_pos = min(BUFFER_SIZE, byteplex->units_in_buffer);
226        int blocks_in_buffer = (buffer_limit_pos + BLOCKSIZE - 1)/BLOCKSIZE;
227        x8data = byteplex->x8data;
228        lexer = Lexer<B::Base>::LexerFactory(e, buf);
229        bitplex->TransposeToBitStreams(byteplex->x8data, blocks_in_buffer);
230        lexer->AnalyzeBuffer(bitplex->x8basis, buffer_base_pos, buffer_rel_pos, buffer_limit_pos);
231}
232
233template <class B>
234ParsingEngine<B>::~ParsingEngine() {
235  // How do we do this?  model_info->~Model_Info();
236  entity_Info->~Entity_Info();
237  byteplex->~Byteplex();
238  bitplex->~Bitplex();
239  simd_delete((SIMD_type *) buf);
240  lexer->~Lexer_Interface();
241}
242
243template <class B>
244void ParsingEngine<B>::AdvanceBuffers(){
245#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == ADVANCE_BUFFERS)
246        code_clocker->cc_start_interval();
247#endif
248
249        int advance_amt = text_or_markup_start - buffer_base_pos;
250        advance_amt &= -PACKSIZE; // maintain alignment
251        byteplex->AdvanceInputBuffer(advance_amt);
252        buffer_base_pos += advance_amt;
253        buffer_rel_pos -= advance_amt;
254        buffer_limit_pos = min(BUFFER_SIZE, byteplex->units_in_buffer);
255        int blocks_in_buffer = (buffer_limit_pos + BLOCKSIZE - 1)/BLOCKSIZE;
256#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == BYTEPLEX)
257        code_clocker->cc_start_interval();
258#endif
259        byteplex->DoByteplex();
260        byteplex->PreparePseudoASCII_Stream();
261#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == BYTEPLEX)
262        code_clocker->cc_end_interval(buffer_limit_pos);
263#endif
264#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == BITPLEX)
265        code_clocker->cc_start_interval();
266#endif
267        bitplex->TransposeToBitStreams(byteplex->x8data, blocks_in_buffer);
268#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == BITPLEX)
269        code_clocker->cc_end_interval(buffer_limit_pos);
270#endif
271        lexer->AnalyzeBuffer(bitplex->x8basis, buffer_base_pos, buffer_rel_pos, buffer_limit_pos);
272#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == ADVANCE_BUFFERS)
273        code_clocker->cc_end_interval(buffer_limit_pos);
274#endif
275
276}
277
278template <>
279void ParsingEngine<U16_Buffer>::AdvanceBuffers(){
280#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == ADVANCE_BUFFERS)
281        code_clocker->cc_start_interval();
282#endif
283
284        int advance_amt = text_or_markup_start - buffer_base_pos;
285        advance_amt &= -PACKSIZE; // maintain alignment
286        byteplex->AdvanceInputBuffer(advance_amt);
287        buffer_base_pos += advance_amt;
288        buffer_rel_pos -= advance_amt;
289        buffer_limit_pos = min(BUFFER_SIZE, byteplex->units_in_buffer);
290        int blocks_in_buffer = (buffer_limit_pos + BLOCKSIZE - 1)/BLOCKSIZE;
291#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == BYTEPLEX)
292        code_clocker->cc_start_interval();
293#endif
294        byteplex->DoByteplex();
295        if (at_UTF_16(entity_Info->encoding)) ((U16_Buffer *) byteplex)->Validate_UTF16();
296        byteplex->PreparePseudoASCII_Stream();
297#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == BYTEPLEX)
298        code_clocker->cc_end_interval(buffer_limit_pos);
299#endif
300#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == BITPLEX)
301        code_clocker->cc_start_interval();
302#endif
303        bitplex->TransposeToBitStreams(byteplex->x8data, blocks_in_buffer);
304#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == BITPLEX)
305        code_clocker->cc_end_interval(buffer_limit_pos);
306#endif
307        lexer->AnalyzeBuffer(bitplex->x8basis, buffer_base_pos, buffer_rel_pos, buffer_limit_pos);
308#if defined(PAPI) and defined(CODE_CLOCKING) and (CODE_CLOCKING == ADVANCE_BUFFERS)
309        code_clocker->cc_end_interval(buffer_limit_pos);
310#endif
311
312}
313
314template <class B>
315inline unsigned char * ParsingEngine<B>::cur() const {
316  return &((unsigned char *) x8data)[buffer_rel_pos];
317}
318
319template <class B>
320inline int ParsingEngine<B>::AbsPos() const {
321  return buffer_base_pos + buffer_rel_pos;
322}
323
324template <class B>
325inline int ParsingEngine<B>::LengthFrom(int start_pos) const {
326  return buffer_base_pos + buffer_rel_pos - start_pos;
327}
328
329
330
331template <class B>
332inline int ParsingEngine<B>::BufferRelPos() const {
333  return buffer_rel_pos;
334}
335
336
337template <class B>
338inline bool ParsingEngine<B>::at_EOF() const {
339  return (buffer_rel_pos >= buffer_limit_pos) && 
340         (buffer_limit_pos < BUFFER_SIZE);
341}
342
343//template <class B>
344//inline void ParsingEngine<B>::Advance(int n) {
345//      buffer_rel_pos += n;
346//  if (buffer_rel_pos >= BUFFER_SIZE) {       
347//      FinalizeBuffer_action();
348//      AdvanceBuffers();
349//  }
350//}
351
352#define Advance(n) \
353do {\
354        buffer_rel_pos += n; \
355        if (buffer_rel_pos >= BUFFER_SIZE) {    \
356                FinalizeBuffer_action();\
357        AdvanceBuffers();\
358        }\
359} while(0)
360
361
362template <class B> 
363void ParsingEngine<B>::AdjustBufferEndForIncompleteSequences() {
364}
365
366template <> 
367void ParsingEngine<UTF8_Buffer>::AdjustBufferEndForIncompleteSequences() {
368        if (*(cur()-1) >= 0xC0) buffer_rel_pos--;
369        else if (*(cur()-2) >= 0xE0) buffer_rel_pos -= 2;
370        else if (*(cur()-3) >= 0xF0) buffer_rel_pos -= 3;
371}
372
373template <> 
374void ParsingEngine<U16_Buffer>::AdjustBufferEndForIncompleteSequences() {
375        unsigned short last_u16_unit = *(GetCodeUnitPtr(AbsPos()-1));
376        if ((last_u16_unit >= 0xD800) & (last_u16_unit <= 0xDC00)) buffer_rel_pos--;
377}
378
379
380
381#ifdef OPTIMIZE_SHORT_SCAN
382//
383//  Inline ScanTo with unrolled first test that should almost always
384//  succeed for short scans.
385#define ScanTo(item) \
386do {\
387        unsigned long segment = bitstream_segment_from(buf->item_stream[item], buffer_rel_pos);\
388        if (segment != 0) buffer_rel_pos += cfzl(segment);\
389        else {\
390                buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);\
391                buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);\
392                while (buffer_rel_pos >= BUFFER_SIZE) {\
393                        buffer_rel_pos = BUFFER_SIZE;\
394                        AdjustBufferEndForIncompleteSequences();\
395                        FinalizeBuffer_action();\
396                        AdvanceBuffers();\
397                        buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);\
398                }\
399        }\
400} while(0)
401
402// The following version seems cleaner, but measured mispredictions are higher
403// #define ScanTo(item) \
404// do {\
405//      unsigned long segment = bitstream_segment_from(buf->item_stream[item], buffer_rel_pos);\
406//      while (unlikely (segment == 0)) {\
407//              buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);\
408//              if (buffer_rel_pos >= BUFFER_SIZE) {\
409//                      buffer_rel_pos = BUFFER_SIZE;\
410//                      AdjustBufferEndForIncompleteSequences();\
411//                      FinalizeBuffer_action();\
412//                      AdvanceBuffers();\
413//              }\
414//              segment = bitstream_segment_from(buf->item_stream[item], buffer_rel_pos);\
415//      }\
416//      buffer_rel_pos += cfzl(segment);\
417// } while(0)
418//
419// #define ScanTextTo(item) \
420// do {\
421//      unsigned long segment = bitstream_segment_from(buf->item_stream[item], buffer_rel_pos);\
422//      text_or_markup_start = AbsPos();\
423//      if (segment != 0) buffer_rel_pos += cfzl(segment);\
424//      else {\
425//              buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);\
426//              buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);\
427//              while (buffer_rel_pos >= BUFFER_SIZE) {\
428//                      buffer_rel_pos = BUFFER_SIZE;\
429//                      AdjustBufferEndForIncompleteSequences();\
430//                      Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start), true);\
431//                      text_or_markup_start = AbsPos();\
432//                      FinalizeBuffer_action();\
433//                      AdvanceBuffers();\
434//                      buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);\
435//              }\
436//      }\
437// } while(0)
438
439template <class B>
440inline void ParsingEngine<B>::ScanTextTo(int item) {
441        text_or_markup_start = AbsPos();
442        unsigned long segment = bitstream_segment_from(buf->item_stream[item], buffer_rel_pos);
443        if (segment != 0) buffer_rel_pos += cfzl(segment);
444        else {
445                buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);
446                buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
447                while (buffer_rel_pos >= BUFFER_SIZE) {
448                        buffer_rel_pos = BUFFER_SIZE;
449                        AdjustBufferEndForIncompleteSequences();
450                        Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start), true);
451                        text_or_markup_start = AbsPos();
452                        FinalizeBuffer_action();
453                        AdvanceBuffers();
454                        buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
455                }
456        }
457}
458
459#endif
460
461#ifndef OPTIMIZE_SHORT_SCAN
462
463#define ScanTo(item) \
464do {\
465  buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);\
466  while (buffer_rel_pos >= BUFFER_SIZE) {\
467        AdjustBufferEndForIncompleteSequences();\
468        FinalizeBuffer_action();\
469        AdvanceBuffers();\
470        buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);\
471  }\
472} while(0)
473
474
475// template <class B>
476// inline void ParsingEngine<B>::ScanTo(int item) {
477//      buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
478//      while (buffer_rel_pos >= BUFFER_SIZE) {
479//              AdjustBufferEndForIncompleteSequences();
480//              FinalizeBuffer_action();
481//              AdvanceBuffers();
482//              buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
483//      }
484// }
485
486template <class B>
487inline void ParsingEngine<B>::ScanTextTo(int item) {
488        text_or_markup_start = AbsPos();
489        buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
490        while (buffer_rel_pos >= BUFFER_SIZE) {
491                AdjustBufferEndForIncompleteSequences();
492                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start), true);
493                text_or_markup_start = AbsPos();
494                FinalizeBuffer_action();
495                AdvanceBuffers();
496                buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
497        }
498}
499#endif
500
501template <class B>
502void ParsingEngine<B>::WF_Error (XML_Constraint errCode) {
503        printf("Error at position %i in input.\n", AbsPos());
504        ShowConstraintError(errCode);
505        exit(-1);
506//      Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
507}
508       
509
510template <class B>
511void ParsingEngine<B>::Validity_Error (XML_Constraint errCode) {
512        printf("Error at position %i in input.\n", AbsPos());
513        ShowConstraintError(errCode);
514        exit(-1);
515//      Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
516}
517       
518template <class B>
519void ParsingEngine<B>::Syntax_Error (XML_NonTerminal errNT) {
520        printf("Error at position %i in input.\n", AbsPos());
521        ShowSyntaxError(errNT);
522        exit(-1);
523//      Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
524}
525       
526
527/* Parse a comment beginning "<!--" */
528template <class B>
529void ParsingEngine<B>::Parse_Comment() {
530
531        Advance(4); /* Skip "<!--". */
532        ScanTo(Hyphen);
533        while (!at_DoubleHyphen<B::Base>(cur())) {
534                if(at_EOF())
535                        Syntax_Error(NT_CDSect);
536                Advance(2); /* Skip hyphen-nonhyphen pair */
537                ScanTo(Hyphen); 
538        }
539        if (at_Comment_End<B::Base>(cur())) {
540                Advance(3); /* Skip "-->". */
541                Comment_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
542        }
543        else {
544                Advance(2);  /* "--" */
545                Syntax_Error(NT_Comment);
546        }
547}
548
549/* Parse an end tag beginning "</" */
550template <class B>
551inline void ParsingEngine<B>::Parse_EndTag() {
552        Advance(2); /* Skip "</". */
553        int nameID = Parse_Name();
554        if (AtChar<B::Base,'>'>(cur())) {
555                Advance(1);
556                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
557        }
558        else {
559                ScanTo(NonWS);
560                if (AtChar<B::Base,'>'>(cur())) {
561                        Advance(1);
562                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
563                }
564                else Syntax_Error(NT_ETag);
565        }
566}
567
568/* Parse a CDATA section beginning "<![CDATA". */
569template <class B>
570void ParsingEngine<B>::Parse_CDATA() {
571                Advance(8); /* Skip "<![CDATA". */
572        if (!AtChar<B::Base,'['>(cur())) {
573                Syntax_Error(NT_CDStart);
574        }
575        else { 
576                Advance(1);
577                CDATA_start_action(GetCodeUnitPtr(text_or_markup_start));
578                text_or_markup_start = AbsPos();
579                ScanTextTo(CD_End_check);
580                while (!at_CDATA_End<B::Base>(cur())) {
581                        if (at_EOF())
582                                Syntax_Error(NT_CDSect);
583                        Advance(1);
584                        ScanTextTo(CD_End_check);
585                }
586                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start), true);
587                Advance(3); /* Skip "]]>". */
588                CDATA_end_action(GetCodeUnitPtr(AbsPos()));
589        }
590}
591
592template <class B>
593void ParsingEngine<B>::Parse_EntityRef() {
594    Advance(1);  // skip "&"
595        int nameID = Parse_Name();  /* Name delimiter */
596    if (!AtChar<B::Base,';'>(cur())) {
597                Syntax_Error(NT_Reference);
598    }
599        else {
600                Advance(1);
601                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
602               
603                //      The following code will replace Reference_Action.
604                GEntity_info * this_info;
605                Parser_Interface * entity_parser;
606                int entityID = model_info->GlobalGEntityTable[nameID]; 
607                if (entityID == 0)
608                        WF_Error(wfErr_wf_entdeclared);
609                else{
610                        this_info = model_info->GEntityData[entityID-1];
611                        if (this_info->is_external){
612                               
613                        if (entity_Info->standalone != Standalone_no)
614                                WF_Error(wfErr_NoExternalRefs);
615                        else {
616                                        entity_parser = ParserFactory(this_info->systemLiteral, model_info);
617                                        entity_parser->Parse_WF_Content();
618                                        if(!entity_parser->at_EOF())
619                                                Syntax_Error(NT_content);
620                                        entity_parser->~Parser_Interface();
621                        }
622                        }
623                        else {
624                                if (this_info->is_simple == true);
625//                                      printf("Entity is %s\n",this_info->ReplacementText);
626                                else{
627//                                      printf("Not a simple text: %s\n",this_info->ReplacementText);
628                                        entity_parser = ParserFactory(this_info->ReplacementText, strlen(this_info->ReplacementText),entity_Info, model_info);
629                                        entity_parser->Parse_WF_Content();
630                                        if(!entity_parser->at_EOF())
631                                                Syntax_Error(NT_content);
632                                        entity_parser->~Parser_Interface();
633                                }
634                        }
635                }
636               
637        }
638}
639
640template <class B>
641void ParsingEngine<B>::Parse_EntityRef_inMixed(symbol_set_t elems) {
642    Advance(1);  // skip "&"
643        int nameID = Parse_Name();  /* Name delimiter */
644    if (!AtChar<B::Base,';'>(cur())) {
645                Syntax_Error(NT_Reference);
646    }
647        else {
648                Advance(1);
649                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
650               
651                //      The following code will replace Reference_Action.
652                GEntity_info * this_info;
653                Parser_Interface * entity_parser;
654                int entityID = model_info->GlobalGEntityTable[nameID]; 
655                if (entityID == 0)
656                        WF_Error(wfErr_wf_entdeclared);
657                else{
658                        this_info = model_info->GEntityData[entityID-1];
659                        if (this_info->is_external){
660                               
661                        if (entity_Info->standalone != Standalone_no)
662                                WF_Error(wfErr_NoExternalRefs);
663                        else {
664                                        entity_parser = ParserFactory(this_info->systemLiteral, model_info);
665                                        entity_parser->Parse_MixedContent(elems);
666                                        if(!entity_parser->at_EOF())
667                                                Syntax_Error(NT_content);
668                                        entity_parser->~Parser_Interface();
669                        }
670                        }
671                        else {
672                                if (this_info->is_simple == true);
673//                                      printf("Entity is %s\n",this_info->ReplacementText);
674                                else{
675//                                      printf("Not a simple text: %s\n",this_info->ReplacementText);
676                                        entity_parser = ParserFactory(this_info->ReplacementText, strlen(this_info->ReplacementText),entity_Info, model_info);
677                                        entity_parser->Parse_MixedContent(elems);
678                                        if(!entity_parser->at_EOF())
679                                                Syntax_Error(NT_content);
680                                        entity_parser->~Parser_Interface();
681                                }
682                        }
683                }
684               
685        }
686}
687
688template <class B>
689void ParsingEngine<B>::Parse_EntityRef_inAnyContent() {
690    Advance(1);  // skip "&"
691        int nameID = Parse_Name();  /* Name delimiter */
692    if (!AtChar<B::Base,';'>(cur())) {
693                Syntax_Error(NT_Reference);
694    }
695        else {
696                Advance(1);
697                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
698               
699                //      The following code will replace Reference_Action.
700                GEntity_info * this_info;
701                Parser_Interface * entity_parser;
702                int entityID = model_info->GlobalGEntityTable[nameID]; 
703                if (entityID == 0)
704                        WF_Error(wfErr_wf_entdeclared);
705                else{
706                        this_info = model_info->GEntityData[entityID-1];
707                        if (this_info->is_external){
708                               
709                        if (entity_Info->standalone != Standalone_no)
710                                WF_Error(wfErr_NoExternalRefs);
711                        else {
712                                        entity_parser = ParserFactory(this_info->systemLiteral, model_info);
713                                        entity_parser->Parse_AnyContent();
714                                        if(!entity_parser->at_EOF())
715                                                Syntax_Error(NT_content);
716                                        entity_parser->~Parser_Interface();
717                        }
718                        }
719                        else {
720                                if (this_info->is_simple == true);
721//                                      printf("Entity is %s\n",this_info->ReplacementText);
722                                else{
723//                                      printf("Not a simple text: %s\n",this_info->ReplacementText);
724                                        entity_parser = ParserFactory(this_info->ReplacementText, strlen(this_info->ReplacementText),entity_Info, model_info);
725                                        entity_parser->Parse_AnyContent();
726                                        if(!entity_parser->at_EOF())
727                                                Syntax_Error(NT_content);
728                                        entity_parser->~Parser_Interface();
729                                }
730                        }
731                }
732               
733        }
734}
735
736template <class B>
737void ParsingEngine<B>::Parse_ValidEntityRef(CM_RegExp * cre, int & cur_state) {
738    Advance(1);  // skip "&"
739        int nameID = Parse_Name();  /* Name delimiter */
740    if (!AtChar<B::Base,';'>(cur())) {
741                Syntax_Error(NT_Reference);
742    }
743        else {
744                Advance(1);
745                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
746               
747                //      The following code will replace Reference_Action.
748                GEntity_info * this_info;
749                Parser_Interface * entity_parser;
750                int entityID = model_info->GlobalGEntityTable[nameID]; 
751                if (entityID == 0)
752                        WF_Error(wfErr_wf_entdeclared);
753                else{
754                        this_info = model_info->GEntityData[entityID-1];
755                        if (this_info->is_external){
756                               
757                        if (entity_Info->standalone != Standalone_no)
758                                WF_Error(wfErr_NoExternalRefs);
759                        else {
760                                        entity_parser = ParserFactory(this_info->systemLiteral, model_info);
761                                        entity_parser->Parse_ValidContent(cre, cur_state);
762                                        if(!entity_parser->at_EOF())
763                                                Syntax_Error(NT_content);
764                                        entity_parser->~Parser_Interface();
765                        }
766                        }
767                        else {
768                                if (this_info->is_simple == true);
769//                                      printf("Entity is %s\n",this_info->ReplacementText);
770                                else{
771//                                      printf("Not a simple text: %s\n",this_info->ReplacementText);
772                                        entity_parser = ParserFactory(this_info->ReplacementText, strlen(this_info->ReplacementText),entity_Info, model_info);
773                                        entity_parser->Parse_ValidContent(cre, cur_state);
774                                        if(!entity_parser->at_EOF())
775                                                Syntax_Error(NT_content);
776                                        entity_parser->~Parser_Interface();
777                                }
778                        }
779                }
780               
781        }
782}
783       
784template <class B>
785void ParsingEngine<B>::Parse_CharRef() {
786        Advance(2);  // skip "&#"
787        int ch_val = 0;
788        if (AtChar<B::Base,'x'>(cur())) {
789                Advance(1);
790                while(at_HexDigit<B::Base>(cur())){
791                        ch_val = HexVal<B::Base>(cur()[0]) + (ch_val<<4);
792                        if (ch_val> 0x10FFFF )
793                                WF_Error(wfErr_wf_Legalchar);
794                        Advance(1);
795                }
796        }
797        else {
798                while(at_Digit<B::Base>(cur())){
799                        ch_val = DigitVal<B::Base>(cur()[0]) + ch_val*10;
800                        if (ch_val> 0x10FFFF )
801                                WF_Error(wfErr_wf_Legalchar);
802                        Advance(1);
803                }
804        }
805        if ((ch_val == 0x0) || ((ch_val | 0x7FF) == 0xDFFF)|| ((ch_val | 0x1) == 0xFFFF))
806                                WF_Error(wfErr_wf_Legalchar);   
807                else  if (entity_Info->version != XML_1_1)
808                        if (((ch_val < 0x20) && (ch_val != 0x9) && (ch_val != 0xD) && (ch_val != 0xA)))
809                                WF_Error(wfErr_wf_Legalchar); 
810                               
811        if (!AtChar<B::Base,';'>(cur())) {
812                        Syntax_Error(NT_CharRef);
813        }
814                else {
815                        Advance(1);
816                        Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
817                }
818}
819
820template <class B>
821void ParsingEngine<B>::Parse_PI (){
822        int nameID;
823        Advance(2); /* Skip "<?". */
824        int target_start = AbsPos();
825        if (at_XxMmLll<B::Base>(cur())) {
826                nameID = Parse_Name();
827                if (AbsPos() - target_start == 3) Syntax_Error(NT_PI);
828        }
829        else nameID = Parse_Name();
830        PI_Target_action(GetCodeUnitPtr(target_start), LengthFrom(target_start));
831        if (!at_PI_End<B::Base>(cur())) requireWS();
832        ScanTo(QMark);
833        while (!at_PI_End<B::Base>(cur())) {
834                if(at_EOF())
835                        Syntax_Error(NT_PI);
836                Advance(1);
837                ScanTo(QMark);
838        }
839        Advance(2); /* Skip "?>". */
840        PI_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
841}
842 
843/* Parse a start or empty element tag. */
844template <class B>
845inline void ParsingEngine<B>::Parse_StartTag (){
846        int att_name_start;
847        int att_val_start;
848        int att_name_end, att_val_end;
849        unsigned char quoteCh;
850        Advance(1);
851        int nameID = Parse_Name();  /* Name delimiter: WS, "/" or ">" */
852        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
853        /* The following test optimizes the most common case of a
854        start tag with no attributes.  */
855        if (AtChar<B::Base,'>'>(cur())) {
856                Advance(1);
857                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
858        }
859        else {
860                ScanTo(NonWS);
861                if (AtChar<B::Base,'>'>(cur())) {
862                        Advance(1);
863                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
864                }
865                else if (at_EmptyElementDelim<B::Base>(cur())) {
866                        Advance(2);
867                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
868                }
869                else do {
870                        /* Must be an attribute-value pair or error. */
871                        att_name_start = AbsPos();
872                        int att_nameID = Parse_Name();
873                        att_name_end = AbsPos();
874               
875                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
876                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
877                        else {
878                                if (LastAttOccurrence[attID] > text_or_markup_start) {
879                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
880                                        break;
881                                }                       
882                        }
883                        LastAttOccurrence[attID] = att_name_start;
884                        /* The following optimized tests handle the frequently occurring
885                        case that there are no blanks on either side of the equals sign.
886                        In many cases, the very first test handles 100% of actual
887                        attribute-value pairs encountered. */
888                        if (at_EqualsQuote<B::Base>(cur())) Advance(1); 
889                        else {
890                                ScanTo(NonWS);
891                                if (!AtChar<B::Base,'='>(cur())) {
892                                        Syntax_Error(NT_STag); 
893                                        break;
894                                }
895                                Advance(1);
896                                ScanTo(NonWS);
897                                if (!AtQuote<B::Base>(cur())) {
898                                        Syntax_Error(NT_STag); 
899                                        break;
900                                }
901                        }
902                        att_val_start = AbsPos()+1;
903                        Parse_AttValue();
904                        att_val_end = AbsPos()-1;
905                        if (at_xmlns<B::Base>(cur()+att_name_start-AbsPos())) {
906                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
907                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
908                        }
909                        else {
910                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
911                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
912                        }
913                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
914                        if (AtChar<B::Base,'>'>(cur())) {
915                                Advance(1);
916                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
917                                break;
918                        }
919                        else if (at_EmptyElementDelim<B::Base>(cur())) {
920                                Advance(2);
921                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
922                                break;
923                        }
924                        ScanTo(NonWS);
925                        if (AtChar<B::Base,'>'>(cur())) {
926                                Advance(1);
927                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
928                                break;
929                        }
930                        else if (at_EmptyElementDelim<B::Base>(cur())) {
931                                Advance(2);
932                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
933                                break;
934                        }
935                        else if (AbsPos() == att_val_end + 1) { 
936                                /* No WS following att value */
937                                Syntax_Error(NT_STag);
938                                break;
939                        }
940                } while (1);
941        }
942}
943
944template <class B>
945inline void ParsingEngine<B>::text_if_nonnull_action(bool more){
946        if (AbsPos() > text_or_markup_start) {
947                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start), more);
948                text_or_markup_start = AbsPos();
949        }
950}
951
952template <class B>
953void ParsingEngine<B>::Parse_WF_EndTag(int nameID) {
954        Advance(2);
955        int end_nameID = Parse_Name();
956        if(end_nameID != nameID)
957                WF_Error(wfErr_GIMatch);
958        if (AtChar<B::Base,'>'>(cur())) {
959                Advance(1);
960                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
961        }
962    else {
963                ScanTo(NonWS);
964                if (AtChar<B::Base,'>'>(cur())) {
965                        Advance(1);
966                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
967                }
968                else Syntax_Error(NT_ETag);
969    }
970}
971
972template <>
973void ParsingEngine<UTF8_Buffer>::Parse_WF_EndTag(int nameID) {
974        Advance(2); /* Skip "</". */
975       
976        int name_start = AbsPos();
977//      ScanTo(NameFollow);
978//      int lgth = AbsPos()-name_start;
979
980#if (not defined(OMISSION)) or ((OMISSION != END_TAG_MATCHING)  and (OMISSION != NAME_LOOKUP))
981        char * start_elem_name = model_info->symbol_table->Get_UTF8_name(nameID);
982        int lgth = model_info->symbol_table->Get_UTF8_lgth(nameID);
983        char * end_elem_name = &((char *) x8data)[buffer_rel_pos];
984       
985#ifdef TEMPLATED_SIMD_LIB       
986        BytePack byte_compare =  simd<8>::eq(sisd_load_unaligned((BytePack *) end_elem_name),
987                                                           sisd_load_unaligned((BytePack *) start_elem_name));
988#endif
989#ifndef TEMPLATED_SIMD_LIB     
990        BytePack byte_compare =  simd_eq_8(sisd_load_unaligned((BytePack *) end_elem_name),
991                                                           sisd_load_unaligned((BytePack *) start_elem_name));
992#endif
993        if (lgth < 16) {
994                int expected_bits = ~(-1 << lgth);
995            if ((_mm_movemask_epi8(byte_compare) & expected_bits) != expected_bits) {
996                        WF_Error(wfErr_GIMatch);
997            }
998        }
999        else {
1000            /* Must compare with bytes beyond the first 16.  Set up to
1001               compare 16 bytes at a time, with the first additional compare
1002               overlapping with the first byte_compare. */
1003            int pos = (lgth - 1) % PACKSIZE + 1;
1004#ifdef TEMPLATED_SIMD_LIB
1005            byte_compare =  simd_or(byte_compare, simd<8>::eq(sisd_load_unaligned((BytePack *) &end_elem_name[pos]),
1006                                                                                        sisd_load_unaligned((BytePack *) &start_elem_name[pos])));
1007#endif
1008#ifndef TEMPLATED_SIMD_LIB
1009            byte_compare =  simd_or(byte_compare, simd_eq_8(sisd_load_unaligned((BytePack *) &end_elem_name[pos]),
1010                                                                                        sisd_load_unaligned((BytePack *) &start_elem_name[pos])));
1011#endif
1012            pos += 16;
1013            while (pos < lgth) {
1014                if (_mm_movemask_epi8(byte_compare) != 0xFFFF) {
1015                        WF_Error(wfErr_GIMatch);
1016                }
1017#ifdef TEMPLATED_SIMD_LIB
1018                byte_compare =  simd<8>::eq(sisd_load_unaligned((BytePack *) &end_elem_name[pos]),
1019                                                  sisd_load_unaligned((BytePack *) &start_elem_name[pos]));
1020#endif
1021#ifndef TEMPLATED_SIMD_LIB
1022                byte_compare =  simd_eq_8(sisd_load_unaligned((BytePack *) &end_elem_name[pos]),
1023                                                  sisd_load_unaligned((BytePack *) &start_elem_name[pos]));
1024#endif
1025                pos += 16;
1026            }
1027            if (_mm_movemask_epi8(byte_compare) != 0xFFFF) {
1028                        WF_Error(wfErr_GIMatch);
1029            }
1030        }
1031        Advance(lgth);
1032
1033#endif
1034#if defined(OMISSION) and ((OMISSION == END_TAG_MATCHING) or (OMISSION == NAME_LOOKUP))
1035        ScanTo(NameFollow);
1036#endif
1037//      for(int i=0; i<lgth; i++) {
1038//              if (start_elem_name[i] != end_elem_name[i])
1039//                      WF_Error(wfErr_GIMatch);
1040//      }
1041//      if (start_elem_name[lgth] != '\0') WF_Error(wfErr_GIMatch);
1042
1043        if (AtChar<ASCII,'>'>(cur())) {
1044                Advance(1);
1045                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1046        }
1047    else {
1048                ScanTo(NonWS);
1049                if (AtChar<ASCII,'>'>(cur())) {
1050                        Advance(1);
1051                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1052                }
1053                else Syntax_Error(NT_ETag);
1054    }
1055}
1056/* Parse a valid start or empty element tag. */
1057template <class B>
1058int ParsingEngine<B>::Parse_WF_StartTag (bool& is_emptyStartTag){
1059        int att_name_start;
1060        int att_val_start;
1061        int att_name_end, att_val_end;
1062        unsigned char quoteCh;
1063        Advance(1);
1064       
1065        #if (not defined(OMISSION)) or (OMISSION != NAME_LOOKUP)
1066        int nameID = Parse_Name(); 
1067        #endif
1068        #if (defined(OMISSION)) and (OMISSION == NAME_LOOKUP)
1069        ScanTo(NameFollow);
1070        int nameID = 0;
1071        #endif
1072        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
1073        /* The following test optimizes the most common case of a
1074        start tag with no attributes.  */
1075        if (AtChar<B::Base,'>'>(cur())) {
1076                Advance(1);
1077                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1078        }
1079        else {
1080                ScanTo(NonWS);
1081                if (AtChar<B::Base,'>'>(cur())) {
1082                        Advance(1);
1083                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1084                }
1085                else if (at_EmptyElementDelim<B::Base>(cur())) {
1086                        Advance(2);
1087                        is_emptyStartTag = true;
1088                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1089                }
1090                else do {
1091                        /* Must be an attribute-value pair or error. */
1092                        att_name_start = AbsPos();
1093                        #if (not defined(OMISSION)) or (OMISSION != NAME_LOOKUP)
1094                        int att_nameID = Parse_Name(); 
1095                        #endif
1096                        #if (defined(OMISSION)) and (OMISSION == NAME_LOOKUP)
1097                        ScanTo(NameFollow);
1098                        int att_nameID = 0;
1099                        #endif
1100            att_name_end = AbsPos();
1101                #if (not defined(OMISSION)) or ((OMISSION != ATTRIBUTE_UNIQUENESS) and (OMISSION != NAME_LOOKUP))
1102                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
1103                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1104                        else {
1105                                if (LastAttOccurrence[attID] > text_or_markup_start) {
1106                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
1107                                        break;
1108                                }                       
1109                        }
1110                        LastAttOccurrence[attID] = att_name_start;
1111                 #endif
1112                        /* The following optimized tests handle the frequently occurring
1113                        case that there are no blanks on either side of the equals sign.
1114                        In many cases, the very first test handles 100% of actual
1115                        attribute-value pairs encountered. */
1116                        if (at_EqualsQuote<B::Base>(cur())) Advance(1); 
1117                        else {
1118                                ScanTo(NonWS);
1119                                if (!AtChar<B::Base,'='>(cur())) {
1120                                        Syntax_Error(NT_STag); 
1121                                        break;
1122                                }
1123                                Advance(1);
1124                                ScanTo(NonWS);
1125                                if (!AtQuote<B::Base>(cur())) {
1126                                        Syntax_Error(NT_STag); 
1127                                        break;
1128                                }
1129                        }
1130                        att_val_start = AbsPos()+1;
1131                        Parse_AttValue();
1132                        att_val_end = AbsPos()-1;
1133                        if (at_xmlns<B::Base>(cur()+att_name_start-AbsPos())) {
1134                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
1135                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
1136                        }
1137                        else {
1138                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
1139                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
1140                        }
1141                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
1142                        if (AtChar<B::Base,'>'>(cur())) {
1143                                Advance(1);
1144                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1145                                break;
1146                        }
1147                        else if (at_EmptyElementDelim<B::Base>(cur())) {
1148                                Advance(2);
1149                                is_emptyStartTag = true;       
1150                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1151                                break;
1152                        }
1153                        ScanTo(NonWS);
1154                        if (AtChar<B::Base,'>'>(cur())) {
1155                                Advance(1);
1156                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1157                                break;
1158                        }
1159                        else if (at_EmptyElementDelim<B::Base>(cur())) {
1160                                Advance(2);
1161                                is_emptyStartTag = true;
1162                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1163                                break;
1164                        }
1165                        else if (AbsPos() == att_val_end + 1) { 
1166                                /* No WS following att value */
1167                                Syntax_Error(NT_STag);
1168                                break;
1169                        }
1170                } while (1);
1171        }
1172        return nameID;
1173}
1174
1175
1176
1177template <class B>
1178void ParsingEngine<B>::Parse_WF_Element() {
1179        bool is_emptyStartTag = false;
1180        int nameID = Parse_WF_StartTag(is_emptyStartTag);
1181#ifdef DEBUG
1182        printf("Parse_Element: nameID = %d, is_emptyStartTag=%i\n",nameID, is_emptyStartTag);
1183#endif
1184        if (!is_emptyStartTag) {
1185                Parse_WF_Content();
1186                Parse_WF_EndTag(nameID);
1187        }
1188}
1189
1190
1191template <class B>
1192void ParsingEngine<B>::Parse_WF_Content() {
1193        do {
1194                text_or_markup_start = AbsPos();
1195                ScanTextTo(MarkupStart); /* '<', '&', or ']' for ']]>' test */
1196                if (at_ElementTag_Start<B::Base>(cur())) {
1197                        text_if_nonnull_action(false);
1198                        Parse_WF_Element();
1199                }
1200                else if (at_EndTag_Start<B::Base>(cur())) {
1201                        text_if_nonnull_action(false);
1202                        return;
1203                }
1204                else if (at_Comment_Start<B::Base>(cur())) {
1205                        text_if_nonnull_action(false);
1206                        Parse_Comment();
1207                }
1208                else if (at_CharRef_Start<B::Base>(cur())) {
1209                        text_if_nonnull_action(true);
1210                        Parse_CharRef();
1211                }
1212                else if (AtChar<B::Base,'&'>(cur())) {
1213                        text_if_nonnull_action(true);
1214                        Parse_EntityRef();
1215                }
1216                else if (at_CDATA_Start<B::Base>(cur())) {
1217                        text_if_nonnull_action(true);
1218                        Parse_CDATA();
1219                }
1220                else if (at_PI_Start<B::Base>(cur())) {
1221                        text_if_nonnull_action(false);
1222                        Parse_PI();
1223                }
1224                else if (at_CDATA_End<B::Base>(cur())) {
1225                        text_if_nonnull_action(true);
1226                        Advance(3);
1227                        Syntax_Error(NT_CharData);
1228                }
1229                else if (at_EOF()) {
1230                        text_if_nonnull_action(false);
1231                        return;
1232                }
1233                else if (AtChar<B::Base,'<'>(cur())) {
1234                        Syntax_Error(NT_markupdecl);
1235                }
1236                else {
1237                        Advance(1);
1238                        continue;
1239                }
1240        } while (1);
1241}
1242
1243
1244
1245template <class B>
1246void ParsingEngine<B>::ParseContent() {
1247        DocumentStart_action(); 
1248        bool is_emptyStartTag = false;
1249        do {
1250                text_or_markup_start = AbsPos();
1251                ScanTextTo(MarkupStart); /* '<', '&', or ']' for ']]>' test */
1252/*              if (AtChar<B::Base,'<'>(cur())) {
1253                        text_if_nonnull_action();
1254                        Parse_Markup<B>();
1255                }*/
1256                if (at_ElementTag_Start<B::Base>(cur())) {
1257                        text_if_nonnull_action(false);
1258                        Parse_StartTag();
1259                }
1260                else if (at_EndTag_Start<B::Base>(cur())) {
1261                        text_if_nonnull_action(false);
1262                        Parse_EndTag();
1263                }
1264                else if (at_Comment_Start<B::Base>(cur())) {
1265                        text_if_nonnull_action(false);
1266                        Parse_Comment();
1267                }
1268                else if (at_CharRef_Start<B::Base>(cur())) {
1269                        text_if_nonnull_action(true);
1270                        Parse_CharRef();
1271                }
1272                else if (AtChar<B::Base,'&'>(cur())) {
1273                        text_if_nonnull_action(true);
1274                        Parse_EntityRef();
1275                }
1276                else if (at_CDATA_Start<B::Base>(cur())) {
1277                        text_if_nonnull_action(true);
1278                        Parse_CDATA();
1279                }
1280                else if (at_PI_Start<B::Base>(cur())) {
1281                        text_if_nonnull_action(false);
1282                        Parse_PI();
1283                }
1284                else if (at_CDATA_End<B::Base>(cur())) {
1285                        text_if_nonnull_action(true);
1286                        Advance(3);
1287                        Syntax_Error(NT_CharData);
1288                }
1289                else if (at_EOF()) {
1290                        text_if_nonnull_action(false);
1291                        break;
1292                }
1293                else if (AtChar<B::Base,'<'>(cur())) {
1294                        Syntax_Error(NT_markupdecl);
1295                }
1296                else {
1297                        Advance(1);
1298                        continue;
1299                }
1300        } while (1);
1301        DocumentEnd_action();   
1302}
1303
1304
1305template <class B>
1306void ParsingEngine<B>::Parse_DocType (){
1307
1308        int old_abspos, start_pos;
1309        ScanTo(NonWS);
1310        start_pos = AbsPos();
1311       
1312        if (at_DOCTYPE_start<B::Base>(cur()))
1313        Advance(9);
1314        else{
1315//              printf("No Document definition!\n");
1316                return;
1317        }
1318        requireWS();
1319        int nameID = Parse_Name();
1320
1321        old_abspos = AbsPos(); 
1322    ScanTo(NonWS);
1323    if(at_SYSTEM<B::Base>(cur())||at_PUBLIC<B::Base>(cur())){
1324        model_info->has_external_DTD = true;
1325        if(old_abspos == AbsPos())
1326                Syntax_Error(NT_doctypedecl);
1327        Parse_ExternalID(model_info->external_DTD_systemLiteral, model_info->external_DTD_pubidLiteral);
1328        Parser_Interface * entity_parser;
1329        entity_parser = ParserFactory(model_info->external_DTD_systemLiteral, model_info);
1330                entity_parser->Parse_ExtSubsetDecl();
1331                entity_parser->~Parser_Interface();
1332    }
1333    else model_info->has_external_DTD = false;
1334    ScanTo(NonWS);     
1335
1336        if (AtChar<B::Base,'['>(cur())){
1337                Advance(1);
1338                Parse_IntSubset();
1339                if (AtChar<B::Base,']'>(cur()))
1340                        Advance(1);
1341                else
1342                Syntax_Error(NT_doctypedecl);
1343                ScanTo(NonWS);
1344        }
1345       
1346        if (AtChar<B::Base,'>'>(cur())){
1347                Advance(1); 
1348
1349                CRE_Seq * rslt = new CRE_Seq();
1350                rslt->subCMs.push_back(new CRE_Name(nameID));
1351                CM_RegExp * cre = new CM_RegExp();
1352                cre->content_re = rslt;         
1353               
1354                int id_count = cre->content_re->Set_IDs(0);
1355                cre->content_re->Set_First_Map();               
1356                symbol_set_t * transition_map = new symbol_set_t[id_count+1];
1357                cre->content_re->follow_map[0] = id_count+1;
1358               
1359                cre->content_re->Set_Follow_Map(transition_map);
1360                transition_map[0] = cre->content_re->first_map;
1361                if (cre->content_re->matches_empty)
1362                        transition_map[0][0]=id_count+1;
1363                       
1364                cre -> transition_map = transition_map;
1365               
1366                model_info->rootModel = cre;
1367               
1368                /* Check for notations that were used, but not defined by the end of the DTD. */
1369                #if (VALIDATION_MODE == ON)
1370                hash_map<int, int >::iterator j;
1371                for (j=model_info->GlobalNotationTable.begin(); j!=model_info->GlobalNotationTable.end(); j++) {
1372                        if (j->second == -1)
1373                                Validity_Error(vErr_notatn);
1374                }
1375                #endif
1376        }
1377        else
1378                Syntax_Error(NT_doctypedecl);   
1379}
1380
1381template <class B>
1382void ParsingEngine<B>::Parse_ExternalID (char *& systemLiteral, char *& pubidLiteral){
1383        int quot_start, lgth;
1384        if(at_SYSTEM<B::Base>(cur())){
1385                Advance(6);
1386                pubidLiteral = NULL;
1387                requireWS();
1388                if (!AtQuote<B::Base>(cur())) Syntax_Error(NT_ExternalID);
1389                quot_start = AbsPos()+1;
1390                Parse_SystemLiteral (); /*  SystemLiteral */
1391                lgth = AbsPos() - quot_start - 1;                       
1392                systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1393        }
1394        else if (at_PUBLIC<B::Base>(cur())){
1395                Advance(6);
1396                requireWS();
1397                if (!AtQuote<B::Base>(cur())) Syntax_Error(NT_ExternalID);
1398                quot_start = AbsPos()+1;
1399                Parse_PubidLiteral ();/*  PubidLiteral */
1400                lgth = AbsPos() - quot_start - 1;                       
1401                pubidLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1402                systemLiteral = NULL;
1403                if (AtChar<B::Base, '>'>(cur())) return;
1404                requireWS();
1405                if (AtQuote<B::Base>(cur())) {
1406                        quot_start = AbsPos()+1;       
1407                        Parse_SystemLiteral ();/*  SystemLiteral */
1408                        lgth = AbsPos() - quot_start - 1;                       
1409                        systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1410                }
1411        }
1412        else
1413                Syntax_Error(NT_ExternalID); 
1414}
1415
1416template <class B>
1417void ParsingEngine<B>::Parse_SystemLiteral (){
1418        unsigned char quoteCh;
1419        if(AtQuote<B::Base>(cur())){
1420                quoteCh = cur()[0];
1421                Advance(1);
1422        }       
1423        ScanTo(Quote);                 
1424        while (cur()[0] != quoteCh){
1425                if(at_EOF())
1426                        Syntax_Error(NT_SystemLiteral);
1427                Advance(1);
1428                ScanTo(Quote);
1429        }
1430        Advance(1);
1431}
1432
1433template <class B>
1434void ParsingEngine<B>::Parse_PubidLiteral (){
1435        unsigned char quoteCh;
1436        quoteCh = cur()[0];
1437        Advance(1);
1438        while (at_PubidChar<B::Base>(cur()) && (cur()[0] != quoteCh)) {
1439                Advance(1);
1440        }
1441        if (cur()[0] != quoteCh){
1442                Syntax_Error(NT_PubidLiteral);
1443        }
1444        Advance(1);
1445}
1446
1447template <class B>
1448void ParsingEngine<B>::Parse_IntSubset (){
1449       
1450        while(1){
1451                ScanTo(NonWS); 
1452                text_or_markup_start = AbsPos();
1453                if (AtChar<B::Base,'%'>(cur()))
1454                        Parse_PEReference();   
1455                else if (at_PI_Start<B::Base>(cur())) {
1456                        Parse_PI();
1457                }
1458                else if (at_Comment_Start<B::Base>(cur())) {
1459                        Parse_Comment();
1460                }
1461                else if (AtChar<B::Base,'<'>(cur())){
1462                        Advance(1);
1463                        if(AtChar<B::Base,'!'>(cur())){
1464                                Advance(1);
1465                                if (at_ELEMENT<B::Base>(cur()))
1466                                        Parse_Elementdecl();
1467                                else if (at_ATTLIST<B::Base>(cur()))
1468                                        Parse_AttlistDecl();
1469                                else if (at_ENTITY<B::Base>(cur()))
1470                                        Parse_Entitydecl();
1471                                else if (at_NOTATION<B::Base>(cur()))
1472                                        Parse_Notationdecl();
1473                                else {
1474                                        Syntax_Error(NT_markupdecl);           
1475                                }                                                               
1476                        }
1477                        else
1478                                Syntax_Error(NT_markupdecl); 
1479                }
1480                else if (AtChar<B::Base,']'>(cur())){
1481                        break;
1482                }
1483                else
1484                        Syntax_Error(NT_intSubset); 
1485        }
1486}
1487
1488
1489template <class B>
1490void ParsingEngine<B>::Parse_PEReference (){
1491
1492        Advance(1); /* Skip "%". */
1493        fprintf(stderr,"Parameter Reference has not been completed yet.\n");
1494        exit(-1);
1495        int nameID = Parse_Name(); 
1496        if (AtChar<B::Base,';'>(cur())) {
1497                Advance(1);
1498                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1499                PEntity_info * this_info;
1500                Parser_Interface * entity_parser;
1501                int entityID = model_info->GlobalPEntityTable[nameID]; 
1502                if (entityID == 0)
1503                        WF_Error(wfErr_wf_entdeclared);
1504                else{
1505                        this_info = model_info->PEntityData[entityID-1];
1506                        if (this_info->is_external){
1507                               
1508//                      if (entity_Info->standalone != Standalone_no)
1509//                              WF_Error(wfErr_NoExternalRefs);
1510//                      else {
1511                                        entity_parser = ParserFactory(this_info->systemLiteral, model_info);
1512                                        entity_parser->Parse_WF_Content();
1513                                        if(!entity_parser->at_EOF())
1514                                                Syntax_Error(NT_content);
1515                                        entity_parser->~Parser_Interface();
1516//                      }
1517                        }
1518                        else {
1519                        }
1520                }
1521        }
1522        else
1523                Syntax_Error(NT_PEReference);
1524}
1525
1526
1527template <class B>
1528void ParsingEngine<B>::Parse_Elementdecl (){
1529
1530        Advance(7); /* Skip "<!ELEMENT". */
1531
1532    requireWS();
1533        int nameID = Parse_Name();
1534        int elemID = model_info->getOrInsertGlobalElement(nameID);
1535
1536        requireWS();
1537        ContentModel * cm;
1538        /* Start parsing "contentspec"*/
1539        if (at_EMPTY<B::Base>(cur())) {
1540        Advance(5);
1541        cm = new CM_Empty();
1542        model_info->ContentModelData[nameID] = cm;
1543        }
1544    else if (at_ANY<B::Base>(cur())) {
1545        Advance(3);
1546        cm = new CM_Any();
1547        model_info->ContentModelData[nameID] = cm;
1548    }
1549    else {
1550        if (AtChar<B::Base,'('>(cur()))
1551                        Advance(1);
1552                ScanTo(NonWS);
1553                if (at_PCDATA<B::Base>(cur())){
1554                        cm = Parse_RemainingMixed();
1555                        model_info->ContentModelData[nameID] = cm;
1556                }
1557                else{
1558
1559                        CM_RegExp * cre = new CM_RegExp;
1560                        cre->content_re = Parse_RemainingChildren();
1561
1562                        int id_count = cre->content_re->Set_IDs(0);
1563                        cre->content_re->Set_First_Map();       
1564                        symbol_set_t * transition_map = new symbol_set_t[id_count+1];
1565                        cre->content_re->follow_map[0] = id_count+1;
1566                       
1567                        cre->content_re->Set_Follow_Map(transition_map);
1568                        transition_map[0] = cre->content_re->first_map;
1569                       
1570                        if (cre->content_re->matches_empty)
1571                                transition_map[0][0]=id_count+1;
1572                               
1573                        cre -> transition_map = transition_map;
1574                       
1575                        model_info->ContentModelData[nameID] = cre;
1576                        cm = cre;
1577                }                       
1578    }
1579    ScanTo(NonWS);   
1580
1581        if (AtChar<B::Base,'>'>(cur())) {
1582                Advance(1);
1583        }
1584        else
1585                Syntax_Error(NT_elementdecl);
1586}
1587template <class B>
1588ContentModel * ParsingEngine<B>::Parse_RemainingMixed (){
1589        CM_Mixed * r = new CM_Mixed();
1590        Advance(7);  /* Skip "#PCDATA". */
1591   
1592    if (AtChar<B::Base,')'>(cur())){
1593        if (AtChar<B::Base,'*'>(cur())) {
1594                Advance(2);
1595                }
1596                else {
1597                        Advance(1);
1598                }
1599    }
1600    else{
1601        ScanTo(NonWS);
1602        int k = 0;
1603        while (AtChar<B::Base,'|'>(cur())){
1604                        Advance(1);
1605                        ScanTo(NonWS);
1606                        int nameID = Parse_Name();
1607                        r->elements[nameID] = ++k;
1608                        ScanTo(NonWS);
1609                }
1610                if (at_Para_star<B::Base>(cur())) Advance(2);
1611                else {
1612                        Syntax_Error(NT_Mixed);
1613                        exit(-1);
1614        }
1615    }
1616    return r;
1617}
1618
1619
1620template <class B>
1621Content_RE * ParsingEngine<B>::Parse_RemainingChildren (){
1622        Content_RE * c1 = Parse_Cp();
1623        Content_RE * r = c1;
1624        ScanTo(NonWS);
1625        if(AtChar<B::Base,'|'>(cur())){
1626                CRE_Choice * rslt = new CRE_Choice;
1627                rslt->subCMs.push_back(c1);
1628                Advance(1);
1629                ScanTo(NonWS);
1630                rslt->subCMs.push_back(Parse_Cp());
1631                ScanTo(NonWS);
1632                while(!AtChar<B::Base,')'>(cur())){
1633                        if(AtChar<B::Base,'|'>(cur()))
1634                                Advance(1);
1635                        else
1636                                Syntax_Error(NT_children);
1637                        ScanTo(NonWS);
1638                        rslt->subCMs.push_back(Parse_Cp());
1639                        ScanTo(NonWS);
1640                }
1641                Advance(1);
1642                rslt->Compile();
1643                r = rslt;
1644        }
1645        else if(AtChar<B::Base,','>(cur())){
1646                CRE_Seq * rslt = new CRE_Seq;
1647                rslt->subCMs.push_back(c1);
1648                Advance(1);
1649                ScanTo(NonWS);
1650                rslt->subCMs.push_back(Parse_Cp());
1651                ScanTo(NonWS);
1652                while(!AtChar<B::Base,')'>(cur())){
1653                        if(AtChar<B::Base,','>(cur()))
1654                                Advance(1);
1655                        else
1656                                Syntax_Error(NT_children);
1657                        ScanTo(NonWS);
1658                        rslt->subCMs.push_back(Parse_Cp());
1659                        ScanTo(NonWS);
1660                }
1661                Advance(1);
1662                rslt->Compile();
1663                r = rslt;
1664        }       
1665        else if(AtChar<B::Base,')'>(cur())){
1666                Advance(1);
1667        }
1668        else
1669                Syntax_Error(NT_children);
1670               
1671        if (AtChar<B::Base,'?'>(cur())) {
1672                Advance(1);
1673                r = new CRE_Opt(r);
1674        }
1675        else if (AtChar<B::Base,'*'>(cur())) {
1676                Advance(1);
1677                r = new CRE_Star(r);
1678        }
1679        else if (AtChar<B::Base,'+'>(cur())) {
1680                Advance(1);
1681                r = new CRE_Plus(r);
1682        }
1683
1684        return r;
1685}
1686
1687template <class B>
1688Content_RE * ParsingEngine<B>::Parse_Cp (){
1689        if (AtChar<B::Base,'('>(cur())){
1690                Advance(1);
1691                ScanTo(NonWS);
1692                Parse_RemainingChildren();
1693        }
1694        else{
1695                int nameID = Parse_Name();
1696                CRE_Name * r = new CRE_Name(nameID);
1697
1698                if (AtChar<B::Base,'?'>(cur())) {
1699                        Advance(1);
1700                        return new CRE_Opt(r);
1701                }
1702                else if (AtChar<B::Base,'*'>(cur())) {
1703                        Advance(1);
1704                        return new CRE_Star(r);
1705                }
1706                else if (AtChar<B::Base,'+'>(cur())) {
1707                        Advance(1);
1708                        return new CRE_Plus(r);
1709                }
1710                else return r;
1711        }
1712}
1713
1714template <class B>
1715void ParsingEngine<B>::Parse_AttlistDecl (){
1716       
1717        int old_abspos;
1718       
1719        int name_start;
1720        int lgth;
1721       
1722        int elemID;
1723        int attID;
1724       
1725        Advance(7); /* Skip "ATTLIST. */
1726        requireWS();
1727       
1728        int nameID = Parse_Name();
1729        elemID = model_info->getOrInsertGlobalElement(nameID);
1730       
1731        old_abspos = AbsPos();
1732        ScanTo(NonWS);
1733        while(!AtChar<B::Base,'>'>(cur())) {
1734                if(old_abspos == AbsPos())
1735                Syntax_Error(NT_AttlistDecl);
1736               
1737                int att_nameID = Parse_Name();
1738               
1739                attID = model_info->getOrInsertGlobalAttName(att_nameID);
1740                if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1741        ATT_info * this_info = new ATT_info;
1742        this_info->globalATT_id = attID;
1743        requireWS();
1744        if (at_CDATA<B::Base>(cur())){
1745                Advance(5);
1746                this_info->attType = CDATA_att;
1747        }
1748        else if(at_ID<B::Base>(cur())){
1749                Advance(2);
1750                this_info->attType = ID_att;
1751        }
1752        /* Make sure to check IDREFS before IDREF*/
1753        else if(at_IDREFS<B::Base>(cur())){
1754                Advance(6);
1755                this_info->attType = IDREFS_att;
1756        }
1757        else if(at_IDREF<B::Base>(cur())){
1758                Advance(5);
1759                this_info->attType = IDREF_att;
1760        }
1761        else if(at_ENTITY<B::Base>(cur())){
1762                Advance(6);
1763                this_info->attType = ENTITY_att;
1764        }
1765        else if(at_ENTITIES<B::Base>(cur())){
1766                Advance(8);
1767                this_info->attType = ENTITIES_att;
1768        }
1769        /* Make sure to check NMTOKENS before NMTOKEN*/
1770        else if(at_NMTOKENS<B::Base>(cur())){
1771                Advance(8);
1772                this_info->attType = NMTOKENS_att;
1773        }
1774        else if(at_NMTOKEN<B::Base>(cur())){
1775                Advance(7);
1776                this_info->attType = NMTOKEN_att;
1777        }
1778        else if(at_NOTATION<B::Base>(cur())){ /* NotationType = 'NOTATION' S Enumeration
1779                                                                         when Nmtoken = Name */
1780                Advance(8);
1781                        requireWS();
1782                Parse_Notation(this_info);
1783                this_info->attType = NOTATION_att;
1784        }
1785        else if(AtChar<B::Base,'('>(cur())){
1786                Parse_Enumeration(this_info);
1787                this_info->attType = enumeration_att;
1788        }
1789        else
1790                Syntax_Error(NT_AttlistDecl);
1791        requireWS();
1792        Parse_DefaultDecl(this_info);
1793
1794                ScanTo(NonWS);
1795                model_info->ElementAttributeData[elemID].push_back(this_info);
1796        }
1797
1798        Advance(1);
1799}
1800
1801template <class B>
1802void ParsingEngine<B>::Parse_Notation (ATT_info * this_info){
1803
1804        if(AtChar<B::Base,'('>(cur()))
1805                Advance(1);
1806        else
1807                Syntax_Error(NT_NotationType);
1808        ScanTo(NonWS);
1809       
1810    int notn_nameID = Parse_Name();
1811
1812        /*Notation name is not in the global table!*/
1813        if(model_info->GlobalNotationTable[notn_nameID]==0)
1814                model_info->GlobalNotationTable[notn_nameID] = -1;
1815       
1816        ScanTo(NonWS);
1817        while(AtChar<B::Base,'|'>(cur())){
1818                Advance(1);
1819                ScanTo(NonWS); 
1820                notn_nameID = Parse_Name();
1821                       
1822                if(model_info->GlobalNotationTable[notn_nameID]==0)
1823//                      Validity_Error(vErr_notatn);
1824                        model_info->GlobalNotationTable[notn_nameID] = -1;
1825                       
1826                ScanTo(NonWS);
1827        }
1828        if (AtChar<B::Base,')'>(cur())) 
1829                Advance(1);
1830        else
1831                Syntax_Error(NT_NotationType);
1832}
1833
1834template <class B>
1835void ParsingEngine<B>::Parse_Enumeration (ATT_info * this_info){
1836
1837        int enumCount=0;
1838        if(AtChar<B::Base,'('>(cur()))
1839                Advance(1);
1840        else
1841                Syntax_Error(NT_Enumeration);
1842        ScanTo(NonWS);
1843       
1844        int nmtokenID = Parse_Nmtoken();
1845       
1846        this_info->enumValues[nmtokenID]=++(enumCount);
1847       
1848        ScanTo(NonWS);
1849        while(AtChar<B::Base,'|'>(cur())){
1850                Advance(1);
1851                ScanTo(NonWS); 
1852                int nmtokenID = Parse_Nmtoken();
1853       
1854                int enumID = this_info->enumValues[nmtokenID];
1855                if(enumID==0){ 
1856                        this_info->enumValues[nmtokenID]=++(enumCount);
1857                        enumID = enumCount;
1858                }
1859                else if(!StrictWellFormedness){
1860                        Validity_Error(vErr_NoDuplicateTokens);
1861                }
1862                ScanTo(NonWS);
1863        }
1864        if (AtChar<B::Base,')'>(cur())) 
1865                Advance(1);
1866        else
1867                Syntax_Error(NT_Enumeration);
1868}
1869
1870template <class B>
1871void ParsingEngine<B>::Parse_DefaultDecl (ATT_info * this_info){
1872        if(at_REQUIRED<B::Base>(cur())){
1873                Advance(9);
1874                this_info->defaultKind = REQUIRED_att;
1875        }
1876        else if(at_IMPLIED<B::Base>(cur())){
1877                Advance(8);
1878                this_info->defaultKind = IMPLIED_att;
1879        }
1880        else {
1881                if(at_FIXED<B::Base>(cur())){
1882                        Advance(6);
1883                        requireWS();
1884                        this_info->defaultKind = FIXED_att;
1885                }
1886                else this_info->defaultKind = DEFAULT_att;
1887                if(AtQuote<B::Base>(cur())){
1888                        int quot_start = AbsPos()+1;
1889                        Parse_AttValue();
1890                        /* need to normalize */
1891                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
1892                       
1893                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
1894                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
1895                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
1896                        }
1897                else
1898                        Syntax_Error(NT_DefaultDecl);
1899        }
1900}
1901
1902template <class B>
1903void ParsingEngine<B>::Parse_Entitydecl (){
1904       
1905        int name_start;
1906        int quot_start;
1907        int lgth;
1908        int old_abspos;
1909        char * s;
1910       
1911        Advance(6); /* Skip "ENTITY. */
1912        requireWS();
1913       
1914        if (AtChar<B::Base,'%'>(cur())){
1915                Advance(1);
1916                requireWS();
1917               
1918                int nameID = Parse_Name();
1919                PEntity_info * this_info = new PEntity_info;
1920                int entityID = model_info->GlobalPEntityTable[nameID];
1921                if(entityID==0){       
1922                        model_info->GlobalPEntityTable[nameID]=++(model_info->globalPEntityCount);
1923                        entityID = model_info->globalPEntityCount;
1924                        this_info->globalPEntity_id = entityID;
1925                }
1926                else
1927                        printf("Warning: Entity definition already exist!\n");
1928       
1929                requireWS();
1930                if(AtQuote<B::Base>(cur())){
1931                Parse_PEntityValue(this_info);
1932                this_info->is_external = false;
1933        }
1934        else {
1935                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1936                this_info->is_external = true;
1937                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1938        }
1939        model_info->PEntityData.push_back(this_info);
1940        }
1941        else{
1942                int nameID = Parse_Name();
1943       
1944                GEntity_info * this_info = new GEntity_info();
1945                int entityID = model_info->GlobalGEntityTable[nameID];
1946                if(entityID==0){       
1947                        model_info->GlobalGEntityTable[nameID]=++(model_info->globalGEntityCount);
1948                        entityID = model_info->globalGEntityCount;
1949                        this_info->globalGEntity_id = entityID;
1950                }
1951                else
1952                        printf("Warning: Entity definition already exists!\n");
1953                       
1954                requireWS();
1955               
1956                if(AtQuote<B::Base>(cur())){
1957                Parse_GEntityValue(this_info);                 
1958                this_info->is_external = false;
1959        }
1960        else {
1961                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1962                this_info->is_external = true;
1963                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1964                        old_abspos = AbsPos();
1965                        ScanTo(NonWS);
1966                if(at_NDATA<B::Base>(cur())){
1967                        if(old_abspos == AbsPos())
1968                                Syntax_Error(NT_EntityDecl);
1969                        else
1970                                Advance(5);
1971                        requireWS();
1972                        name_start = AbsPos();
1973                        int nameID = Parse_Name();
1974                        lgth = AbsPos() - name_start;
1975                                this_info->NDataName = copy_string(GetCodeUnitPtr(name_start),lgth);
1976                }
1977                }
1978        model_info->GEntityData.push_back(this_info);
1979        }
1980        ScanTo(NonWS);
1981        if (AtChar<B::Base,'>'>(cur())){
1982                Advance(1);
1983        }
1984        else
1985                Syntax_Error(NT_EntityDecl);
1986}
1987
1988template <class B>
1989void ParsingEngine<B>::Parse_Notationdecl (){
1990
1991        int old_abspos;
1992        Advance(8); /* Skip "NOTATION. */
1993        requireWS();
1994       
1995        int nameID = Parse_Name();
1996
1997        int notationID = model_info->GlobalNotationTable[nameID];
1998        /* notationID == -1: used but not yet defined; == 0: new, > 0 prev. defined */
1999        if(notationID <= 0){   
2000                model_info->GlobalNotationTable[nameID]=++(model_info->globalNotationCount);
2001                notationID = model_info->globalNotationCount;
2002        }
2003        else /*Duplicate notation name!*/
2004                Validity_Error(vErr_NoDuplicateTokens);
2005        Notation_info * this_info = new Notation_info;
2006        ScanTo(NonWS);         
2007    Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
2008        ScanTo(NonWS);
2009        if (AtChar<B::Base,'>'>(cur())) {
2010                Advance(1);
2011        }
2012        else
2013                Syntax_Error(NT_NotationDecl);
2014}
2015
2016template <class B>
2017void ParsingEngine<B>::requireWS(){
2018       
2019    int old_abspos = AbsPos(); 
2020    ScanTo(NonWS);
2021    if(old_abspos == AbsPos())
2022        Syntax_Error(NT_S);
2023}
2024
2025template <class B>
2026void ParsingEngine<B>::Parse_AttValue(){
2027       
2028        int     quoteCh = cur()[0];
2029        Advance(1); /* Skip " or ' */
2030
2031        ScanTo(Quote);                 
2032        while (cur()[0] != quoteCh){
2033                if (at_CharRef_Start<B::Base>(cur())){
2034                        Parse_CharRef();
2035                        ScanTo(Quote);
2036                }
2037                else if (AtChar<B::Base,'&'>(cur())){
2038                        Parse_EntityRef();
2039                        ScanTo(Quote);
2040                }
2041                else if (AtQuote<B::Base>(cur())) {
2042                        Advance(1);
2043                        ScanTo(Quote);
2044                }
2045                else /* if (AtChar<B::Base,'<'>(cur())) */
2046                        WF_Error(wfErr_CleanAttrVals);
2047        }
2048        Advance(1);
2049}
2050
2051template <class B>
2052void ParsingEngine<B>::Parse_GEntityValue(GEntity_info * this_info){
2053       
2054        int     quoteCh = cur()[0];
2055        Advance(1); /* Skip " or ' */
2056        this_info->is_simple = true;
2057        int quot_start = AbsPos();
2058        char * replText;
2059        ScanTo(Quote);         
2060        replText = copy_string(GetCodeUnitPtr(quot_start),AbsPos()-quot_start);
2061        while (cur()[0] != quoteCh){
2062                if (at_CharRef_Start<B::Base>(cur())){
2063                        strcat (replText,Replace_CharRef());
2064                        quot_start = AbsPos();
2065                        ScanTo(Quote);
2066                }
2067                else if (AtQuote<B::Base>(cur())) {
2068                        quot_start = AbsPos();
2069                        Advance(1);
2070                        ScanTo(Quote);
2071                }
2072                else if (at_EOF()) {
2073                        Syntax_Error(NT_EntityValue);
2074                }
2075                else { /* '<' or '&' found */
2076                        quot_start = AbsPos();
2077                        Advance(1);
2078                        ScanTo(Quote);
2079                        this_info->is_simple = false;                   
2080                }
2081                replText = cat_string (replText,(char *)GetCodeUnitPtr(quot_start), strlen(replText), AbsPos()-quot_start);
2082        }
2083        this_info->ReplacementText = replText;
2084        Advance(1);
2085}
2086
2087template <class B>
2088char * ParsingEngine<B>::Replace_EntityRef(bool& is_simple){
2089        Advance(1);
2090        int nameID = Parse_Name(); 
2091        if (AtChar<B::Base,';'>(cur()))
2092                Advance(1);
2093        else
2094                Syntax_Error(NT_EntityValue);
2095        int entityID = model_info->GlobalGEntityTable[nameID]; 
2096        if (entityID == 0)
2097                WF_Error(wfErr_wf_entdeclared);
2098        else{
2099                if (model_info->GEntityData[entityID-1]->is_simple == false)
2100                        is_simple = false;
2101                return model_info->GEntityData[entityID-1]->ReplacementText;
2102        }
2103       
2104}
2105
2106template <class B>
2107void ParsingEngine<B>::Parse_PEntityValue(PEntity_info * this_info){
2108        fprintf(stderr,"parsing of parameter entity value has not been completed yet.\n");
2109        exit(-1);
2110}
2111
2112template <class B>
2113char * ParsingEngine<B>::Replace_CharRef(){
2114        Advance(2);
2115        fprintf(stderr,"Replacement of Character Reference has not been completed yet.\n");
2116        exit(-1);
2117}
2118
2119template <class B>
2120void ParsingEngine<B>::Parse_Prolog(){
2121        ScanTo(NonWS);
2122        int old_pos = AbsPos();
2123        while (!at_DOCTYPE_start<B::Base>(cur())) {             
2124                text_or_markup_start = AbsPos();
2125                if (at_Comment_Start<B::Base>(cur())) 
2126                        Parse_Comment();
2127                else if (at_PI_Start<B::Base>(cur()))
2128                                Parse_PI();
2129                else{
2130                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
2131                        return;
2132                }
2133                ScanTo(NonWS);
2134        }
2135        Parse_DocType();
2136        ScanTo(NonWS);
2137        while(at_Comment_Start<B::Base>(cur()) || at_PI_Start<B::Base>(cur()) ){               
2138                text_or_markup_start = AbsPos();
2139                if (at_Comment_Start<B::Base>(cur()))
2140                        Parse_Comment();
2141                else 
2142                        Parse_PI();
2143                ScanTo(NonWS);
2144        }
2145        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
2146}
2147
2148template <class B>
2149void ParsingEngine<B>::Parse_ExtSubsetDecl() {
2150        ScanTo(NonWS);
2151        int start_pos=AbsPos();
2152        while(!at_EOF()){
2153                if(at_condSect_start<B::Base>(cur())){         
2154                        Advance(3);
2155                        ScanTo(NonWS);
2156                        if (at_INCLUDE<B::Base>(cur())){
2157                                Advance(7);
2158                                ScanTo(NonWS);
2159                                if(AtChar<B::Base,'['>(cur())){
2160                                        Advance(1);
2161                                        Parse_ExtSubsetDecl();
2162                                        if(at_CDATA_End<B::Base>(cur()))
2163                                                Advance(3);
2164                                        else Syntax_Error(NT_includeSect);
2165                                }
2166                                else Syntax_Error(NT_includeSect);
2167                        }
2168                        else if (at_IGNORE<B::Base>(cur())){
2169                                Advance(6);
2170                                ScanTo(NonWS);         
2171                                if(AtChar<B::Base,'['>(cur())){
2172                                        int section_depth=1;
2173                                        Advance(1);
2174                                        while(!at_EOF()){
2175                                                ScanTextTo(MarkupStart);
2176                                                if(at_condSect_start<B::Base>(cur())){
2177                                                        Advance(3);
2178                                                        section_depth++;
2179                                                }
2180                                                else if(at_CDATA_End<B::Base>(cur())){
2181                                                        Advance(3);
2182                                                        section_depth--;
2183                                                }
2184                                                else
2185                                                        Advance(1);
2186                                                if(section_depth==0) return;                                   
2187                                        }
2188                                        Syntax_Error(NT_ignoreSectContents);   
2189                                }
2190                                else Syntax_Error(NT_ignoreSect);
2191                        }
2192                        else Syntax_Error(NT_conditionalSect);
2193                }
2194                else if (AtChar<B::Base,'%'>(cur()))
2195                        Parse_PEReference();   
2196                else if (at_PI_Start<B::Base>(cur())) {
2197                        Parse_PI();
2198                }
2199                else if (at_Comment_Start<B::Base>(cur())) {
2200                        Parse_Comment();
2201                }
2202                else if (AtChar<B::Base,'<'>(cur())){
2203                        Advance(1);
2204
2205                        if(AtChar<B::Base,'!'>(cur())){
2206                                Advance(1);
2207                                if(at_ELEMENT<B::Base>(cur()))
2208                                        Parse_Elementdecl();
2209                                else if(at_ATTLIST<B::Base>(cur()))
2210                                        Parse_AttlistDecl();
2211                                else if(at_ENTITY<B::Base>(cur()))
2212                                        Parse_Entitydecl();
2213                                else if(at_NOTATION<B::Base>(cur()))
2214                                        Parse_Notationdecl();                                   
2215                                else{
2216                                        Syntax_Error(NT_markupdecl);   
2217                                }                                                               
2218                        }
2219                        else
2220                                Syntax_Error(NT_markupdecl); 
2221                }
2222                else
2223                        Syntax_Error(NT_extSubsetDecl); 
2224                ScanTo(NonWS);
2225        }
2226        ExtSubsetDecl_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
2227}
2228
2229/* Parse a valid start or empty element tag. */
2230template <class B>
2231inline int ParsingEngine<B>::Parse_ValidStartTag (bool& is_emptyStartTag){
2232        int att_name_start;
2233        int att_val_start;
2234        int att_name_end, att_val_end;
2235        unsigned char quoteCh;
2236        Advance(1);
2237
2238        int nameID = Parse_Name(); 
2239        int elemID = model_info->GlobalElementTable[nameID];
2240        if(elemID==0)
2241                        Validity_Error(vErr_elementvalid);
2242       
2243        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
2244        /* The following test optimizes the most common case of a
2245        start tag with no attributes.  */
2246        if (AtChar<B::Base,'>'>(cur())) {
2247                Advance(1);
2248                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2249        }
2250        else {
2251                ScanTo(NonWS);
2252                if (AtChar<B::Base,'>'>(cur())) {
2253                        Advance(1);
2254                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2255                }
2256                else if (at_EmptyElementDelim<B::Base>(cur())) {
2257                        Advance(2);
2258                        is_emptyStartTag = true;
2259                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2260                }
2261                else do {
2262                        /* Must be an attribute-value pair or error. */
2263                        att_name_start = AbsPos();
2264                        int att_nameID = Parse_Name();
2265                        #if (not defined(OMISSION)) or (OMISSION != ATTRIBUTE_UNIQUENESS) 
2266                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
2267                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
2268                        else {
2269                                if (LastAttOccurrence[attID] > text_or_markup_start) {
2270                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
2271                                        break;
2272                                }                       
2273                        }
2274                        LastAttOccurrence[attID] = att_name_start;
2275                        #endif
2276                        /* The following optimized tests handle the frequently occurring
2277                        case that there are no blanks on either side of the equals sign.
2278                        In many cases, the very first test handles 100% of actual
2279                        attribute-value pairs encountered. */
2280                        if (at_EqualsQuote<B::Base>(cur())) Advance(1); 
2281                        else {
2282                                ScanTo(NonWS);
2283                                if (!AtChar<B::Base,'='>(cur())) {
2284                                        Syntax_Error(NT_STag); 
2285                                        break;
2286                                }
2287                                Advance(1); 
2288                                ScanTo(NonWS);
2289                                if (!AtQuote<B::Base>(cur())) {
2290                                        Syntax_Error(NT_STag); 
2291                                        break;
2292                                }
2293                        }
2294                        att_val_start = AbsPos()+1;
2295                        Parse_AttValue();
2296                        att_val_end = AbsPos()-1;
2297                        if (at_xmlns<B::Base>(cur()+att_name_start-AbsPos())) {
2298                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
2299                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
2300                        }
2301                        else {
2302                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
2303                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
2304                        }
2305                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
2306                        if (AtChar<B::Base,'>'>(cur())) {
2307                                Advance(1);
2308                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2309                                break;
2310                        }
2311                        else if (at_EmptyElementDelim<B::Base>(cur())) {
2312                                Advance(2);
2313                                is_emptyStartTag = true;       
2314                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2315                                break;
2316                        }
2317                        ScanTo(NonWS);
2318                        if (AtChar<B::Base,'>'>(cur())) {
2319                                Advance(1);
2320                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2321                                break;
2322                        }
2323                        else if (at_EmptyElementDelim<B::Base>(cur())) {
2324                                Advance(2);
2325                                is_emptyStartTag = true;
2326                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2327                                break;
2328                        }
2329                        else if (AbsPos() == att_val_end + 1) { 
2330                                /* No WS following att value */
2331                                Syntax_Error(NT_STag);
2332                                break;
2333                        }
2334                } while (1);
2335        }
2336        return nameID;
2337}
2338
2339template <class B>
2340int ParsingEngine<B>::Parse_ValidElement() {
2341        bool is_emptyStartTag = false;
2342        int nameID = Parse_ValidStartTag(is_emptyStartTag);
2343#ifdef DEBUG
2344        printf("Parse_ValidElement: nameID = %d, name = %s, is_emptyStartTag=%i\n",nameID, model_info->symbol_table->Get_UTF8_name(nameID), is_emptyStartTag);
2345#endif
2346        ContentModel * cm = model_info->ContentModelData[nameID];
2347        switch (cm->cm_type) {
2348                case cm_Empty:
2349                        if (!is_emptyStartTag) {
2350                                if (at_EndTag_Start<B::Base>(cur())) {
2351                                        Parse_WF_EndTag(nameID);
2352                                }
2353                                else {
2354                                        Validity_Error(vErr_elementvalid);
2355                                }
2356                        }
2357                        break;
2358                case cm_Any:           
2359                        if (!is_emptyStartTag) {
2360                                Parse_AnyContent();
2361                                Parse_WF_EndTag(nameID);
2362                        }
2363                        break;
2364                case cm_Mixed:         
2365                        if (!is_emptyStartTag) {
2366                                Parse_MixedContent(((CM_Mixed *) cm)->elements);
2367                                Parse_WF_EndTag(nameID);
2368                        }
2369                        break;
2370                case cm_RegExp:
2371                        CM_RegExp * cre = (CM_RegExp *) cm;
2372                        int content_state = 0;
2373                        if (!is_emptyStartTag) {
2374                                Parse_ValidContent(cre, content_state);
2375                                #ifdef DEBUG
2376                                printf("Final content_state = %i, nameID = %i\n", content_state, nameID);
2377                                #endif
2378                                Parse_WF_EndTag(nameID);               
2379                        }
2380                        if (cre->transition_map[content_state][0]==0) {
2381                                Validity_Error(vErr_elementvalid);
2382                        }
2383        }
2384        return nameID;
2385}
2386
2387template <class B>
2388void ParsingEngine<B>::Parse_ValidContent(CM_RegExp * cre, int & cur_state) {
2389        do {
2390                ScanTo(NonWS);
2391                /* If non-null report WS  WS_action()? */
2392                text_or_markup_start = AbsPos();
2393                if (at_EndTag_Start<B::Base>(cur())) {
2394                        break;
2395                }
2396                else if (at_ElementTag_Start<B::Base>(cur())) {
2397                        int nameID = Parse_ValidElement();
2398#ifdef DEBUG
2399                        printf("Content model state transition %i", cur_state);
2400#endif
2401                        cur_state = cre->transition_map[cur_state][nameID];
2402#ifdef DEBUG
2403                        printf("-> %i\n", cur_state);
2404#endif
2405                }
2406                else if (at_Comment_Start<B::Base>(cur())) {
2407                        Parse_Comment();
2408                }
2409                else if (at_PI_Start<B::Base>(cur())) {
2410                        Parse_PI();
2411                }
2412                else if (AtChar<B::Base,'&'>(cur())) {
2413                        Parse_ValidEntityRef(cre, cur_state);
2414#ifdef DEBUG
2415                        printf("EntityRef complete, cur_state = %i\n", cur_state);
2416#endif
2417                       
2418                }
2419                else if (at_EOF()) {
2420                        break;
2421                }
2422                else if (AtChar<B::Base,'<'>(cur())) {
2423                        Syntax_Error(NT_markupdecl);
2424                }
2425                else {
2426                        Validity_Error(vErr_elementvalid);
2427                }
2428        } while(1);
2429}
2430
2431
2432template <class B>
2433void ParsingEngine<B>::Parse_AnyContent() {
2434        do {
2435                text_or_markup_start = AbsPos();
2436                ScanTextTo(MarkupStart); /* '<', '&', or ']' for ']]>' test */
2437                if (at_ElementTag_Start<B::Base>(cur())) {
2438                        text_if_nonnull_action(false);
2439                        int nameID = Parse_ValidElement();
2440                }
2441                else if (at_EndTag_Start<B::Base>(cur())) {
2442                        text_if_nonnull_action(false);
2443                        return;
2444                }
2445                else if (at_Comment_Start<B::Base>(cur())) {
2446                        text_if_nonnull_action(false);
2447                        Parse_Comment();
2448                }
2449                else if (at_CharRef_Start<B::Base>(cur())) {
2450                        text_if_nonnull_action(true);
2451                        Parse_CharRef();
2452                }
2453                else if (AtChar<B::Base,'&'>(cur())) {
2454                        text_if_nonnull_action(true);
2455                        Parse_EntityRef_inAnyContent();
2456                }
2457                else if (at_CDATA_Start<B::Base>(cur())) {
2458                        text_if_nonnull_action(true);
2459                        Parse_CDATA();
2460                }
2461                else if (at_PI_Start<B::Base>(cur())) {
2462                        text_if_nonnull_action(false);
2463                        Parse_PI();
2464                }
2465                else if (at_CDATA_End<B::Base>(cur())) {
2466                        text_if_nonnull_action(true);
2467                        Advance(3);
2468                        Syntax_Error(NT_CharData);
2469                }
2470                else if (at_EOF()) {
2471                        text_if_nonnull_action(false);
2472                        return;
2473                }
2474                else if (AtChar<B::Base,'<'>(cur())) {
2475                        Syntax_Error(NT_markupdecl);
2476                }
2477                else {
2478                        Advance(1);
2479                        continue;
2480                }
2481        } while (1);
2482}
2483template <class B>
2484void ParsingEngine<B>::Parse_MixedContent(symbol_set_t elems) {
2485        do {
2486                text_or_markup_start = AbsPos();
2487                ScanTextTo(MarkupStart); /* '<', '&', or ']' for ']]>' test */
2488/*              if (AtChar<B::Base,'<'>(cur())) {
2489                        text_if_nonnull_action();
2490                        Parse_Markup<B>();
2491                }*/
2492                if (at_ElementTag_Start<B::Base>(cur())) {
2493                        text_if_nonnull_action(false);
2494                        int nameID = Parse_ValidElement();
2495                        if (elems[nameID] == 0) {
2496                                Validity_Error(vErr_elementvalid);
2497                        }
2498                }
2499                else if (at_EndTag_Start<B::Base>(cur())) {
2500                        text_if_nonnull_action(false);
2501                        return;
2502                }
2503                else if (at_Comment_Start<B::Base>(cur())) {
2504                        text_if_nonnull_action(false);
2505                        Parse_Comment();
2506                }
2507                else if (at_CharRef_Start<B::Base>(cur())) {
2508                        text_if_nonnull_action(true);
2509                        Parse_CharRef();
2510                }
2511                else if (AtChar<B::Base,'&'>(cur())) {
2512                        text_if_nonnull_action(true);
2513                        Parse_EntityRef_inMixed(elems);
2514                }
2515                else if (at_CDATA_Start<B::Base>(cur())) {
2516                        text_if_nonnull_action(true);
2517                        Parse_CDATA();
2518                }
2519                else if (at_PI_Start<B::Base>(cur())) {
2520                        text_if_nonnull_action(false);
2521                        Parse_PI();
2522                }
2523                else if (at_CDATA_End<B::Base>(cur())) {
2524                        text_if_nonnull_action(true);
2525                        Advance(3);
2526                        Syntax_Error(NT_CharData);
2527                }
2528                else if (at_EOF()) {
2529                        text_if_nonnull_action(false);
2530                        return;
2531                }
2532                else if (AtChar<B::Base,'<'>(cur())) {
2533                        Syntax_Error(NT_markupdecl);
2534                }
2535                else {
2536                        Advance(1);
2537                        continue;
2538                }
2539        } while (1);
2540}
2541
2542
2543template <class B>
2544int ParsingEngine<B>::Parse_Name() {
2545        int name_pos = AbsPos();
2546        ScanTo(NameFollow);
2547        int lgth = AbsPos()-name_pos;
2548        int nameID = model_info->symbol_table->ASCII_Lookup_or_Insert_Name(&((char *) x8data)[buffer_rel_pos-lgth], lgth);
2549        if (nameID != 0) return nameID;
2550        else {
2551                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2552                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2553                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2554                return model_info->symbol_table->LookupOrInsertReserved();
2555        }
2556}
2557
2558template <>
2559int ParsingEngine< X8_Buffer<EBCDIC> >::Parse_Name() {
2560        int name_pos = AbsPos();
2561        ScanTo(NameFollow);
2562        int lgth = AbsPos()-name_pos;
2563//      int nameID = local_EBCDIC_table->Lookup_or_Insert(GetCodeUnitPtr(name_pos), lgth);
2564//      if (nameID != 0) return nameID;
2565//      else {
2566                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2567                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2568                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2569                return model_info->symbol_table->LookupOrInsertReserved();
2570//      }
2571}
2572
2573template <>
2574inline int ParsingEngine<UTF8_Buffer>::Parse_Name() {
2575        int name_pos = AbsPos();
2576        ScanTo(NameFollow);
2577        int lgth = AbsPos()-name_pos;
2578        return model_info->symbol_table->UTF8_Lookup_or_Insert_Name(&((char *)x8data)[buffer_rel_pos-lgth], lgth);
2579}
2580
2581template <class B>
2582int ParsingEngine<B>::Parse_Nmtoken() {
2583        int name_pos = AbsPos();
2584        ScanTo(NameFollow);
2585        int lgth = AbsPos()-name_pos;
2586        int nameID = model_info->symbol_table->ASCII_Lookup_or_Insert_Nmtoken(&((char *) x8data)[buffer_rel_pos-lgth], lgth);
2587        if (nameID != 0) return nameID;
2588        else {
2589                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2590                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2591                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2592                return model_info->symbol_table->LookupOrInsertReserved_nmtoken();
2593        }
2594}
2595
2596template <>
2597int ParsingEngine< X8_Buffer<EBCDIC> >::Parse_Nmtoken() {
2598        int name_pos = AbsPos();
2599        ScanTo(NameFollow);
2600        int lgth = AbsPos()-name_pos;
2601//      int nameID = local_EBCDIC_table->Lookup_or_Insert(GetCodeUnitPtr(name_pos), lgth);
2602//      if (nameID != 0) return nameID;
2603//      else {
2604                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2605                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2606                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2607                return model_info->symbol_table->LookupOrInsertReserved_nmtoken();
2608//      }
2609}
2610template <>
2611int ParsingEngine<UTF8_Buffer>::Parse_Nmtoken() {
2612        int name_pos = AbsPos();
2613        ScanTo(NameFollow);
2614        int lgth = AbsPos()-name_pos;
2615        return model_info->symbol_table->UTF8_Lookup_or_Insert_Nmtoken(&((char *)x8data)[buffer_rel_pos-lgth], lgth);
2616}
2617
2618template <class B>
2619void ParsingEngine<B>::Parse_DocumentContent() {
2620#if (VALIDATION_MODE == ON)
2621        int cur_state = 0;
2622        Parse_ValidContent(model_info->rootModel, cur_state);
2623        if (model_info->rootModel->transition_map[cur_state][0]==0) {
2624                Validity_Error(vErr_elementvalid);
2625        }
2626#endif
2627#if (VALIDATION_MODE == OFF)
2628        Parse_WF_Element();
2629        ScanTo(NonWS);
2630        while(at_Comment_Start<B::Base>(cur()) || at_PI_Start<B::Base>(cur()) ){
2631                if (at_Comment_Start<B::Base>(cur()))
2632                        Parse_Comment();
2633                else 
2634                        Parse_PI();
2635                ScanTo(NonWS);
2636        }
2637        if (!at_EOF()) {
2638                Syntax_Error(NT_document);
2639        }       
2640#endif
2641}
2642
Note: See TracBrowser for help on using the repository browser.