source: trunk/src/engine.c @ 124

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

Name checking and other well-formedness checking.

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