source: trunk/src/engine.c @ 160

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

Restructured character set architecture; StringPool? in symbol table.

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