source: trunk/src/engine.c @ 151

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

Performance test definitions.

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