source: trunk/src/engine.c @ 189

Last change on this file since 189 was 189, checked in by cameron, 11 years ago

OPTIMIZE_SHORT_SCAN version

File size: 72.8 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                if (at_Comment_Start<B::Base>(cur())) 
2125                        Parse_Comment();
2126                else if (at_PI_Start<B::Base>(cur()))
2127                                Parse_PI();
2128                else{
2129                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
2130                        return;
2131                }
2132                ScanTo(NonWS);
2133        }
2134        Parse_DocType();
2135        ScanTo(NonWS);
2136        while(at_Comment_Start<B::Base>(cur()) || at_PI_Start<B::Base>(cur()) ){
2137                if (at_Comment_Start<B::Base>(cur()))
2138                        Parse_Comment();
2139                else 
2140                        Parse_PI();
2141                ScanTo(NonWS);
2142        }
2143        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
2144}
2145
2146template <class B>
2147void ParsingEngine<B>::Parse_ExtSubsetDecl() {
2148        ScanTo(NonWS);
2149        int start_pos=AbsPos();
2150        while(!at_EOF()){
2151                if(at_condSect_start<B::Base>(cur())){         
2152                        Advance(3);
2153                        ScanTo(NonWS);
2154                        if (at_INCLUDE<B::Base>(cur())){
2155                                Advance(7);
2156                                ScanTo(NonWS);
2157                                if(AtChar<B::Base,'['>(cur())){
2158                                        Advance(1);
2159                                        Parse_ExtSubsetDecl();
2160                                        if(at_CDATA_End<B::Base>(cur()))
2161                                                Advance(3);
2162                                        else Syntax_Error(NT_includeSect);
2163                                }
2164                                else Syntax_Error(NT_includeSect);
2165                        }
2166                        else if (at_IGNORE<B::Base>(cur())){
2167                                Advance(6);
2168                                ScanTo(NonWS);         
2169                                if(AtChar<B::Base,'['>(cur())){
2170                                        int section_depth=1;
2171                                        Advance(1);
2172                                        while(!at_EOF()){
2173                                                ScanTextTo(MarkupStart);
2174                                                if(at_condSect_start<B::Base>(cur())){
2175                                                        Advance(3);
2176                                                        section_depth++;
2177                                                }
2178                                                else if(at_CDATA_End<B::Base>(cur())){
2179                                                        Advance(3);
2180                                                        section_depth--;
2181                                                }
2182                                                else
2183                                                        Advance(1);
2184                                                if(section_depth==0) return;                                   
2185                                        }
2186                                        Syntax_Error(NT_ignoreSectContents);   
2187                                }
2188                                else Syntax_Error(NT_ignoreSect);
2189                        }
2190                        else Syntax_Error(NT_conditionalSect);
2191                }
2192                else if (AtChar<B::Base,'%'>(cur()))
2193                        Parse_PEReference();   
2194                else if (at_PI_Start<B::Base>(cur())) {
2195                        Parse_PI();
2196                }
2197                else if (at_Comment_Start<B::Base>(cur())) {
2198                        Parse_Comment();
2199                }
2200                else if (AtChar<B::Base,'<'>(cur())){
2201                        Advance(1);
2202
2203                        if(AtChar<B::Base,'!'>(cur())){
2204                                Advance(1);
2205                                if(at_ELEMENT<B::Base>(cur()))
2206                                        Parse_Elementdecl();
2207                                else if(at_ATTLIST<B::Base>(cur()))
2208                                        Parse_AttlistDecl();
2209                                else if(at_ENTITY<B::Base>(cur()))
2210                                        Parse_Entitydecl();
2211                                else if(at_NOTATION<B::Base>(cur()))
2212                                        Parse_Notationdecl();                                   
2213                                else{
2214                                        Syntax_Error(NT_markupdecl);   
2215                                }                                                               
2216                        }
2217                        else
2218                                Syntax_Error(NT_markupdecl); 
2219                }
2220                else
2221                        Syntax_Error(NT_extSubsetDecl); 
2222                ScanTo(NonWS);
2223        }
2224        ExtSubsetDecl_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
2225}
2226
2227/* Parse a valid start or empty element tag. */
2228template <class B>
2229inline int ParsingEngine<B>::Parse_ValidStartTag (bool& is_emptyStartTag){
2230        int att_name_start;
2231        int att_val_start;
2232        int att_name_end, att_val_end;
2233        unsigned char quoteCh;
2234        Advance(1);
2235
2236        int nameID = Parse_Name(); 
2237        int elemID = model_info->GlobalElementTable[nameID];
2238        if(elemID==0)
2239                        Validity_Error(vErr_elementvalid);
2240       
2241        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
2242        /* The following test optimizes the most common case of a
2243        start tag with no attributes.  */
2244        if (AtChar<B::Base,'>'>(cur())) {
2245                Advance(1);
2246                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2247        }
2248        else {
2249                ScanTo(NonWS);
2250                if (AtChar<B::Base,'>'>(cur())) {
2251                        Advance(1);
2252                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2253                }
2254                else if (at_EmptyElementDelim<B::Base>(cur())) {
2255                        Advance(2);
2256                        is_emptyStartTag = true;
2257                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2258                }
2259                else do {
2260                        /* Must be an attribute-value pair or error. */
2261                        att_name_start = AbsPos();
2262                        int att_nameID = Parse_Name();
2263                        #if (not defined(OMISSION)) or (OMISSION != ATTRIBUTE_UNIQUENESS) 
2264                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
2265                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
2266                        else {
2267                                if (LastAttOccurrence[attID] > text_or_markup_start) {
2268                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
2269                                        break;
2270                                }                       
2271                        }
2272                        LastAttOccurrence[attID] = att_name_start;
2273                        #endif
2274                        /* The following optimized tests handle the frequently occurring
2275                        case that there are no blanks on either side of the equals sign.
2276                        In many cases, the very first test handles 100% of actual
2277                        attribute-value pairs encountered. */
2278                        if (at_EqualsQuote<B::Base>(cur())) Advance(1); 
2279                        else {
2280                                ScanTo(NonWS);
2281                                if (!AtChar<B::Base,'='>(cur())) {
2282                                        Syntax_Error(NT_STag); 
2283                                        break;
2284                                }
2285                                Advance(1); 
2286                                ScanTo(NonWS);
2287                                if (!AtQuote<B::Base>(cur())) {
2288                                        Syntax_Error(NT_STag); 
2289                                        break;
2290                                }
2291                        }
2292                        att_val_start = AbsPos()+1;
2293                        Parse_AttValue();
2294                        att_val_end = AbsPos()-1;
2295                        if (at_xmlns<B::Base>(cur()+att_name_start-AbsPos())) {
2296                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
2297                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
2298                        }
2299                        else {
2300                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
2301                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
2302                        }
2303                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
2304                        if (AtChar<B::Base,'>'>(cur())) {
2305                                Advance(1);
2306                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2307                                break;
2308                        }
2309                        else if (at_EmptyElementDelim<B::Base>(cur())) {
2310                                Advance(2);
2311                                is_emptyStartTag = true;       
2312                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2313                                break;
2314                        }
2315                        ScanTo(NonWS);
2316                        if (AtChar<B::Base,'>'>(cur())) {
2317                                Advance(1);
2318                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2319                                break;
2320                        }
2321                        else if (at_EmptyElementDelim<B::Base>(cur())) {
2322                                Advance(2);
2323                                is_emptyStartTag = true;
2324                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2325                                break;
2326                        }
2327                        else if (AbsPos() == att_val_end + 1) { 
2328                                /* No WS following att value */
2329                                Syntax_Error(NT_STag);
2330                                break;
2331                        }
2332                } while (1);
2333        }
2334        return nameID;
2335}
2336
2337template <class B>
2338int ParsingEngine<B>::Parse_ValidElement() {
2339        bool is_emptyStartTag = false;
2340        int nameID = Parse_ValidStartTag(is_emptyStartTag);
2341#ifdef DEBUG
2342        printf("Parse_ValidElement: nameID = %d, name = %s, is_emptyStartTag=%i\n",nameID, model_info->symbol_table->Get_UTF8_name(nameID), is_emptyStartTag);
2343#endif
2344        ContentModel * cm = model_info->ContentModelData[nameID];
2345        switch (cm->cm_type) {
2346                case cm_Empty:
2347                        if (!is_emptyStartTag) {
2348                                if (at_EndTag_Start<B::Base>(cur())) {
2349                                        Parse_WF_EndTag(nameID);
2350                                }
2351                                else {
2352                                        Validity_Error(vErr_elementvalid);
2353                                }
2354                        }
2355                        break;
2356                case cm_Any:           
2357                        if (!is_emptyStartTag) {
2358                                Parse_AnyContent();
2359                                Parse_WF_EndTag(nameID);
2360                        }
2361                        break;
2362                case cm_Mixed:         
2363                        if (!is_emptyStartTag) {
2364                                Parse_MixedContent(((CM_Mixed *) cm)->elements);
2365                                Parse_WF_EndTag(nameID);
2366                        }
2367                        break;
2368                case cm_RegExp:
2369                        CM_RegExp * cre = (CM_RegExp *) cm;
2370                        int content_state = 0;
2371                        if (!is_emptyStartTag) {
2372                                Parse_ValidContent(cre, content_state);
2373                                #ifdef DEBUG
2374                                printf("Final content_state = %i, nameID = %i\n", content_state, nameID);
2375                                #endif
2376                                Parse_WF_EndTag(nameID);               
2377                        }
2378                        if (cre->transition_map[content_state][0]==0) {
2379                                Validity_Error(vErr_elementvalid);
2380                        }
2381        }
2382        return nameID;
2383}
2384
2385template <class B>
2386void ParsingEngine<B>::Parse_ValidContent(CM_RegExp * cre, int & cur_state) {
2387        do {
2388                ScanTo(NonWS);
2389                /* If non-null report WS  WS_action()? */
2390                text_or_markup_start = AbsPos();
2391                if (at_EndTag_Start<B::Base>(cur())) {
2392                        break;
2393                }
2394                else if (at_ElementTag_Start<B::Base>(cur())) {
2395                        int nameID = Parse_ValidElement();
2396#ifdef DEBUG
2397                        printf("Content model state transition %i", cur_state);
2398#endif
2399                        cur_state = cre->transition_map[cur_state][nameID];
2400#ifdef DEBUG
2401                        printf("-> %i\n", cur_state);
2402#endif
2403                }
2404                else if (at_Comment_Start<B::Base>(cur())) {
2405                        Parse_Comment();
2406                }
2407                else if (at_PI_Start<B::Base>(cur())) {
2408                        Parse_PI();
2409                }
2410                else if (AtChar<B::Base,'&'>(cur())) {
2411                        Parse_ValidEntityRef(cre, cur_state);
2412#ifdef DEBUG
2413                        printf("EntityRef complete, cur_state = %i\n", cur_state);
2414#endif
2415                       
2416                }
2417                else if (at_EOF()) {
2418                        break;
2419                }
2420                else if (AtChar<B::Base,'<'>(cur())) {
2421                        Syntax_Error(NT_markupdecl);
2422                }
2423                else {
2424                        Validity_Error(vErr_elementvalid);
2425                }
2426        } while(1);
2427}
2428
2429
2430template <class B>
2431void ParsingEngine<B>::Parse_AnyContent() {
2432        do {
2433                text_or_markup_start = AbsPos();
2434                ScanTextTo(MarkupStart); /* '<', '&', or ']' for ']]>' test */
2435                if (at_ElementTag_Start<B::Base>(cur())) {
2436                        text_if_nonnull_action(false);
2437                        int nameID = Parse_ValidElement();
2438                }
2439                else if (at_EndTag_Start<B::Base>(cur())) {
2440                        text_if_nonnull_action(false);
2441                        return;
2442                }
2443                else if (at_Comment_Start<B::Base>(cur())) {
2444                        text_if_nonnull_action(false);
2445                        Parse_Comment();
2446                }
2447                else if (at_CharRef_Start<B::Base>(cur())) {
2448                        text_if_nonnull_action(true);
2449                        Parse_CharRef();
2450                }
2451                else if (AtChar<B::Base,'&'>(cur())) {
2452                        text_if_nonnull_action(true);
2453                        Parse_EntityRef_inAnyContent();
2454                }
2455                else if (at_CDATA_Start<B::Base>(cur())) {
2456                        text_if_nonnull_action(true);
2457                        Parse_CDATA();
2458                }
2459                else if (at_PI_Start<B::Base>(cur())) {
2460                        text_if_nonnull_action(false);
2461                        Parse_PI();
2462                }
2463                else if (at_CDATA_End<B::Base>(cur())) {
2464                        text_if_nonnull_action(true);
2465                        Advance(3);
2466                        Syntax_Error(NT_CharData);
2467                }
2468                else if (at_EOF()) {
2469                        text_if_nonnull_action(false);
2470                        return;
2471                }
2472                else if (AtChar<B::Base,'<'>(cur())) {
2473                        Syntax_Error(NT_markupdecl);
2474                }
2475                else {
2476                        Advance(1);
2477                        continue;
2478                }
2479        } while (1);
2480}
2481template <class B>
2482void ParsingEngine<B>::Parse_MixedContent(symbol_set_t elems) {
2483        do {
2484                text_or_markup_start = AbsPos();
2485                ScanTextTo(MarkupStart); /* '<', '&', or ']' for ']]>' test */
2486/*              if (AtChar<B::Base,'<'>(cur())) {
2487                        text_if_nonnull_action();
2488                        Parse_Markup<B>();
2489                }*/
2490                if (at_ElementTag_Start<B::Base>(cur())) {
2491                        text_if_nonnull_action(false);
2492                        int nameID = Parse_ValidElement();
2493                        if (elems[nameID] == 0) {
2494                                Validity_Error(vErr_elementvalid);
2495                        }
2496                }
2497                else if (at_EndTag_Start<B::Base>(cur())) {
2498                        text_if_nonnull_action(false);
2499                        return;
2500                }
2501                else if (at_Comment_Start<B::Base>(cur())) {
2502                        text_if_nonnull_action(false);
2503                        Parse_Comment();
2504                }
2505                else if (at_CharRef_Start<B::Base>(cur())) {
2506                        text_if_nonnull_action(true);
2507                        Parse_CharRef();
2508                }
2509                else if (AtChar<B::Base,'&'>(cur())) {
2510                        text_if_nonnull_action(true);
2511                        Parse_EntityRef_inMixed(elems);
2512                }
2513                else if (at_CDATA_Start<B::Base>(cur())) {
2514                        text_if_nonnull_action(true);
2515                        Parse_CDATA();
2516                }
2517                else if (at_PI_Start<B::Base>(cur())) {
2518                        text_if_nonnull_action(false);
2519                        Parse_PI();
2520                }
2521                else if (at_CDATA_End<B::Base>(cur())) {
2522                        text_if_nonnull_action(true);
2523                        Advance(3);
2524                        Syntax_Error(NT_CharData);
2525                }
2526                else if (at_EOF()) {
2527                        text_if_nonnull_action(false);
2528                        return;
2529                }
2530                else if (AtChar<B::Base,'<'>(cur())) {
2531                        Syntax_Error(NT_markupdecl);
2532                }
2533                else {
2534                        Advance(1);
2535                        continue;
2536                }
2537        } while (1);
2538}
2539
2540
2541template <class B>
2542int ParsingEngine<B>::Parse_Name() {
2543        int name_pos = AbsPos();
2544        ScanTo(NameFollow);
2545        int lgth = AbsPos()-name_pos;
2546        int nameID = model_info->symbol_table->ASCII_Lookup_or_Insert_Name(&((char *) x8data)[buffer_rel_pos-lgth], lgth);
2547        if (nameID != 0) return nameID;
2548        else {
2549                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2550                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2551                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2552                return model_info->symbol_table->LookupOrInsertReserved();
2553        }
2554}
2555
2556template <>
2557int ParsingEngine< X8_Buffer<EBCDIC> >::Parse_Name() {
2558        int name_pos = AbsPos();
2559        ScanTo(NameFollow);
2560        int lgth = AbsPos()-name_pos;
2561//      int nameID = local_EBCDIC_table->Lookup_or_Insert(GetCodeUnitPtr(name_pos), lgth);
2562//      if (nameID != 0) return nameID;
2563//      else {
2564                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2565                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2566                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2567                return model_info->symbol_table->LookupOrInsertReserved();
2568//      }
2569}
2570
2571template <>
2572inline int ParsingEngine<UTF8_Buffer>::Parse_Name() {
2573        int name_pos = AbsPos();
2574        ScanTo(NameFollow);
2575        int lgth = AbsPos()-name_pos;
2576        return model_info->symbol_table->UTF8_Lookup_or_Insert_Name(&((char *)x8data)[buffer_rel_pos-lgth], lgth);
2577}
2578
2579template <class B>
2580int ParsingEngine<B>::Parse_Nmtoken() {
2581        int name_pos = AbsPos();
2582        ScanTo(NameFollow);
2583        int lgth = AbsPos()-name_pos;
2584        int nameID = model_info->symbol_table->ASCII_Lookup_or_Insert_Nmtoken(&((char *) x8data)[buffer_rel_pos-lgth], lgth);
2585        if (nameID != 0) return nameID;
2586        else {
2587                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2588                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2589                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2590                return model_info->symbol_table->LookupOrInsertReserved_nmtoken();
2591        }
2592}
2593
2594template <>
2595int ParsingEngine< X8_Buffer<EBCDIC> >::Parse_Nmtoken() {
2596        int name_pos = AbsPos();
2597        ScanTo(NameFollow);
2598        int lgth = AbsPos()-name_pos;
2599//      int nameID = local_EBCDIC_table->Lookup_or_Insert(GetCodeUnitPtr(name_pos), lgth);
2600//      if (nameID != 0) return nameID;
2601//      else {
2602                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2603                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2604                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2605                return model_info->symbol_table->LookupOrInsertReserved_nmtoken();
2606//      }
2607}
2608template <>
2609int ParsingEngine<UTF8_Buffer>::Parse_Nmtoken() {
2610        int name_pos = AbsPos();
2611        ScanTo(NameFollow);
2612        int lgth = AbsPos()-name_pos;
2613        return model_info->symbol_table->UTF8_Lookup_or_Insert_Nmtoken(&((char *)x8data)[buffer_rel_pos-lgth], lgth);
2614}
2615
2616template <class B>
2617void ParsingEngine<B>::Parse_DocumentContent() {
2618#if (VALIDATION_MODE == ON)
2619        int cur_state = 0;
2620        Parse_ValidContent(model_info->rootModel, cur_state);
2621        if (model_info->rootModel->transition_map[cur_state][0]==0) {
2622                Validity_Error(vErr_elementvalid);
2623        }
2624#endif
2625#if (VALIDATION_MODE == OFF)   
2626        Parse_WF_Element();
2627        ScanTo(NonWS);
2628        while(at_Comment_Start<B::Base>(cur()) || at_PI_Start<B::Base>(cur()) ){
2629                if (at_Comment_Start<B::Base>(cur()))
2630                        Parse_Comment();
2631                else 
2632                        Parse_PI();
2633                ScanTo(NonWS);
2634        }
2635        if (!at_EOF()) {
2636                Syntax_Error(NT_document);
2637        }       
2638#endif
2639}
2640
Note: See TracBrowser for help on using the repository browser.