source: trunk/src/engine.c @ 138

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

Fix calls to Parse_PI and Parse_Comment.

File size: 55.5 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 (at_PI_Start<C>(cur())) {
1041                        Parse_PI();
1042                }
1043                else if (at_Comment_Start<C>(cur())) {
1044                        Parse_Comment();
1045                }
1046                else if (AtChar<C,'<'>(cur())){
1047                        Advance(1);
1048                        if(AtChar<C,'!'>(cur())){
1049                                Advance(1);
1050                                if (at_ELEMENT<C>(cur()))
1051                                        Parse_Elementdecl();
1052                                else if (at_ATTLIST<C>(cur()))
1053                                        Parse_AttlistDecl();
1054                                else if (at_ENTITY<C>(cur()))
1055                                        Parse_Entitydecl();
1056                                else if (at_NOTATION<C>(cur()))
1057                                        Parse_Notationdecl();
1058                                else {
1059                                        Syntax_Error(NT_markupdecl);           
1060                                }                                                               
1061                        }
1062                        else
1063                                Syntax_Error(NT_markupdecl); 
1064                }
1065                else if (AtChar<C,']'>(cur())){
1066                        break;
1067                }
1068                else
1069                        Syntax_Error(NT_intSubset); 
1070        }
1071}
1072
1073
1074template <CodeUnit_Base C>
1075inline void ParsingEngine<C>::Parse_PEReference (){
1076
1077        Advance(1); /* Skip "%". */
1078        int nameID = Parse_Name(); 
1079        if (AtChar<C,';'>(cur())) {
1080                Advance(1);
1081                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1082                PEntity_info * this_info;
1083                Parser_Interface * entity_parser;
1084                int entityID = model_info->GlobalPEntityTable[nameID]; 
1085                if (entityID == 0)
1086                        WF_Error(wfErr_wf_entdeclared);
1087                else{
1088                        this_info = model_info->PEntityData[entityID-1];
1089                        if (this_info->is_external){
1090                               
1091//                      if (entity_Info->standalone != Standalone_no)
1092//                              WF_Error(wfErr_NoExternalRefs);
1093//                      else {
1094                                        entity_parser = ParserFactory(this_info->systemLiteral, model_info);
1095                                        entity_parser->Parse_WF_Content();
1096                                        if(!entity_parser->at_EOF())
1097                                                Syntax_Error(NT_content);
1098                                        entity_parser->~Parser_Interface();
1099//                      }
1100                        }
1101                        else {
1102                        }
1103                }
1104        }
1105        else
1106                Syntax_Error(NT_PEReference);
1107}
1108
1109
1110template <CodeUnit_Base C>
1111inline void ParsingEngine<C>::Parse_Elementdecl (){
1112
1113        Advance(7); /* Skip "<!ELEMENT". */
1114
1115    requireWS();
1116        int nameID = Parse_Name();
1117        int elemID = model_info->getOrInsertGlobalElement(nameID);
1118
1119        requireWS();
1120        ContentModel * cm;
1121        /* Start parsing "contentspec"*/
1122        if (at_EMPTY<C>(cur())) {
1123        Advance(5);
1124        cm = new CM_Empty();
1125        model_info->ContentModelData[nameID] = cm;
1126        }
1127    else if (at_ANY<C>(cur())) {
1128        Advance(3);
1129        cm = new CM_Any();
1130        model_info->ContentModelData[nameID] = cm;
1131    }
1132    else {
1133        if (AtChar<C,'('>(cur()))
1134                        Advance(1);
1135                ScanTo(NonWS);
1136                if (at_PCDATA<C>(cur())){
1137                        cm = Parse_RemainingMixed();
1138                        model_info->ContentModelData[nameID] = cm;
1139                }
1140                else{
1141
1142                        CM_RegExp * cre = new CM_RegExp;
1143                        cre->content_re = Parse_RemainingChildren();
1144
1145                        int id_count = cre->content_re->Set_IDs(0);
1146                        cre->content_re->Set_First_Map();       
1147                        symbol_set_t * transition_map = new symbol_set_t[id_count+1];
1148                        cre->content_re->follow_map[0] = id_count+1;
1149                       
1150                        cre->content_re->Set_Follow_Map(transition_map);
1151                        transition_map[0] = cre->content_re->first_map;
1152                       
1153                        if (cre->content_re->matches_empty)
1154                                transition_map[0][0]=id_count+1;
1155                               
1156                        cre -> transition_map = transition_map;
1157                       
1158                        model_info->ContentModelData[nameID] = cre;
1159                        cm = cre;
1160                }                       
1161    }
1162    ScanTo(NonWS);   
1163
1164        if (AtChar<C,'>'>(cur())) {
1165                Advance(1);
1166        }
1167        else
1168                Syntax_Error(NT_elementdecl);
1169}
1170template <CodeUnit_Base C>
1171inline ContentModel * ParsingEngine<C>::Parse_RemainingMixed (){
1172        CM_Mixed * r = new CM_Mixed();
1173        Advance(7);  /* Skip "#PCDATA". */
1174   
1175    if (AtChar<C,')'>(cur())){
1176        if (AtChar<C,'*'>(cur())) {
1177                Advance(2);
1178                }
1179                else {
1180                        Advance(1);
1181                }
1182    }
1183    else{
1184        ScanTo(NonWS);
1185        int k = 0;
1186        while (AtChar<C,'|'>(cur())){
1187                        Advance(1);
1188                        ScanTo(NonWS);
1189                        int nameID = Parse_Name();
1190                        r->elements[nameID] = ++k;
1191                        ScanTo(NonWS);
1192                }
1193                if (at_Para_star<C>(cur())) Advance(2);
1194                else {
1195                        Syntax_Error(NT_Mixed);
1196                        exit(-1);
1197        }
1198    }
1199    return r;
1200}
1201
1202
1203template <CodeUnit_Base C>
1204inline Content_RE * ParsingEngine<C>::Parse_RemainingChildren (){
1205        Content_RE * c1 = Parse_Cp();
1206        Content_RE * r = c1;
1207        ScanTo(NonWS);
1208        if(AtChar<C,'|'>(cur())){
1209                CRE_Choice * rslt = new CRE_Choice;
1210                rslt->subCMs.push_back(c1);
1211                Advance(1);
1212                ScanTo(NonWS);
1213                rslt->subCMs.push_back(Parse_Cp());
1214                ScanTo(NonWS);
1215                while(!AtChar<C,')'>(cur())){
1216                        if(AtChar<C,'|'>(cur()))
1217                                Advance(1);
1218                        else
1219                                Syntax_Error(NT_children);
1220                        ScanTo(NonWS);
1221                        rslt->subCMs.push_back(Parse_Cp());
1222                        ScanTo(NonWS);
1223                }
1224                Advance(1);
1225                rslt->Compile();
1226                r = rslt;
1227        }
1228        else if(AtChar<C,','>(cur())){
1229                CRE_Seq * rslt = new CRE_Seq;
1230                rslt->subCMs.push_back(c1);
1231                Advance(1);
1232                ScanTo(NonWS);
1233                rslt->subCMs.push_back(Parse_Cp());
1234                ScanTo(NonWS);
1235                while(!AtChar<C,')'>(cur())){
1236                        if(AtChar<C,','>(cur()))
1237                                Advance(1);
1238                        else
1239                                Syntax_Error(NT_children);
1240                        ScanTo(NonWS);
1241                        rslt->subCMs.push_back(Parse_Cp());
1242                        ScanTo(NonWS);
1243                }
1244                Advance(1);
1245                rslt->Compile();
1246                r = rslt;
1247        }       
1248        else if(AtChar<C,')'>(cur())){
1249                Advance(1);
1250        }
1251        else
1252                Syntax_Error(NT_children);
1253               
1254        if (AtChar<C,'?'>(cur())) {
1255                Advance(1);
1256                r = new CRE_Opt(r);
1257        }
1258        else if (AtChar<C,'*'>(cur())) {
1259                Advance(1);
1260                r = new CRE_Star(r);
1261        }
1262        else if (AtChar<C,'+'>(cur())) {
1263                Advance(1);
1264                r = new CRE_Plus(r);
1265        }
1266
1267        return r;
1268}
1269
1270template <CodeUnit_Base C>
1271inline Content_RE * ParsingEngine<C>::Parse_Cp (){
1272        if (AtChar<C,'('>(cur())){
1273                Advance(1);
1274                ScanTo(NonWS);
1275                Parse_RemainingChildren();
1276        }
1277        else{
1278                int nameID = Parse_Name();
1279                CRE_Name * r = new CRE_Name(nameID);
1280
1281                if (AtChar<C,'?'>(cur())) {
1282                        Advance(1);
1283                        return new CRE_Opt(r);
1284                }
1285                else if (AtChar<C,'*'>(cur())) {
1286                        Advance(1);
1287                        return new CRE_Star(r);
1288                }
1289                else if (AtChar<C,'+'>(cur())) {
1290                        Advance(1);
1291                        return new CRE_Plus(r);
1292                }
1293                else return r;
1294        }
1295}
1296
1297template <CodeUnit_Base C>
1298inline void ParsingEngine<C>::Parse_AttlistDecl (){
1299       
1300        int old_abspos;
1301       
1302        int name_start;
1303        int lgth;
1304       
1305        int elemID;
1306        int attID;
1307       
1308        Advance(7); /* Skip "ATTLIST. */
1309        requireWS();
1310       
1311        int nameID = Parse_Name();
1312        elemID = model_info->getOrInsertGlobalElement(nameID);
1313       
1314        old_abspos = AbsPos();
1315        ScanTo(NonWS);
1316        while(!AtChar<C,'>'>(cur())) {
1317                if(old_abspos == AbsPos())
1318                Syntax_Error(NT_AttlistDecl);
1319               
1320                int att_nameID = Parse_Name();
1321               
1322                attID = model_info->getOrInsertGlobalAttName(att_nameID);
1323                if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1324        ATT_info * this_info = new ATT_info;
1325        this_info->globalATT_id = attID;
1326        requireWS();
1327        if (at_CDATA<C>(cur())){
1328                Advance(5);
1329                this_info->attType = CDATA_att;
1330        }
1331        else if(at_ID<C>(cur())){
1332                Advance(2);
1333                this_info->attType = ID_att;
1334        }
1335        /* Make sure to check IDREFS before IDREF*/
1336        else if(at_IDREFS<C>(cur())){
1337                Advance(6);
1338                this_info->attType = IDREFS_att;
1339        }
1340        else if(at_IDREF<C>(cur())){
1341                Advance(5);
1342                this_info->attType = IDREF_att;
1343        }
1344        else if(at_ENTITY<C>(cur())){
1345                Advance(6);
1346                this_info->attType = ENTITY_att;
1347        }
1348        else if(at_ENTITIES<C>(cur())){
1349                Advance(8);
1350                this_info->attType = ENTITIES_att;
1351        }
1352        /* Make sure to check NMTOKENS before NMTOKEN*/
1353        else if(at_NMTOKENS<C>(cur())){
1354                Advance(8);
1355                this_info->attType = NMTOKENS_att;
1356        }
1357        else if(at_NMTOKEN<C>(cur())){
1358                Advance(7);
1359                this_info->attType = NMTOKEN_att;
1360        }
1361        else if(at_NOTATION<C>(cur())){ /* NotationType = 'NOTATION' S Enumeration
1362                                                                         when Nmtoken = Name */
1363                Advance(8);
1364                        requireWS();
1365                Parse_Notation(this_info);
1366                this_info->attType = NOTATION_att;
1367        }
1368        else if(AtChar<C,'('>(cur())){
1369                Parse_Enumeration(this_info);
1370                this_info->attType = enumeration_att;
1371        }
1372        else
1373                Syntax_Error(NT_AttlistDecl);
1374        requireWS();
1375        Parse_DefaultDecl(this_info);
1376
1377                ScanTo(NonWS);
1378                model_info->ElementAttributeData[elemID].push_back(this_info);
1379        }
1380
1381        Advance(1);
1382}
1383
1384template <CodeUnit_Base C>
1385inline void ParsingEngine<C>::Parse_Notation (ATT_info * this_info){
1386
1387        if(AtChar<C,'('>(cur()))
1388                Advance(1);
1389        else
1390                Syntax_Error(NT_NotationType);
1391        ScanTo(NonWS);
1392       
1393    int nameID = Parse_Name();
1394
1395        /*Notation name is not in the global table!*/
1396        if(model_info->GlobalNotationTable[nameID]==0)
1397                Validity_Error(vErr_notatn);
1398       
1399        ScanTo(NonWS);
1400        while(AtChar<C,'|'>(cur())){
1401                Advance(1);
1402                ScanTo(NonWS); 
1403                int not_nameID = Parse_Name();
1404                       
1405                if(model_info->GlobalNotationTable[not_nameID]==0)
1406                        Validity_Error(vErr_notatn);
1407                       
1408                ScanTo(NonWS);
1409        }
1410        if (AtChar<C,')'>(cur())) 
1411                Advance(1);
1412        else
1413                Syntax_Error(NT_NotationType);
1414}
1415
1416template <CodeUnit_Base C>
1417inline void ParsingEngine<C>::Parse_Enumeration (ATT_info * this_info){
1418
1419        int enumCount=0;
1420        if(AtChar<C,'('>(cur()))
1421                Advance(1);
1422        else
1423                Syntax_Error(NT_Enumeration);
1424        ScanTo(NonWS);
1425       
1426        int nameID = Parse_Name();
1427       
1428        this_info->enumValues[nameID]=++(enumCount);
1429       
1430        ScanTo(NonWS);
1431        while(AtChar<C,'|'>(cur())){
1432                Advance(1);
1433                ScanTo(NonWS); 
1434                int nameID = Parse_Name();
1435       
1436                int enumID = this_info->enumValues[nameID];
1437                if(enumID==0){ 
1438                        this_info->enumValues[nameID]=++(enumCount);
1439                        enumID = enumCount;
1440                }
1441                else if(!StrictWellFormedness){
1442                        Validity_Error(vErr_NoDuplicateTokens);
1443                }
1444                ScanTo(NonWS);
1445        }
1446        if (AtChar<C,')'>(cur())) 
1447                Advance(1);
1448        else
1449                Syntax_Error(NT_Enumeration);
1450}
1451
1452template <CodeUnit_Base C>
1453inline void ParsingEngine<C>::Parse_DefaultDecl (ATT_info * this_info){
1454        if(at_REQUIRED<C>(cur())){
1455                Advance(9);
1456                this_info->defaultKind = REQUIRED_att;
1457        }
1458        else if(at_IMPLIED<C>(cur())){
1459                Advance(8);
1460                this_info->defaultKind = IMPLIED_att;
1461        }
1462        else {
1463                if(at_FIXED<C>(cur())){
1464                        Advance(6);
1465                        requireWS();
1466                        this_info->defaultKind = FIXED_att;
1467                }
1468                else this_info->defaultKind = DEFAULT_att;
1469                if(AtQuote<C>(cur())){
1470                        int quot_start = AbsPos()+1;
1471                        Parse_AttValue();
1472                        /* need to normalize */
1473                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
1474                       
1475                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
1476                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
1477                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
1478                        }
1479                else
1480                        Syntax_Error(NT_DefaultDecl);
1481        }
1482}
1483
1484template <CodeUnit_Base C>
1485inline void ParsingEngine<C>::Parse_Entitydecl (){
1486       
1487        int name_start;
1488        int quot_start;
1489        int lgth;
1490        int old_abspos;
1491        char * s;
1492       
1493        Advance(6); /* Skip "ENTITY. */
1494        requireWS();
1495       
1496        if (AtChar<C,'%'>(cur())){
1497                Advance(1);
1498                requireWS();
1499               
1500                int nameID = Parse_Name();
1501       
1502                PEntity_info * this_info = new PEntity_info;
1503                int entityID = model_info->GlobalPEntityTable[nameID];
1504                if(entityID==0){       
1505                        model_info->GlobalPEntityTable[nameID]=++(model_info->globalPEntityCount);
1506                        entityID = model_info->globalPEntityCount;
1507                        this_info->globalPEntity_id = entityID;
1508                }
1509                else
1510                        printf("Warning: Entity definition already exist!\n");
1511       
1512                requireWS();
1513                if(AtQuote<C>(cur())){
1514                Parse_PEntityValue(this_info);
1515                this_info->is_external = false;
1516        }
1517        else {
1518                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1519                this_info->is_external = true;
1520                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1521        }
1522        model_info->PEntityData.push_back(this_info);
1523        }
1524        else{
1525                int nameID = Parse_Name();
1526       
1527                GEntity_info * this_info = new GEntity_info();
1528                int entityID = model_info->GlobalGEntityTable[nameID];
1529                if(entityID==0){       
1530                        model_info->GlobalGEntityTable[nameID]=++(model_info->globalGEntityCount);
1531                        entityID = model_info->globalGEntityCount;
1532                        this_info->globalGEntity_id = entityID;
1533                }
1534                else
1535                        printf("Warning: Entity definition already exist!\n");
1536                       
1537                requireWS();
1538               
1539                if(AtQuote<C>(cur())){
1540                Parse_GEntityValue(this_info);                 
1541                this_info->is_external = false;
1542        }
1543        else {
1544                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1545                this_info->is_external = true;
1546                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1547                        old_abspos = AbsPos();
1548                        ScanTo(NonWS);
1549                if(at_NDATA<C>(cur())){
1550                        if(old_abspos == AbsPos())
1551                                Syntax_Error(NT_EntityDecl);
1552                        else
1553                                Advance(5);
1554                        requireWS();
1555                        name_start = AbsPos();
1556                        int nameID = Parse_Name();
1557                        lgth = AbsPos() - name_start;
1558                                this_info->NDataName = copy_string(GetCodeUnitPtr(name_start),lgth);
1559                }
1560                }
1561        model_info->GEntityData.push_back(this_info);
1562        }
1563        ScanTo(NonWS);
1564        if (AtChar<C,'>'>(cur())){
1565                Advance(1);
1566        }
1567        else
1568                Syntax_Error(NT_EntityDecl);
1569}
1570
1571template <CodeUnit_Base C>
1572inline void ParsingEngine<C>::Parse_Notationdecl (){
1573
1574        int old_abspos;
1575        Advance(8); /* Skip "NOTATION. */
1576        requireWS();
1577       
1578        int nameID = Parse_Name();
1579
1580        int notationID = model_info->GlobalNotationTable[nameID];
1581        if(notationID==0){     
1582                model_info->GlobalNotationTable[nameID]=++(model_info->globalNotationCount);
1583                notationID = model_info->globalNotationCount;
1584        }
1585        else /*Duplicate notation name!*/
1586                Validity_Error(vErr_NoDuplicateTokens);
1587        Notation_info * this_info = new Notation_info;
1588                       
1589    Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1590        ScanTo(NonWS);
1591        if (AtChar<C,'>'>(cur())) {
1592                Advance(1);
1593        }
1594        else
1595                Syntax_Error(NT_NotationDecl);
1596}
1597
1598template <CodeUnit_Base C>
1599inline void ParsingEngine<C>::requireWS(){
1600       
1601    int old_abspos = AbsPos(); 
1602    ScanTo(NonWS);
1603    if(old_abspos == AbsPos())
1604        Syntax_Error(NT_S);
1605}
1606
1607template <CodeUnit_Base C>
1608inline void ParsingEngine<C>::Parse_AttValue(){
1609       
1610        int     quoteCh = cur()[0];
1611        Advance(1); /* Skip " or ' */
1612
1613        ScanTo(Quote);                 
1614        while (cur()[0] != quoteCh){
1615                if (at_CharRef_Start<C>(cur())){
1616                        Parse_CharRef();
1617                        ScanTo(Quote);
1618                }
1619                else if (AtChar<C,'&'>(cur())){
1620                        Parse_EntityRef();
1621                        ScanTo(Quote);
1622                }
1623                else if (AtQuote<C>(cur())) {
1624                        Advance(1);
1625                        ScanTo(Quote);
1626                }
1627                else /* if (AtChar<C,'<'>(cur())) */
1628                        WF_Error(wfErr_CleanAttrVals);
1629        }
1630        Advance(1);
1631}
1632
1633template <CodeUnit_Base C>
1634inline void ParsingEngine<C>::Parse_GEntityValue(GEntity_info * this_info){
1635       
1636        int     quoteCh = cur()[0];
1637        Advance(1); /* Skip " or ' */
1638        this_info->is_simple = true;
1639        int quot_start = AbsPos();
1640        ScanTo(Quote);         
1641        char *  replText = copy_string(GetCodeUnitPtr(quot_start),AbsPos()-quot_start);
1642
1643        while (cur()[0] != quoteCh){
1644                if (at_CharRef_Start<C>(cur())){
1645                        strcat (replText,Replace_CharRef());
1646                        quot_start = AbsPos();
1647                        ScanTo(Quote);
1648                }
1649                else if (AtChar<C,'&'>(cur())){
1650                        strcat (replText,Replace_EntityRef(this_info->is_simple));
1651                        quot_start = AbsPos();
1652                        ScanTo(Quote);
1653                }
1654                else if (AtQuote<C>(cur())) {
1655                        quot_start = AbsPos();
1656                        Advance(1);
1657                        ScanTo(Quote);
1658                }
1659                else { /* '<' found */
1660                        quot_start = AbsPos();
1661                        Advance(1);
1662                        ScanTo(Quote);
1663                        this_info->is_simple = false;
1664                       
1665                }
1666                replText = cat_string (replText,(char *)GetCodeUnitPtr(quot_start), strlen(replText), AbsPos()-quot_start);
1667        }
1668        this_info->ReplacementText = replText;
1669        Advance(1);
1670}
1671
1672template <CodeUnit_Base C>
1673inline char * ParsingEngine<C>::Replace_EntityRef(bool& is_simple){
1674        Advance(1);
1675        int nameID = Parse_Name(); 
1676        if (AtChar<C,';'>(cur()))
1677                Advance(1);
1678        else
1679                Syntax_Error(NT_EntityValue);
1680        int entityID = model_info->GlobalGEntityTable[nameID]; 
1681        if (entityID == 0)
1682                WF_Error(wfErr_wf_entdeclared);
1683        else{
1684                if (model_info->GEntityData[entityID-1]->is_simple == false)
1685                        is_simple = false;
1686                return model_info->GEntityData[entityID-1]->ReplacementText;
1687        }
1688       
1689}
1690
1691template <CodeUnit_Base C>
1692inline void ParsingEngine<C>::Parse_PEntityValue(PEntity_info * this_info){
1693}
1694
1695template <CodeUnit_Base C>
1696inline char * ParsingEngine<C>::Replace_CharRef(){
1697        Advance(1);
1698        int nameID = Parse_Name(); 
1699        int entityID = model_info->GlobalGEntityTable[nameID]; 
1700        if (entityID == 0)
1701                WF_Error(wfErr_wf_entdeclared);
1702        else
1703                return model_info->GEntityData[entityID-1]->ReplacementText;   
1704       
1705}
1706
1707template <CodeUnit_Base C>
1708inline void ParsingEngine<C>::Parse_Prolog(){
1709        ScanTo(NonWS);
1710        int old_pos = AbsPos();
1711        while (!at_DOCTYPE_start<C>(cur())) {
1712                if (at_Comment_Start<C>(cur())) 
1713                        Parse_Comment();
1714                else if (at_PI_Start<C>(cur()))
1715                                Parse_PI();
1716                else{
1717                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1718                        return;
1719                }
1720                ScanTo(NonWS);
1721        }
1722        Parse_DocType();
1723        ScanTo(NonWS);
1724        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
1725                if (at_Comment_Start<C>(cur()))
1726                        Parse_Comment();
1727                else 
1728                        Parse_PI();
1729                ScanTo(NonWS);
1730        }
1731        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1732}
1733
1734template <CodeUnit_Base C>
1735inline void ParsingEngine<C>::Parse_ExtSubsetDecl() {
1736        int start_pos=AbsPos();
1737        while(!at_EOF()){
1738                if(at_condSect_start<C>(cur())){               
1739                        Advance(3);
1740                        ScanTo(NonWS);
1741                        if (at_INCLUDE<C>(cur())){
1742                                Advance(7);
1743                                ScanTo(NonWS);
1744                                if(AtChar<C,'['>(cur())){
1745                                        Advance(1);
1746                                        Parse_ExtSubsetDecl();
1747                                        if(at_CDATA_End<C>(cur()))
1748                                                Advance(3);
1749                                        else Syntax_Error(NT_includeSect);
1750                                }
1751                                else Syntax_Error(NT_includeSect);
1752                        }
1753                        else if (at_IGNORE<C>(cur())){
1754                                Advance(6);
1755                                ScanTo(NonWS);         
1756                                if(AtChar<C,'['>(cur())){
1757                                        int section_depth=1;
1758                                        Advance(1);
1759                                        while(!at_EOF()){
1760                                                ScanToMarkupStart();
1761                                                if(at_condSect_start<C>(cur())){
1762                                                        Advance(3);
1763                                                        section_depth++;
1764                                                }
1765                                                else if(at_CDATA_End<C>(cur())){
1766                                                        Advance(3);
1767                                                        section_depth--;
1768                                                }
1769                                                else
1770                                                        Advance(1);
1771                                                if(section_depth==0) return;                                   
1772                                        }
1773                                        Syntax_Error(NT_ignoreSectContents);   
1774                                }
1775                                else Syntax_Error(NT_ignoreSect);
1776                        }
1777                        else Syntax_Error(NT_conditionalSect);
1778                }
1779                else if (AtChar<C,'%'>(cur()))
1780                        Parse_PEReference();   
1781                else if (at_PI_Start<C>(cur())) {
1782                        Parse_PI();
1783                }
1784                else if (at_Comment_Start<C>(cur())) {
1785                        Parse_Comment();
1786                }
1787                else if (AtChar<C,'<'>(cur())){
1788                        Advance(1);
1789
1790                        if(AtChar<C,'!'>(cur())){
1791                                Advance(1);
1792                                if(at_ELEMENT<C>(cur()))
1793                                        Parse_Elementdecl();
1794                                else if(at_ATTLIST<C>(cur()))
1795                                        Parse_AttlistDecl();
1796                                else if(at_ENTITY<C>(cur()))
1797                                        Parse_Entitydecl();
1798                                else if(at_NOTATION<C>(cur()))
1799                                        Parse_Notationdecl();                                   
1800                                else{
1801                                        Syntax_Error(NT_markupdecl);   
1802                                }                                                               
1803                        }
1804                        else
1805                                Syntax_Error(NT_markupdecl); 
1806                }
1807                else
1808                        Syntax_Error(NT_extSubsetDecl); 
1809                ScanTo(NonWS);
1810        }
1811        ExtSubsetDecl_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
1812}
1813
1814/* Parse a valid start or empty element tag. */
1815template <CodeUnit_Base C>
1816inline int ParsingEngine<C>::Parse_ValidStartTag (bool& is_emptyStartTag){
1817        int att_name_start;
1818        int att_val_start;
1819        int att_name_end, att_val_end;
1820        unsigned char quoteCh;
1821        Advance(1);
1822
1823        int nameID = Parse_Name(); 
1824        int elemID = model_info->GlobalElementTable[nameID];
1825        if(elemID==0)
1826                        Validity_Error(vErr_elementvalid);
1827       
1828        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
1829        /* The following test optimizes the most common case of a
1830        start tag with no attributes.  */
1831        if (AtChar<C,'>'>(cur())) {
1832                Advance(1);
1833                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1834        }
1835        else {
1836                ScanTo(NonWS);
1837                if (AtChar<C,'>'>(cur())) {
1838                        Advance(1);
1839                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1840                }
1841                else if (at_EmptyElementDelim<C>(cur())) {
1842                        Advance(2);
1843                        is_emptyStartTag = true;
1844                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1845                }
1846                else do {
1847                        /* Must be an attribute-value pair or error. */
1848                        att_name_start = AbsPos();
1849                        int att_nameID = Parse_Name();
1850               
1851                        int attID = model_info->getOrInsertGlobalAttName(att_nameID);
1852                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1853                        else {
1854                                if (LastAttOccurrence[attID] > text_or_markup_start) {
1855                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
1856                                        break;
1857                                }                       
1858                        }
1859                        LastAttOccurrence[attID] = att_name_start;
1860                        /* The following optimized tests handle the frequently occurring
1861                        case that there are no blanks on either side of the equals sign.
1862                        In many cases, the very first test handles 100% of actual
1863                        attribute-value pairs encountered. */
1864                        if (at_EqualsQuote<C>(cur())) Advance(1); 
1865                        else {
1866                                ScanTo(NonWS);
1867                                if (!AtChar<C,'='>(cur())) {
1868                                        Syntax_Error(NT_STag); 
1869                                        break;
1870                                }
1871                                ScanTo(NonWS);
1872                                if (!AtQuote<C>(cur())) {
1873                                        Syntax_Error(NT_STag); 
1874                                        break;
1875                                }
1876                        }
1877                        att_val_start = AbsPos()+1;
1878                        Parse_AttValue();
1879                        att_val_end = AbsPos()-1;
1880                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
1881                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
1882                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
1883                        }
1884                        else {
1885                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
1886                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
1887                        }
1888                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
1889                        if (AtChar<C,'>'>(cur())) {
1890                                Advance(1);
1891                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1892                                break;
1893                        }
1894                        else if (at_EmptyElementDelim<C>(cur())) {
1895                                Advance(2);
1896                                is_emptyStartTag = true;       
1897                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1898                                break;
1899                        }
1900                        ScanTo(NonWS);
1901                        if (AtChar<C,'>'>(cur())) {
1902                                Advance(1);
1903                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1904                                break;
1905                        }
1906                        else if (at_EmptyElementDelim<C>(cur())) {
1907                                Advance(2);
1908                                is_emptyStartTag = true;
1909                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1910                                break;
1911                        }
1912                        else if (AbsPos() == att_val_end + 1) { 
1913                                /* No WS following att value */
1914                                Syntax_Error(NT_STag);
1915                                break;
1916                        }
1917                } while (1);
1918        }
1919        return nameID;
1920}
1921
1922template <CodeUnit_Base C>
1923inline int ParsingEngine<C>::Parse_ValidElement() {
1924        bool is_emptyStartTag = false;
1925        int nameID = Parse_ValidStartTag(is_emptyStartTag);
1926#ifdef DEBUG
1927        printf("Parse_ValidElement: nameID = %d, is_emptyStartTag=%i\n",nameID, is_emptyStartTag);
1928#endif
1929        ContentModel * cm = model_info->ContentModelData[nameID];
1930        switch (cm->cm_type) {
1931                case cm_Empty:
1932                        if (!is_emptyStartTag) {
1933                                if (at_EndTag_Start<C>(cur())) {
1934                                        Parse_WF_EndTag(nameID);
1935                                }
1936                                else {
1937                                        Validity_Error(vErr_elementvalid);
1938                                }
1939                        }
1940                        break;
1941                case cm_Any:           
1942                        if (!is_emptyStartTag) {
1943                                Parse_AnyContent();
1944                                Parse_WF_EndTag(nameID);
1945                        }
1946                        break;
1947                case cm_Mixed:         
1948                        if (!is_emptyStartTag) {
1949                                Parse_MixedContent(((CM_Mixed *) cm)->elements);
1950                                Parse_WF_EndTag(nameID);
1951                        }
1952                        break;
1953                case cm_RegExp:
1954                        CM_RegExp * cre = (CM_RegExp *) cm;
1955                        int content_state = 0;
1956                        if (!is_emptyStartTag) {
1957                                content_state = Parse_ValidContent(cre);
1958                                Parse_WF_EndTag(nameID);               
1959                        }
1960                        if (cre->transition_map[content_state][0]==0) {
1961                                Validity_Error(vErr_elementvalid);
1962                        }
1963        }
1964        return nameID;
1965}
1966
1967template <CodeUnit_Base C>
1968inline int ParsingEngine<C>::Parse_ValidContent(CM_RegExp * cre) {
1969        int cur_state = 0;
1970        do {
1971                ScanTo(NonWS);
1972                /* If non-null report WS  WS_action()? */
1973                text_or_markup_start = AbsPos();
1974                if (at_EndTag_Start<C>(cur())) {
1975                        break;
1976                }
1977                else if (at_ElementTag_Start<C>(cur())) {
1978                        int nameID = Parse_ValidElement();
1979#ifdef DEBUG
1980                        printf("Content model state transition %i", cur_state);
1981#endif
1982                        cur_state = cre->transition_map[cur_state][nameID];
1983#ifdef DEBUG
1984                        printf("-> %i\n", cur_state);
1985#endif
1986                }
1987                else if (at_Comment_Start<C>(cur())) {
1988                        Parse_Comment();
1989                }
1990                else if (at_PI_Start<C>(cur())) {
1991                        Parse_PI();
1992                }
1993                else if (AtChar<C,'&'>(cur())) {
1994                        Parse_EntityRef();
1995                }
1996                else if (at_EOF()) {
1997                        break;
1998                }
1999                else if (AtChar<C,'<'>(cur())) {
2000                        Syntax_Error(NT_markupdecl);
2001                }
2002                else {
2003                        Validity_Error(vErr_elementvalid);
2004                }
2005        } while(1);
2006        return cur_state;
2007}
2008
2009
2010template <CodeUnit_Base C>
2011inline void ParsingEngine<C>::Parse_AnyContent() {
2012        do {
2013                text_or_markup_start = AbsPos();
2014                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
2015                if (at_ElementTag_Start<C>(cur())) {
2016                        text_if_nonnull_action();
2017                        int nameID = Parse_ValidElement();
2018                }
2019                else if (at_EndTag_Start<C>(cur())) {
2020                        text_if_nonnull_action();
2021                        return;
2022                }
2023                else if (at_Comment_Start<C>(cur())) {
2024                        text_if_nonnull_action();
2025                        Parse_Comment();
2026                }
2027                else if (at_CharRef_Start<C>(cur())) {
2028                        text_if_nonnull_action();
2029                        Parse_CharRef();
2030                }
2031                else if (AtChar<C,'&'>(cur())) {
2032                        text_if_nonnull_action();
2033                        Parse_EntityRef();
2034                }
2035                else if (at_CDATA_Start<C>(cur())) {
2036                        text_if_nonnull_action();
2037                        Parse_CDATA();
2038                }
2039                else if (at_PI_Start<C>(cur())) {
2040                        text_if_nonnull_action();
2041                        Parse_PI();
2042                }
2043                else if (at_CDATA_End<C>(cur())) {
2044                        text_if_nonnull_action();
2045                        Advance(3);
2046                        Syntax_Error(NT_CharData);
2047                }
2048                else if (at_EOF()) {
2049                        text_if_nonnull_action();
2050                        return;
2051                }
2052                else if (AtChar<C,'<'>(cur())) {
2053                        Syntax_Error(NT_markupdecl);
2054                }
2055                else {
2056                        Advance(1);
2057                        continue;
2058                }
2059        } while (1);
2060}
2061template <CodeUnit_Base C>
2062inline void ParsingEngine<C>::Parse_MixedContent(symbol_set_t elems) {
2063        do {
2064                text_or_markup_start = AbsPos();
2065                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
2066/*              if (AtChar<C,'<'>(cur())) {
2067                        text_if_nonnull_action();
2068                        Parse_Markup<C>();
2069                }*/
2070                if (at_ElementTag_Start<C>(cur())) {
2071                        text_if_nonnull_action();
2072                        int nameID = Parse_ValidElement();
2073                        if (elems[nameID] == 0) {
2074                                Validity_Error(vErr_elementvalid);
2075                        }
2076                }
2077                else if (at_EndTag_Start<C>(cur())) {
2078                        text_if_nonnull_action();
2079                        return;
2080                }
2081                else if (at_Comment_Start<C>(cur())) {
2082                        text_if_nonnull_action();
2083                        Parse_Comment();
2084                }
2085                else if (at_CharRef_Start<C>(cur())) {
2086                        text_if_nonnull_action();
2087                        Parse_CharRef();
2088                }
2089                else if (AtChar<C,'&'>(cur())) {
2090                        text_if_nonnull_action();
2091                        Parse_EntityRef();
2092                }
2093                else if (at_CDATA_Start<C>(cur())) {
2094                        text_if_nonnull_action();
2095                        Parse_CDATA();
2096                }
2097                else if (at_PI_Start<C>(cur())) {
2098                        text_if_nonnull_action();
2099                        Parse_PI();
2100                }
2101                else if (at_CDATA_End<C>(cur())) {
2102                        text_if_nonnull_action();
2103                        Advance(3);
2104                        Syntax_Error(NT_CharData);
2105                }
2106                else if (at_EOF()) {
2107                        text_if_nonnull_action();
2108                        return;
2109                }
2110                else if (AtChar<C,'<'>(cur())) {
2111                        Syntax_Error(NT_markupdecl);
2112                }
2113                else {
2114                        Advance(1);
2115                        continue;
2116                }
2117        } while (1);
2118}
2119
2120template <CodeUnit_Base C>
2121inline int ParsingEngine<C>::Parse_Name() {
2122        int name_pos = AbsPos();
2123        ScanTo(NameFollow);
2124        int lgth = AbsPos()-name_pos;
2125        if (entity_Info->version == XML_1_1){
2126                return model_info->symbol_table->UTF8_Lookup_or_Insert_XML11_Name((char *)GetCodeUnitPtr(name_pos),lgth);
2127        }
2128        else
2129                return model_info->symbol_table->UTF8_Lookup_or_Insert_XML10_Name((char *)GetCodeUnitPtr(name_pos),lgth);
2130}
2131
2132
2133template <CodeUnit_Base C>
2134inline void ParsingEngine<C>::Parse_DocumentContent() {
2135#ifdef VALIDATION
2136        printf("Validation Mode On!\n");
2137        int final_state = Parse_ValidContent(model_info->rootModel);
2138        if (model_info->rootModel->transition_map[final_state][0]==0) {
2139                Validity_Error(vErr_elementvalid);
2140        }
2141#endif
2142#ifndef VALIDATION     
2143        Parse_WF_Element();
2144        ScanTo(NonWS);
2145        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
2146                if (at_Comment_Start<C>(cur()))
2147                        Parse_Comment();
2148                else 
2149                        Parse_PI();
2150                ScanTo(NonWS);
2151        }
2152        if (!at_EOF()) {
2153                Syntax_Error(NT_document);
2154        }       
2155#endif
2156}
2157
Note: See TracBrowser for help on using the repository browser.