source: trunk/src/engine.c @ 132

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

Set text_or_markup_start for Parse_ValidContent().

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