source: trunk/src/engine.c @ 140

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

End Tag matching with SIMD compare.

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