source: trunk/src/engine.c @ 128

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

Set lexer_base_pos for error reporting.

File size: 56.6 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_base_pos, 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_base_pos, 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                        att_name_start = AbsPos();
531                        int att_nameID = Parse_Name();
532                        att_name_end = AbsPos();
533               
534                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
535                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
536                        else {
537                                if (LastAttOccurrence[attID] > text_or_markup_start) {
538                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
539                                        break;
540                                }                       
541                        }
542                        LastAttOccurrence[attID] = att_name_start;
543                        /* The following optimized tests handle the frequently occurring
544                        case that there are no blanks on either side of the equals sign.
545                        In many cases, the very first test handles 100% of actual
546                        attribute-value pairs encountered. */
547                        if (at_EqualsQuote<C>(cur())) Advance(1); 
548                        else {
549                                ScanTo(NonWS);
550                                if (!AtChar<C,'='>(cur())) {
551                                        Syntax_Error(NT_STag); 
552                                        break;
553                                }
554                                Advance(1);
555                                ScanTo(NonWS);
556                                if (!AtQuote<C>(cur())) {
557                                        Syntax_Error(NT_STag); 
558                                        break;
559                                }
560                        }
561                        att_val_start = AbsPos()+1;
562                        Parse_AttValue();
563                        att_val_end = AbsPos()-1;
564                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
565                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
566                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
567                        }
568                        else {
569                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
570                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
571                        }
572                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
573                        if (AtChar<C,'>'>(cur())) {
574                                Advance(1);
575                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
576                                break;
577                        }
578                        else if (at_EmptyElementDelim<C>(cur())) {
579                                Advance(2);
580                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
581                                break;
582                        }
583                        ScanTo(NonWS);
584                        if (AtChar<C,'>'>(cur())) {
585                                Advance(1);
586                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
587                                break;
588                        }
589                        else if (at_EmptyElementDelim<C>(cur())) {
590                                Advance(2);
591                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
592                                break;
593                        }
594                        else if (AbsPos() == att_val_end + 1) { 
595                                /* No WS following att value */
596                                Syntax_Error(NT_STag);
597                                break;
598                        }
599                } while (1);
600        }
601}
602
603template <CodeUnit_Base C>
604inline void ParsingEngine<C>::text_if_nonnull_action(){
605        if (AbsPos() > text_or_markup_start) {
606                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
607                text_or_markup_start = AbsPos();
608        }
609}
610
611
612
613template <CodeUnit_Base C>
614inline void ParsingEngine<C>::Parse_WF_EndTag(int nameID) {
615        Advance(2); /* Skip "</". */
616       
617        int name_start = AbsPos();
618       
619        int endNameID = Parse_Name();  /* Name delimiter: WS, "/" or ">" */
620        if (nameID != endNameID)
621                        WF_Error(wfErr_GIMatch);
622                       
623        if (AtChar<C,'>'>(cur())) {
624                Advance(1);
625                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
626        }
627    else {
628                ScanTo(NonWS);
629                if (AtChar<C,'>'>(cur())) {
630                        Advance(1);
631                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
632                }
633                else Syntax_Error(NT_ETag);
634    }
635}
636/* Parse a valid start or empty element tag. */
637template <CodeUnit_Base C>
638inline int ParsingEngine<C>::Parse_WF_StartTag (bool& is_emptyStartTag){
639        int att_name_start;
640        int att_val_start;
641        int att_name_end, att_val_end;
642        unsigned char quoteCh;
643        Advance(1);
644       
645        int nameID = Parse_Name(); 
646       
647        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
648        /* The following test optimizes the most common case of a
649        start tag with no attributes.  */
650        if (AtChar<C,'>'>(cur())) {
651                Advance(1);
652                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
653        }
654        else {
655                ScanTo(NonWS);
656                if (AtChar<C,'>'>(cur())) {
657                        Advance(1);
658                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
659                }
660                else if (at_EmptyElementDelim<C>(cur())) {
661                        Advance(2);
662                        is_emptyStartTag = true;
663                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
664                }
665                else do {
666                        /* Must be an attribute-value pair or error. */
667                        att_name_start = AbsPos();
668                        int att_nameID = Parse_Name();
669                        att_name_end = AbsPos();
670               
671                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
672                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
673                        else {
674                                if (LastAttOccurrence[attID] > text_or_markup_start) {
675                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
676                                        break;
677                                }                       
678                        }
679                        LastAttOccurrence[attID] = att_name_start;
680                        /* The following optimized tests handle the frequently occurring
681                        case that there are no blanks on either side of the equals sign.
682                        In many cases, the very first test handles 100% of actual
683                        attribute-value pairs encountered. */
684                        if (at_EqualsQuote<C>(cur())) Advance(1); 
685                        else {
686                                ScanTo(NonWS);
687                                if (!AtChar<C,'='>(cur())) {
688                                        Syntax_Error(NT_STag); 
689                                        break;
690                                }
691                                ScanTo(NonWS);
692                                if (!AtQuote<C>(cur())) {
693                                        Syntax_Error(NT_STag); 
694                                        break;
695                                }
696                        }
697                        att_val_start = AbsPos()+1;
698                        Parse_AttValue();
699                        att_val_end = AbsPos()-1;
700                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
701                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
702                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
703                        }
704                        else {
705                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
706                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
707                        }
708                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
709                        if (AtChar<C,'>'>(cur())) {
710                                Advance(1);
711                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
712                                break;
713                        }
714                        else if (at_EmptyElementDelim<C>(cur())) {
715                                Advance(2);
716                                is_emptyStartTag = true;       
717                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
718                                break;
719                        }
720                        ScanTo(NonWS);
721                        if (AtChar<C,'>'>(cur())) {
722                                Advance(1);
723                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
724                                break;
725                        }
726                        else if (at_EmptyElementDelim<C>(cur())) {
727                                Advance(2);
728                                is_emptyStartTag = true;
729                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
730                                break;
731                        }
732                        else if (AbsPos() == att_val_end + 1) { 
733                                /* No WS following att value */
734                                Syntax_Error(NT_STag);
735                                break;
736                        }
737                } while (1);
738        }
739        return nameID;
740}
741
742
743
744template <CodeUnit_Base C>
745inline void ParsingEngine<C>::Parse_WF_Element() {
746        bool is_emptyStartTag = false;
747        int nameID = Parse_WF_StartTag(is_emptyStartTag);
748#ifdef DEBUG
749        printf("Parse_Element: elemID = %d, is_emptyStartTag=%i\n",elemID, is_emptyStartTag);
750#endif
751        if (!is_emptyStartTag) {
752                Parse_WF_Content();
753                Parse_WF_EndTag(nameID);
754        }
755}
756
757
758template <CodeUnit_Base C>
759inline void ParsingEngine<C>::Parse_WF_Content() {
760        do {
761                text_or_markup_start = AbsPos();
762                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
763                if (at_ElementTag_Start<C>(cur())) {
764                        text_if_nonnull_action();
765                        Parse_WF_Element();
766                }
767                else if (at_EndTag_Start<C>(cur())) {
768                        text_if_nonnull_action();
769                        return;
770                }
771                else if (at_Comment_Start<C>(cur())) {
772                        text_if_nonnull_action();
773                        Parse_Comment();
774                }
775                else if (at_CharRef_Start<C>(cur())) {
776                        text_if_nonnull_action();
777                        Parse_CharRef();
778                }
779                else if (AtChar<C,'&'>(cur())) {
780                        text_if_nonnull_action();
781                        Parse_EntityRef();
782                }
783                else if (at_CDATA_Start<C>(cur())) {
784                        text_if_nonnull_action();
785                        Parse_CDATA();
786                }
787                else if (at_PI_Start<C>(cur())) {
788                        text_if_nonnull_action();
789                        Parse_PI();
790                }
791                else if (at_CDATA_End<C>(cur())) {
792                        text_if_nonnull_action();
793                        Advance(3);
794                        Syntax_Error(NT_CharData);
795                }
796                else if (at_EOF()) {
797                        text_if_nonnull_action();
798                        return;
799                }
800                else if (AtChar<C,'<'>(cur())) {
801                        Syntax_Error(NT_markupdecl);
802                }
803                else {
804                        Advance(1);
805                        continue;
806                }
807        } while (1);
808}
809
810
811
812template <CodeUnit_Base C>
813inline void ParsingEngine<C>::ParseContent() {
814        DocumentStart_action(); 
815        vector<int> elemStack;
816        int elemID;
817        bool is_emptyStartTag = false;
818        do {
819                text_or_markup_start = AbsPos();
820                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
821/*              if (AtChar<C,'<'>(cur())) {
822                        text_if_nonnull_action();
823                        Parse_Markup<C>();
824                }*/
825                if (at_ElementTag_Start<C>(cur())) {
826                        text_if_nonnull_action();
827                        Parse_StartTag();
828//                      elemID = Parse_ValidStartTag(is_emptyStartTag);
829//                      if(!is_emptyStartTag)
830//                              elemStack.push_back(elemID);
831//                      else
832//                              is_emptyStartTag = false;
833                }
834                else if (at_EndTag_Start<C>(cur())) {
835                        text_if_nonnull_action();
836                        Parse_EndTag();
837//                      elemID = Parse_ValidEndTag();
838//                      if (elemStack.size()<= 0 || elemID != elemStack[elemStack.size()-1])
839//                              Syntax_Error(NT_ETag);
840//                      else
841//                              elemStack.pop_back();
842                }
843                else if (at_Comment_Start<C>(cur())) {
844                        text_if_nonnull_action();
845                        Parse_Comment();
846                }
847                else if (at_CharRef_Start<C>(cur())) {
848                        text_if_nonnull_action();
849                        Parse_CharRef();
850                }
851                else if (AtChar<C,'&'>(cur())) {
852                        text_if_nonnull_action();
853                        Parse_EntityRef();
854                }
855                else if (at_CDATA_Start<C>(cur())) {
856                        text_if_nonnull_action();
857                        Parse_CDATA();
858                }
859                else if (at_PI_Start<C>(cur())) {
860                        text_if_nonnull_action();
861                        Parse_PI();
862                }
863                else if (at_CDATA_End<C>(cur())) {
864                        text_if_nonnull_action();
865                        Advance(3);
866                        Syntax_Error(NT_CharData);
867                }
868                else if (at_EOF()) {
869                        text_if_nonnull_action();
870                        break;
871                }
872                else if (AtChar<C,'<'>(cur())) {
873                        Syntax_Error(NT_markupdecl);
874                }
875                else {
876                        Advance(1);
877                        continue;
878                }
879        } while (1);
880        DocumentEnd_action();   
881}
882
883
884template <CodeUnit_Base C>
885inline void ParsingEngine<C>::Parse_DocType (){
886
887        int old_abspos, start_pos;
888        ScanTo(NonWS);
889        start_pos = AbsPos();
890       
891        if (at_DOCTYPE_start<C>(cur()))
892        Advance(9);
893        else{
894//              printf("No Document definition!\n");
895                return;
896        }
897        requireWS();
898        int nameID = Parse_Name();
899
900        old_abspos = AbsPos(); 
901    ScanTo(NonWS);
902    if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
903        model_info->has_external_DTD = true;
904        if(old_abspos == AbsPos())
905                Syntax_Error(NT_doctypedecl);
906        Parse_ExternalID(model_info->external_DTD_systemLiteral, model_info->external_DTD_pubidLiteral);
907        Parser_Interface * entity_parser;
908        entity_parser = ParserFactory(model_info->external_DTD_systemLiteral, model_info);
909                entity_parser->Parse_ExtSubsetDecl();
910                entity_parser->~Parser_Interface();
911    }
912    else model_info->has_external_DTD = false;
913    ScanTo(NonWS);     
914
915        if (AtChar<C,'['>(cur())){
916                Advance(1);
917                Parse_IntSubset();
918                if (AtChar<C,']'>(cur()))
919                        Advance(1);
920                else
921                Syntax_Error(NT_doctypedecl);
922                ScanTo(NonWS);
923        }
924       
925        if (AtChar<C,'>'>(cur())){
926                Advance(1);   
927                int rootID = model_info->GlobalElementTable[nameID];
928
929                CRE_Seq * rslt = new CRE_Seq();
930                rslt->subCMs.push_back(new CRE_Name(rootID));
931                CM_RegExp * cre = new CM_RegExp();
932                cre->content_re = rslt;         
933               
934                int id_count = cre->content_re->Set_IDs(0);
935                cre->content_re->Set_First_Map();               
936                symbol_set_t * transition_map = new symbol_set_t[id_count+1];
937                cre->content_re->follow_map[0] = id_count+1;
938               
939                cre->content_re->Set_Follow_Map(transition_map);
940                transition_map[0] = cre->content_re->first_map;
941                if (cre->content_re->matches_empty)
942                        transition_map[0][0]=id_count+1;
943                       
944                cre -> transition_map = transition_map;
945               
946                model_info->rootModel = cre;
947
948        }
949        else
950                Syntax_Error(NT_doctypedecl);   
951}
952
953template <CodeUnit_Base C>
954inline void ParsingEngine<C>::Parse_ExternalID (char *& systemLiteral, char *& pubidLiteral){
955        int quot_start, lgth;
956        if(at_SYSTEM<C>(cur())){
957                Advance(6);
958                pubidLiteral = NULL;
959                requireWS();
960                if (!AtQuote<C>(cur())) Syntax_Error(NT_ExternalID);
961                quot_start = AbsPos()+1;
962                Parse_SystemLiteral (); /*  SystemLiteral */
963                lgth = AbsPos() - quot_start - 1;                       
964                systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
965        }
966        else if (at_PUBLIC<C>(cur())){
967                Advance(6);
968                requireWS();
969                if (!AtQuote<C>(cur())) Syntax_Error(NT_ExternalID);
970                quot_start = AbsPos()+1;
971                Parse_PubidLiteral ();/*  PubidLiteral */
972                lgth = AbsPos() - quot_start - 1;                       
973                pubidLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
974                systemLiteral = NULL;
975                if (AtChar<C, '>'>(cur())) return;
976                requireWS();
977                if (AtQuote<C>(cur())) {
978                        quot_start = AbsPos()+1;       
979                        Parse_SystemLiteral ();/*  SystemLiteral */
980                        lgth = AbsPos() - quot_start - 1;                       
981                        systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
982                }
983        }
984        else
985                Syntax_Error(NT_ExternalID); 
986}
987
988template <CodeUnit_Base C>
989inline void ParsingEngine<C>::Parse_SystemLiteral (){
990        unsigned char quoteCh;
991        if(AtQuote<C>(cur())){
992                quoteCh = cur()[0];
993                Advance(1);
994        }       
995        ScanTo(Quote);                 
996        while (cur()[0] != quoteCh){
997                if(at_EOF())
998                        Syntax_Error(NT_SystemLiteral);
999                Advance(1);
1000                ScanTo(Quote);
1001        }
1002        Advance(1);
1003}
1004
1005template <CodeUnit_Base C>
1006inline void ParsingEngine<C>::Parse_PubidLiteral (){
1007        unsigned char quoteCh;
1008        if(AtQuote<C>(cur())){
1009                quoteCh = cur()[0];
1010                Advance(1);
1011        }       
1012        while (at_PubidChar<C>(cur())) Advance(1);
1013        if (cur()[0] != quoteCh){
1014                Syntax_Error(NT_PubidLiteral);
1015        }
1016        Advance(1);
1017}
1018
1019template <CodeUnit_Base C>
1020inline void ParsingEngine<C>::Parse_IntSubset (){
1021       
1022        while(1){
1023                ScanTo(NonWS); 
1024                text_or_markup_start = AbsPos();
1025                if (AtChar<C,'%'>(cur()))
1026                        Parse_PEReference();   
1027                else if (AtChar<C,'<'>(cur())){
1028                        Advance(1);
1029
1030                        if (AtChar<C,'?'>(cur())){
1031                                if (at_xml<C>(cur()))
1032                                        Syntax_Error(NT_intSubset);
1033                                else
1034                                        Parse_PI();
1035                        }
1036                        else if(AtChar<C,'!'>(cur())){
1037                                Advance(1);
1038                                if(at_DoubleHyphen<C>(cur()))
1039                                        Parse_Comment();
1040                                else if(at_ELEMENT<C>(cur()))
1041                                        Parse_Elementdecl();
1042                                else if(at_ATTLIST<C>(cur()))
1043                                        Parse_AttlistDecl();
1044                                else if(at_ENTITY<C>(cur()))
1045                                        Parse_Entitydecl();
1046                                else if(at_NOTATION<C>(cur()))
1047                                        Parse_Notationdecl();
1048                                else{
1049                                        Syntax_Error(NT_markupdecl);           
1050                                }                                                               
1051                        }
1052                        else
1053                                Syntax_Error(NT_markupdecl); 
1054                }
1055                else if (AtChar<C,']'>(cur())){
1056                        break;
1057                }
1058                else
1059                        Syntax_Error(NT_intSubset); 
1060        }
1061}
1062
1063
1064template <CodeUnit_Base C>
1065inline void ParsingEngine<C>::Parse_PEReference (){
1066
1067        Advance(1); /* Skip "%". */
1068        int nameID = Parse_Name(); 
1069        if (AtChar<C,';'>(cur())) {
1070                Advance(1);
1071                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1072                PEntity_info * this_info;
1073                Parser_Interface * entity_parser;
1074                int entityID = model_info->GlobalGEntityTable[nameID]; 
1075                if (entityID == 0)
1076                        WF_Error(wfErr_wf_entdeclared);
1077                else{
1078                        this_info = model_info->PEntityData[entityID-1];
1079                        if (this_info->is_external){
1080                               
1081                        if (entity_Info->standalone != Standalone_no)
1082                                WF_Error(wfErr_NoExternalRefs);
1083                        else {
1084                                        entity_parser = ParserFactory(this_info->systemLiteral, model_info);
1085                                        entity_parser->Parse_WF_Content();
1086                                        if(!entity_parser->at_EOF())
1087                                                Syntax_Error(NT_content);
1088                                        entity_parser->~Parser_Interface();
1089                        }
1090                        }
1091                        else {
1092                        }
1093                }
1094        }
1095        else
1096                Syntax_Error(NT_PEReference);
1097}
1098
1099
1100template <CodeUnit_Base C>
1101inline void ParsingEngine<C>::Parse_Elementdecl (){
1102
1103        Advance(7); /* Skip "<!ELEMENT". */
1104
1105    requireWS();
1106        int nameID = Parse_Name();
1107        int elemID = model_info->getOrInsertGlobalElement(nameID);
1108
1109        requireWS();
1110        ContentModel * cm;
1111        /* Start parsing "contentspec"*/
1112        if (at_EMPTY<C>(cur())) {
1113        Advance(5);
1114        cm = new CM_Empty();
1115        model_info->ContentModelData[elemID] = cm;
1116        }
1117    else if (at_ANY<C>(cur())) {
1118        Advance(3);
1119        cm = new CM_Any();
1120        model_info->ContentModelData[elemID] = cm;
1121    }
1122    else {
1123        if (AtChar<C,'('>(cur()))
1124                        Advance(1);
1125                ScanTo(NonWS);
1126                if (at_PCDATA<C>(cur())){
1127                        cm = Parse_RemainingMixed();
1128                        model_info->ContentModelData[elemID] = cm;
1129                }
1130                else{
1131
1132                        CM_RegExp * cre = new CM_RegExp;
1133                        cre->content_re = Parse_RemainingChildren();
1134
1135                        int id_count = cre->content_re->Set_IDs(0);
1136                        cre->content_re->Set_First_Map();       
1137                        symbol_set_t * transition_map = new symbol_set_t[id_count+1];
1138                        cre->content_re->follow_map[0] = id_count+1;
1139                       
1140                        cre->content_re->Set_Follow_Map(transition_map);
1141                        transition_map[0] = cre->content_re->first_map;
1142                       
1143                        if (cre->content_re->matches_empty)
1144                                transition_map[0][0]=id_count+1;
1145                               
1146                        cre -> transition_map = transition_map;
1147                       
1148                        model_info->ContentModelData[elemID] = cre;
1149                        cm = cre;
1150                }                       
1151    }
1152    ScanTo(NonWS);   
1153
1154        if (AtChar<C,'>'>(cur())) {
1155                Advance(1);
1156        }
1157        else
1158                Syntax_Error(NT_elementdecl);
1159}
1160template <CodeUnit_Base C>
1161inline ContentModel * ParsingEngine<C>::Parse_RemainingMixed (){
1162        CM_Mixed * r = new CM_Mixed();
1163        Advance(7);  /* Skip "#PCDATA". */
1164   
1165    if (AtChar<C,')'>(cur())){
1166        if (AtChar<C,'*'>(cur())) {
1167                Advance(2);
1168                }
1169                else {
1170                        Advance(1);
1171                }
1172    }
1173    else{
1174        ScanTo(NonWS);
1175        int k = 0;
1176        while (AtChar<C,'|'>(cur())){
1177                        Advance(1);
1178                        ScanTo(NonWS);
1179                        int nameID = Parse_Name();
1180                        int elemID = model_info->getOrInsertGlobalElement(nameID);
1181                        r->elements[elemID] = ++k;
1182                        ScanTo(NonWS);
1183                }
1184                if (at_Para_star<C>(cur())) Advance(2);
1185                else {
1186                        Syntax_Error(NT_Mixed);
1187                        exit(-1);
1188        }
1189    }
1190    return r;
1191}
1192
1193
1194template <CodeUnit_Base C>
1195inline Content_RE * ParsingEngine<C>::Parse_RemainingChildren (){
1196        Content_RE * c1 = Parse_Cp();
1197        Content_RE * r = c1;
1198        ScanTo(NonWS);
1199        if(AtChar<C,'|'>(cur())){
1200                CRE_Choice * rslt = new CRE_Choice;
1201                rslt->subCMs.push_back(c1);
1202                Advance(1);
1203                ScanTo(NonWS);
1204                rslt->subCMs.push_back(Parse_Cp());
1205                ScanTo(NonWS);
1206                while(!AtChar<C,')'>(cur())){
1207                        if(AtChar<C,'|'>(cur()))
1208                                Advance(1);
1209                        else
1210                                Syntax_Error(NT_children);
1211                        ScanTo(NonWS);
1212                        rslt->subCMs.push_back(Parse_Cp());
1213                        ScanTo(NonWS);
1214                }
1215                Advance(1);
1216                rslt->Compile();
1217                r = rslt;
1218        }
1219        else if(AtChar<C,','>(cur())){
1220                CRE_Seq * rslt = new CRE_Seq;
1221                rslt->subCMs.push_back(c1);
1222                Advance(1);
1223                ScanTo(NonWS);
1224                rslt->subCMs.push_back(Parse_Cp());
1225                ScanTo(NonWS);
1226                while(!AtChar<C,')'>(cur())){
1227                        if(AtChar<C,','>(cur()))
1228                                Advance(1);
1229                        else
1230                                Syntax_Error(NT_children);
1231                        ScanTo(NonWS);
1232                        rslt->subCMs.push_back(Parse_Cp());
1233                        ScanTo(NonWS);
1234                }
1235                Advance(1);
1236                rslt->Compile();
1237                r = rslt;
1238        }       
1239        else if(AtChar<C,')'>(cur())){
1240                Advance(1);
1241        }
1242        else
1243                Syntax_Error(NT_children);
1244               
1245        if (AtChar<C,'?'>(cur())) {
1246                Advance(1);
1247                r = new CRE_Opt(r);
1248        }
1249        else if (AtChar<C,'*'>(cur())) {
1250                Advance(1);
1251                r = new CRE_Star(r);
1252        }
1253        else if (AtChar<C,'+'>(cur())) {
1254                Advance(1);
1255                r = new CRE_Plus(r);
1256        }
1257
1258        return r;
1259}
1260
1261template <CodeUnit_Base C>
1262inline Content_RE * ParsingEngine<C>::Parse_Cp (){
1263        if (AtChar<C,'('>(cur())){
1264                Advance(1);
1265                ScanTo(NonWS);
1266                Parse_RemainingChildren();
1267        }
1268        else{
1269                int nameID = Parse_Name();
1270                int elemID = model_info->getOrInsertGlobalElement(nameID);
1271                CRE_Name * r = new CRE_Name(elemID);
1272
1273                if (AtChar<C,'?'>(cur())) {
1274                        Advance(1);
1275                        return new CRE_Opt(r);
1276                }
1277                else if (AtChar<C,'*'>(cur())) {
1278                        Advance(1);
1279                        return new CRE_Star(r);
1280                }
1281                else if (AtChar<C,'+'>(cur())) {
1282                        Advance(1);
1283                        return new CRE_Plus(r);
1284                }
1285                else return r;
1286        }
1287}
1288
1289template <CodeUnit_Base C>
1290inline void ParsingEngine<C>::Parse_AttlistDecl (){
1291       
1292        int old_abspos;
1293       
1294        int name_start;
1295        int lgth;
1296       
1297        int elemID;
1298        int attID;
1299       
1300        Advance(7); /* Skip "ATTLIST. */
1301        requireWS();
1302       
1303        int nameID = Parse_Name();
1304        elemID = model_info->getOrInsertGlobalElement(nameID);
1305       
1306        old_abspos = AbsPos();
1307        ScanTo(NonWS);
1308        while(!AtChar<C,'>'>(cur())) {
1309                if(old_abspos == AbsPos())
1310                Syntax_Error(NT_AttlistDecl);
1311               
1312                int att_nameID = Parse_Name();
1313               
1314                attID = model_info->getOrInsertGlobalAttName(att_nameID);
1315                if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1316        ATT_info * this_info = new ATT_info;
1317        this_info->globalATT_id = attID;
1318        requireWS();
1319        if (at_CDATA<C>(cur())){
1320                Advance(5);
1321                this_info->attType = CDATA_att;
1322        }
1323        else if(at_ID<C>(cur())){
1324                Advance(2);
1325                this_info->attType = ID_att;
1326        }
1327        /* Make sure to check IDREFS before IDREF*/
1328        else if(at_IDREFS<C>(cur())){
1329                Advance(6);
1330                this_info->attType = IDREFS_att;
1331        }
1332        else if(at_IDREF<C>(cur())){
1333                Advance(5);
1334                this_info->attType = IDREF_att;
1335        }
1336        else if(at_ENTITY<C>(cur())){
1337                Advance(6);
1338                this_info->attType = ENTITY_att;
1339        }
1340        else if(at_ENTITIES<C>(cur())){
1341                Advance(8);
1342                this_info->attType = ENTITIES_att;
1343        }
1344        /* Make sure to check NMTOKENS before NMTOKEN*/
1345        else if(at_NMTOKENS<C>(cur())){
1346                Advance(8);
1347                this_info->attType = NMTOKENS_att;
1348        }
1349        else if(at_NMTOKEN<C>(cur())){
1350                Advance(7);
1351                this_info->attType = NMTOKEN_att;
1352        }
1353        else if(at_NOTATION<C>(cur())){ /* NotationType = 'NOTATION' S Enumeration
1354                                                                         when Nmtoken = Name */
1355                Advance(8);
1356                        requireWS();
1357                Parse_Notation(this_info);
1358                this_info->attType = NOTATION_att;
1359        }
1360        else if(AtChar<C,'('>(cur())){
1361                Parse_Enumeration(this_info);
1362                this_info->attType = enumeration_att;
1363        }
1364        else
1365                Syntax_Error(NT_AttlistDecl);
1366        requireWS();
1367        Parse_DefaultDecl(this_info);
1368
1369                ScanTo(NonWS);
1370                model_info->ElementAttributeData[elemID].push_back(this_info);
1371        }
1372
1373        Advance(1);
1374}
1375
1376template <CodeUnit_Base C>
1377inline void ParsingEngine<C>::Parse_Notation (ATT_info * this_info){
1378
1379        if(AtChar<C,'('>(cur()))
1380                Advance(1);
1381        else
1382                Syntax_Error(NT_NotationType);
1383        ScanTo(NonWS);
1384       
1385    int nameID = Parse_Name();
1386
1387        /*Notation name is not in the global table!*/
1388        if(model_info->GlobalNotationTable[nameID]==0)
1389                Validity_Error(vErr_notatn);
1390       
1391        ScanTo(NonWS);
1392        while(AtChar<C,'|'>(cur())){
1393                Advance(1);
1394                ScanTo(NonWS); 
1395                int not_nameID = Parse_Name();
1396                       
1397                if(model_info->GlobalNotationTable[not_nameID]==0)
1398                        Validity_Error(vErr_notatn);
1399                       
1400                ScanTo(NonWS);
1401        }
1402        if (AtChar<C,')'>(cur())) 
1403                Advance(1);
1404        else
1405                Syntax_Error(NT_NotationType);
1406}
1407
1408template <CodeUnit_Base C>
1409inline void ParsingEngine<C>::Parse_Enumeration (ATT_info * this_info){
1410
1411        int enumCount=0;
1412        if(AtChar<C,'('>(cur()))
1413                Advance(1);
1414        else
1415                Syntax_Error(NT_Enumeration);
1416        ScanTo(NonWS);
1417       
1418        int     name_start = AbsPos();
1419        int nameID = Parse_Name();
1420        int     lgth = AbsPos()-name_start;
1421       
1422        char *s = new char[lgth+1];
1423        memcpy(s, GetCodeUnitPtr(name_start), lgth);
1424        s[lgth] = '\0';
1425       
1426        this_info->enumValues[s]=++(enumCount);
1427       
1428        ScanTo(NonWS);
1429        while(AtChar<C,'|'>(cur())){
1430                Advance(1);
1431                ScanTo(NonWS);         
1432                name_start = AbsPos();
1433                int nameID = Parse_Name();
1434                lgth = AbsPos()-name_start;
1435       
1436                char *s = new char[lgth+1];
1437                memcpy(s, GetCodeUnitPtr(name_start), lgth);
1438                s[lgth] = '\0';
1439       
1440                int enumID = this_info->enumValues[s];
1441                if(enumID==0){ 
1442                        this_info->enumValues[s]=++(enumCount);
1443                        enumID = enumCount;
1444                }
1445                else if(!StrictWellFormedness){
1446                        Validity_Error(vErr_NoDuplicateTokens);
1447                }
1448                ScanTo(NonWS);
1449        }
1450        if (AtChar<C,')'>(cur())) 
1451                Advance(1);
1452        else
1453                Syntax_Error(NT_Enumeration);
1454}
1455
1456template <CodeUnit_Base C>
1457inline void ParsingEngine<C>::Parse_DefaultDecl (ATT_info * this_info){
1458        if(at_REQUIRED<C>(cur())){
1459                Advance(9);
1460                this_info->defaultKind = REQUIRED_att;
1461        }
1462        else if(at_IMPLIED<C>(cur())){
1463                Advance(8);
1464                this_info->defaultKind = IMPLIED_att;
1465        }
1466        else {
1467                if(at_FIXED<C>(cur())){
1468                        Advance(6);
1469                        requireWS();
1470                        this_info->defaultKind = FIXED_att;
1471                }
1472                else this_info->defaultKind = DEFAULT_att;
1473                if(AtQuote<C>(cur())){
1474                        int quot_start = AbsPos()+1;
1475                        Parse_AttValue();
1476                        /* need to normalize */
1477                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
1478                       
1479                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
1480                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
1481                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
1482                        }
1483                else
1484                        Syntax_Error(NT_DefaultDecl);
1485        }
1486}
1487
1488template <CodeUnit_Base C>
1489inline void ParsingEngine<C>::Parse_Entitydecl (){
1490       
1491        int name_start;
1492        int quot_start;
1493        int lgth;
1494        int old_abspos;
1495        char * s;
1496       
1497        Advance(6); /* Skip "ENTITY. */
1498        requireWS();
1499       
1500        if (AtChar<C,'%'>(cur())){
1501                Advance(1);
1502                requireWS();
1503               
1504                int nameID = Parse_Name();
1505       
1506                PEntity_info * this_info = new PEntity_info;
1507                int entityID = model_info->GlobalPEntityTable[nameID];
1508                if(entityID==0){       
1509                        model_info->GlobalPEntityTable[nameID]=++(model_info->globalPEntityCount);
1510                        entityID = model_info->globalPEntityCount;
1511                        this_info->globalPEntity_id = entityID;
1512                }
1513                else
1514                        printf("Warning: Entity definition already exist!\n");
1515       
1516                requireWS();
1517                if(AtQuote<C>(cur())){
1518                Parse_PEntityValue(this_info);
1519                this_info->is_external = false;
1520        }
1521        else {
1522                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1523                this_info->is_external = true;
1524                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1525        }
1526        model_info->PEntityData.push_back(this_info);
1527        }
1528        else{
1529                int nameID = Parse_Name();
1530       
1531                GEntity_info * this_info = new GEntity_info();
1532                int entityID = model_info->GlobalGEntityTable[nameID];
1533                if(entityID==0){       
1534                        model_info->GlobalGEntityTable[nameID]=++(model_info->globalGEntityCount);
1535                        entityID = model_info->globalGEntityCount;
1536                        this_info->globalGEntity_id = entityID;
1537                }
1538                else
1539                        printf("Warning: Entity definition already exist!\n");
1540                       
1541                requireWS();
1542               
1543                if(AtQuote<C>(cur())){
1544                Parse_GEntityValue(this_info);                 
1545                this_info->is_external = false;
1546        }
1547        else {
1548                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1549                this_info->is_external = true;
1550                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1551                        old_abspos = AbsPos();
1552                        ScanTo(NonWS);
1553                if(at_NDATA<C>(cur())){
1554                        if(old_abspos == AbsPos())
1555                                Syntax_Error(NT_EntityDecl);
1556                        else
1557                                Advance(5);
1558                        requireWS();
1559                        name_start = AbsPos();
1560                        int nameID = Parse_Name();
1561                        lgth = AbsPos() - name_start;
1562                                this_info->NDataName = copy_string(GetCodeUnitPtr(name_start),lgth);
1563                }
1564                }
1565        model_info->GEntityData.push_back(this_info);
1566        }
1567        ScanTo(NonWS);
1568        if (AtChar<C,'>'>(cur())){
1569                Advance(1);
1570        }
1571        else
1572                Syntax_Error(NT_EntityDecl);
1573}
1574
1575template <CodeUnit_Base C>
1576inline void ParsingEngine<C>::Parse_Notationdecl (){
1577
1578        int old_abspos;
1579        Advance(8); /* Skip "NOTATION. */
1580        requireWS();
1581       
1582        int nameID = Parse_Name();
1583
1584        int notationID = model_info->GlobalNotationTable[nameID];
1585        if(notationID==0){     
1586                model_info->GlobalNotationTable[nameID]=++(model_info->globalNotationCount);
1587                notationID = model_info->globalNotationCount;
1588        }
1589        else /*Duplicate notation name!*/
1590                Validity_Error(vErr_NoDuplicateTokens);
1591        Notation_info * this_info = new Notation_info;
1592                       
1593    Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1594        ScanTo(NonWS);
1595        if (AtChar<C,'>'>(cur())) {
1596                Advance(1);
1597        }
1598        else
1599                Syntax_Error(NT_NotationDecl);
1600}
1601
1602template <CodeUnit_Base C>
1603inline void ParsingEngine<C>::requireWS(){
1604       
1605    int old_abspos = AbsPos(); 
1606    ScanTo(NonWS);
1607    if(old_abspos == AbsPos())
1608        Syntax_Error(NT_S);
1609}
1610
1611template <CodeUnit_Base C>
1612inline void ParsingEngine<C>::Parse_AttValue(){
1613       
1614        int     quoteCh = cur()[0];
1615        Advance(1); /* Skip " or ' */
1616
1617        ScanTo(Quote);                 
1618        while (cur()[0] != quoteCh){
1619                if (at_CharRef_Start<C>(cur())){
1620                        Parse_CharRef();
1621                        ScanTo(Quote);
1622                }
1623                else if (AtChar<C,'&'>(cur())){
1624                        Parse_EntityRef();
1625                        ScanTo(Quote);
1626                }
1627                else if (AtQuote<C>(cur())) {
1628                        Advance(1);
1629                        ScanTo(Quote);
1630                }
1631                else /* if (AtChar<C,'<'>(cur())) */
1632                        WF_Error(wfErr_CleanAttrVals);
1633        }
1634        Advance(1);
1635}
1636
1637template <CodeUnit_Base C>
1638inline void ParsingEngine<C>::Parse_GEntityValue(GEntity_info * this_info){
1639       
1640        int     quoteCh = cur()[0];
1641        Advance(1); /* Skip " or ' */
1642        this_info->is_simple = true;
1643        int quot_start = AbsPos();
1644        ScanTo(Quote);         
1645        char *  replText = copy_string(GetCodeUnitPtr(quot_start),AbsPos()-quot_start);
1646
1647        while (cur()[0] != quoteCh){
1648                if (at_CharRef_Start<C>(cur())){
1649                        strcat (replText,Replace_CharRef());
1650                        quot_start = AbsPos();
1651                        ScanTo(Quote);
1652                }
1653                else if (AtChar<C,'&'>(cur())){
1654                        strcat (replText,Replace_EntityRef(this_info->is_simple));
1655                        quot_start = AbsPos();
1656                        ScanTo(Quote);
1657                }
1658                else if (AtQuote<C>(cur())) {
1659                        quot_start = AbsPos();
1660                        Advance(1);
1661                        ScanTo(Quote);
1662                }
1663                else { /* '<' found */
1664                        quot_start = AbsPos();
1665                        Advance(1);
1666                        ScanTo(Quote);
1667                        this_info->is_simple = false;
1668                       
1669                }
1670                replText = cat_string (replText,(char *)GetCodeUnitPtr(quot_start), strlen(replText), AbsPos()-quot_start);
1671        }
1672        this_info->ReplacementText = replText;
1673        Advance(1);
1674}
1675
1676template <CodeUnit_Base C>
1677inline char * ParsingEngine<C>::Replace_EntityRef(bool& is_simple){
1678        Advance(1);
1679        int nameID = Parse_Name(); 
1680        if (AtChar<C,';'>(cur()))
1681                Advance(1);
1682        else
1683                Syntax_Error(NT_EntityValue);
1684        int entityID = model_info->GlobalGEntityTable[nameID]; 
1685        if (entityID == 0)
1686                WF_Error(wfErr_wf_entdeclared);
1687        else{
1688                if (model_info->GEntityData[entityID-1]->is_simple == false)
1689                        is_simple = false;
1690                return model_info->GEntityData[entityID-1]->ReplacementText;
1691        }
1692       
1693}
1694
1695template <CodeUnit_Base C>
1696inline void ParsingEngine<C>::Parse_PEntityValue(PEntity_info * this_info){
1697}
1698
1699template <CodeUnit_Base C>
1700inline char * ParsingEngine<C>::Replace_CharRef(){
1701        Advance(1);
1702        int nameID = Parse_Name(); 
1703        int entityID = model_info->GlobalGEntityTable[nameID]; 
1704        if (entityID == 0)
1705                WF_Error(wfErr_wf_entdeclared);
1706        else
1707                return model_info->GEntityData[entityID-1]->ReplacementText;   
1708       
1709}
1710
1711template <CodeUnit_Base C>
1712inline void ParsingEngine<C>::Parse_Prolog(){
1713        ScanTo(NonWS);
1714        int old_pos = AbsPos();
1715        while (!at_DOCTYPE_start<C>(cur())) {
1716                if (at_Comment_Start<C>(cur())) 
1717                        Parse_Comment();
1718                else if (at_PI_Start<C>(cur()))
1719                                Parse_PI();
1720                else{
1721                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1722                        return;
1723                }
1724                ScanTo(NonWS);
1725        }
1726        Parse_DocType();
1727        ScanTo(NonWS);
1728        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
1729                if (at_Comment_Start<C>(cur()))
1730                        Parse_Comment();
1731                else 
1732                        Parse_PI();
1733                ScanTo(NonWS);
1734        }
1735        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1736}
1737
1738template <CodeUnit_Base C>
1739inline void ParsingEngine<C>::Parse_ExtSubsetDecl() {
1740        int start_pos=AbsPos();
1741        while(!at_EOF()){
1742                if(at_condSect_start<C>(cur())){               
1743                        Advance(3);
1744                        ScanTo(NonWS);
1745                        if (at_INCLUDE<C>(cur())){
1746                                Advance(7);
1747                                ScanTo(NonWS);
1748                                if(AtChar<C,'['>(cur())){
1749                                        Advance(1);
1750                                        Parse_ExtSubsetDecl();
1751                                        if(at_CDATA_End<C>(cur()))
1752                                                Advance(3);
1753                                        else Syntax_Error(NT_includeSect);
1754                                }
1755                                else Syntax_Error(NT_includeSect);
1756                        }
1757                        else if (at_IGNORE<C>(cur())){
1758                                Advance(6);
1759                                ScanTo(NonWS);         
1760                                if(AtChar<C,'['>(cur())){
1761                                        int section_depth=1;
1762                                        Advance(1);
1763                                        while(!at_EOF()){
1764                                                ScanToMarkupStart();
1765                                                if(at_condSect_start<C>(cur())){
1766                                                        Advance(3);
1767                                                        section_depth++;
1768                                                }
1769                                                else if(at_CDATA_End<C>(cur())){
1770                                                        Advance(3);
1771                                                        section_depth--;
1772                                                }
1773                                                else
1774                                                        Advance(1);
1775                                                if(section_depth==0) return;                                   
1776                                        }
1777                                        Syntax_Error(NT_ignoreSectContents);   
1778                                }
1779                                else Syntax_Error(NT_ignoreSect);
1780                        }
1781                        else Syntax_Error(NT_conditionalSect);
1782                }
1783                else if (AtChar<C,'%'>(cur()))
1784                        Parse_PEReference();   
1785                else if (AtChar<C,'<'>(cur())){
1786                        Advance(1);
1787
1788                        if (AtChar<C,'?'>(cur())){
1789                                Parse_PI();
1790                        }
1791                        else if(AtChar<C,'!'>(cur())){
1792                                Advance(1);
1793                                if(at_DoubleHyphen<C>(cur()))
1794                                        Parse_Comment();
1795                                else if(at_ELEMENT<C>(cur()))
1796                                        Parse_Elementdecl();
1797                                else if(at_ATTLIST<C>(cur()))
1798                                        Parse_AttlistDecl();
1799                                else if(at_ENTITY<C>(cur()))
1800                                        Parse_Entitydecl();
1801                                else if(at_NOTATION<C>(cur()))
1802                                        Parse_Notationdecl();                                   
1803                                else{
1804                                        Syntax_Error(NT_markupdecl);   
1805                                }                                                               
1806                        }
1807                        else
1808                                Syntax_Error(NT_markupdecl); 
1809                }
1810                else
1811                        Syntax_Error(NT_extSubsetDecl); 
1812                ScanTo(NonWS);
1813        }
1814        ExtSubsetDecl_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
1815}
1816
1817template <CodeUnit_Base C>
1818inline int ParsingEngine<C>::Parse_ValidEndTag() {
1819        Advance(2); /* Skip "</". */
1820       
1821        int name_start = AbsPos();
1822        int nameID = Parse_Name();  /* Name delimiter: WS, "/" or ">" */
1823        char * s = copy_string(GetCodeUnitPtr(name_start),AbsPos()-name_start);
1824        int elemID = model_info->GlobalElementTable[s];
1825        if(elemID==0)
1826                        Validity_Error(vErr_elementvalid);
1827                       
1828        if (AtChar<C,'>'>(cur())) {
1829                Advance(1);
1830                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1831        }
1832    else {
1833                ScanTo(NonWS);
1834                if (AtChar<C,'>'>(cur())) {
1835                        Advance(1);
1836                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1837                }
1838                else Syntax_Error(NT_ETag);
1839    }
1840    return elemID;
1841}
1842/* Parse a valid start or empty element tag. */
1843template <CodeUnit_Base C>
1844inline int ParsingEngine<C>::Parse_ValidStartTag (bool& is_emptyStartTag){
1845        int att_name_start;
1846        int att_val_start;
1847        int att_name_end, att_val_end;
1848        unsigned char quoteCh;
1849        Advance(1);
1850       
1851        int name_start = AbsPos();
1852        int nameID = Parse_Name();  /* Name delimiter: WS, "/" or ">" */
1853        char * s = copy_string(GetCodeUnitPtr(name_start),AbsPos()-name_start);
1854        int elemID = model_info->GlobalElementTable[s];
1855        if(elemID==0)
1856                        Validity_Error(vErr_elementvalid);
1857       
1858        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
1859        /* The following test optimizes the most common case of a
1860        start tag with no attributes.  */
1861        if (AtChar<C,'>'>(cur())) {
1862                Advance(1);
1863                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1864        }
1865        else {
1866                ScanTo(NonWS);
1867                if (AtChar<C,'>'>(cur())) {
1868                        Advance(1);
1869                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1870                }
1871                else if (at_EmptyElementDelim<C>(cur())) {
1872                        Advance(2);
1873                        is_emptyStartTag = true;
1874                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1875                }
1876                else do {
1877                        /* Must be an attribute-value pair or error. */
1878                        att_name_start = AbsPos();
1879                        int nameID = Parse_Name();
1880                        att_name_end = AbsPos();
1881                        int lgth = att_name_end-att_name_start;
1882               
1883                        int attID = model_info->getOrInsertGlobalAttName(GetCodeUnitPtr(att_name_start), lgth);
1884                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1885                        else {
1886                                if (LastAttOccurrence[attID] > text_or_markup_start) {
1887                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
1888                                        break;
1889                                }                       
1890                        }
1891                        LastAttOccurrence[attID] = att_name_start;
1892                        /* The following optimized tests handle the frequently occurring
1893                        case that there are no blanks on either side of the equals sign.
1894                        In many cases, the very first test handles 100% of actual
1895                        attribute-value pairs encountered. */
1896                        if (at_EqualsQuote<C>(cur())) Advance(1); 
1897                        else {
1898                                ScanTo(NonWS);
1899                                if (!AtChar<C,'='>(cur())) {
1900                                        Syntax_Error(NT_STag); 
1901                                        break;
1902                                }
1903                                ScanTo(NonWS);
1904                                if (!AtQuote<C>(cur())) {
1905                                        Syntax_Error(NT_STag); 
1906                                        break;
1907                                }
1908                        }
1909                        att_val_start = AbsPos()+1;
1910                        Parse_AttValue();
1911                        att_val_end = AbsPos()-1;
1912                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
1913                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
1914                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
1915                        }
1916                        else {
1917                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
1918                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
1919                        }
1920                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
1921                        if (AtChar<C,'>'>(cur())) {
1922                                Advance(1);
1923                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1924                                break;
1925                        }
1926                        else if (at_EmptyElementDelim<C>(cur())) {
1927                                Advance(2);
1928                                is_emptyStartTag = true;       
1929                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1930                                break;
1931                        }
1932                        ScanTo(NonWS);
1933                        if (AtChar<C,'>'>(cur())) {
1934                                Advance(1);
1935                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1936                                break;
1937                        }
1938                        else if (at_EmptyElementDelim<C>(cur())) {
1939                                Advance(2);
1940                                is_emptyStartTag = true;
1941                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1942                                break;
1943                        }
1944                        else if (AbsPos() == att_val_end + 1) { 
1945                                /* No WS following att value */
1946                                Syntax_Error(NT_STag);
1947                                break;
1948                        }
1949                } while (1);
1950        }
1951        return elemID;
1952}
1953
1954template <CodeUnit_Base C>
1955inline int ParsingEngine<C>::Parse_ValidElement() {
1956        bool is_emptyStartTag = false;
1957        int elemID = Parse_ValidStartTag(is_emptyStartTag);
1958#ifdef DEBUG
1959        printf("Parse_ValidElement: elemID = %d, is_emptyStartTag=%i\n",elemID, is_emptyStartTag);
1960#endif
1961        ContentModel * cm = model_info->ContentModelData[elemID];
1962        switch (cm->cm_type) {
1963                case cm_Empty:
1964                        if (!is_emptyStartTag) {
1965                                if (at_EndTag_Start<C>(cur())) {
1966                                        if (Parse_ValidEndTag()!=elemID) Validity_Error(vErr_elementvalid);
1967//                                      Parse_EndTag();
1968                                }
1969                                else {
1970                                        Validity_Error(vErr_elementvalid);
1971                                }
1972                        }
1973                        break;
1974                case cm_Any:           
1975                        if (!is_emptyStartTag) {
1976                                Parse_AnyContent();
1977                                if (Parse_ValidEndTag()!=elemID) Validity_Error(vErr_elementvalid);
1978                        }
1979                        break;
1980                case cm_Mixed:         
1981                        if (!is_emptyStartTag) {
1982                                Parse_MixedContent(((CM_Mixed *) cm)->elements);
1983                                if (Parse_ValidEndTag()!=elemID) Validity_Error(vErr_elementvalid);
1984                        }
1985                        break;
1986                case cm_RegExp:
1987                        CM_RegExp * cre = (CM_RegExp *) cm;
1988                        int content_state = 0;
1989                        if (!is_emptyStartTag) {
1990                                content_state = Parse_ValidContent(cre);
1991                                if (Parse_ValidEndTag()!=elemID) Validity_Error(vErr_elementvalid);                     
1992                        }
1993                        if (cre->transition_map[content_state][0]==0) {
1994                                Validity_Error(vErr_elementvalid);
1995                        }
1996        }
1997        return elemID;
1998}
1999
2000template <CodeUnit_Base C>
2001inline int ParsingEngine<C>::Parse_ValidContent(CM_RegExp * cre) {
2002        int cur_state = 0;
2003        do {
2004                ScanTo(NonWS);
2005                /* If non-null report WS  WS_action()? */
2006                if (at_EndTag_Start<C>(cur())) {
2007                        break;
2008                }
2009                else if (at_ElementTag_Start<C>(cur())) {
2010                        int elemID = Parse_ValidElement();
2011#ifdef DEBUG
2012                        printf("Content model state transition %i", cur_state);
2013#endif
2014                        cur_state = cre->transition_map[cur_state][elemID];
2015#ifdef DEBUG
2016                        printf("-> %i\n", cur_state);
2017#endif
2018                }
2019                else if (at_Comment_Start<C>(cur())) {
2020                        Parse_Comment();
2021                }
2022                else if (at_PI_Start<C>(cur())) {
2023                        Parse_PI();
2024                }
2025                else if (AtChar<C,'&'>(cur())) {
2026                        Parse_EntityRef();
2027                }
2028                else if (at_EOF()) {
2029                        break;
2030                }
2031                else if (AtChar<C,'<'>(cur())) {
2032                        Syntax_Error(NT_markupdecl);
2033                }
2034                else {
2035                        Validity_Error(vErr_elementvalid);
2036                }
2037        } while(1);
2038        return cur_state;
2039}
2040
2041
2042template <CodeUnit_Base C>
2043inline void ParsingEngine<C>::Parse_AnyContent() {
2044        do {
2045                text_or_markup_start = AbsPos();
2046                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
2047                if (at_ElementTag_Start<C>(cur())) {
2048                        text_if_nonnull_action();
2049                        int elemID = Parse_ValidElement();
2050                }
2051                else if (at_EndTag_Start<C>(cur())) {
2052                        text_if_nonnull_action();
2053                        return;
2054                }
2055                else if (at_Comment_Start<C>(cur())) {
2056                        text_if_nonnull_action();
2057                        Parse_Comment();
2058                }
2059                else if (at_CharRef_Start<C>(cur())) {
2060                        text_if_nonnull_action();
2061                        Parse_CharRef();
2062                }
2063                else if (AtChar<C,'&'>(cur())) {
2064                        text_if_nonnull_action();
2065                        Parse_EntityRef();
2066                }
2067                else if (at_CDATA_Start<C>(cur())) {
2068                        text_if_nonnull_action();
2069                        Parse_CDATA();
2070                }
2071                else if (at_PI_Start<C>(cur())) {
2072                        text_if_nonnull_action();
2073                        Parse_PI();
2074                }
2075                else if (at_CDATA_End<C>(cur())) {
2076                        text_if_nonnull_action();
2077                        Advance(3);
2078                        Syntax_Error(NT_CharData);
2079                }
2080                else if (at_EOF()) {
2081                        text_if_nonnull_action();
2082                        return;
2083                }
2084                else if (AtChar<C,'<'>(cur())) {
2085                        Syntax_Error(NT_markupdecl);
2086                }
2087                else {
2088                        Advance(1);
2089                        continue;
2090                }
2091        } while (1);
2092}
2093template <CodeUnit_Base C>
2094inline void ParsingEngine<C>::Parse_MixedContent(symbol_set_t elems) {
2095        do {
2096                text_or_markup_start = AbsPos();
2097                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
2098/*              if (AtChar<C,'<'>(cur())) {
2099                        text_if_nonnull_action();
2100                        Parse_Markup<C>();
2101                }*/
2102                if (at_ElementTag_Start<C>(cur())) {
2103                        text_if_nonnull_action();
2104                        int elemID = Parse_ValidElement();
2105                        if (elems[elemID] == 0) {
2106                                Validity_Error(vErr_elementvalid);
2107                        }
2108                }
2109                else if (at_EndTag_Start<C>(cur())) {
2110                        text_if_nonnull_action();
2111                        return;
2112                }
2113                else if (at_Comment_Start<C>(cur())) {
2114                        text_if_nonnull_action();
2115                        Parse_Comment();
2116                }
2117                else if (at_CharRef_Start<C>(cur())) {
2118                        text_if_nonnull_action();
2119                        Parse_CharRef();
2120                }
2121                else if (AtChar<C,'&'>(cur())) {
2122                        text_if_nonnull_action();
2123                        Parse_EntityRef();
2124                }
2125                else if (at_CDATA_Start<C>(cur())) {
2126                        text_if_nonnull_action();
2127                        Parse_CDATA();
2128                }
2129                else if (at_PI_Start<C>(cur())) {
2130                        text_if_nonnull_action();
2131                        Parse_PI();
2132                }
2133                else if (at_CDATA_End<C>(cur())) {
2134                        text_if_nonnull_action();
2135                        Advance(3);
2136                        Syntax_Error(NT_CharData);
2137                }
2138                else if (at_EOF()) {
2139                        text_if_nonnull_action();
2140                        return;
2141                }
2142                else if (AtChar<C,'<'>(cur())) {
2143                        Syntax_Error(NT_markupdecl);
2144                }
2145                else {
2146                        Advance(1);
2147                        continue;
2148                }
2149        } while (1);
2150}
2151
2152template <CodeUnit_Base C>
2153inline int ParsingEngine<C>::Parse_Name() {
2154        int name_pos = AbsPos();
2155        ScanTo(NameFollow);
2156        int lgth = AbsPos()-name_pos;
2157        char * s = copy_string(GetCodeUnitPtr(name_pos),lgth);
2158        int nameID = model_info->GlobalNameTable[s];
2159        if(nameID == 0){
2160                if (entity_Info->version == XML_1_1){
2161                        if (!is_XML11_UTF8_Name(GetCodeUnitPtr(name_pos),lgth)) Syntax_Error(NT_Name);
2162                }
2163                else if (!is_XML10_UTF8_Name(GetCodeUnitPtr(name_pos),lgth)) Syntax_Error(NT_Name);
2164                model_info->GlobalNameTable[s]=++(model_info->globalNameCount);
2165                nameID = model_info->globalNameCount;
2166        }
2167        return nameID;
2168}
2169
2170
2171template <CodeUnit_Base C>
2172inline void ParsingEngine<C>::Parse_DocumentContent() {
2173#ifdef VALIDATION
2174        int final_state = Parse_ValidContent(model_info->rootModel);
2175        if (model_info->rootModel->transition_map[final_state][0]==0) {
2176                Validity_Error(vErr_elementvalid);
2177        }
2178#endif
2179#ifndef VALIDATION
2180        Parse_WF_Element();
2181        ScanTo(NonWS);
2182        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
2183                if (at_Comment_Start<C>(cur()))
2184                        Parse_Comment();
2185                else 
2186                        Parse_PI();
2187                ScanTo(NonWS);
2188        }
2189        if (!at_EOF()) {
2190                Syntax_Error(NT_document);
2191        }       
2192#endif
2193}
2194
Note: See TracBrowser for help on using the repository browser.