source: trunk/src/engine.c @ 134

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

Simplify buffer processing by eliminated unused preserve_pos.

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