source: trunk/src/engine.c @ 179

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

Templated SIMD Library - initial version

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