source: trunk/src/engine.c @ 169

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

UTF-16/32 validation.

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