source: trunk/src/engine.c @ 126

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

Use NameID vs. name string as key for element, attribute, ... maps.

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