source: trunk/src/engine.c @ 137

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

ATT_info: emumValues using nameID.

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