source: trunk/src/engine.c @ 100

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

Parsers for internal and external entities.

File size: 38.3 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 "errcodes.h"
14
15#include <assert.h>
16#include <stdlib.h>
17#include <errno.h>
18#include <string.h>
19#include <string>
20#include <iostream>
21using namespace std;
22       
23inline char * copy_string (unsigned char * s, int lgth){               
24        char * d = new char[lgth+1];
25        memcpy(d, (char *)s,lgth); 
26        d[lgth] = '\0'; 
27        return d;
28}
29
30Parser_Interface * Parser_Interface::ParserFactory(char * filename) {
31       
32        int chars_read;
33        unsigned char signature[4];
34        FILE * infile;
35        infile = fopen(filename, "rb");
36        if (!infile) {
37                fprintf(stderr, "Error: cannot open %s for input.\n", filename);
38                exit(-1);
39        }
40        fread(signature,1,4,infile);
41        Entity_Info * e = new Entity_Info;
42        Model_Info * m = new Model_Info;
43        e->AnalyzeSignature(signature);
44        Byteplex * b = Byteplex::ByteplexFactory(e, infile);
45        b->InitializeBuffer(signature,4);
46
47        if (e->code_unit_base == ASCII) {
48                return new ParsingEngine<ASCII>(e, m, b, false);
49        }
50        else /* if (e->code_unit_base == EBCDIC) */ {
51                return new ParsingEngine<EBCDIC>(e, m, b, false);
52        }       
53}
54
55Parser_Interface * Parser_Interface::ParserFactory(char * filename, Model_Info * m) {
56       
57        int chars_read;
58        unsigned char signature[4];
59        FILE * infile;
60        infile = fopen(filename, "rb");
61        if (!infile) {
62                fprintf(stderr, "Error: cannot open %s for input.\n", filename);
63                exit(-1);
64        }
65        fread(signature,1,4,infile);
66        Entity_Info * e = new Entity_Info;
67        e->AnalyzeSignature(signature);
68        Byteplex * b = Byteplex::ByteplexFactory(e, infile);
69        b->InitializeBuffer(signature,4);
70
71        if (e->code_unit_base == ASCII) {
72                return new ParsingEngine<ASCII>(e, m, b, true);
73        }
74        else /* if (e->code_unit_base == EBCDIC) */ {
75                return new ParsingEngine<EBCDIC>(e, m, b, true);
76        }       
77}
78
79Parser_Interface * Parser_Interface::ParserFactory(char * byte_buffer, int byte_count, Entity_Info * e, Model_Info * m){
80        Byteplex * b = Byteplex::ByteplexFactory(e, (unsigned char *) byte_buffer, byte_count);
81        if (e->code_unit_base == ASCII) {
82                return new ParsingEngine<ASCII>(e, m, b, false);
83        }
84        else {
85                return new ParsingEngine<EBCDIC>(e, m, b, false);
86        }       
87}
88
89Parser_Interface::~Parser_Interface() {
90}
91
92
93bool Parser_Interface::has_ByteOrderMark() {
94        return entity_Info->BOM_units > 0;
95}
96
97XML_version Parser_Interface::get_version() {
98        return entity_Info->version;
99}
100
101XML_standalone Parser_Interface::standalone_status() {
102        return entity_Info->standalone;
103}
104
105bool Parser_Interface::has_EncodingDecl() {
106        return entity_Info->has_encoding_decl;
107}
108
109unsigned char * Parser_Interface::get_Encoding() {
110        return entity_Info->encoding;
111}
112
113unsigned char * Parser_Interface::GetCodeUnitPtr(int pos) {
114        int rel_pos = pos - buffer_base_pos;
115        return &((unsigned char *) (byteplex->src_buffer))[rel_pos * (int) entity_Info->code_unit_size];
116}
117
118
119
120
121template <CodeUnit_Base C>
122ParsingEngine<C>::ParsingEngine(Entity_Info * e, Model_Info * m, Byteplex * b, bool is_external) : Parser_Interface () {
123        entity_Info = e;
124        model_info = m;
125        byteplex = b;
126
127        byteplex->DoByteplex();
128        byteplex->PreparePseudoASCII_Stream();
129         StrictWellFormedness=false;
130        LastAttOccurrence.assign(m->globalAttributeCount+1, 0);
131//      LastAttOccurrence.push_back(0);
132       
133        decl_parser = new XML_Decl_Parser<C>(byteplex);
134        int content_start = 0;
135        if(is_external == true)
136                content_start = decl_parser->ReadTextDeclaration(entity_Info);
137        else
138                content_start = decl_parser->ReadXMLInfo(entity_Info);
139       
140        bitplex = new Bitplex;
141        buf = (LexicalStreamSet *) simd_new(sizeof(LexicalStreamSet)/PACKSIZE);
142
143  /* Install sentinels for every lexical item stream*/
144#ifndef OPTIMIZE_SHORT_SCAN
145        BitBlock sentinel_value = simd_const_1(1);
146#endif
147#ifdef OPTIMIZE_SHORT_SCAN
148        BitBlock sentinel_value = sisd_sfli(simd_const_1(1), 8*sizeof(unsigned long));
149#endif
150        for (int j = minLexicalItem; j < LexicalItemCount; j++) {
151                buf->item_stream[j][BUFFER_BLOCKS] = sentinel_value;
152        }
153
154        buffer_base_pos = 0;
155        buffer_rel_pos = content_start;
156        buffer_limit_pos = min(BUFFER_SIZE, byteplex->units_in_buffer);
157        int blocks_in_buffer = (buffer_limit_pos + BLOCKSIZE - 1)/BLOCKSIZE;
158        x8data = byteplex->x8data;
159        lexer = Lexer<C>::LexerFactory(e, buf);
160        bitplex->TransposeToBitStreams(byteplex->x8data, blocks_in_buffer);
161        lexer->AnalyzeBuffer(bitplex->x8basis, buffer_limit_pos);
162}
163
164template <CodeUnit_Base C>
165ParsingEngine<C>::~ParsingEngine() {
166  // How do we do this?  model_info->~Model_Info();
167  entity_Info->~Entity_Info();
168  byteplex->~Byteplex();
169  decl_parser->~XML_Decl_Parser<C>();
170  bitplex->~Bitplex();
171  simd_delete((SIMD_type *) buf);
172  lexer->~Lexer_Interface();
173}
174
175template <CodeUnit_Base C>
176inline void ParsingEngine<C>::AdvanceBuffers(int preserve_pos){
177        int advance_amt = min(preserve_pos, text_or_markup_start) - buffer_base_pos;
178        advance_amt &= -PACKSIZE; // maintain alignment
179        byteplex->AdvanceInputBuffer(advance_amt);
180        buffer_base_pos += advance_amt;
181        buffer_rel_pos -= advance_amt;
182        buffer_limit_pos = min(BUFFER_SIZE, byteplex->units_in_buffer);
183        int blocks_in_buffer = (buffer_limit_pos + BLOCKSIZE - 1)/BLOCKSIZE;
184        byteplex->DoByteplex();
185        byteplex->PreparePseudoASCII_Stream();
186        bitplex->TransposeToBitStreams(byteplex->x8data, blocks_in_buffer);
187        lexer->AnalyzeBuffer(bitplex->x8basis, buffer_limit_pos);
188}
189
190template <CodeUnit_Base C>
191inline unsigned char * ParsingEngine<C>::cur() const {
192  return &((unsigned char *) x8data)[buffer_rel_pos];
193}
194
195template <CodeUnit_Base C>
196inline int ParsingEngine<C>::AbsPos() const {
197  return buffer_base_pos + buffer_rel_pos;
198}
199
200template <CodeUnit_Base C>
201inline int ParsingEngine<C>::LengthFrom(int start_pos) const {
202  return buffer_base_pos + buffer_rel_pos - start_pos;
203}
204
205
206
207template <CodeUnit_Base C>
208inline int ParsingEngine<C>::BufferRelPos() const {
209  return buffer_rel_pos;
210}
211
212
213template <CodeUnit_Base C>
214inline bool ParsingEngine<C>::at_EOF() const {
215  return (buffer_rel_pos >= buffer_limit_pos) && 
216         (buffer_limit_pos < BUFFER_SIZE);
217}
218
219template <CodeUnit_Base C>
220inline void ParsingEngine<C>::Advance(int n) {
221        int preserve_pos;
222        buffer_rel_pos += n;
223#ifndef OMIT_BITBUFFER_LIMIT_TEST_IN_ADVANCE
224  if (buffer_rel_pos >= BUFFER_SIZE) {
225        FinalizeBuffer_action(preserve_pos);
226        AdvanceBuffers(preserve_pos);
227  }
228#endif
229}
230
231
232#ifndef OPTIMIZE_SHORT_SCAN
233template <CodeUnit_Base C>
234inline void ParsingEngine<C>::ScanTo(int item) {
235        int preserve_pos;
236  buffer_rel_pos = bitstream_scan(buf->item_stream[item], 
237                                      buffer_rel_pos);
238  while (buffer_rel_pos >= BUFFER_SIZE) {
239        FinalizeBuffer_action(preserve_pos);
240        AdvanceBuffers(preserve_pos);
241        buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
242  }
243}
244#endif
245
246template <CodeUnit_Base C>
247inline void ParsingEngine<C>::ScanToMarkupStart() {
248        int preserve_pos;
249        text_or_markup_start = AbsPos();
250        buffer_rel_pos = bitstream_scan(buf->item_stream[MarkupStart], buffer_rel_pos);
251        while (buffer_rel_pos >= BUFFER_SIZE) {
252                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
253                text_or_markup_start = AbsPos();
254                FinalizeBuffer_action(preserve_pos);
255                AdvanceBuffers(preserve_pos);
256                buffer_rel_pos = bitstream_scan(buf->item_stream[MarkupStart], buffer_rel_pos);
257        }
258}
259
260template <CodeUnit_Base C>
261inline void ParsingEngine<C>::ScanToCD_End_check() {
262        int preserve_pos;
263        buffer_rel_pos = bitstream_scan(buf->item_stream[CD_End_check], buffer_rel_pos);
264        while (buffer_rel_pos >= BUFFER_SIZE) {
265                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
266                text_or_markup_start = AbsPos();
267                FinalizeBuffer_action(preserve_pos);
268                AdvanceBuffers(preserve_pos);
269                buffer_rel_pos = bitstream_scan(buf->item_stream[CD_End_check], buffer_rel_pos);
270        }
271}
272
273#ifdef OPTIMIZE_SHORT_SCAN
274template <CodeUnit_Base C>
275inline void ParsingEngine<C>::ScanTo(int item) {
276  SIMD_type * stream = buf->item_stream[item];
277  unsigned long * bitstream_ptr = (unsigned long *) (((intptr_t) stream) + buffer_rel_pos/8);
278  unsigned long bitstream_slice = *bitstream_ptr >> buffer_rel_pos % 8;
279  if (bitstream_slice != 0) {
280    buffer_rel_pos += __builtin_ctzl(bitstream_slice);
281  }
282  else {
283    buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);
284    buffer_rel_pos += bitstream_scan0((SIMD_type *) &bitstream_ptr[1]);
285    while (buffer_rel_pos >= BUFFER_BLOCKS * BLOCKSIZE) {
286      buffer_rel_pos = BUFFER_BLOCKS * BLOCKSIZE;
287      FinalizeBuffer_action(preserve_pos);
288          AdvanceBuffers(preserve_pos);
289      buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
290    }
291  }
292}
293#endif
294
295template <CodeUnit_Base C>
296inline void ParsingEngine<C>::WF_Error (XML_Error errCode) {
297        ShowConstraintError(errCode);
298        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
299}
300       
301
302template <CodeUnit_Base C>
303inline void ParsingEngine<C>::Validity_Error (XML_Error errCode) {
304        ShowConstraintError(errCode);
305        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
306}
307       
308template <CodeUnit_Base C>
309inline void ParsingEngine<C>::Syntax_Error (XML_NonTerminal errNT) {
310        ShowSyntaxError(errNT);
311        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
312}
313       
314
315/* Parse a comment beginning "<!--" */
316template <CodeUnit_Base C>
317inline void ParsingEngine<C>::Parse_Comment() {
318
319        Advance(4); /* Skip "<!--". */
320        ScanTo(Hyphen);
321        while (!at_DoubleHyphen<C>(cur())) {
322                Advance(2); /* Skip hyphen-nonhyphen pair */
323                ScanTo(Hyphen); 
324        }
325        if (at_Comment_End<C>(cur())) {
326                Advance(3); /* Skip "-->". */
327                Comment_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
328        }
329        else {
330                Advance(2);  /* "--" */
331                Syntax_Error(NT_Comment);
332        }
333}
334
335/* Parse an end tag beginning "</" */
336template <CodeUnit_Base C>
337inline void ParsingEngine<C>::Parse_EndTag() {
338        Advance(2); /* Skip "</". */
339        ScanTo(NameFollow);
340        if (AtChar<C,'>'>(cur())) {
341                Advance(1);
342                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
343        }
344        else {
345                ScanTo(NonWS);
346                if (AtChar<C,'>'>(cur())) {
347                        Advance(1);
348                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
349                }
350                else Syntax_Error(NT_ETag);
351        }
352}
353
354/* Parse a CDATA section beginning "<![CDATA". */
355template <CodeUnit_Base C>
356inline void ParsingEngine<C>::Parse_CDATA() {
357        Advance(8); /* Skip "<![CDATA". */
358        if (!AtChar<C,'['>(cur())) {
359                Syntax_Error(NT_CDStart);
360        }
361        else { 
362                Advance(1);
363                CDATA_start_action(GetCodeUnitPtr(text_or_markup_start));
364                text_or_markup_start = AbsPos();
365                ScanTo(CD_End_check);
366                while (!at_CDATA_End<C>(cur())) {
367                        Advance(1);
368                        ScanTo(CD_End_check);
369                }
370                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
371                Advance(3); /* Skip "]]>". */
372                CDATA_end_action(GetCodeUnitPtr(AbsPos()));
373        }
374}
375
376template <CodeUnit_Base C>
377inline void ParsingEngine<C>::Parse_EntityRef() {
378    Advance(1);  // skip "&"
379    int ref_start = AbsPos();
380        ScanTo(NameFollow);  /* Name delimiter */
381    if (!AtChar<C,';'>(cur())) {
382                Syntax_Error(NT_Reference);
383    }
384        else {
385                int lgth = AbsPos()-ref_start;
386                char * s = new char[lgth+1];
387                memcpy(s, GetCodeUnitPtr(ref_start),lgth); 
388                s[lgth] = '\0';
389               
390                Advance(1);
391                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
392               
393                //      The following code will replace Reference_Action.
394                GEntity_info * this_info;
395                Parser_Interface * entity_parser;
396                int entityID = model_info->GlobalGEntityTable[s]; 
397                if (entityID == 0)
398                        WF_Error(wfErr_wf_entdeclared);
399                else{
400                        this_info = model_info->GEntityData[entityID-1];
401                        if (this_info->is_external){
402                                entity_parser = ParserFactory(this_info->systemLiteral, model_info);
403                                entity_parser->ParseContent();
404                                entity_parser->~Parser_Interface();
405                        }
406                        else {
407                                if (this_info->is_simple == true)
408                                        printf("Entity is %s\n",this_info->ReplacementText);
409                                else{
410                                        printf("Not a simple text: %s\n",this_info->ReplacementText);
411                                        entity_parser = ParserFactory(this_info->ReplacementText, strlen(this_info->ReplacementText),entity_Info, model_info);
412                                        entity_parser->ParseContent();
413                                        entity_parser->~Parser_Interface();
414                                }
415                        }
416                }
417               
418        }
419}
420
421template <CodeUnit_Base C>
422inline void ParsingEngine<C>::Parse_CharRef() {
423        Advance(2);  // skip "&#"
424        ScanTo(NameFollow);  /* Name delimiter */
425        if (!AtChar<C,';'>(cur())) {
426                Syntax_Error(NT_Reference);
427        }
428        else {
429                Advance(1);
430                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
431        }
432}
433
434template <CodeUnit_Base C>
435inline void ParsingEngine<C>::Parse_PI (){
436        Advance(2); /* Skip "<?". */
437        int target_start = AbsPos();
438        // Check for illegal [Xx][Mm][Ll] target.
439        if (at_XxMmLll_WS<C>(cur())) {
440                Advance(4);
441                Syntax_Error(NT_PI);
442                return;
443        } 
444        ScanTo(NameFollow);  /* Name delimiter */
445        PI_Target_action(GetCodeUnitPtr(target_start), LengthFrom(target_start));
446        ScanTo(QMark);
447        while (!at_PI_End<C>(cur())) {
448                Advance(1);
449                ScanTo(QMark);
450        }
451        Advance(2); /* Skip "?>". */
452        PI_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
453}
454 
455/* Parse a start or empty element tag. */
456template <CodeUnit_Base C>
457inline void ParsingEngine<C>::Parse_StartTag (){
458        int att_name_start;
459        int att_val_start;
460        int att_name_end, att_val_end;
461        unsigned char quoteCh;
462        Advance(1);
463        ScanTo(NameFollow);  /* Name delimiter: WS, "/" or ">" */
464        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
465        /* The following test optimizes the most common case of a
466        start tag with no attributes.  */
467        if (AtChar<C,'>'>(cur())) {
468                Advance(1);
469                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
470        }
471        else {
472                ScanTo(NonWS);
473                if (AtChar<C,'>'>(cur())) {
474                        Advance(1);
475                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
476                }
477                else if (at_EmptyElementDelim<C>(cur())) {
478                        Advance(2);
479                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
480                }
481                else do {
482                        /* Must be an attribute-value pair or error. */
483                        att_name_start = AbsPos();
484                        ScanTo(NameFollow);
485                        att_name_end = AbsPos();
486                        int lgth = att_name_end-att_name_start;
487               
488                        int attID = model_info->getOrInsertGlobalAttName(GetCodeUnitPtr(att_name_start), lgth);
489                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
490                        else {
491                                if (LastAttOccurrence[attID] > text_or_markup_start) {
492                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
493                                        break;
494                                }                       
495                        }
496                        LastAttOccurrence[attID] = att_name_start;
497                        /* The following optimized tests handle the frequently occurring
498                        case that there are no blanks on either side of the equals sign.
499                        In many cases, the very first test handles 100% of actual
500                        attribute-value pairs encountered. */
501                        if (at_EqualsQuote<C>(cur())) Advance(1); 
502                        else {
503                                ScanTo(NonWS);
504                                if (!AtChar<C,'='>(cur())) {
505                                        Syntax_Error(NT_STag); 
506                                        break;
507                                }
508                                ScanTo(NonWS);
509                                if (!AtQuote<C>(cur())) {
510                                        Syntax_Error(NT_STag); 
511                                        break;
512                                }
513                        }
514                        att_val_start = AbsPos()+1;
515                        Parse_AttValue();
516                        att_val_end = AbsPos()-1;
517                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
518                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
519                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
520                        }
521                        else {
522                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
523                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
524                        }
525                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
526                        if (AtChar<C,'>'>(cur())) {
527                                Advance(1);
528                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
529                                break;
530                        }
531                        else if (at_EmptyElementDelim<C>(cur())) {
532                                Advance(2);
533                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
534                                break;
535                        }
536                        ScanTo(NonWS);
537                        if (AtChar<C,'>'>(cur())) {
538                                Advance(1);
539                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
540                                break;
541                        }
542                        else if (at_EmptyElementDelim<C>(cur())) {
543                                Advance(2);
544                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
545                                break;
546                        }
547                        else if (AbsPos() == att_val_end + 1) { 
548                                /* No WS following att value */
549                                Syntax_Error(NT_STag);
550                                break;
551                        }
552                } while (1);
553        }
554}
555
556template <CodeUnit_Base C>
557inline void ParsingEngine<C>::text_if_nonnull_action(){
558        if (AbsPos() > text_or_markup_start) {
559                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
560                text_or_markup_start = AbsPos();
561        }
562}
563
564template <CodeUnit_Base C>
565inline void ParsingEngine<C>::ParseContent() {
566        DocumentStart_action(); 
567        do {
568                text_or_markup_start = AbsPos();
569                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
570/*              if (AtChar<C,'<'>(cur())) {
571                        text_if_nonnull_action();
572                        Parse_Markup<C>();
573                }*/
574                if (at_ElementTag_Start<C>(cur())) {
575                        text_if_nonnull_action();
576                        Parse_StartTag();
577                }
578                else if (at_EndTag_Start<C>(cur())) {
579                        text_if_nonnull_action();
580                        Parse_EndTag();
581                }
582                else if (at_Comment_Start<C>(cur())) {
583                        text_if_nonnull_action();
584                        Parse_Comment();
585                }
586                else if (at_CharRef_Start<C>(cur())) {
587                        text_if_nonnull_action();
588                        Parse_CharRef();
589                }
590                else if (AtChar<C,'&'>(cur())) {
591                        text_if_nonnull_action();
592                        Parse_EntityRef();
593                }
594                else if (at_CDATA_Start<C>(cur())) {
595                        text_if_nonnull_action();
596                        Parse_CDATA();
597                }
598                else if (at_PI_Start<C>(cur())) {
599                        text_if_nonnull_action();
600                        Parse_PI();
601                }
602                else if (at_CDATA_End<C>(cur())) {
603                        text_if_nonnull_action();
604                        Advance(3);
605                        Syntax_Error(NT_CharData);
606                }
607                else if (at_EOF()) {
608                        text_if_nonnull_action();
609                        break;
610                }
611                else {
612                        Advance(1);
613                        continue;
614                }
615        } while (1);
616        DocumentEnd_action();   
617}
618
619
620template <CodeUnit_Base C>
621inline void ParsingEngine<C>::Parse_DocType (){
622
623        int old_abspos, start_pos;
624        ScanTo(NonWS);
625        start_pos = AbsPos();
626       
627        if (at_DOCTYPE_start<C>(cur()))
628        Advance(9);
629        else{
630//              printf("No Document definition!\n");
631                return;
632        }
633        requireWS();
634       
635        ScanTo(NameFollow);
636       
637        old_abspos = AbsPos(); 
638    ScanTo(NonWS);
639    if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
640        if(old_abspos == AbsPos())
641                Syntax_Error(NT_doctypedecl);
642        Parse_ExternalID();
643    }
644   
645    ScanTo(NonWS);     
646
647        if (AtChar<C,'['>(cur())){
648                Advance(1);
649                Parse_IntSubset();
650                if (AtChar<C,']'>(cur()))
651                        Advance(1);
652                else
653                Syntax_Error(NT_doctypedecl);
654                ScanTo(NonWS);
655        }
656       
657        if (AtChar<C,'>'>(cur())){
658                Advance(1);   
659                Doctype_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
660        }
661}
662
663template <CodeUnit_Base C>
664inline void ParsingEngine<C>::Parse_ExternalID (){
665
666        if(at_SYSTEM<C>(cur())){
667                Advance(6);
668                requireWS();
669                Parse_MatchedQuote (); /*  SystemLiteral */
670        }
671        else if (at_PUBLIC<C>(cur())){
672                Advance(6);
673                requireWS();
674                Parse_MatchedQuote ();/*  PubidLiteral */
675                requireWS();
676                Parse_MatchedQuote ();/*  SystemLiteral */
677        }
678        else
679                Syntax_Error(NT_ExternalID); 
680}
681
682template <CodeUnit_Base C>
683inline void ParsingEngine<C>::Parse_MatchedQuote (){
684        unsigned char quoteCh;
685        if(AtQuote<C>(cur())){
686                quoteCh = cur()[0];
687                Advance(1);
688        }
689        ScanTo(Quote);                 
690        while (cur()[0] != quoteCh){
691                Advance(1);
692                ScanTo(Quote);
693        }
694        Advance(1);
695}
696
697template <CodeUnit_Base C>
698inline void ParsingEngine<C>::Parse_IntSubset (){
699       
700        while(1){
701                ScanTo(NonWS); 
702                text_or_markup_start = AbsPos();
703                if (AtChar<C,'%'>(cur()))
704                        Parse_PEReference();   
705                else if (AtChar<C,'<'>(cur())){
706                        Advance(1);
707
708                        if (AtChar<C,'?'>(cur())){
709                                Parse_PI();
710                        }
711                        else if(AtChar<C,'!'>(cur())){
712                                Advance(1);
713                                if(at_DoubleHyphen<C>(cur()))
714                                        Parse_Comment();
715                                else if(at_ELEMENT<C>(cur()))
716                                        Parse_Elementdecl();
717                                else if(at_ATTLIST<C>(cur()))
718                                        Parse_AttlistDecl();
719                                else if(at_ENTITY<C>(cur()))
720                                        Parse_Entitydecl();
721                                else if(at_NOTATION<C>(cur()))
722                                        Parse_Notationdecl();
723                                else{
724                                        Syntax_Error(NT_markupdecl);           
725                                }                                                               
726                        }
727                        else
728                                Syntax_Error(NT_markupdecl); 
729                }
730                else if (AtChar<C,']'>(cur())){
731                        break;
732                }
733                else
734                        Syntax_Error(NT_intSubset); 
735        }
736}
737
738
739template <CodeUnit_Base C>
740inline void ParsingEngine<C>::Parse_PEReference (){
741
742        Advance(1); /* Skip "%". */
743        ScanTo(NameFollow); 
744        if (AtChar<C,';'>(cur())) {
745                Advance(1);
746                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
747        }
748        else
749                Syntax_Error(NT_PEReference);
750}
751
752
753template <CodeUnit_Base C>
754inline void ParsingEngine<C>::Parse_Elementdecl (){
755
756        Advance(7); /* Skip "<!ELEMENT". */
757
758    requireWS();
759    int name_start = AbsPos();
760        ScanTo(NameFollow);
761        int lgth = AbsPos() - name_start;
762        int elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
763        requireWS();
764       
765        /* Start parsing "contentspec"*/
766        if (at_EMPTY<C>(cur()))
767        Advance(5);
768    else if (at_ANY<C>(cur()))
769        Advance(3);
770    else {
771        if (AtChar<C,'('>(cur()))
772                        Advance(1);
773                ScanTo(NonWS);
774                if (at_PCDATA<C>(cur()))
775                        Parse_RemainingMixed();
776                else
777                        Parse_RemainingChildren();
778    }
779               
780        if (AtChar<C,'>'>(cur())) {
781                Advance(1);
782                Elementdecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
783        }
784        else
785                Syntax_Error(NT_elementdecl);
786}
787template <CodeUnit_Base C>
788inline void ParsingEngine<C>::Parse_RemainingMixed (){
789       
790        Advance(7);  /* Skip "#PCDATA". */
791   
792    if (AtChar<C,')'>(cur())){
793        if (AtChar<C,'*'>(cur()))
794                Advance(2);
795                else
796                        Advance(1);
797    }
798    else{
799        ScanTo(NonWS);
800        while(!at_Para_star<C>(cur())){
801                if (AtChar<C,'|'>(cur())){
802                                Advance(1);
803                                ScanTo(NonWS);
804                                ScanTo(NameFollow);
805                                ScanTo(NonWS);
806                }
807        }
808        Advance(2);
809    }
810}
811
812
813template <CodeUnit_Base C>
814inline void ParsingEngine<C>::Parse_RemainingChildren (){
815        Parse_Cp();
816        ScanTo(NonWS);
817        if(AtChar<C,'|'>(cur())){
818                Advance(1);
819                ScanTo(NonWS);
820                Parse_Cp();
821                ScanTo(NonWS);
822                while(!AtChar<C,')'>(cur())){
823                        if(AtChar<C,'|'>(cur()))
824                                Advance(1);
825                        ScanTo(NonWS);
826                        Parse_Cp();
827                        ScanTo(NonWS);
828                }
829                Advance(1);
830        }
831        else if(AtChar<C,','>(cur())){
832                Advance(1);
833                ScanTo(NonWS);
834                Parse_Cp();
835                ScanTo(NonWS);
836                while(!AtChar<C,')'>(cur())){
837                        if(AtChar<C,','>(cur()))
838                                Advance(1);
839                        ScanTo(NonWS);
840                        Parse_Cp();
841                        ScanTo(NonWS);
842                }
843                Advance(1);
844        }       
845        else if(AtChar<C,')'>(cur())){
846                Advance(1);
847        }
848        else
849                Syntax_Error(NT_children);
850               
851        if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
852                Advance(1);
853}
854
855template <CodeUnit_Base C>
856inline void ParsingEngine<C>::Parse_Cp (){
857        if (AtChar<C,'('>(cur())){
858                Advance(1);
859                ScanTo(NonWS);
860                Parse_RemainingChildren();
861        }
862        else{
863                ScanTo(NameFollow);
864                if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
865                        Advance(1);
866        }
867}
868
869template <CodeUnit_Base C>
870inline void ParsingEngine<C>::Parse_AttlistDecl (){
871       
872        int old_abspos;
873       
874        int name_start;
875        int lgth;
876       
877        int elemID;
878        int attID;
879       
880        Advance(7); /* Skip "ATTLIST. */
881        requireWS();
882       
883        name_start = AbsPos();
884        ScanTo(NameFollow);
885        lgth = AbsPos()-name_start;
886        elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
887       
888        old_abspos = AbsPos();
889        ScanTo(NonWS);
890        while(!AtChar<C,'>'>(cur())) {
891                if(old_abspos == AbsPos())
892                Syntax_Error(NT_AttlistDecl);
893               
894        name_start = AbsPos();
895                ScanTo(NameFollow);
896                lgth = AbsPos()-name_start;
897               
898                attID = model_info->getOrInsertGlobalAttName(GetCodeUnitPtr(name_start), lgth);
899                if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
900        ATT_info * this_info = new ATT_info;
901        this_info->globalATT_id = attID;
902        requireWS();
903        if (at_CDATA<C>(cur())){
904                Advance(5);
905                this_info->attType = CDATA_att;
906        }
907        else if(at_ID<C>(cur())){
908                Advance(2);
909                this_info->attType = ID_att;
910        }
911        /* Make sure to check IDREFS before IDREF*/
912        else if(at_IDREFS<C>(cur())){
913                Advance(6);
914                this_info->attType = IDREFS_att;
915        }
916        else if(at_IDREF<C>(cur())){
917                Advance(5);
918                this_info->attType = IDREF_att;
919        }
920        else if(at_ENTITY<C>(cur())){
921                Advance(6);
922                this_info->attType = ENTITY_att;
923        }
924        else if(at_ENTITIES<C>(cur())){
925                Advance(8);
926                this_info->attType = ENTITIES_att;
927        }
928        /* Make sure to check NMTOKENS before NMTOKEN*/
929        else if(at_NMTOKENS<C>(cur())){
930                Advance(8);
931                this_info->attType = NMTOKENS_att;
932        }
933        else if(at_NMTOKEN<C>(cur())){
934                Advance(7);
935                this_info->attType = NMTOKEN_att;
936        }
937        else if(at_NOTATION<C>(cur())){ /* NotationType = 'NOTATION' S Enumeration
938                                                                         when Nmtoken = Name */
939                Advance(8);
940                        requireWS();
941                Parse_Notation(this_info);
942                this_info->attType = NOTATION_att;
943        }
944        else if(AtChar<C,'('>(cur())){
945                Parse_Enumeration(this_info);
946                this_info->attType = enumeration_att;
947        }
948        else
949                Syntax_Error(NT_AttlistDecl);
950        requireWS();
951        Parse_DefaultDecl(this_info);
952
953                ScanTo(NonWS);
954                model_info->ElementAttributeData[elemID].push_back(this_info);
955        }
956
957        Advance(1);
958        AttlistDecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
959}
960
961template <CodeUnit_Base C>
962inline void ParsingEngine<C>::Parse_Notation (ATT_info * this_info){
963
964        if(AtChar<C,'('>(cur()))
965                Advance(1);
966        else
967                Syntax_Error(NT_NotationType);
968        ScanTo(NonWS);
969       
970    int name_start = AbsPos();
971        ScanTo(NameFollow);
972        int     lgth = AbsPos()-name_start;
973       
974        char *s = new char[lgth+1];
975        memcpy(s, GetCodeUnitPtr(name_start), lgth);
976        s[lgth] = '\0';
977
978        /*Notation name is not in the global table!*/
979        if(model_info->GlobalNotationTable[s]==0)
980                Validity_Error(vErr_notatn);
981       
982        ScanTo(NonWS);
983        while(AtChar<C,'|'>(cur())){
984                Advance(1);
985                ScanTo(NonWS);         
986                name_start = AbsPos();
987                ScanTo(NameFollow);
988                lgth = AbsPos()-name_start;
989       
990                char *s = new char[lgth+1];
991                memcpy(s, GetCodeUnitPtr(name_start), lgth);
992                s[lgth] = '\0';
993       
994                if(model_info->GlobalNotationTable[s]==0)
995                        Validity_Error(vErr_notatn);
996                       
997                ScanTo(NonWS);
998        }
999        if (AtChar<C,')'>(cur())) 
1000                Advance(1);
1001        else
1002                Syntax_Error(NT_NotationType);
1003}
1004
1005template <CodeUnit_Base C>
1006inline void ParsingEngine<C>::Parse_Enumeration (ATT_info * this_info){
1007
1008        int enumCount=0;
1009        if(AtChar<C,'('>(cur()))
1010                Advance(1);
1011        else
1012                Syntax_Error(NT_Enumeration);
1013        ScanTo(NonWS);
1014       
1015        int     name_start = AbsPos();
1016        ScanTo(NameFollow);
1017        int     lgth = AbsPos()-name_start;
1018       
1019        char *s = new char[lgth+1];
1020        memcpy(s, GetCodeUnitPtr(name_start), lgth);
1021        s[lgth] = '\0';
1022       
1023        this_info->enumValues[s]=++(enumCount);
1024       
1025        ScanTo(NonWS);
1026        while(AtChar<C,'|'>(cur())){
1027                Advance(1);
1028                ScanTo(NonWS);         
1029                name_start = AbsPos();
1030                ScanTo(NameFollow);
1031                lgth = AbsPos()-name_start;
1032       
1033                char *s = new char[lgth+1];
1034                memcpy(s, GetCodeUnitPtr(name_start), lgth);
1035                s[lgth] = '\0';
1036       
1037                int enumID = this_info->enumValues[s];
1038                if(enumID==0){ 
1039                        this_info->enumValues[s]=++(enumCount);
1040                        enumID = enumCount;
1041                }
1042                else if(!StrictWellFormedness){
1043                        Validity_Error(vErr_NoDuplicateTokens);
1044                }
1045                ScanTo(NonWS);
1046        }
1047        if (AtChar<C,')'>(cur())) 
1048                Advance(1);
1049        else
1050                Syntax_Error(NT_Enumeration);
1051}
1052
1053template <CodeUnit_Base C>
1054inline void ParsingEngine<C>::Parse_DefaultDecl (ATT_info * this_info){
1055        if(at_REQUIRED<C>(cur())){
1056                Advance(9);
1057                this_info->defaultKind = REQUIRED_att;
1058        }
1059        else if(at_IMPLIED<C>(cur())){
1060                Advance(8);
1061                this_info->defaultKind = IMPLIED_att;
1062        }
1063        else {
1064                if(at_FIXED<C>(cur())){
1065                        Advance(6);
1066                        requireWS();
1067                        this_info->defaultKind = FIXED_att;
1068                }
1069                else this_info->defaultKind = DEFAULT_att;
1070                if(AtQuote<C>(cur())){
1071                        int quot_start = AbsPos()+1;
1072                        Parse_AttValue();
1073                        /* need to normalize */
1074                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
1075                       
1076                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
1077                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
1078                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
1079                        }
1080                else
1081                        Syntax_Error(NT_DefaultDecl);
1082        }
1083}
1084
1085template <CodeUnit_Base C>
1086inline void ParsingEngine<C>::Parse_Entitydecl (){
1087       
1088        int name_start;
1089        int quot_start;
1090        int lgth;
1091        int old_abspos;
1092        char * s;
1093       
1094        Advance(6); /* Skip "ENTITY. */
1095        requireWS();
1096       
1097        if (AtChar<C,'%'>(cur())){
1098                Advance(1);
1099                requireWS();
1100               
1101                name_start = AbsPos();
1102                ScanTo(NameFollow);
1103                lgth = AbsPos()- name_start;
1104                s = new char[lgth+1];
1105                memcpy(s, GetCodeUnitPtr(name_start),lgth); 
1106                s[lgth] = '\0';
1107       
1108                PEntity_info * this_info = new PEntity_info;
1109                int entityID = model_info->GlobalPEntityTable[s];
1110                if(entityID==0){       
1111                        model_info->GlobalPEntityTable[s]=++(model_info->globalPEntityCount);
1112                        entityID = model_info->globalPEntityCount;
1113                        this_info->globalPEntity_id = entityID;
1114                }
1115                else
1116                        printf("Warning: Entity definition already exist!\n");
1117       
1118                requireWS();
1119                if(at_SYSTEM<C>(cur())){
1120                        Advance(6);
1121                        requireWS();
1122                        quot_start = AbsPos()+1;
1123                        Parse_MatchedQuote (); /*  SystemLiteral */
1124                        lgth = AbsPos() - quot_start - 1;                       
1125                        this_info->systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1126                        this_info->is_external = true;
1127                }
1128                else if (at_PUBLIC<C>(cur())){
1129                        Advance(6);
1130                        requireWS();
1131                       
1132                        quot_start = AbsPos()+1;
1133                        Parse_MatchedQuote ();/*  PubidLiteral */               
1134                        lgth = AbsPos() - quot_start - 1;                       
1135                        this_info->pubidLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1136                        this_info->is_external = true; 
1137                       
1138                        requireWS();
1139                       
1140                        quot_start = AbsPos()+1;
1141                        Parse_MatchedQuote (); /*  SystemLiteral */
1142                        lgth = AbsPos() - quot_start - 1;                       
1143                        this_info->systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1144                        this_info->is_external = true;
1145                }
1146        else if(AtQuote<C>(cur())){
1147                Parse_PEntityValue(this_info);
1148                this_info->is_external = false;
1149        }
1150        else
1151                Syntax_Error(NT_EntityDecl);
1152        model_info->PEntityData.push_back(this_info);
1153        }
1154        else{
1155                name_start = AbsPos();
1156                ScanTo(NameFollow);
1157                lgth = AbsPos()- name_start;
1158                s = new char[lgth+1];
1159                memcpy(s, GetCodeUnitPtr(name_start),lgth); 
1160                s[lgth] = '\0';
1161       
1162                GEntity_info * this_info = new GEntity_info;
1163                int entityID = model_info->GlobalGEntityTable[s];
1164                if(entityID==0){       
1165                        model_info->GlobalGEntityTable[s]=++(model_info->globalGEntityCount);
1166                        entityID = model_info->globalGEntityCount;
1167                        this_info->globalGEntity_id = entityID;
1168                }
1169                else
1170                        printf("Warning: Entity definition already exist!\n");
1171                       
1172                requireWS();
1173               
1174                if(at_SYSTEM<C>(cur())){
1175                        Advance(6);
1176                        requireWS();
1177                        quot_start = AbsPos()+1;
1178                        Parse_MatchedQuote (); /*  SystemLiteral */
1179                        lgth = AbsPos() - quot_start - 1;                       
1180                        this_info->systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1181                        this_info->is_external = true;
1182                       
1183                        old_abspos = AbsPos();
1184                        ScanTo(NonWS);
1185                if(at_NDATA<C>(cur())){
1186                        if(old_abspos == AbsPos())
1187                                Syntax_Error(NT_EntityDecl);
1188                        else
1189                                Advance(5);
1190                        requireWS();
1191                        name_start = AbsPos();
1192                        ScanTo(NameFollow);
1193                        lgth = AbsPos() - name_start;
1194                                this_info->NDataName = copy_string(GetCodeUnitPtr(name_start),lgth);
1195                }
1196                }
1197                else if (at_PUBLIC<C>(cur())){
1198                        Advance(6);
1199                        requireWS();
1200                       
1201                        quot_start = AbsPos()+1;
1202                        Parse_MatchedQuote ();/*  PubidLiteral */               
1203                        lgth = AbsPos() - quot_start - 1;                       
1204                        this_info->pubidLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1205                        this_info->is_external = true; 
1206                       
1207                        requireWS();
1208                       
1209                        quot_start = AbsPos()+1;
1210                        Parse_MatchedQuote (); /*  SystemLiteral */
1211                        lgth = AbsPos() - quot_start - 1;                       
1212                        this_info->systemLiteral = copy_string(GetCodeUnitPtr(quot_start),lgth);
1213                        this_info->is_external = true;
1214                       
1215                        old_abspos = AbsPos();
1216                        ScanTo(NonWS);
1217                if(at_NDATA<C>(cur())){
1218                        if(old_abspos == AbsPos())
1219                                Syntax_Error(NT_EntityDecl);
1220                        else
1221                                Advance(5);
1222                        requireWS();
1223                        name_start = AbsPos();
1224                        ScanTo(NameFollow);
1225                        lgth = AbsPos() - name_start;
1226                        this_info->NDataName = copy_string(GetCodeUnitPtr(name_start),lgth);
1227                }
1228                }
1229                else if(AtQuote<C>(cur())){
1230                Parse_GEntityValue(this_info);
1231                this_info->is_external = false;
1232        }
1233        else
1234                Syntax_Error(NT_EntityDecl);
1235        model_info->GEntityData.push_back(this_info);
1236        }
1237        ScanTo(NonWS);
1238        if (AtChar<C,'>'>(cur())){
1239                Advance(1);
1240                Entitydecl_action(GetCodeUnitPtr(name_start), lgth, 
1241                                  GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1242        }
1243        else
1244                Syntax_Error(NT_EntityDecl);
1245}
1246       
1247template <CodeUnit_Base C>
1248inline void ParsingEngine<C>::Parse_Notationdecl (){
1249
1250        int old_abspos;
1251        Advance(8); /* Skip "NOTATION. */
1252        requireWS();
1253       
1254        int name_start = AbsPos();
1255        ScanTo(NameFollow);
1256        int     lgth = AbsPos()-name_start;
1257       
1258        char *s = new char[lgth+1];
1259        memcpy(s, GetCodeUnitPtr(name_start), lgth);
1260        s[lgth] = '\0';
1261
1262        int notationID = model_info->GlobalNotationTable[s];
1263        if(notationID==0){     
1264                model_info->GlobalNotationTable[s]=++(model_info->globalNotationCount);
1265                notationID = model_info->globalNotationCount;
1266        }
1267        else /*Duplicate notation name!*/
1268                Validity_Error(vErr_NoDuplicateTokens);
1269               
1270        requireWS();
1271        if(at_SYSTEM<C>(cur())){
1272                Advance(6);
1273                requireWS();
1274                Parse_MatchedQuote (); /*  SystemLiteral */
1275        }
1276        else if (at_PUBLIC<C>(cur())){
1277                Advance(6);
1278                requireWS();
1279                Parse_MatchedQuote (); /*  PubidLiteral */
1280                ScanTo(NonWS);
1281                if (!AtChar<C,'>'>(cur())){
1282                        if (old_abspos == AbsPos())
1283                                Syntax_Error(NT_NotationDecl);
1284                        Parse_MatchedQuote (); /*  SystemLiteral */
1285                }
1286        }
1287        else
1288                Syntax_Error(NT_NotationDecl);
1289        ScanTo(NonWS);
1290        if (AtChar<C,'>'>(cur())) {
1291                Advance(1);
1292                Notationdecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1293        }
1294        else
1295                Syntax_Error(NT_NotationDecl);
1296}
1297
1298template <CodeUnit_Base C>
1299inline void ParsingEngine<C>::requireWS(){
1300       
1301    int old_abspos = AbsPos(); 
1302    ScanTo(NonWS);
1303    if(old_abspos == AbsPos())
1304        Syntax_Error(NT_S);
1305}
1306
1307template <CodeUnit_Base C>
1308inline void ParsingEngine<C>::Parse_AttValue(){
1309       
1310        int     quoteCh = cur()[0];
1311        Advance(1); /* Skip " or ' */
1312
1313        ScanTo(Quote);                 
1314        while (cur()[0] != quoteCh){
1315                if (at_CharRef_Start<C>(cur())){
1316                        Parse_CharRef();
1317                        ScanTo(Quote);
1318                }
1319                else if (AtChar<C,'&'>(cur())){
1320                        Parse_EntityRef();
1321                        ScanTo(Quote);
1322                }
1323                else if (AtQuote<C>(cur())) {
1324                        Advance(1);
1325                        ScanTo(Quote);
1326                }
1327                else /* if (AtChar<C,'<'>(cur())) */
1328                        WF_Error(wfErr_CleanAttrVals);
1329        }
1330        Advance(1);
1331}
1332
1333template <CodeUnit_Base C>
1334inline void ParsingEngine<C>::Parse_GEntityValue(GEntity_info * this_info){
1335       
1336        int     quoteCh = cur()[0];
1337        Advance(1); /* Skip " or ' */
1338        this_info->is_simple = true;
1339        int quot_start = AbsPos();
1340        ScanTo(Quote);         
1341        char *  replText = copy_string(GetCodeUnitPtr(quot_start),AbsPos()-quot_start);
1342
1343        while (cur()[0] != quoteCh){
1344                if (at_CharRef_Start<C>(cur())){
1345                        strcat (replText,Replace_CharRef());
1346                        quot_start = AbsPos();
1347                        ScanTo(Quote);
1348                }
1349                else if (AtChar<C,'&'>(cur())){
1350                        strcat (replText,Replace_EntityRef(this_info->is_simple));
1351                        quot_start = AbsPos();
1352                        ScanTo(Quote);
1353                }
1354                else if (AtQuote<C>(cur())) {
1355                        quot_start = AbsPos();
1356                        Advance(1);
1357                        ScanTo(Quote);
1358
1359                }
1360                else { /* '<' found */
1361                        quot_start = AbsPos();
1362                        Advance(1);
1363                        ScanTo(Quote);
1364                        this_info->is_simple = false;
1365                }
1366                strcat (replText,copy_string(GetCodeUnitPtr(quot_start),AbsPos()-quot_start));                 
1367        }
1368        this_info->ReplacementText = replText;
1369        Advance(1);
1370}
1371
1372template <CodeUnit_Base C>
1373inline char * ParsingEngine<C>::Replace_EntityRef(bool& is_simple){
1374        Advance(1);
1375        int entity_start = AbsPos();
1376        ScanTo(NameFollow); 
1377        char * s = copy_string(GetCodeUnitPtr(entity_start),AbsPos()-entity_start);
1378        if (AtChar<C,';'>(cur()))
1379                Advance(1);
1380        else
1381                Syntax_Error(NT_EntityValue);
1382        int entityID = model_info->GlobalGEntityTable[s]; 
1383        if (entityID == 0)
1384                WF_Error(wfErr_wf_entdeclared);
1385        else{
1386                if (model_info->GEntityData[entityID-1]->is_simple == false)
1387                        is_simple = false;
1388                return model_info->GEntityData[entityID-1]->ReplacementText;
1389        }
1390       
1391}
1392
1393template <CodeUnit_Base C>
1394inline void ParsingEngine<C>::Parse_PEntityValue(PEntity_info * this_info){
1395}
1396
1397template <CodeUnit_Base C>
1398inline char * ParsingEngine<C>::Replace_CharRef(){
1399        Advance(1);
1400        int entity_start = AbsPos();
1401        ScanTo(NameFollow); 
1402        char * s = copy_string(GetCodeUnitPtr(entity_start),AbsPos()-entity_start);
1403        int entityID = model_info->GlobalGEntityTable[s]; 
1404        if (entityID == 0)
1405                WF_Error(wfErr_wf_entdeclared);
1406        else
1407                return model_info->GEntityData[entityID-1]->ReplacementText;
1408       
1409       
1410}
1411
1412template <CodeUnit_Base C>
1413inline void ParsingEngine<C>::Parse_Prolog(){
1414        ScanTo(NonWS);
1415        int old_pos = AbsPos();
1416        while (!at_DOCTYPE_start<C>(cur())) {
1417                if (at_Comment_Start<C>(cur())) 
1418                        Parse_Comment();
1419                else if (at_PI_Start<C>(cur()))
1420                                Parse_PI();
1421                else{
1422                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1423                        return;
1424                }
1425                ScanTo(NonWS);
1426        }
1427        Parse_DocType();
1428        ScanTo(NonWS);
1429        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
1430                if (at_Comment_Start<C>(cur()))
1431                        Parse_Comment();
1432                else 
1433                        Parse_PI();
1434                ScanTo(NonWS);
1435        }
1436        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1437}
1438
1439template <CodeUnit_Base C>
1440inline void ParsingEngine<C>::Parse_ExtSubsetDecl() {
1441        int start_pos=AbsPos();
1442        while(!at_EOF()){
1443                if(at_condSect_start<C>(cur())){               
1444                        Advance(3);
1445                        ScanTo(NonWS);
1446                        if (at_INCLUDE<C>(cur())){
1447                                Advance(7);
1448                                ScanTo(NonWS);
1449                                if(AtChar<C,'['>(cur())){
1450                                        Advance(1);
1451                                        Parse_ExtSubsetDecl();
1452                                        if(at_CDATA_End<C>(cur()))
1453                                                Advance(3);
1454                                        else Syntax_Error(NT_includeSect);
1455                                }
1456                                else Syntax_Error(NT_includeSect);
1457                        }
1458                        else if (at_IGNORE<C>(cur())){
1459                                Advance(6);
1460                                ScanTo(NonWS);         
1461                                if(AtChar<C,'['>(cur())){
1462                                        int section_depth=1;
1463                                        Advance(1);
1464                                        while(!at_EOF()){
1465                                                ScanToMarkupStart();
1466                                                if(at_condSect_start<C>(cur())){
1467                                                        Advance(3);
1468                                                        section_depth++;
1469                                                }
1470                                                else if(at_CDATA_End<C>(cur())){
1471                                                        Advance(3);
1472                                                        section_depth--;
1473                                                }
1474                                                if(section_depth==0) return;                                   
1475                                        }
1476                                        Syntax_Error(NT_ignoreSectContents);   
1477                                }
1478                                else Syntax_Error(NT_ignoreSect);
1479                        }
1480                        else Syntax_Error(NT_conditionalSect);
1481                }
1482                else if (AtChar<C,'%'>(cur()))
1483                        Parse_PEReference();   
1484                else if (AtChar<C,'<'>(cur())){
1485                        Advance(1);
1486
1487                        if (AtChar<C,'?'>(cur())){
1488                                Parse_PI();
1489                        }
1490                        else if(AtChar<C,'!'>(cur())){
1491                                Advance(1);
1492                                if(at_DoubleHyphen<C>(cur()))
1493                                        Parse_Comment();
1494                                else if(at_ELEMENT<C>(cur()))
1495                                        Parse_Elementdecl();
1496                                else if(at_ATTLIST<C>(cur()))
1497                                        Parse_AttlistDecl();
1498                                else if(at_ENTITY<C>(cur()))
1499                                        Parse_Entitydecl();
1500                                else if(at_NOTATION<C>(cur()))
1501                                        Parse_Notationdecl();                                   
1502                                else{
1503                                        Syntax_Error(NT_markupdecl);   
1504                                }                                                               
1505                        }
1506                        else
1507                                Syntax_Error(NT_markupdecl); 
1508                }
1509                else
1510                        Syntax_Error(NT_extSubsetDecl); 
1511                ScanTo(NonWS);
1512        }
1513        ExtSubsetDecl_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
1514}
Note: See TracBrowser for help on using the repository browser.