source: trunk/src/engine.c @ 173

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

End-tags for non UTF-8; predefined symbol fix; DTD parsing fixes.

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