source: trunk/src/engine.c @ 147

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