source: trunk/src/engine.c @ 139

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

Storing name length in Name Table.

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