source: trunk/src/engine.c @ 183

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

SIMD templated library - restructuring.

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