source: trunk/src/engine.c @ 176

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

Inlining reorganization; delete excess inline keywords; macros for critical code.

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