source: trunk/src/engine.c @ 154

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

Performance test definitions.

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