source: trunk/src/engine.c @ 135

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

SymbolTable? class and end tag checking.

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