source: trunk/src/engine.c @ 155

Last change on this file since 155 was 155, checked in by cameron, 11 years ago

More performance instrumentation.

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