source: trunk/src/engine.c @ 115

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

various error checks in parsing

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