source: trunk/src/engine.c @ 106

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

Content Models.

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