source: trunk/src/engine.c @ 133

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

PAPI instrumentation of various parabix components.

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