source: trunk/src/engine.c @ 172

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

UTF-16 charset validation

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