source: trunk/src/engine.c @ 168

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

UTF-16 end-tag matching

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        char * end_elem_name = &((char *) x8data)[buffer_rel_pos];
749       
750        BytePack byte_compare =  simd_eq_8(sisd_load_unaligned((BytePack *) end_elem_name),
751                                                           sisd_load_unaligned((BytePack *) start_elem_name));
752        if (lgth < 16) {
753                int expected_bits = ~(-1 << lgth);
754            if ((_mm_movemask_epi8(byte_compare) & expected_bits) != expected_bits) {
755                        WF_Error(wfErr_GIMatch);
756            }
757        }
758        else {
759            /* Must compare with bytes beyond the first 16.  Set up to
760               compare 16 bytes at a time, with the first additional compare
761               overlapping with the first byte_compare. */
762            int pos = (lgth - 1) % PACKSIZE + 1;
763            byte_compare =  simd_or(byte_compare, simd_eq_8(sisd_load_unaligned((BytePack *) &end_elem_name[pos]),
764                                                                                        sisd_load_unaligned((BytePack *) &start_elem_name[pos])));
765            pos += 16;
766            while (pos < lgth) {
767                if (_mm_movemask_epi8(byte_compare) != 0xFFFF) {
768                        WF_Error(wfErr_GIMatch);
769                }
770                byte_compare =  simd_eq_8(sisd_load_unaligned((BytePack *) &end_elem_name[pos]),
771                                                  sisd_load_unaligned((BytePack *) &start_elem_name[pos]));
772                pos += 16;
773            }
774            if (_mm_movemask_epi8(byte_compare) != 0xFFFF) {
775                        WF_Error(wfErr_GIMatch);
776            }
777        }
778        Advance(lgth);
779
780#endif
781#if defined(OMISSION) and ((OMISSION == END_TAG_MATCHING) or (OMISSION == NAME_LOOKUP))
782        ScanTo(NameFollow);
783#endif
784//      for(int i=0; i<lgth; i++) {
785//              if (start_elem_name[i] != end_elem_name[i])
786//                      WF_Error(wfErr_GIMatch);
787//      }
788//      if (start_elem_name[lgth] != '\0') WF_Error(wfErr_GIMatch);
789
790        if (AtChar<B::Base,'>'>(cur())) {
791                Advance(1);
792                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
793        }
794    else {
795                ScanTo(NonWS);
796                if (AtChar<B::Base,'>'>(cur())) {
797                        Advance(1);
798                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
799                }
800                else Syntax_Error(NT_ETag);
801    }
802}
803/* Parse a valid start or empty element tag. */
804template <class B>
805inline int ParsingEngine<B>::Parse_WF_StartTag (bool& is_emptyStartTag){
806        int att_name_start;
807        int att_val_start;
808        int att_name_end, att_val_end;
809        unsigned char quoteCh;
810        Advance(1);
811       
812        #if (not defined(OMISSION)) or (OMISSION != NAME_LOOKUP)
813        int nameID = Parse_Name(); 
814        #endif
815        #if (defined(OMISSION)) and (OMISSION == NAME_LOOKUP)
816        ScanTo(NameFollow);
817        int nameID = 0;
818        #endif
819        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
820        /* The following test optimizes the most common case of a
821        start tag with no attributes.  */
822        if (AtChar<B::Base,'>'>(cur())) {
823                Advance(1);
824                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
825        }
826        else {
827                ScanTo(NonWS);
828                if (AtChar<B::Base,'>'>(cur())) {
829                        Advance(1);
830                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
831                }
832                else if (at_EmptyElementDelim<B::Base>(cur())) {
833                        Advance(2);
834                        is_emptyStartTag = true;
835                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
836                }
837                else do {
838                        /* Must be an attribute-value pair or error. */
839                        att_name_start = AbsPos();
840                        #if (not defined(OMISSION)) or (OMISSION != NAME_LOOKUP)
841                        int att_nameID = Parse_Name(); 
842                        #endif
843                        #if (defined(OMISSION)) and (OMISSION == NAME_LOOKUP)
844                        ScanTo(NameFollow);
845                        int att_nameID = 0;
846                        #endif
847            att_name_end = AbsPos();
848                #if (not defined(OMISSION)) or ((OMISSION != ATTRIBUTE_UNIQUENESS) and (OMISSION != NAME_LOOKUP))
849                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
850                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
851                        else {
852                                if (LastAttOccurrence[attID] > text_or_markup_start) {
853                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
854                                        break;
855                                }                       
856                        }
857                        LastAttOccurrence[attID] = att_name_start;
858                 #endif
859                        /* The following optimized tests handle the frequently occurring
860                        case that there are no blanks on either side of the equals sign.
861                        In many cases, the very first test handles 100% of actual
862                        attribute-value pairs encountered. */
863                        if (at_EqualsQuote<B::Base>(cur())) Advance(1); 
864                        else {
865                                ScanTo(NonWS);
866                                if (!AtChar<B::Base,'='>(cur())) {
867                                        Syntax_Error(NT_STag); 
868                                        break;
869                                }
870                                Advance(1);
871                                ScanTo(NonWS);
872                                if (!AtQuote<B::Base>(cur())) {
873                                        Syntax_Error(NT_STag); 
874                                        break;
875                                }
876                        }
877                        att_val_start = AbsPos()+1;
878                        Parse_AttValue();
879                        att_val_end = AbsPos()-1;
880                        if (at_xmlns<B::Base>(cur()+att_name_start-AbsPos())) {
881                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
882                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
883                        }
884                        else {
885                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
886                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
887                        }
888                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
889                        if (AtChar<B::Base,'>'>(cur())) {
890                                Advance(1);
891                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
892                                break;
893                        }
894                        else if (at_EmptyElementDelim<B::Base>(cur())) {
895                                Advance(2);
896                                is_emptyStartTag = true;       
897                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
898                                break;
899                        }
900                        ScanTo(NonWS);
901                        if (AtChar<B::Base,'>'>(cur())) {
902                                Advance(1);
903                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
904                                break;
905                        }
906                        else if (at_EmptyElementDelim<B::Base>(cur())) {
907                                Advance(2);
908                                is_emptyStartTag = true;
909                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
910                                break;
911                        }
912                        else if (AbsPos() == att_val_end + 1) { 
913                                /* No WS following att value */
914                                Syntax_Error(NT_STag);
915                                break;
916                        }
917                } while (1);
918        }
919        return nameID;
920}
921
922
923
924template <class B>
925inline void ParsingEngine<B>::Parse_WF_Element() {
926        bool is_emptyStartTag = false;
927        int nameID = Parse_WF_StartTag(is_emptyStartTag);
928#ifdef DEBUG
929        printf("Parse_Element: nameID = %d, is_emptyStartTag=%i\n",nameID, is_emptyStartTag);
930#endif
931        if (!is_emptyStartTag) {
932                Parse_WF_Content();
933                Parse_WF_EndTag(nameID);
934        }
935}
936
937
938template <class B>
939inline void ParsingEngine<B>::Parse_WF_Content() {
940        do {
941                text_or_markup_start = AbsPos();
942                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
943                if (at_ElementTag_Start<B::Base>(cur())) {
944                        text_if_nonnull_action();
945                        Parse_WF_Element();
946                }
947                else if (at_EndTag_Start<B::Base>(cur())) {
948                        text_if_nonnull_action();
949                        return;
950                }
951                else if (at_Comment_Start<B::Base>(cur())) {
952                        text_if_nonnull_action();
953                        Parse_Comment();
954                }
955                else if (at_CharRef_Start<B::Base>(cur())) {
956                        text_if_nonnull_action();
957                        Parse_CharRef();
958                }
959                else if (AtChar<B::Base,'&'>(cur())) {
960                        text_if_nonnull_action();
961                        Parse_EntityRef();
962                }
963                else if (at_CDATA_Start<B::Base>(cur())) {
964                        text_if_nonnull_action();
965                        Parse_CDATA();
966                }
967                else if (at_PI_Start<B::Base>(cur())) {
968                        text_if_nonnull_action();
969                        Parse_PI();
970                }
971                else if (at_CDATA_End<B::Base>(cur())) {
972                        text_if_nonnull_action();
973                        Advance(3);
974                        Syntax_Error(NT_CharData);
975                }
976                else if (at_EOF()) {
977                        text_if_nonnull_action();
978                        return;
979                }
980                else if (AtChar<B::Base,'<'>(cur())) {
981                        Syntax_Error(NT_markupdecl);
982                }
983                else {
984                        Advance(1);
985                        continue;
986                }
987        } while (1);
988}
989
990
991
992template <class B>
993inline void ParsingEngine<B>::ParseContent() {
994        DocumentStart_action(); 
995        bool is_emptyStartTag = false;
996        do {
997                text_or_markup_start = AbsPos();
998                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
999/*              if (AtChar<B::Base,'<'>(cur())) {
1000                        text_if_nonnull_action();
1001                        Parse_Markup<B>();
1002                }*/
1003                if (at_ElementTag_Start<B::Base>(cur())) {
1004                        text_if_nonnull_action();
1005                        Parse_StartTag();
1006                }
1007                else if (at_EndTag_Start<B::Base>(cur())) {
1008                        text_if_nonnull_action();
1009                        Parse_EndTag();
1010                }
1011                else if (at_Comment_Start<B::Base>(cur())) {
1012                        text_if_nonnull_action();
1013                        Parse_Comment();
1014                }
1015                else if (at_CharRef_Start<B::Base>(cur())) {
1016                        text_if_nonnull_action();
1017                        Parse_CharRef();
1018                }
1019                else if (AtChar<B::Base,'&'>(cur())) {
1020                        text_if_nonnull_action();
1021                        Parse_EntityRef();
1022                }
1023                else if (at_CDATA_Start<B::Base>(cur())) {
1024                        text_if_nonnull_action();
1025                        Parse_CDATA();
1026                }
1027                else if (at_PI_Start<B::Base>(cur())) {
1028                        text_if_nonnull_action();
1029                        Parse_PI();
1030                }
1031                else if (at_CDATA_End<B::Base>(cur())) {
1032                        text_if_nonnull_action();
1033                        Advance(3);
1034                        Syntax_Error(NT_CharData);
1035                }
1036                else if (at_EOF()) {
1037                        text_if_nonnull_action();
1038                        break;
1039                }
1040                else if (AtChar<B::Base,'<'>(cur())) {
1041                        Syntax_Error(NT_markupdecl);
1042                }
1043                else {
1044                        Advance(1);
1045                        continue;
1046                }
1047        } while (1);
1048        DocumentEnd_action();   
1049}
1050
1051
1052template <class B>
1053inline void ParsingEngine<B>::Parse_DocType (){
1054
1055        int old_abspos, start_pos;
1056        ScanTo(NonWS);
1057        start_pos = AbsPos();
1058       
1059        if (at_DOCTYPE_start<B::Base>(cur()))
1060        Advance(9);
1061        else{
1062//              printf("No Document definition!\n");
1063                return;
1064        }
1065        requireWS();
1066        int nameID = Parse_Name();
1067
1068        old_abspos = AbsPos(); 
1069    ScanTo(NonWS);
1070    if(at_SYSTEM<B::Base>(cur())||at_PUBLIC<B::Base>(cur())){
1071        model_info->has_external_DTD = true;
1072        if(old_abspos == AbsPos())
1073                Syntax_Error(NT_doctypedecl);
1074        Parse_ExternalID(model_info->external_DTD_systemLiteral, model_info->external_DTD_pubidLiteral);
1075        Parser_Interface * entity_parser;
1076        entity_parser = ParserFactory(model_info->external_DTD_systemLiteral, model_info);
1077                entity_parser->Parse_ExtSubsetDecl();
1078                entity_parser->~Parser_Interface();
1079    }
1080    else model_info->has_external_DTD = false;
1081    ScanTo(NonWS);     
1082
1083        if (AtChar<B::Base,'['>(cur())){
1084                Advance(1);
1085                Parse_IntSubset();
1086                if (AtChar<B::Base,']'>(cur()))
1087                        Advance(1);
1088                else
1089                Syntax_Error(NT_doctypedecl);
1090                ScanTo(NonWS);
1091        }
1092       
1093        if (AtChar<B::Base,'>'>(cur())){
1094                Advance(1); 
1095
1096                CRE_Seq * rslt = new CRE_Seq();
1097                rslt->subCMs.push_back(new CRE_Name(nameID));
1098                CM_RegExp * cre = new CM_RegExp();
1099                cre->content_re = rslt;         
1100               
1101                int id_count = cre->content_re->Set_IDs(0);
1102                cre->content_re->Set_First_Map();               
1103                symbol_set_t * transition_map = new symbol_set_t[id_count+1];
1104                cre->content_re->follow_map[0] = id_count+1;
1105               
1106                cre->content_re->Set_Follow_Map(transition_map);
1107                transition_map[0] = cre->content_re->first_map;
1108                if (cre->content_re->matches_empty)
1109                        transition_map[0][0]=id_count+1;
1110                       
1111                cre -> transition_map = transition_map;
1112               
1113                model_info->rootModel = cre;
1114
1115        }
1116        else
1117                Syntax_Error(NT_doctypedecl);   
1118}
1119
1120template <class B>
1121inline void ParsingEngine<B>::Parse_ExternalID (char *& systemLiteral, char *& pubidLiteral){
1122        int quot_start, lgth;
1123        if(at_SYSTEM<B::Base>(cur())){
1124                Advance(6);
1125                pubidLiteral = NULL;
1126                requireWS();
1127                if (!AtQuote<B::Base>(cur())) Syntax_Error(NT_ExternalID);
1128                quot_start = AbsPos()+1;
1129                Parse_SystemLiteral (); /*  SystemLiteral */
1130                lgth = AbsPos() - quot_start - 1;                       
1131                systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1132        }
1133        else if (at_PUBLIC<B::Base>(cur())){
1134                Advance(6);
1135                requireWS();
1136                if (!AtQuote<B::Base>(cur())) Syntax_Error(NT_ExternalID);
1137                quot_start = AbsPos()+1;
1138                Parse_PubidLiteral ();/*  PubidLiteral */
1139                lgth = AbsPos() - quot_start - 1;                       
1140                pubidLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1141                systemLiteral = NULL;
1142                if (AtChar<B::Base, '>'>(cur())) return;
1143                requireWS();
1144                if (AtQuote<B::Base>(cur())) {
1145                        quot_start = AbsPos()+1;       
1146                        Parse_SystemLiteral ();/*  SystemLiteral */
1147                        lgth = AbsPos() - quot_start - 1;                       
1148                        systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1149                }
1150        }
1151        else
1152                Syntax_Error(NT_ExternalID); 
1153}
1154
1155template <class B>
1156inline void ParsingEngine<B>::Parse_SystemLiteral (){
1157        unsigned char quoteCh;
1158        if(AtQuote<B::Base>(cur())){
1159                quoteCh = cur()[0];
1160                Advance(1);
1161        }       
1162        ScanTo(Quote);                 
1163        while (cur()[0] != quoteCh){
1164                if(at_EOF())
1165                        Syntax_Error(NT_SystemLiteral);
1166                Advance(1);
1167                ScanTo(Quote);
1168        }
1169        Advance(1);
1170}
1171
1172template <class B>
1173inline void ParsingEngine<B>::Parse_PubidLiteral (){
1174        unsigned char quoteCh;
1175        if(AtQuote<B::Base>(cur())){
1176                quoteCh = cur()[0];
1177                Advance(1);
1178        }       
1179        while (at_PubidChar<B::Base>(cur())) Advance(1);
1180        if (cur()[0] != quoteCh){
1181                Syntax_Error(NT_PubidLiteral);
1182        }
1183        Advance(1);
1184}
1185
1186template <class B>
1187inline void ParsingEngine<B>::Parse_IntSubset (){
1188       
1189        while(1){
1190                ScanTo(NonWS); 
1191                text_or_markup_start = AbsPos();
1192                if (AtChar<B::Base,'%'>(cur()))
1193                        Parse_PEReference();   
1194                else if (at_PI_Start<B::Base>(cur())) {
1195                        Parse_PI();
1196                }
1197                else if (at_Comment_Start<B::Base>(cur())) {
1198                        Parse_Comment();
1199                }
1200                else if (AtChar<B::Base,'<'>(cur())){
1201                        Advance(1);
1202                        if(AtChar<B::Base,'!'>(cur())){
1203                                Advance(1);
1204                                if (at_ELEMENT<B::Base>(cur()))
1205                                        Parse_Elementdecl();
1206                                else if (at_ATTLIST<B::Base>(cur()))
1207                                        Parse_AttlistDecl();
1208                                else if (at_ENTITY<B::Base>(cur()))
1209                                        Parse_Entitydecl();
1210                                else if (at_NOTATION<B::Base>(cur()))
1211                                        Parse_Notationdecl();
1212                                else {
1213                                        Syntax_Error(NT_markupdecl);           
1214                                }                                                               
1215                        }
1216                        else
1217                                Syntax_Error(NT_markupdecl); 
1218                }
1219                else if (AtChar<B::Base,']'>(cur())){
1220                        break;
1221                }
1222                else
1223                        Syntax_Error(NT_intSubset); 
1224        }
1225}
1226
1227
1228template <class B>
1229inline void ParsingEngine<B>::Parse_PEReference (){
1230
1231        Advance(1); /* Skip "%". */
1232        int nameID = Parse_Name(); 
1233        if (AtChar<B::Base,';'>(cur())) {
1234                Advance(1);
1235                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1236                PEntity_info * this_info;
1237                Parser_Interface * entity_parser;
1238                int entityID = model_info->GlobalPEntityTable[nameID]; 
1239                if (entityID == 0)
1240                        WF_Error(wfErr_wf_entdeclared);
1241                else{
1242                        this_info = model_info->PEntityData[entityID-1];
1243                        if (this_info->is_external){
1244                               
1245//                      if (entity_Info->standalone != Standalone_no)
1246//                              WF_Error(wfErr_NoExternalRefs);
1247//                      else {
1248                                        entity_parser = ParserFactory(this_info->systemLiteral, model_info);
1249                                        entity_parser->Parse_WF_Content();
1250                                        if(!entity_parser->at_EOF())
1251                                                Syntax_Error(NT_content);
1252                                        entity_parser->~Parser_Interface();
1253//                      }
1254                        }
1255                        else {
1256                        }
1257                }
1258        }
1259        else
1260                Syntax_Error(NT_PEReference);
1261}
1262
1263
1264template <class B>
1265inline void ParsingEngine<B>::Parse_Elementdecl (){
1266
1267        Advance(7); /* Skip "<!ELEMENT". */
1268
1269    requireWS();
1270        int nameID = Parse_Name();
1271        int elemID = model_info->getOrInsertGlobalElement(nameID);
1272
1273        requireWS();
1274        ContentModel * cm;
1275        /* Start parsing "contentspec"*/
1276        if (at_EMPTY<B::Base>(cur())) {
1277        Advance(5);
1278        cm = new CM_Empty();
1279        model_info->ContentModelData[nameID] = cm;
1280        }
1281    else if (at_ANY<B::Base>(cur())) {
1282        Advance(3);
1283        cm = new CM_Any();
1284        model_info->ContentModelData[nameID] = cm;
1285    }
1286    else {
1287        if (AtChar<B::Base,'('>(cur()))
1288                        Advance(1);
1289                ScanTo(NonWS);
1290                if (at_PCDATA<B::Base>(cur())){
1291                        cm = Parse_RemainingMixed();
1292                        model_info->ContentModelData[nameID] = cm;
1293                }
1294                else{
1295
1296                        CM_RegExp * cre = new CM_RegExp;
1297                        cre->content_re = Parse_RemainingChildren();
1298
1299                        int id_count = cre->content_re->Set_IDs(0);
1300                        cre->content_re->Set_First_Map();       
1301                        symbol_set_t * transition_map = new symbol_set_t[id_count+1];
1302                        cre->content_re->follow_map[0] = id_count+1;
1303                       
1304                        cre->content_re->Set_Follow_Map(transition_map);
1305                        transition_map[0] = cre->content_re->first_map;
1306                       
1307                        if (cre->content_re->matches_empty)
1308                                transition_map[0][0]=id_count+1;
1309                               
1310                        cre -> transition_map = transition_map;
1311                       
1312                        model_info->ContentModelData[nameID] = cre;
1313                        cm = cre;
1314                }                       
1315    }
1316    ScanTo(NonWS);   
1317
1318        if (AtChar<B::Base,'>'>(cur())) {
1319                Advance(1);
1320        }
1321        else
1322                Syntax_Error(NT_elementdecl);
1323}
1324template <class B>
1325inline ContentModel * ParsingEngine<B>::Parse_RemainingMixed (){
1326        CM_Mixed * r = new CM_Mixed();
1327        Advance(7);  /* Skip "#PCDATA". */
1328   
1329    if (AtChar<B::Base,')'>(cur())){
1330        if (AtChar<B::Base,'*'>(cur())) {
1331                Advance(2);
1332                }
1333                else {
1334                        Advance(1);
1335                }
1336    }
1337    else{
1338        ScanTo(NonWS);
1339        int k = 0;
1340        while (AtChar<B::Base,'|'>(cur())){
1341                        Advance(1);
1342                        ScanTo(NonWS);
1343                        int nameID = Parse_Name();
1344                        r->elements[nameID] = ++k;
1345                        ScanTo(NonWS);
1346                }
1347                if (at_Para_star<B::Base>(cur())) Advance(2);
1348                else {
1349                        Syntax_Error(NT_Mixed);
1350                        exit(-1);
1351        }
1352    }
1353    return r;
1354}
1355
1356
1357template <class B>
1358inline Content_RE * ParsingEngine<B>::Parse_RemainingChildren (){
1359        Content_RE * c1 = Parse_Cp();
1360        Content_RE * r = c1;
1361        ScanTo(NonWS);
1362        if(AtChar<B::Base,'|'>(cur())){
1363                CRE_Choice * rslt = new CRE_Choice;
1364                rslt->subCMs.push_back(c1);
1365                Advance(1);
1366                ScanTo(NonWS);
1367                rslt->subCMs.push_back(Parse_Cp());
1368                ScanTo(NonWS);
1369                while(!AtChar<B::Base,')'>(cur())){
1370                        if(AtChar<B::Base,'|'>(cur()))
1371                                Advance(1);
1372                        else
1373                                Syntax_Error(NT_children);
1374                        ScanTo(NonWS);
1375                        rslt->subCMs.push_back(Parse_Cp());
1376                        ScanTo(NonWS);
1377                }
1378                Advance(1);
1379                rslt->Compile();
1380                r = rslt;
1381        }
1382        else if(AtChar<B::Base,','>(cur())){
1383                CRE_Seq * rslt = new CRE_Seq;
1384                rslt->subCMs.push_back(c1);
1385                Advance(1);
1386                ScanTo(NonWS);
1387                rslt->subCMs.push_back(Parse_Cp());
1388                ScanTo(NonWS);
1389                while(!AtChar<B::Base,')'>(cur())){
1390                        if(AtChar<B::Base,','>(cur()))
1391                                Advance(1);
1392                        else
1393                                Syntax_Error(NT_children);
1394                        ScanTo(NonWS);
1395                        rslt->subCMs.push_back(Parse_Cp());
1396                        ScanTo(NonWS);
1397                }
1398                Advance(1);
1399                rslt->Compile();
1400                r = rslt;
1401        }       
1402        else if(AtChar<B::Base,')'>(cur())){
1403                Advance(1);
1404        }
1405        else
1406                Syntax_Error(NT_children);
1407               
1408        if (AtChar<B::Base,'?'>(cur())) {
1409                Advance(1);
1410                r = new CRE_Opt(r);
1411        }
1412        else if (AtChar<B::Base,'*'>(cur())) {
1413                Advance(1);
1414                r = new CRE_Star(r);
1415        }
1416        else if (AtChar<B::Base,'+'>(cur())) {
1417                Advance(1);
1418                r = new CRE_Plus(r);
1419        }
1420
1421        return r;
1422}
1423
1424template <class B>
1425inline Content_RE * ParsingEngine<B>::Parse_Cp (){
1426        if (AtChar<B::Base,'('>(cur())){
1427                Advance(1);
1428                ScanTo(NonWS);
1429                Parse_RemainingChildren();
1430        }
1431        else{
1432                int nameID = Parse_Name();
1433                CRE_Name * r = new CRE_Name(nameID);
1434
1435                if (AtChar<B::Base,'?'>(cur())) {
1436                        Advance(1);
1437                        return new CRE_Opt(r);
1438                }
1439                else if (AtChar<B::Base,'*'>(cur())) {
1440                        Advance(1);
1441                        return new CRE_Star(r);
1442                }
1443                else if (AtChar<B::Base,'+'>(cur())) {
1444                        Advance(1);
1445                        return new CRE_Plus(r);
1446                }
1447                else return r;
1448        }
1449}
1450
1451template <class B>
1452inline void ParsingEngine<B>::Parse_AttlistDecl (){
1453       
1454        int old_abspos;
1455       
1456        int name_start;
1457        int lgth;
1458       
1459        int elemID;
1460        int attID;
1461       
1462        Advance(7); /* Skip "ATTLIST. */
1463        requireWS();
1464       
1465        int nameID = Parse_Name();
1466        elemID = model_info->getOrInsertGlobalElement(nameID);
1467       
1468        old_abspos = AbsPos();
1469        ScanTo(NonWS);
1470        while(!AtChar<B::Base,'>'>(cur())) {
1471                if(old_abspos == AbsPos())
1472                Syntax_Error(NT_AttlistDecl);
1473               
1474                int att_nameID = Parse_Name();
1475               
1476                attID = model_info->getOrInsertGlobalAttName(att_nameID);
1477                if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1478        ATT_info * this_info = new ATT_info;
1479        this_info->globalATT_id = attID;
1480        requireWS();
1481        if (at_CDATA<B::Base>(cur())){
1482                Advance(5);
1483                this_info->attType = CDATA_att;
1484        }
1485        else if(at_ID<B::Base>(cur())){
1486                Advance(2);
1487                this_info->attType = ID_att;
1488        }
1489        /* Make sure to check IDREFS before IDREF*/
1490        else if(at_IDREFS<B::Base>(cur())){
1491                Advance(6);
1492                this_info->attType = IDREFS_att;
1493        }
1494        else if(at_IDREF<B::Base>(cur())){
1495                Advance(5);
1496                this_info->attType = IDREF_att;
1497        }
1498        else if(at_ENTITY<B::Base>(cur())){
1499                Advance(6);
1500                this_info->attType = ENTITY_att;
1501        }
1502        else if(at_ENTITIES<B::Base>(cur())){
1503                Advance(8);
1504                this_info->attType = ENTITIES_att;
1505        }
1506        /* Make sure to check NMTOKENS before NMTOKEN*/
1507        else if(at_NMTOKENS<B::Base>(cur())){
1508                Advance(8);
1509                this_info->attType = NMTOKENS_att;
1510        }
1511        else if(at_NMTOKEN<B::Base>(cur())){
1512                Advance(7);
1513                this_info->attType = NMTOKEN_att;
1514        }
1515        else if(at_NOTATION<B::Base>(cur())){ /* NotationType = 'NOTATION' S Enumeration
1516                                                                         when Nmtoken = Name */
1517                Advance(8);
1518                        requireWS();
1519                Parse_Notation(this_info);
1520                this_info->attType = NOTATION_att;
1521        }
1522        else if(AtChar<B::Base,'('>(cur())){
1523                Parse_Enumeration(this_info);
1524                this_info->attType = enumeration_att;
1525        }
1526        else
1527                Syntax_Error(NT_AttlistDecl);
1528        requireWS();
1529        Parse_DefaultDecl(this_info);
1530
1531                ScanTo(NonWS);
1532                model_info->ElementAttributeData[elemID].push_back(this_info);
1533        }
1534
1535        Advance(1);
1536}
1537
1538template <class B>
1539inline void ParsingEngine<B>::Parse_Notation (ATT_info * this_info){
1540
1541        if(AtChar<B::Base,'('>(cur()))
1542                Advance(1);
1543        else
1544                Syntax_Error(NT_NotationType);
1545        ScanTo(NonWS);
1546       
1547    int nameID = Parse_Name();
1548
1549        /*Notation name is not in the global table!*/
1550        if(model_info->GlobalNotationTable[nameID]==0)
1551                Validity_Error(vErr_notatn);
1552       
1553        ScanTo(NonWS);
1554        while(AtChar<B::Base,'|'>(cur())){
1555                Advance(1);
1556                ScanTo(NonWS); 
1557                int not_nameID = Parse_Name();
1558                       
1559                if(model_info->GlobalNotationTable[not_nameID]==0)
1560                        Validity_Error(vErr_notatn);
1561                       
1562                ScanTo(NonWS);
1563        }
1564        if (AtChar<B::Base,')'>(cur())) 
1565                Advance(1);
1566        else
1567                Syntax_Error(NT_NotationType);
1568}
1569
1570template <class B>
1571inline void ParsingEngine<B>::Parse_Enumeration (ATT_info * this_info){
1572
1573        int enumCount=0;
1574        if(AtChar<B::Base,'('>(cur()))
1575                Advance(1);
1576        else
1577                Syntax_Error(NT_Enumeration);
1578        ScanTo(NonWS);
1579       
1580        int nameID = Parse_Name();
1581       
1582        this_info->enumValues[nameID]=++(enumCount);
1583       
1584        ScanTo(NonWS);
1585        while(AtChar<B::Base,'|'>(cur())){
1586                Advance(1);
1587                ScanTo(NonWS); 
1588                int nameID = Parse_Name();
1589       
1590                int enumID = this_info->enumValues[nameID];
1591                if(enumID==0){ 
1592                        this_info->enumValues[nameID]=++(enumCount);
1593                        enumID = enumCount;
1594                }
1595                else if(!StrictWellFormedness){
1596                        Validity_Error(vErr_NoDuplicateTokens);
1597                }
1598                ScanTo(NonWS);
1599        }
1600        if (AtChar<B::Base,')'>(cur())) 
1601                Advance(1);
1602        else
1603                Syntax_Error(NT_Enumeration);
1604}
1605
1606template <class B>
1607inline void ParsingEngine<B>::Parse_DefaultDecl (ATT_info * this_info){
1608        if(at_REQUIRED<B::Base>(cur())){
1609                Advance(9);
1610                this_info->defaultKind = REQUIRED_att;
1611        }
1612        else if(at_IMPLIED<B::Base>(cur())){
1613                Advance(8);
1614                this_info->defaultKind = IMPLIED_att;
1615        }
1616        else {
1617                if(at_FIXED<B::Base>(cur())){
1618                        Advance(6);
1619                        requireWS();
1620                        this_info->defaultKind = FIXED_att;
1621                }
1622                else this_info->defaultKind = DEFAULT_att;
1623                if(AtQuote<B::Base>(cur())){
1624                        int quot_start = AbsPos()+1;
1625                        Parse_AttValue();
1626                        /* need to normalize */
1627                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
1628                       
1629                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
1630                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
1631                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
1632                        }
1633                else
1634                        Syntax_Error(NT_DefaultDecl);
1635        }
1636}
1637
1638template <class B>
1639inline void ParsingEngine<B>::Parse_Entitydecl (){
1640       
1641        int name_start;
1642        int quot_start;
1643        int lgth;
1644        int old_abspos;
1645        char * s;
1646       
1647        Advance(6); /* Skip "ENTITY. */
1648        requireWS();
1649       
1650        if (AtChar<B::Base,'%'>(cur())){
1651                Advance(1);
1652                requireWS();
1653               
1654                int nameID = Parse_Name();
1655       
1656                PEntity_info * this_info = new PEntity_info;
1657                int entityID = model_info->GlobalPEntityTable[nameID];
1658                if(entityID==0){       
1659                        model_info->GlobalPEntityTable[nameID]=++(model_info->globalPEntityCount);
1660                        entityID = model_info->globalPEntityCount;
1661                        this_info->globalPEntity_id = entityID;
1662                }
1663                else
1664                        printf("Warning: Entity definition already exist!\n");
1665       
1666                requireWS();
1667                if(AtQuote<B::Base>(cur())){
1668                Parse_PEntityValue(this_info);
1669                this_info->is_external = false;
1670        }
1671        else {
1672                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1673                this_info->is_external = true;
1674                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1675        }
1676        model_info->PEntityData.push_back(this_info);
1677        }
1678        else{
1679                int nameID = Parse_Name();
1680       
1681                GEntity_info * this_info = new GEntity_info();
1682                int entityID = model_info->GlobalGEntityTable[nameID];
1683                if(entityID==0){       
1684                        model_info->GlobalGEntityTable[nameID]=++(model_info->globalGEntityCount);
1685                        entityID = model_info->globalGEntityCount;
1686                        this_info->globalGEntity_id = entityID;
1687                }
1688                else
1689                        printf("Warning: Entity definition already exist!\n");
1690                       
1691                requireWS();
1692               
1693                if(AtQuote<B::Base>(cur())){
1694                Parse_GEntityValue(this_info);                 
1695                this_info->is_external = false;
1696        }
1697        else {
1698                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1699                this_info->is_external = true;
1700                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1701                        old_abspos = AbsPos();
1702                        ScanTo(NonWS);
1703                if(at_NDATA<B::Base>(cur())){
1704                        if(old_abspos == AbsPos())
1705                                Syntax_Error(NT_EntityDecl);
1706                        else
1707                                Advance(5);
1708                        requireWS();
1709                        name_start = AbsPos();
1710                        int nameID = Parse_Name();
1711                        lgth = AbsPos() - name_start;
1712                                this_info->NDataName = copy_string(GetCodeUnitPtr(name_start),lgth);
1713                }
1714                }
1715        model_info->GEntityData.push_back(this_info);
1716        }
1717        ScanTo(NonWS);
1718        if (AtChar<B::Base,'>'>(cur())){
1719                Advance(1);
1720        }
1721        else
1722                Syntax_Error(NT_EntityDecl);
1723}
1724
1725template <class B>
1726inline void ParsingEngine<B>::Parse_Notationdecl (){
1727
1728        int old_abspos;
1729        Advance(8); /* Skip "NOTATION. */
1730        requireWS();
1731       
1732        int nameID = Parse_Name();
1733
1734        int notationID = model_info->GlobalNotationTable[nameID];
1735        if(notationID==0){     
1736                model_info->GlobalNotationTable[nameID]=++(model_info->globalNotationCount);
1737                notationID = model_info->globalNotationCount;
1738        }
1739        else /*Duplicate notation name!*/
1740                Validity_Error(vErr_NoDuplicateTokens);
1741        Notation_info * this_info = new Notation_info;
1742                       
1743    Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1744        ScanTo(NonWS);
1745        if (AtChar<B::Base,'>'>(cur())) {
1746                Advance(1);
1747        }
1748        else
1749                Syntax_Error(NT_NotationDecl);
1750}
1751
1752template <class B>
1753inline void ParsingEngine<B>::requireWS(){
1754       
1755    int old_abspos = AbsPos(); 
1756    ScanTo(NonWS);
1757    if(old_abspos == AbsPos())
1758        Syntax_Error(NT_S);
1759}
1760
1761template <class B>
1762inline void ParsingEngine<B>::Parse_AttValue(){
1763       
1764        int     quoteCh = cur()[0];
1765        Advance(1); /* Skip " or ' */
1766
1767        ScanTo(Quote);                 
1768        while (cur()[0] != quoteCh){
1769                if (at_CharRef_Start<B::Base>(cur())){
1770                        Parse_CharRef();
1771                        ScanTo(Quote);
1772                }
1773                else if (AtChar<B::Base,'&'>(cur())){
1774                        Parse_EntityRef();
1775                        ScanTo(Quote);
1776                }
1777                else if (AtQuote<B::Base>(cur())) {
1778                        Advance(1);
1779                        ScanTo(Quote);
1780                }
1781                else /* if (AtChar<B::Base,'<'>(cur())) */
1782                        WF_Error(wfErr_CleanAttrVals);
1783        }
1784        Advance(1);
1785}
1786
1787template <class B>
1788inline void ParsingEngine<B>::Parse_GEntityValue(GEntity_info * this_info){
1789       
1790        int     quoteCh = cur()[0];
1791        Advance(1); /* Skip " or ' */
1792        this_info->is_simple = true;
1793        int quot_start = AbsPos();
1794        ScanTo(Quote);         
1795        char *  replText = copy_string(GetCodeUnitPtr(quot_start),AbsPos()-quot_start);
1796
1797        while (cur()[0] != quoteCh){
1798                if (at_CharRef_Start<B::Base>(cur())){
1799                        strcat (replText,Replace_CharRef());
1800                        quot_start = AbsPos();
1801                        ScanTo(Quote);
1802                }
1803                else if (AtChar<B::Base,'&'>(cur())){
1804                        strcat (replText,Replace_EntityRef(this_info->is_simple));
1805                        quot_start = AbsPos();
1806                        ScanTo(Quote);
1807                }
1808                else if (AtQuote<B::Base>(cur())) {
1809                        quot_start = AbsPos();
1810                        Advance(1);
1811                        ScanTo(Quote);
1812                }
1813                else { /* '<' found */
1814                        quot_start = AbsPos();
1815                        Advance(1);
1816                        ScanTo(Quote);
1817                        this_info->is_simple = false;
1818                       
1819                }
1820                replText = cat_string (replText,(char *)GetCodeUnitPtr(quot_start), strlen(replText), AbsPos()-quot_start);
1821        }
1822        this_info->ReplacementText = replText;
1823        Advance(1);
1824}
1825
1826template <class B>
1827inline char * ParsingEngine<B>::Replace_EntityRef(bool& is_simple){
1828        Advance(1);
1829        int nameID = Parse_Name(); 
1830        if (AtChar<B::Base,';'>(cur()))
1831                Advance(1);
1832        else
1833                Syntax_Error(NT_EntityValue);
1834        int entityID = model_info->GlobalGEntityTable[nameID]; 
1835        if (entityID == 0)
1836                WF_Error(wfErr_wf_entdeclared);
1837        else{
1838                if (model_info->GEntityData[entityID-1]->is_simple == false)
1839                        is_simple = false;
1840                return model_info->GEntityData[entityID-1]->ReplacementText;
1841        }
1842       
1843}
1844
1845template <class B>
1846inline void ParsingEngine<B>::Parse_PEntityValue(PEntity_info * this_info){
1847}
1848
1849template <class B>
1850inline char * ParsingEngine<B>::Replace_CharRef(){
1851        Advance(1);
1852        int nameID = Parse_Name(); 
1853        int entityID = model_info->GlobalGEntityTable[nameID]; 
1854        if (entityID == 0)
1855                WF_Error(wfErr_wf_entdeclared);
1856        else
1857                return model_info->GEntityData[entityID-1]->ReplacementText;   
1858       
1859}
1860
1861template <class B>
1862inline void ParsingEngine<B>::Parse_Prolog(){
1863        ScanTo(NonWS);
1864        int old_pos = AbsPos();
1865        while (!at_DOCTYPE_start<B::Base>(cur())) {
1866                if (at_Comment_Start<B::Base>(cur())) 
1867                        Parse_Comment();
1868                else if (at_PI_Start<B::Base>(cur()))
1869                                Parse_PI();
1870                else{
1871                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1872                        return;
1873                }
1874                ScanTo(NonWS);
1875        }
1876        Parse_DocType();
1877        ScanTo(NonWS);
1878        while(at_Comment_Start<B::Base>(cur()) || at_PI_Start<B::Base>(cur()) ){
1879                if (at_Comment_Start<B::Base>(cur()))
1880                        Parse_Comment();
1881                else 
1882                        Parse_PI();
1883                ScanTo(NonWS);
1884        }
1885        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1886}
1887
1888template <class B>
1889inline void ParsingEngine<B>::Parse_ExtSubsetDecl() {
1890        int start_pos=AbsPos();
1891        while(!at_EOF()){
1892                if(at_condSect_start<B::Base>(cur())){         
1893                        Advance(3);
1894                        ScanTo(NonWS);
1895                        if (at_INCLUDE<B::Base>(cur())){
1896                                Advance(7);
1897                                ScanTo(NonWS);
1898                                if(AtChar<B::Base,'['>(cur())){
1899                                        Advance(1);
1900                                        Parse_ExtSubsetDecl();
1901                                        if(at_CDATA_End<B::Base>(cur()))
1902                                                Advance(3);
1903                                        else Syntax_Error(NT_includeSect);
1904                                }
1905                                else Syntax_Error(NT_includeSect);
1906                        }
1907                        else if (at_IGNORE<B::Base>(cur())){
1908                                Advance(6);
1909                                ScanTo(NonWS);         
1910                                if(AtChar<B::Base,'['>(cur())){
1911                                        int section_depth=1;
1912                                        Advance(1);
1913                                        while(!at_EOF()){
1914                                                ScanToMarkupStart();
1915                                                if(at_condSect_start<B::Base>(cur())){
1916                                                        Advance(3);
1917                                                        section_depth++;
1918                                                }
1919                                                else if(at_CDATA_End<B::Base>(cur())){
1920                                                        Advance(3);
1921                                                        section_depth--;
1922                                                }
1923                                                else
1924                                                        Advance(1);
1925                                                if(section_depth==0) return;                                   
1926                                        }
1927                                        Syntax_Error(NT_ignoreSectContents);   
1928                                }
1929                                else Syntax_Error(NT_ignoreSect);
1930                        }
1931                        else Syntax_Error(NT_conditionalSect);
1932                }
1933                else if (AtChar<B::Base,'%'>(cur()))
1934                        Parse_PEReference();   
1935                else if (at_PI_Start<B::Base>(cur())) {
1936                        Parse_PI();
1937                }
1938                else if (at_Comment_Start<B::Base>(cur())) {
1939                        Parse_Comment();
1940                }
1941                else if (AtChar<B::Base,'<'>(cur())){
1942                        Advance(1);
1943
1944                        if(AtChar<B::Base,'!'>(cur())){
1945                                Advance(1);
1946                                if(at_ELEMENT<B::Base>(cur()))
1947                                        Parse_Elementdecl();
1948                                else if(at_ATTLIST<B::Base>(cur()))
1949                                        Parse_AttlistDecl();
1950                                else if(at_ENTITY<B::Base>(cur()))
1951                                        Parse_Entitydecl();
1952                                else if(at_NOTATION<B::Base>(cur()))
1953                                        Parse_Notationdecl();                                   
1954                                else{
1955                                        Syntax_Error(NT_markupdecl);   
1956                                }                                                               
1957                        }
1958                        else
1959                                Syntax_Error(NT_markupdecl); 
1960                }
1961                else
1962                        Syntax_Error(NT_extSubsetDecl); 
1963                ScanTo(NonWS);
1964        }
1965        ExtSubsetDecl_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
1966}
1967
1968/* Parse a valid start or empty element tag. */
1969template <class B>
1970inline int ParsingEngine<B>::Parse_ValidStartTag (bool& is_emptyStartTag){
1971        int att_name_start;
1972        int att_val_start;
1973        int att_name_end, att_val_end;
1974        unsigned char quoteCh;
1975        Advance(1);
1976
1977        int nameID = Parse_Name(); 
1978        int elemID = model_info->GlobalElementTable[nameID];
1979        if(elemID==0)
1980                        Validity_Error(vErr_elementvalid);
1981       
1982        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
1983        /* The following test optimizes the most common case of a
1984        start tag with no attributes.  */
1985        if (AtChar<B::Base,'>'>(cur())) {
1986                Advance(1);
1987                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1988        }
1989        else {
1990                ScanTo(NonWS);
1991                if (AtChar<B::Base,'>'>(cur())) {
1992                        Advance(1);
1993                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1994                }
1995                else if (at_EmptyElementDelim<B::Base>(cur())) {
1996                        Advance(2);
1997                        is_emptyStartTag = true;
1998                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1999                }
2000                else do {
2001                        /* Must be an attribute-value pair or error. */
2002                        att_name_start = AbsPos();
2003                        int att_nameID = Parse_Name();
2004                        #if (not defined(OMISSION)) or (OMISSION != ATTRIBUTE_UNIQUENESS) 
2005                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
2006                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
2007                        else {
2008                                if (LastAttOccurrence[attID] > text_or_markup_start) {
2009                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
2010                                        break;
2011                                }                       
2012                        }
2013                        LastAttOccurrence[attID] = att_name_start;
2014                        #endif
2015                        /* The following optimized tests handle the frequently occurring
2016                        case that there are no blanks on either side of the equals sign.
2017                        In many cases, the very first test handles 100% of actual
2018                        attribute-value pairs encountered. */
2019                        if (at_EqualsQuote<B::Base>(cur())) Advance(1); 
2020                        else {
2021                                ScanTo(NonWS);
2022                                if (!AtChar<B::Base,'='>(cur())) {
2023                                        Syntax_Error(NT_STag); 
2024                                        break;
2025                                }
2026                                Advance(1); 
2027                                ScanTo(NonWS);
2028                                if (!AtQuote<B::Base>(cur())) {
2029                                        Syntax_Error(NT_STag); 
2030                                        break;
2031                                }
2032                        }
2033                        att_val_start = AbsPos()+1;
2034                        Parse_AttValue();
2035                        att_val_end = AbsPos()-1;
2036                        if (at_xmlns<B::Base>(cur()+att_name_start-AbsPos())) {
2037                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
2038                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
2039                        }
2040                        else {
2041                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
2042                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
2043                        }
2044                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
2045                        if (AtChar<B::Base,'>'>(cur())) {
2046                                Advance(1);
2047                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2048                                break;
2049                        }
2050                        else if (at_EmptyElementDelim<B::Base>(cur())) {
2051                                Advance(2);
2052                                is_emptyStartTag = true;       
2053                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2054                                break;
2055                        }
2056                        ScanTo(NonWS);
2057                        if (AtChar<B::Base,'>'>(cur())) {
2058                                Advance(1);
2059                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2060                                break;
2061                        }
2062                        else if (at_EmptyElementDelim<B::Base>(cur())) {
2063                                Advance(2);
2064                                is_emptyStartTag = true;
2065                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2066                                break;
2067                        }
2068                        else if (AbsPos() == att_val_end + 1) { 
2069                                /* No WS following att value */
2070                                Syntax_Error(NT_STag);
2071                                break;
2072                        }
2073                } while (1);
2074        }
2075        return nameID;
2076}
2077
2078template <class B>
2079inline int ParsingEngine<B>::Parse_ValidElement() {
2080        bool is_emptyStartTag = false;
2081        int nameID = Parse_ValidStartTag(is_emptyStartTag);
2082#ifdef DEBUG
2083        printf("Parse_ValidElement: nameID = %d, is_emptyStartTag=%i\n",nameID, is_emptyStartTag);
2084#endif
2085        ContentModel * cm = model_info->ContentModelData[nameID];
2086        switch (cm->cm_type) {
2087                case cm_Empty:
2088                        if (!is_emptyStartTag) {
2089                                if (at_EndTag_Start<B::Base>(cur())) {
2090                                        Parse_WF_EndTag(nameID);
2091                                }
2092                                else {
2093                                        Validity_Error(vErr_elementvalid);
2094                                }
2095                        }
2096                        break;
2097                case cm_Any:           
2098                        if (!is_emptyStartTag) {
2099                                Parse_AnyContent();
2100                                Parse_WF_EndTag(nameID);
2101                        }
2102                        break;
2103                case cm_Mixed:         
2104                        if (!is_emptyStartTag) {
2105                                Parse_MixedContent(((CM_Mixed *) cm)->elements);
2106                                Parse_WF_EndTag(nameID);
2107                        }
2108                        break;
2109                case cm_RegExp:
2110                        CM_RegExp * cre = (CM_RegExp *) cm;
2111                        int content_state = 0;
2112                        if (!is_emptyStartTag) {
2113                                Parse_ValidContent(cre, content_state);
2114                                #ifdef DEBUG
2115                                printf("Final content_state = %i, nameID = %i\n", content_state, nameID);
2116                                #endif
2117                                Parse_WF_EndTag(nameID);               
2118                        }
2119                        if (cre->transition_map[content_state][0]==0) {
2120                                Validity_Error(vErr_elementvalid);
2121                        }
2122        }
2123        return nameID;
2124}
2125
2126template <class B>
2127inline void ParsingEngine<B>::Parse_ValidContent(CM_RegExp * cre, int & cur_state) {
2128        do {
2129                ScanTo(NonWS);
2130                /* If non-null report WS  WS_action()? */
2131                text_or_markup_start = AbsPos();
2132                if (at_EndTag_Start<B::Base>(cur())) {
2133                        break;
2134                }
2135                else if (at_ElementTag_Start<B::Base>(cur())) {
2136                        int nameID = Parse_ValidElement();
2137#ifdef DEBUG
2138                        printf("Content model state transition %i", cur_state);
2139#endif
2140                        cur_state = cre->transition_map[cur_state][nameID];
2141#ifdef DEBUG
2142                        printf("-> %i\n", cur_state);
2143#endif
2144                }
2145                else if (at_Comment_Start<B::Base>(cur())) {
2146                        Parse_Comment();
2147                }
2148                else if (at_PI_Start<B::Base>(cur())) {
2149                        Parse_PI();
2150                }
2151                else if (AtChar<B::Base,'&'>(cur())) {
2152                        Parse_ValidEntityRef(cre, cur_state);
2153#ifdef DEBUG
2154                        printf("EntityRef complete, cur_state = %i\n", cur_state);
2155#endif
2156                       
2157                }
2158                else if (at_EOF()) {
2159                        break;
2160                }
2161                else if (AtChar<B::Base,'<'>(cur())) {
2162                        Syntax_Error(NT_markupdecl);
2163                }
2164                else {
2165                        Validity_Error(vErr_elementvalid);
2166                }
2167        } while(1);
2168}
2169
2170
2171template <class B>
2172inline void ParsingEngine<B>::Parse_AnyContent() {
2173        do {
2174                text_or_markup_start = AbsPos();
2175                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
2176                if (at_ElementTag_Start<B::Base>(cur())) {
2177                        text_if_nonnull_action();
2178                        int nameID = Parse_ValidElement();
2179                }
2180                else if (at_EndTag_Start<B::Base>(cur())) {
2181                        text_if_nonnull_action();
2182                        return;
2183                }
2184                else if (at_Comment_Start<B::Base>(cur())) {
2185                        text_if_nonnull_action();
2186                        Parse_Comment();
2187                }
2188                else if (at_CharRef_Start<B::Base>(cur())) {
2189                        text_if_nonnull_action();
2190                        Parse_CharRef();
2191                }
2192                else if (AtChar<B::Base,'&'>(cur())) {
2193                        text_if_nonnull_action();
2194                        Parse_EntityRef();
2195                }
2196                else if (at_CDATA_Start<B::Base>(cur())) {
2197                        text_if_nonnull_action();
2198                        Parse_CDATA();
2199                }
2200                else if (at_PI_Start<B::Base>(cur())) {
2201                        text_if_nonnull_action();
2202                        Parse_PI();
2203                }
2204                else if (at_CDATA_End<B::Base>(cur())) {
2205                        text_if_nonnull_action();
2206                        Advance(3);
2207                        Syntax_Error(NT_CharData);
2208                }
2209                else if (at_EOF()) {
2210                        text_if_nonnull_action();
2211                        return;
2212                }
2213                else if (AtChar<B::Base,'<'>(cur())) {
2214                        Syntax_Error(NT_markupdecl);
2215                }
2216                else {
2217                        Advance(1);
2218                        continue;
2219                }
2220        } while (1);
2221}
2222template <class B>
2223inline void ParsingEngine<B>::Parse_MixedContent(symbol_set_t elems) {
2224        do {
2225                text_or_markup_start = AbsPos();
2226                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
2227/*              if (AtChar<B::Base,'<'>(cur())) {
2228                        text_if_nonnull_action();
2229                        Parse_Markup<B>();
2230                }*/
2231                if (at_ElementTag_Start<B::Base>(cur())) {
2232                        text_if_nonnull_action();
2233                        int nameID = Parse_ValidElement();
2234                        if (elems[nameID] == 0) {
2235                                Validity_Error(vErr_elementvalid);
2236                        }
2237                }
2238                else if (at_EndTag_Start<B::Base>(cur())) {
2239                        text_if_nonnull_action();
2240                        return;
2241                }
2242                else if (at_Comment_Start<B::Base>(cur())) {
2243                        text_if_nonnull_action();
2244                        Parse_Comment();
2245                }
2246                else if (at_CharRef_Start<B::Base>(cur())) {
2247                        text_if_nonnull_action();
2248                        Parse_CharRef();
2249                }
2250                else if (AtChar<B::Base,'&'>(cur())) {
2251                        text_if_nonnull_action();
2252                        Parse_EntityRef();
2253                }
2254                else if (at_CDATA_Start<B::Base>(cur())) {
2255                        text_if_nonnull_action();
2256                        Parse_CDATA();
2257                }
2258                else if (at_PI_Start<B::Base>(cur())) {
2259                        text_if_nonnull_action();
2260                        Parse_PI();
2261                }
2262                else if (at_CDATA_End<B::Base>(cur())) {
2263                        text_if_nonnull_action();
2264                        Advance(3);
2265                        Syntax_Error(NT_CharData);
2266                }
2267                else if (at_EOF()) {
2268                        text_if_nonnull_action();
2269                        return;
2270                }
2271                else if (AtChar<B::Base,'<'>(cur())) {
2272                        Syntax_Error(NT_markupdecl);
2273                }
2274                else {
2275                        Advance(1);
2276                        continue;
2277                }
2278        } while (1);
2279}
2280
2281
2282template <class B>
2283inline int ParsingEngine<B>::Parse_Name() {
2284        int name_pos = AbsPos();
2285        ScanTo(NameFollow);
2286        int lgth = AbsPos()-name_pos;
2287        int nameID = model_info->symbol_table->ASCII_Lookup_or_Insert(&((char *) x8data)[buffer_rel_pos-lgth], lgth);
2288        if (nameID != 0) return nameID;
2289        else {
2290                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2291                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2292                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2293                return model_info->symbol_table->LookupOrInsertReserved();
2294        }
2295}
2296
2297template <>
2298inline int ParsingEngine< X8_Buffer<EBCDIC> >::Parse_Name() {
2299        int name_pos = AbsPos();
2300        ScanTo(NameFollow);
2301        int lgth = AbsPos()-name_pos;
2302//      int nameID = local_EBCDIC_table->Lookup_or_Insert(GetCodeUnitPtr(name_pos), lgth);
2303//      if (nameID != 0) return nameID;
2304//      else {
2305                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2306                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2307                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2308                return model_info->symbol_table->LookupOrInsertReserved();
2309//      }
2310}
2311
2312template <>
2313inline int ParsingEngine<UTF8_Buffer>::Parse_Name() {
2314        int name_pos = AbsPos();
2315        ScanTo(NameFollow);
2316        int lgth = AbsPos()-name_pos;
2317        return model_info->symbol_table->UTF8_Lookup_or_Insert(&((char *)x8data)[buffer_rel_pos-lgth], lgth);
2318}
2319
2320
2321template <class B>
2322inline void ParsingEngine<B>::Parse_DocumentContent() {
2323#if (VALIDATION_MODE == ON)
2324        int cur_state = 0;
2325        Parse_ValidContent(model_info->rootModel, cur_state);
2326        if (model_info->rootModel->transition_map[cur_state][0]==0) {
2327                Validity_Error(vErr_elementvalid);
2328        }
2329#endif
2330#if (VALIDATION_MODE == OFF)   
2331        Parse_WF_Element();
2332        ScanTo(NonWS);
2333        while(at_Comment_Start<B::Base>(cur()) || at_PI_Start<B::Base>(cur()) ){
2334                if (at_Comment_Start<B::Base>(cur()))
2335                        Parse_Comment();
2336                else 
2337                        Parse_PI();
2338                ScanTo(NonWS);
2339        }
2340        if (!at_EOF()) {
2341                Syntax_Error(NT_document);
2342        }       
2343#endif
2344}
2345
Note: See TracBrowser for help on using the repository browser.