source: trunk/src/engine.c @ 174

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

Nmtokens.

File size: 67.1 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                /* Check for notations that were used, but not defined by the end of the DTD. */
1182                #if (VALIDATION_MODE == ON)
1183                hash_map<int, int >::iterator j;
1184                for (j=model_info->GlobalNotationTable.begin(); j!=model_info->GlobalNotationTable.end(); j++) {
1185                        if (j->second == -1)
1186                                Validity_Error(vErr_notatn);
1187                }
1188                #endif
1189        }
1190        else
1191                Syntax_Error(NT_doctypedecl);   
1192}
1193
1194template <class B>
1195inline void ParsingEngine<B>::Parse_ExternalID (char *& systemLiteral, char *& pubidLiteral){
1196        int quot_start, lgth;
1197        if(at_SYSTEM<B::Base>(cur())){
1198                Advance(6);
1199                pubidLiteral = NULL;
1200                requireWS();
1201                if (!AtQuote<B::Base>(cur())) Syntax_Error(NT_ExternalID);
1202                quot_start = AbsPos()+1;
1203                Parse_SystemLiteral (); /*  SystemLiteral */
1204                lgth = AbsPos() - quot_start - 1;                       
1205                systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1206        }
1207        else if (at_PUBLIC<B::Base>(cur())){
1208                Advance(6);
1209                requireWS();
1210                if (!AtQuote<B::Base>(cur())) Syntax_Error(NT_ExternalID);
1211                quot_start = AbsPos()+1;
1212                Parse_PubidLiteral ();/*  PubidLiteral */
1213                lgth = AbsPos() - quot_start - 1;                       
1214                pubidLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1215                systemLiteral = NULL;
1216                if (AtChar<B::Base, '>'>(cur())) return;
1217                requireWS();
1218                if (AtQuote<B::Base>(cur())) {
1219                        quot_start = AbsPos()+1;       
1220                        Parse_SystemLiteral ();/*  SystemLiteral */
1221                        lgth = AbsPos() - quot_start - 1;                       
1222                        systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1223                }
1224        }
1225        else
1226                Syntax_Error(NT_ExternalID); 
1227}
1228
1229template <class B>
1230inline void ParsingEngine<B>::Parse_SystemLiteral (){
1231        unsigned char quoteCh;
1232        if(AtQuote<B::Base>(cur())){
1233                quoteCh = cur()[0];
1234                Advance(1);
1235        }       
1236        ScanTo(Quote);                 
1237        while (cur()[0] != quoteCh){
1238                if(at_EOF())
1239                        Syntax_Error(NT_SystemLiteral);
1240                Advance(1);
1241                ScanTo(Quote);
1242        }
1243        Advance(1);
1244}
1245
1246template <class B>
1247inline void ParsingEngine<B>::Parse_PubidLiteral (){
1248        unsigned char quoteCh;
1249        if(AtQuote<B::Base>(cur())){
1250                quoteCh = cur()[0];
1251                Advance(1);
1252        }       
1253        while (at_PubidChar<B::Base>(cur())) Advance(1);
1254        if (cur()[0] != quoteCh){
1255                Syntax_Error(NT_PubidLiteral);
1256        }
1257        Advance(1);
1258}
1259
1260template <class B>
1261inline void ParsingEngine<B>::Parse_IntSubset (){
1262       
1263        while(1){
1264                ScanTo(NonWS); 
1265                text_or_markup_start = AbsPos();
1266                if (AtChar<B::Base,'%'>(cur()))
1267                        Parse_PEReference();   
1268                else if (at_PI_Start<B::Base>(cur())) {
1269                        Parse_PI();
1270                }
1271                else if (at_Comment_Start<B::Base>(cur())) {
1272                        Parse_Comment();
1273                }
1274                else if (AtChar<B::Base,'<'>(cur())){
1275                        Advance(1);
1276                        if(AtChar<B::Base,'!'>(cur())){
1277                                Advance(1);
1278                                if (at_ELEMENT<B::Base>(cur()))
1279                                        Parse_Elementdecl();
1280                                else if (at_ATTLIST<B::Base>(cur()))
1281                                        Parse_AttlistDecl();
1282                                else if (at_ENTITY<B::Base>(cur()))
1283                                        Parse_Entitydecl();
1284                                else if (at_NOTATION<B::Base>(cur()))
1285                                        Parse_Notationdecl();
1286                                else {
1287                                        Syntax_Error(NT_markupdecl);           
1288                                }                                                               
1289                        }
1290                        else
1291                                Syntax_Error(NT_markupdecl); 
1292                }
1293                else if (AtChar<B::Base,']'>(cur())){
1294                        break;
1295                }
1296                else
1297                        Syntax_Error(NT_intSubset); 
1298        }
1299}
1300
1301
1302template <class B>
1303inline void ParsingEngine<B>::Parse_PEReference (){
1304
1305        Advance(1); /* Skip "%". */
1306        int nameID = Parse_Name(); 
1307        if (AtChar<B::Base,';'>(cur())) {
1308                Advance(1);
1309                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1310                PEntity_info * this_info;
1311                Parser_Interface * entity_parser;
1312                int entityID = model_info->GlobalPEntityTable[nameID]; 
1313                if (entityID == 0)
1314                        WF_Error(wfErr_wf_entdeclared);
1315                else{
1316                        this_info = model_info->PEntityData[entityID-1];
1317                        if (this_info->is_external){
1318                               
1319//                      if (entity_Info->standalone != Standalone_no)
1320//                              WF_Error(wfErr_NoExternalRefs);
1321//                      else {
1322                                        entity_parser = ParserFactory(this_info->systemLiteral, model_info);
1323                                        entity_parser->Parse_WF_Content();
1324                                        if(!entity_parser->at_EOF())
1325                                                Syntax_Error(NT_content);
1326                                        entity_parser->~Parser_Interface();
1327//                      }
1328                        }
1329                        else {
1330                        }
1331                }
1332        }
1333        else
1334                Syntax_Error(NT_PEReference);
1335}
1336
1337
1338template <class B>
1339inline void ParsingEngine<B>::Parse_Elementdecl (){
1340
1341        Advance(7); /* Skip "<!ELEMENT". */
1342
1343    requireWS();
1344        int nameID = Parse_Name();
1345        int elemID = model_info->getOrInsertGlobalElement(nameID);
1346
1347        requireWS();
1348        ContentModel * cm;
1349        /* Start parsing "contentspec"*/
1350        if (at_EMPTY<B::Base>(cur())) {
1351        Advance(5);
1352        cm = new CM_Empty();
1353        model_info->ContentModelData[nameID] = cm;
1354        }
1355    else if (at_ANY<B::Base>(cur())) {
1356        Advance(3);
1357        cm = new CM_Any();
1358        model_info->ContentModelData[nameID] = cm;
1359    }
1360    else {
1361        if (AtChar<B::Base,'('>(cur()))
1362                        Advance(1);
1363                ScanTo(NonWS);
1364                if (at_PCDATA<B::Base>(cur())){
1365                        cm = Parse_RemainingMixed();
1366                        model_info->ContentModelData[nameID] = cm;
1367                }
1368                else{
1369
1370                        CM_RegExp * cre = new CM_RegExp;
1371                        cre->content_re = Parse_RemainingChildren();
1372
1373                        int id_count = cre->content_re->Set_IDs(0);
1374                        cre->content_re->Set_First_Map();       
1375                        symbol_set_t * transition_map = new symbol_set_t[id_count+1];
1376                        cre->content_re->follow_map[0] = id_count+1;
1377                       
1378                        cre->content_re->Set_Follow_Map(transition_map);
1379                        transition_map[0] = cre->content_re->first_map;
1380                       
1381                        if (cre->content_re->matches_empty)
1382                                transition_map[0][0]=id_count+1;
1383                               
1384                        cre -> transition_map = transition_map;
1385                       
1386                        model_info->ContentModelData[nameID] = cre;
1387                        cm = cre;
1388                }                       
1389    }
1390    ScanTo(NonWS);   
1391
1392        if (AtChar<B::Base,'>'>(cur())) {
1393                Advance(1);
1394        }
1395        else
1396                Syntax_Error(NT_elementdecl);
1397}
1398template <class B>
1399inline ContentModel * ParsingEngine<B>::Parse_RemainingMixed (){
1400        CM_Mixed * r = new CM_Mixed();
1401        Advance(7);  /* Skip "#PCDATA". */
1402   
1403    if (AtChar<B::Base,')'>(cur())){
1404        if (AtChar<B::Base,'*'>(cur())) {
1405                Advance(2);
1406                }
1407                else {
1408                        Advance(1);
1409                }
1410    }
1411    else{
1412        ScanTo(NonWS);
1413        int k = 0;
1414        while (AtChar<B::Base,'|'>(cur())){
1415                        Advance(1);
1416                        ScanTo(NonWS);
1417                        int nameID = Parse_Name();
1418                        r->elements[nameID] = ++k;
1419                        ScanTo(NonWS);
1420                }
1421                if (at_Para_star<B::Base>(cur())) Advance(2);
1422                else {
1423                        Syntax_Error(NT_Mixed);
1424                        exit(-1);
1425        }
1426    }
1427    return r;
1428}
1429
1430
1431template <class B>
1432inline Content_RE * ParsingEngine<B>::Parse_RemainingChildren (){
1433        Content_RE * c1 = Parse_Cp();
1434        Content_RE * r = c1;
1435        ScanTo(NonWS);
1436        if(AtChar<B::Base,'|'>(cur())){
1437                CRE_Choice * rslt = new CRE_Choice;
1438                rslt->subCMs.push_back(c1);
1439                Advance(1);
1440                ScanTo(NonWS);
1441                rslt->subCMs.push_back(Parse_Cp());
1442                ScanTo(NonWS);
1443                while(!AtChar<B::Base,')'>(cur())){
1444                        if(AtChar<B::Base,'|'>(cur()))
1445                                Advance(1);
1446                        else
1447                                Syntax_Error(NT_children);
1448                        ScanTo(NonWS);
1449                        rslt->subCMs.push_back(Parse_Cp());
1450                        ScanTo(NonWS);
1451                }
1452                Advance(1);
1453                rslt->Compile();
1454                r = rslt;
1455        }
1456        else if(AtChar<B::Base,','>(cur())){
1457                CRE_Seq * rslt = new CRE_Seq;
1458                rslt->subCMs.push_back(c1);
1459                Advance(1);
1460                ScanTo(NonWS);
1461                rslt->subCMs.push_back(Parse_Cp());
1462                ScanTo(NonWS);
1463                while(!AtChar<B::Base,')'>(cur())){
1464                        if(AtChar<B::Base,','>(cur()))
1465                                Advance(1);
1466                        else
1467                                Syntax_Error(NT_children);
1468                        ScanTo(NonWS);
1469                        rslt->subCMs.push_back(Parse_Cp());
1470                        ScanTo(NonWS);
1471                }
1472                Advance(1);
1473                rslt->Compile();
1474                r = rslt;
1475        }       
1476        else if(AtChar<B::Base,')'>(cur())){
1477                Advance(1);
1478        }
1479        else
1480                Syntax_Error(NT_children);
1481               
1482        if (AtChar<B::Base,'?'>(cur())) {
1483                Advance(1);
1484                r = new CRE_Opt(r);
1485        }
1486        else if (AtChar<B::Base,'*'>(cur())) {
1487                Advance(1);
1488                r = new CRE_Star(r);
1489        }
1490        else if (AtChar<B::Base,'+'>(cur())) {
1491                Advance(1);
1492                r = new CRE_Plus(r);
1493        }
1494
1495        return r;
1496}
1497
1498template <class B>
1499inline Content_RE * ParsingEngine<B>::Parse_Cp (){
1500        if (AtChar<B::Base,'('>(cur())){
1501                Advance(1);
1502                ScanTo(NonWS);
1503                Parse_RemainingChildren();
1504        }
1505        else{
1506                int nameID = Parse_Name();
1507                CRE_Name * r = new CRE_Name(nameID);
1508
1509                if (AtChar<B::Base,'?'>(cur())) {
1510                        Advance(1);
1511                        return new CRE_Opt(r);
1512                }
1513                else if (AtChar<B::Base,'*'>(cur())) {
1514                        Advance(1);
1515                        return new CRE_Star(r);
1516                }
1517                else if (AtChar<B::Base,'+'>(cur())) {
1518                        Advance(1);
1519                        return new CRE_Plus(r);
1520                }
1521                else return r;
1522        }
1523}
1524
1525template <class B>
1526inline void ParsingEngine<B>::Parse_AttlistDecl (){
1527       
1528        int old_abspos;
1529       
1530        int name_start;
1531        int lgth;
1532       
1533        int elemID;
1534        int attID;
1535       
1536        Advance(7); /* Skip "ATTLIST. */
1537        requireWS();
1538       
1539        int nameID = Parse_Name();
1540        elemID = model_info->getOrInsertGlobalElement(nameID);
1541       
1542        old_abspos = AbsPos();
1543        ScanTo(NonWS);
1544        while(!AtChar<B::Base,'>'>(cur())) {
1545                if(old_abspos == AbsPos())
1546                Syntax_Error(NT_AttlistDecl);
1547               
1548                int att_nameID = Parse_Name();
1549               
1550                attID = model_info->getOrInsertGlobalAttName(att_nameID);
1551                if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1552        ATT_info * this_info = new ATT_info;
1553        this_info->globalATT_id = attID;
1554        requireWS();
1555        if (at_CDATA<B::Base>(cur())){
1556                Advance(5);
1557                this_info->attType = CDATA_att;
1558        }
1559        else if(at_ID<B::Base>(cur())){
1560                Advance(2);
1561                this_info->attType = ID_att;
1562        }
1563        /* Make sure to check IDREFS before IDREF*/
1564        else if(at_IDREFS<B::Base>(cur())){
1565                Advance(6);
1566                this_info->attType = IDREFS_att;
1567        }
1568        else if(at_IDREF<B::Base>(cur())){
1569                Advance(5);
1570                this_info->attType = IDREF_att;
1571        }
1572        else if(at_ENTITY<B::Base>(cur())){
1573                Advance(6);
1574                this_info->attType = ENTITY_att;
1575        }
1576        else if(at_ENTITIES<B::Base>(cur())){
1577                Advance(8);
1578                this_info->attType = ENTITIES_att;
1579        }
1580        /* Make sure to check NMTOKENS before NMTOKEN*/
1581        else if(at_NMTOKENS<B::Base>(cur())){
1582                Advance(8);
1583                this_info->attType = NMTOKENS_att;
1584        }
1585        else if(at_NMTOKEN<B::Base>(cur())){
1586                Advance(7);
1587                this_info->attType = NMTOKEN_att;
1588        }
1589        else if(at_NOTATION<B::Base>(cur())){ /* NotationType = 'NOTATION' S Enumeration
1590                                                                         when Nmtoken = Name */
1591                Advance(8);
1592                        requireWS();
1593                Parse_Notation(this_info);
1594                this_info->attType = NOTATION_att;
1595        }
1596        else if(AtChar<B::Base,'('>(cur())){
1597                Parse_Enumeration(this_info);
1598                this_info->attType = enumeration_att;
1599        }
1600        else
1601                Syntax_Error(NT_AttlistDecl);
1602        requireWS();
1603        Parse_DefaultDecl(this_info);
1604
1605                ScanTo(NonWS);
1606                model_info->ElementAttributeData[elemID].push_back(this_info);
1607        }
1608
1609        Advance(1);
1610}
1611
1612template <class B>
1613inline void ParsingEngine<B>::Parse_Notation (ATT_info * this_info){
1614
1615        if(AtChar<B::Base,'('>(cur()))
1616                Advance(1);
1617        else
1618                Syntax_Error(NT_NotationType);
1619        ScanTo(NonWS);
1620       
1621    int notn_nameID = Parse_Name();
1622
1623        /*Notation name is not in the global table!*/
1624        if(model_info->GlobalNotationTable[notn_nameID]==0)
1625                model_info->GlobalNotationTable[notn_nameID] = -1;
1626       
1627        ScanTo(NonWS);
1628        while(AtChar<B::Base,'|'>(cur())){
1629                Advance(1);
1630                ScanTo(NonWS); 
1631                notn_nameID = Parse_Name();
1632                       
1633                if(model_info->GlobalNotationTable[notn_nameID]==0)
1634//                      Validity_Error(vErr_notatn);
1635                        model_info->GlobalNotationTable[notn_nameID] = -1;
1636                       
1637                ScanTo(NonWS);
1638        }
1639        if (AtChar<B::Base,')'>(cur())) 
1640                Advance(1);
1641        else
1642                Syntax_Error(NT_NotationType);
1643}
1644
1645template <class B>
1646inline void ParsingEngine<B>::Parse_Enumeration (ATT_info * this_info){
1647
1648        int enumCount=0;
1649        if(AtChar<B::Base,'('>(cur()))
1650                Advance(1);
1651        else
1652                Syntax_Error(NT_Enumeration);
1653        ScanTo(NonWS);
1654       
1655        int nmtokenID = Parse_Nmtoken();
1656       
1657        this_info->enumValues[nmtokenID]=++(enumCount);
1658       
1659        ScanTo(NonWS);
1660        while(AtChar<B::Base,'|'>(cur())){
1661                Advance(1);
1662                ScanTo(NonWS); 
1663                int nmtokenID = Parse_Nmtoken();
1664       
1665                int enumID = this_info->enumValues[nmtokenID];
1666                if(enumID==0){ 
1667                        this_info->enumValues[nmtokenID]=++(enumCount);
1668                        enumID = enumCount;
1669                }
1670                else if(!StrictWellFormedness){
1671                        Validity_Error(vErr_NoDuplicateTokens);
1672                }
1673                ScanTo(NonWS);
1674        }
1675        if (AtChar<B::Base,')'>(cur())) 
1676                Advance(1);
1677        else
1678                Syntax_Error(NT_Enumeration);
1679}
1680
1681template <class B>
1682inline void ParsingEngine<B>::Parse_DefaultDecl (ATT_info * this_info){
1683        if(at_REQUIRED<B::Base>(cur())){
1684                Advance(9);
1685                this_info->defaultKind = REQUIRED_att;
1686        }
1687        else if(at_IMPLIED<B::Base>(cur())){
1688                Advance(8);
1689                this_info->defaultKind = IMPLIED_att;
1690        }
1691        else {
1692                if(at_FIXED<B::Base>(cur())){
1693                        Advance(6);
1694                        requireWS();
1695                        this_info->defaultKind = FIXED_att;
1696                }
1697                else this_info->defaultKind = DEFAULT_att;
1698                if(AtQuote<B::Base>(cur())){
1699                        int quot_start = AbsPos()+1;
1700                        Parse_AttValue();
1701                        /* need to normalize */
1702                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
1703                       
1704                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
1705                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
1706                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
1707                        }
1708                else
1709                        Syntax_Error(NT_DefaultDecl);
1710        }
1711}
1712
1713template <class B>
1714inline void ParsingEngine<B>::Parse_Entitydecl (){
1715       
1716        int name_start;
1717        int quot_start;
1718        int lgth;
1719        int old_abspos;
1720        char * s;
1721       
1722        Advance(6); /* Skip "ENTITY. */
1723        requireWS();
1724       
1725        if (AtChar<B::Base,'%'>(cur())){
1726                Advance(1);
1727                requireWS();
1728               
1729                int nameID = Parse_Name();
1730                PEntity_info * this_info = new PEntity_info;
1731                int entityID = model_info->GlobalPEntityTable[nameID];
1732                if(entityID==0){       
1733                        model_info->GlobalPEntityTable[nameID]=++(model_info->globalPEntityCount);
1734                        entityID = model_info->globalPEntityCount;
1735                        this_info->globalPEntity_id = entityID;
1736                }
1737                else
1738                        printf("Warning: Entity definition already exist!\n");
1739       
1740                requireWS();
1741                if(AtQuote<B::Base>(cur())){
1742                Parse_PEntityValue(this_info);
1743                this_info->is_external = false;
1744        }
1745        else {
1746                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1747                this_info->is_external = true;
1748                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1749        }
1750        model_info->PEntityData.push_back(this_info);
1751        }
1752        else{
1753                int nameID = Parse_Name();
1754       
1755                GEntity_info * this_info = new GEntity_info();
1756                int entityID = model_info->GlobalGEntityTable[nameID];
1757                if(entityID==0){       
1758                        model_info->GlobalGEntityTable[nameID]=++(model_info->globalGEntityCount);
1759                        entityID = model_info->globalGEntityCount;
1760                        this_info->globalGEntity_id = entityID;
1761                }
1762                else
1763                        printf("Warning: Entity definition already exist!\n");
1764                       
1765                requireWS();
1766               
1767                if(AtQuote<B::Base>(cur())){
1768                Parse_GEntityValue(this_info);                 
1769                this_info->is_external = false;
1770        }
1771        else {
1772                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1773                this_info->is_external = true;
1774                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1775                        old_abspos = AbsPos();
1776                        ScanTo(NonWS);
1777                if(at_NDATA<B::Base>(cur())){
1778                        if(old_abspos == AbsPos())
1779                                Syntax_Error(NT_EntityDecl);
1780                        else
1781                                Advance(5);
1782                        requireWS();
1783                        name_start = AbsPos();
1784                        int nameID = Parse_Name();
1785                        lgth = AbsPos() - name_start;
1786                                this_info->NDataName = copy_string(GetCodeUnitPtr(name_start),lgth);
1787                }
1788                }
1789        model_info->GEntityData.push_back(this_info);
1790        }
1791        ScanTo(NonWS);
1792        if (AtChar<B::Base,'>'>(cur())){
1793                Advance(1);
1794        }
1795        else
1796                Syntax_Error(NT_EntityDecl);
1797}
1798
1799template <class B>
1800inline void ParsingEngine<B>::Parse_Notationdecl (){
1801
1802        int old_abspos;
1803        Advance(8); /* Skip "NOTATION. */
1804        requireWS();
1805       
1806        int nameID = Parse_Name();
1807
1808        int notationID = model_info->GlobalNotationTable[nameID];
1809        /* notationID == -1: used but not yet defined; == 0: new, > 0 prev. defined */
1810        if(notationID <= 0){   
1811                model_info->GlobalNotationTable[nameID]=++(model_info->globalNotationCount);
1812                notationID = model_info->globalNotationCount;
1813        }
1814        else /*Duplicate notation name!*/
1815                Validity_Error(vErr_NoDuplicateTokens);
1816        Notation_info * this_info = new Notation_info;
1817        ScanTo(NonWS);         
1818    Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1819        ScanTo(NonWS);
1820        if (AtChar<B::Base,'>'>(cur())) {
1821                Advance(1);
1822        }
1823        else
1824                Syntax_Error(NT_NotationDecl);
1825}
1826
1827template <class B>
1828inline void ParsingEngine<B>::requireWS(){
1829       
1830    int old_abspos = AbsPos(); 
1831    ScanTo(NonWS);
1832    if(old_abspos == AbsPos())
1833        Syntax_Error(NT_S);
1834}
1835
1836template <class B>
1837inline void ParsingEngine<B>::Parse_AttValue(){
1838       
1839        int     quoteCh = cur()[0];
1840        Advance(1); /* Skip " or ' */
1841
1842        ScanTo(Quote);                 
1843        while (cur()[0] != quoteCh){
1844                if (at_CharRef_Start<B::Base>(cur())){
1845                        Parse_CharRef();
1846                        ScanTo(Quote);
1847                }
1848                else if (AtChar<B::Base,'&'>(cur())){
1849                        Parse_EntityRef();
1850                        ScanTo(Quote);
1851                }
1852                else if (AtQuote<B::Base>(cur())) {
1853                        Advance(1);
1854                        ScanTo(Quote);
1855                }
1856                else /* if (AtChar<B::Base,'<'>(cur())) */
1857                        WF_Error(wfErr_CleanAttrVals);
1858        }
1859        Advance(1);
1860}
1861
1862template <class B>
1863inline void ParsingEngine<B>::Parse_GEntityValue(GEntity_info * this_info){
1864       
1865        int     quoteCh = cur()[0];
1866        Advance(1); /* Skip " or ' */
1867        this_info->is_simple = true;
1868        int quot_start = AbsPos();
1869        char * replText;
1870        ScanTo(Quote);         
1871        replText = copy_string(GetCodeUnitPtr(quot_start),AbsPos()-quot_start);
1872        while (cur()[0] != quoteCh){
1873                if (at_CharRef_Start<B::Base>(cur())){
1874                        strcat (replText,Replace_CharRef());
1875                        quot_start = AbsPos();
1876                        ScanTo(Quote);
1877                }
1878                else if (AtChar<B::Base,'&'>(cur())){
1879                        strcat (replText,Replace_EntityRef(this_info->is_simple));
1880                        quot_start = AbsPos();
1881                        ScanTo(Quote);
1882                }
1883                else if (AtQuote<B::Base>(cur())) {
1884                        quot_start = AbsPos();
1885                        Advance(1);
1886                        ScanTo(Quote);
1887                }
1888                else { /* '<' found */
1889                        quot_start = AbsPos();
1890                        Advance(1);
1891                        ScanTo(Quote);
1892                        this_info->is_simple = false;                   
1893                }
1894                replText = cat_string (replText,(char *)GetCodeUnitPtr(quot_start), strlen(replText), AbsPos()-quot_start);
1895        }
1896        this_info->ReplacementText = replText;
1897        Advance(1);
1898}
1899
1900template <class B>
1901inline char * ParsingEngine<B>::Replace_EntityRef(bool& is_simple){
1902        Advance(1);
1903        int nameID = Parse_Name(); 
1904        if (AtChar<B::Base,';'>(cur()))
1905                Advance(1);
1906        else
1907                Syntax_Error(NT_EntityValue);
1908        int entityID = model_info->GlobalGEntityTable[nameID]; 
1909        if (entityID == 0)
1910                WF_Error(wfErr_wf_entdeclared);
1911        else{
1912                if (model_info->GEntityData[entityID-1]->is_simple == false)
1913                        is_simple = false;
1914                return model_info->GEntityData[entityID-1]->ReplacementText;
1915        }
1916       
1917}
1918
1919template <class B>
1920inline void ParsingEngine<B>::Parse_PEntityValue(PEntity_info * this_info){
1921        fprintf(stderr,"parsing of parameter entity value has not been completed yet.\n");
1922        exit(-1);
1923}
1924
1925template <class B>
1926inline char * ParsingEngine<B>::Replace_CharRef(){
1927        Advance(2);
1928        fprintf(stderr,"Replacement of Character Reference has not been completed yet.\n");
1929        exit(-1);
1930}
1931
1932template <class B>
1933inline void ParsingEngine<B>::Parse_Prolog(){
1934        ScanTo(NonWS);
1935        int old_pos = AbsPos();
1936        while (!at_DOCTYPE_start<B::Base>(cur())) {
1937                if (at_Comment_Start<B::Base>(cur())) 
1938                        Parse_Comment();
1939                else if (at_PI_Start<B::Base>(cur()))
1940                                Parse_PI();
1941                else{
1942                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1943                        return;
1944                }
1945                ScanTo(NonWS);
1946        }
1947        Parse_DocType();
1948        ScanTo(NonWS);
1949        while(at_Comment_Start<B::Base>(cur()) || at_PI_Start<B::Base>(cur()) ){
1950                if (at_Comment_Start<B::Base>(cur()))
1951                        Parse_Comment();
1952                else 
1953                        Parse_PI();
1954                ScanTo(NonWS);
1955        }
1956        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1957}
1958
1959template <class B>
1960inline void ParsingEngine<B>::Parse_ExtSubsetDecl() {
1961        ScanTo(NonWS);
1962        int start_pos=AbsPos();
1963        while(!at_EOF()){
1964                if(at_condSect_start<B::Base>(cur())){         
1965                        Advance(3);
1966                        ScanTo(NonWS);
1967                        if (at_INCLUDE<B::Base>(cur())){
1968                                Advance(7);
1969                                ScanTo(NonWS);
1970                                if(AtChar<B::Base,'['>(cur())){
1971                                        Advance(1);
1972                                        Parse_ExtSubsetDecl();
1973                                        if(at_CDATA_End<B::Base>(cur()))
1974                                                Advance(3);
1975                                        else Syntax_Error(NT_includeSect);
1976                                }
1977                                else Syntax_Error(NT_includeSect);
1978                        }
1979                        else if (at_IGNORE<B::Base>(cur())){
1980                                Advance(6);
1981                                ScanTo(NonWS);         
1982                                if(AtChar<B::Base,'['>(cur())){
1983                                        int section_depth=1;
1984                                        Advance(1);
1985                                        while(!at_EOF()){
1986                                                ScanToMarkupStart();
1987                                                if(at_condSect_start<B::Base>(cur())){
1988                                                        Advance(3);
1989                                                        section_depth++;
1990                                                }
1991                                                else if(at_CDATA_End<B::Base>(cur())){
1992                                                        Advance(3);
1993                                                        section_depth--;
1994                                                }
1995                                                else
1996                                                        Advance(1);
1997                                                if(section_depth==0) return;                                   
1998                                        }
1999                                        Syntax_Error(NT_ignoreSectContents);   
2000                                }
2001                                else Syntax_Error(NT_ignoreSect);
2002                        }
2003                        else Syntax_Error(NT_conditionalSect);
2004                }
2005                else if (AtChar<B::Base,'%'>(cur()))
2006                        Parse_PEReference();   
2007                else if (at_PI_Start<B::Base>(cur())) {
2008                        Parse_PI();
2009                }
2010                else if (at_Comment_Start<B::Base>(cur())) {
2011                        Parse_Comment();
2012                }
2013                else if (AtChar<B::Base,'<'>(cur())){
2014                        Advance(1);
2015
2016                        if(AtChar<B::Base,'!'>(cur())){
2017                                Advance(1);
2018                                if(at_ELEMENT<B::Base>(cur()))
2019                                        Parse_Elementdecl();
2020                                else if(at_ATTLIST<B::Base>(cur()))
2021                                        Parse_AttlistDecl();
2022                                else if(at_ENTITY<B::Base>(cur()))
2023                                        Parse_Entitydecl();
2024                                else if(at_NOTATION<B::Base>(cur()))
2025                                        Parse_Notationdecl();                                   
2026                                else{
2027                                        Syntax_Error(NT_markupdecl);   
2028                                }                                                               
2029                        }
2030                        else
2031                                Syntax_Error(NT_markupdecl); 
2032                }
2033                else
2034                        Syntax_Error(NT_extSubsetDecl); 
2035                ScanTo(NonWS);
2036        }
2037        ExtSubsetDecl_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
2038}
2039
2040/* Parse a valid start or empty element tag. */
2041template <class B>
2042inline int ParsingEngine<B>::Parse_ValidStartTag (bool& is_emptyStartTag){
2043        int att_name_start;
2044        int att_val_start;
2045        int att_name_end, att_val_end;
2046        unsigned char quoteCh;
2047        Advance(1);
2048
2049        int nameID = Parse_Name(); 
2050        int elemID = model_info->GlobalElementTable[nameID];
2051        if(elemID==0)
2052                        Validity_Error(vErr_elementvalid);
2053       
2054        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
2055        /* The following test optimizes the most common case of a
2056        start tag with no attributes.  */
2057        if (AtChar<B::Base,'>'>(cur())) {
2058                Advance(1);
2059                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2060        }
2061        else {
2062                ScanTo(NonWS);
2063                if (AtChar<B::Base,'>'>(cur())) {
2064                        Advance(1);
2065                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2066                }
2067                else if (at_EmptyElementDelim<B::Base>(cur())) {
2068                        Advance(2);
2069                        is_emptyStartTag = true;
2070                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2071                }
2072                else do {
2073                        /* Must be an attribute-value pair or error. */
2074                        att_name_start = AbsPos();
2075                        int att_nameID = Parse_Name();
2076                        #if (not defined(OMISSION)) or (OMISSION != ATTRIBUTE_UNIQUENESS) 
2077                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
2078                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
2079                        else {
2080                                if (LastAttOccurrence[attID] > text_or_markup_start) {
2081                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
2082                                        break;
2083                                }                       
2084                        }
2085                        LastAttOccurrence[attID] = att_name_start;
2086                        #endif
2087                        /* The following optimized tests handle the frequently occurring
2088                        case that there are no blanks on either side of the equals sign.
2089                        In many cases, the very first test handles 100% of actual
2090                        attribute-value pairs encountered. */
2091                        if (at_EqualsQuote<B::Base>(cur())) Advance(1); 
2092                        else {
2093                                ScanTo(NonWS);
2094                                if (!AtChar<B::Base,'='>(cur())) {
2095                                        Syntax_Error(NT_STag); 
2096                                        break;
2097                                }
2098                                Advance(1); 
2099                                ScanTo(NonWS);
2100                                if (!AtQuote<B::Base>(cur())) {
2101                                        Syntax_Error(NT_STag); 
2102                                        break;
2103                                }
2104                        }
2105                        att_val_start = AbsPos()+1;
2106                        Parse_AttValue();
2107                        att_val_end = AbsPos()-1;
2108                        if (at_xmlns<B::Base>(cur()+att_name_start-AbsPos())) {
2109                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
2110                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
2111                        }
2112                        else {
2113                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
2114                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
2115                        }
2116                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
2117                        if (AtChar<B::Base,'>'>(cur())) {
2118                                Advance(1);
2119                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2120                                break;
2121                        }
2122                        else if (at_EmptyElementDelim<B::Base>(cur())) {
2123                                Advance(2);
2124                                is_emptyStartTag = true;       
2125                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2126                                break;
2127                        }
2128                        ScanTo(NonWS);
2129                        if (AtChar<B::Base,'>'>(cur())) {
2130                                Advance(1);
2131                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2132                                break;
2133                        }
2134                        else if (at_EmptyElementDelim<B::Base>(cur())) {
2135                                Advance(2);
2136                                is_emptyStartTag = true;
2137                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
2138                                break;
2139                        }
2140                        else if (AbsPos() == att_val_end + 1) { 
2141                                /* No WS following att value */
2142                                Syntax_Error(NT_STag);
2143                                break;
2144                        }
2145                } while (1);
2146        }
2147        return nameID;
2148}
2149
2150template <class B>
2151inline int ParsingEngine<B>::Parse_ValidElement() {
2152        bool is_emptyStartTag = false;
2153        int nameID = Parse_ValidStartTag(is_emptyStartTag);
2154#ifdef DEBUG
2155        printf("Parse_ValidElement: nameID = %d, name = %s, is_emptyStartTag=%i\n",nameID, model_info->symbol_table->Get_UTF8_name(nameID), is_emptyStartTag);
2156#endif
2157        ContentModel * cm = model_info->ContentModelData[nameID];
2158        switch (cm->cm_type) {
2159                case cm_Empty:
2160                        if (!is_emptyStartTag) {
2161                                if (at_EndTag_Start<B::Base>(cur())) {
2162                                        Parse_WF_EndTag(nameID);
2163                                }
2164                                else {
2165                                        Validity_Error(vErr_elementvalid);
2166                                }
2167                        }
2168                        break;
2169                case cm_Any:           
2170                        if (!is_emptyStartTag) {
2171                                Parse_AnyContent();
2172                                Parse_WF_EndTag(nameID);
2173                        }
2174                        break;
2175                case cm_Mixed:         
2176                        if (!is_emptyStartTag) {
2177                                Parse_MixedContent(((CM_Mixed *) cm)->elements);
2178                                Parse_WF_EndTag(nameID);
2179                        }
2180                        break;
2181                case cm_RegExp:
2182                        CM_RegExp * cre = (CM_RegExp *) cm;
2183                        int content_state = 0;
2184                        if (!is_emptyStartTag) {
2185                                Parse_ValidContent(cre, content_state);
2186                                #ifdef DEBUG
2187                                printf("Final content_state = %i, nameID = %i\n", content_state, nameID);
2188                                #endif
2189                                Parse_WF_EndTag(nameID);               
2190                        }
2191                        if (cre->transition_map[content_state][0]==0) {
2192                                Validity_Error(vErr_elementvalid);
2193                        }
2194        }
2195        return nameID;
2196}
2197
2198template <class B>
2199inline void ParsingEngine<B>::Parse_ValidContent(CM_RegExp * cre, int & cur_state) {
2200        do {
2201                ScanTo(NonWS);
2202                /* If non-null report WS  WS_action()? */
2203                text_or_markup_start = AbsPos();
2204                if (at_EndTag_Start<B::Base>(cur())) {
2205                        break;
2206                }
2207                else if (at_ElementTag_Start<B::Base>(cur())) {
2208                        int nameID = Parse_ValidElement();
2209#ifdef DEBUG
2210                        printf("Content model state transition %i", cur_state);
2211#endif
2212                        cur_state = cre->transition_map[cur_state][nameID];
2213#ifdef DEBUG
2214                        printf("-> %i\n", cur_state);
2215#endif
2216                }
2217                else if (at_Comment_Start<B::Base>(cur())) {
2218                        Parse_Comment();
2219                }
2220                else if (at_PI_Start<B::Base>(cur())) {
2221                        Parse_PI();
2222                }
2223                else if (AtChar<B::Base,'&'>(cur())) {
2224                        Parse_ValidEntityRef(cre, cur_state);
2225#ifdef DEBUG
2226                        printf("EntityRef complete, cur_state = %i\n", cur_state);
2227#endif
2228                       
2229                }
2230                else if (at_EOF()) {
2231                        break;
2232                }
2233                else if (AtChar<B::Base,'<'>(cur())) {
2234                        Syntax_Error(NT_markupdecl);
2235                }
2236                else {
2237                        Validity_Error(vErr_elementvalid);
2238                }
2239        } while(1);
2240}
2241
2242
2243template <class B>
2244inline void ParsingEngine<B>::Parse_AnyContent() {
2245        do {
2246                text_or_markup_start = AbsPos();
2247                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
2248                if (at_ElementTag_Start<B::Base>(cur())) {
2249                        text_if_nonnull_action();
2250                        int nameID = Parse_ValidElement();
2251                }
2252                else if (at_EndTag_Start<B::Base>(cur())) {
2253                        text_if_nonnull_action();
2254                        return;
2255                }
2256                else if (at_Comment_Start<B::Base>(cur())) {
2257                        text_if_nonnull_action();
2258                        Parse_Comment();
2259                }
2260                else if (at_CharRef_Start<B::Base>(cur())) {
2261                        text_if_nonnull_action();
2262                        Parse_CharRef();
2263                }
2264                else if (AtChar<B::Base,'&'>(cur())) {
2265                        text_if_nonnull_action();
2266                        Parse_EntityRef();
2267                }
2268                else if (at_CDATA_Start<B::Base>(cur())) {
2269                        text_if_nonnull_action();
2270                        Parse_CDATA();
2271                }
2272                else if (at_PI_Start<B::Base>(cur())) {
2273                        text_if_nonnull_action();
2274                        Parse_PI();
2275                }
2276                else if (at_CDATA_End<B::Base>(cur())) {
2277                        text_if_nonnull_action();
2278                        Advance(3);
2279                        Syntax_Error(NT_CharData);
2280                }
2281                else if (at_EOF()) {
2282                        text_if_nonnull_action();
2283                        return;
2284                }
2285                else if (AtChar<B::Base,'<'>(cur())) {
2286                        Syntax_Error(NT_markupdecl);
2287                }
2288                else {
2289                        Advance(1);
2290                        continue;
2291                }
2292        } while (1);
2293}
2294template <class B>
2295inline void ParsingEngine<B>::Parse_MixedContent(symbol_set_t elems) {
2296        do {
2297                text_or_markup_start = AbsPos();
2298                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
2299/*              if (AtChar<B::Base,'<'>(cur())) {
2300                        text_if_nonnull_action();
2301                        Parse_Markup<B>();
2302                }*/
2303                if (at_ElementTag_Start<B::Base>(cur())) {
2304                        text_if_nonnull_action();
2305                        int nameID = Parse_ValidElement();
2306                        if (elems[nameID] == 0) {
2307                                Validity_Error(vErr_elementvalid);
2308                        }
2309                }
2310                else if (at_EndTag_Start<B::Base>(cur())) {
2311                        text_if_nonnull_action();
2312                        return;
2313                }
2314                else if (at_Comment_Start<B::Base>(cur())) {
2315                        text_if_nonnull_action();
2316                        Parse_Comment();
2317                }
2318                else if (at_CharRef_Start<B::Base>(cur())) {
2319                        text_if_nonnull_action();
2320                        Parse_CharRef();
2321                }
2322                else if (AtChar<B::Base,'&'>(cur())) {
2323                        text_if_nonnull_action();
2324                        Parse_EntityRef();
2325                }
2326                else if (at_CDATA_Start<B::Base>(cur())) {
2327                        text_if_nonnull_action();
2328                        Parse_CDATA();
2329                }
2330                else if (at_PI_Start<B::Base>(cur())) {
2331                        text_if_nonnull_action();
2332                        Parse_PI();
2333                }
2334                else if (at_CDATA_End<B::Base>(cur())) {
2335                        text_if_nonnull_action();
2336                        Advance(3);
2337                        Syntax_Error(NT_CharData);
2338                }
2339                else if (at_EOF()) {
2340                        text_if_nonnull_action();
2341                        return;
2342                }
2343                else if (AtChar<B::Base,'<'>(cur())) {
2344                        Syntax_Error(NT_markupdecl);
2345                }
2346                else {
2347                        Advance(1);
2348                        continue;
2349                }
2350        } while (1);
2351}
2352
2353
2354template <class B>
2355inline int ParsingEngine<B>::Parse_Name() {
2356        int name_pos = AbsPos();
2357        ScanTo(NameFollow);
2358        int lgth = AbsPos()-name_pos;
2359        int nameID = model_info->symbol_table->ASCII_Lookup_or_Insert_Name(&((char *) x8data)[buffer_rel_pos-lgth], lgth);
2360        if (nameID != 0) return nameID;
2361        else {
2362                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2363                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2364                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2365                return model_info->symbol_table->LookupOrInsertReserved();
2366        }
2367}
2368
2369template <>
2370inline int ParsingEngine< X8_Buffer<EBCDIC> >::Parse_Name() {
2371        int name_pos = AbsPos();
2372        ScanTo(NameFollow);
2373        int lgth = AbsPos()-name_pos;
2374//      int nameID = local_EBCDIC_table->Lookup_or_Insert(GetCodeUnitPtr(name_pos), lgth);
2375//      if (nameID != 0) return nameID;
2376//      else {
2377                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2378                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2379                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2380                return model_info->symbol_table->LookupOrInsertReserved();
2381//      }
2382}
2383
2384template <>
2385inline int ParsingEngine<UTF8_Buffer>::Parse_Name() {
2386        int name_pos = AbsPos();
2387        ScanTo(NameFollow);
2388        int lgth = AbsPos()-name_pos;
2389        return model_info->symbol_table->UTF8_Lookup_or_Insert_Name(&((char *)x8data)[buffer_rel_pos-lgth], lgth);
2390}
2391
2392template <class B>
2393inline int ParsingEngine<B>::Parse_Nmtoken() {
2394        int name_pos = AbsPos();
2395        ScanTo(NameFollow);
2396        int lgth = AbsPos()-name_pos;
2397        int nameID = model_info->symbol_table->ASCII_Lookup_or_Insert_Nmtoken(&((char *) x8data)[buffer_rel_pos-lgth], lgth);
2398        if (nameID != 0) return nameID;
2399        else {
2400                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2401                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2402                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2403                return model_info->symbol_table->LookupOrInsertReserved_nmtoken();
2404        }
2405}
2406
2407template <>
2408inline int ParsingEngine< X8_Buffer<EBCDIC> >::Parse_Nmtoken() {
2409        int name_pos = AbsPos();
2410        ScanTo(NameFollow);
2411        int lgth = AbsPos()-name_pos;
2412//      int nameID = local_EBCDIC_table->Lookup_or_Insert(GetCodeUnitPtr(name_pos), lgth);
2413//      if (nameID != 0) return nameID;
2414//      else {
2415                int u8_lgth = byteplex->UTF8_Length(name_pos, lgth);
2416                char * u8_ptr = model_info->symbol_table->ReserveSymbolSpace(u8_lgth);
2417                byteplex->to_UTF8(name_pos, lgth, u8_ptr);
2418                return model_info->symbol_table->LookupOrInsertReserved_nmtoken();
2419//      }
2420}
2421template <>
2422inline int ParsingEngine<UTF8_Buffer>::Parse_Nmtoken() {
2423        int name_pos = AbsPos();
2424        ScanTo(NameFollow);
2425        int lgth = AbsPos()-name_pos;
2426        return model_info->symbol_table->UTF8_Lookup_or_Insert_Nmtoken(&((char *)x8data)[buffer_rel_pos-lgth], lgth);
2427}
2428
2429template <class B>
2430inline void ParsingEngine<B>::Parse_DocumentContent() {
2431#if (VALIDATION_MODE == ON)
2432        int cur_state = 0;
2433        Parse_ValidContent(model_info->rootModel, cur_state);
2434        if (model_info->rootModel->transition_map[cur_state][0]==0) {
2435                Validity_Error(vErr_elementvalid);
2436        }
2437#endif
2438#if (VALIDATION_MODE == OFF)   
2439        Parse_WF_Element();
2440        ScanTo(NonWS);
2441        while(at_Comment_Start<B::Base>(cur()) || at_PI_Start<B::Base>(cur()) ){
2442                if (at_Comment_Start<B::Base>(cur()))
2443                        Parse_Comment();
2444                else 
2445                        Parse_PI();
2446                ScanTo(NonWS);
2447        }
2448        if (!at_EOF()) {
2449                Syntax_Error(NT_document);
2450        }       
2451#endif
2452}
2453
Note: See TracBrowser for help on using the repository browser.