source: trunk/src/engine.c @ 171

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

XML 5th edition.

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