source: trunk/src/engine.c @ 119

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

Parse_PubidLiteral

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        while (at_PubidChar<C>(cur())) Advance(1);
761        if (cur()[0] != quoteCh){
762                Syntax_Error(NT_PubidLiteral);
763        }
764        Advance(1);
765}
766
767template <CodeUnit_Base C>
768inline void ParsingEngine<C>::Parse_IntSubset (){
769       
770        while(1){
771                ScanTo(NonWS); 
772                text_or_markup_start = AbsPos();
773                if (AtChar<C,'%'>(cur()))
774                        Parse_PEReference();   
775                else if (AtChar<C,'<'>(cur())){
776                        Advance(1);
777
778                        if (AtChar<C,'?'>(cur())){
779                                if (at_xml<C>(cur()))
780                                        Syntax_Error(NT_intSubset);
781                                else
782                                        Parse_PI();
783                        }
784                        else if(AtChar<C,'!'>(cur())){
785                                Advance(1);
786                                if(at_DoubleHyphen<C>(cur()))
787                                        Parse_Comment();
788                                else if(at_ELEMENT<C>(cur()))
789                                        Parse_Elementdecl();
790                                else if(at_ATTLIST<C>(cur()))
791                                        Parse_AttlistDecl();
792                                else if(at_ENTITY<C>(cur()))
793                                        Parse_Entitydecl();
794                                else if(at_NOTATION<C>(cur()))
795                                        Parse_Notationdecl();
796                                else{
797                                        Syntax_Error(NT_markupdecl);           
798                                }                                                               
799                        }
800                        else
801                                Syntax_Error(NT_markupdecl); 
802                }
803                else if (AtChar<C,']'>(cur())){
804                        break;
805                }
806                else
807                        Syntax_Error(NT_intSubset); 
808        }
809}
810
811
812template <CodeUnit_Base C>
813inline void ParsingEngine<C>::Parse_PEReference (){
814
815        Advance(1); /* Skip "%". */
816        ScanTo(NameFollow); 
817        if (AtChar<C,';'>(cur())) {
818                Advance(1);
819                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
820        }
821        else
822                Syntax_Error(NT_PEReference);
823}
824
825
826template <CodeUnit_Base C>
827inline void ParsingEngine<C>::Parse_Elementdecl (){
828
829        Advance(7); /* Skip "<!ELEMENT". */
830
831    requireWS();
832    int name_start = AbsPos();
833        ScanTo(NameFollow);
834        int lgth = AbsPos() - name_start;
835        int elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
836        requireWS();
837        ContentModel * cm;
838        /* Start parsing "contentspec"*/
839        if (at_EMPTY<C>(cur())) {
840        Advance(5);
841        cm = new CM_Empty();
842        model_info->ContentModelData.push_back(cm);
843        }
844    else if (at_ANY<C>(cur())) {
845        Advance(3);
846        cm = new CM_Any();
847        model_info->ContentModelData.push_back(cm);
848    }
849    else {
850        if (AtChar<C,'('>(cur()))
851                        Advance(1);
852                ScanTo(NonWS);
853                if (at_PCDATA<C>(cur())){
854                        cm = Parse_RemainingMixed();
855                        model_info->ContentModelData.push_back(cm);
856                }
857                else{
858
859                        CM_RegExp * cre = new CM_RegExp;
860                        cre->content_re = Parse_RemainingChildren();
861
862                        int id_count = cre->content_re->Set_IDs(0);
863                        cre->content_re->Set_First_Map();       
864                        symbol_set_t * transition_map = new symbol_set_t[id_count+1];
865                        cre->content_re->follow_map[0] = id_count+1;
866                       
867                        cre->content_re->Set_Follow_Map(transition_map);
868                        transition_map[0] = cre->content_re->first_map;
869                       
870                        if (cre->content_re->matches_empty)
871                                transition_map[0][0]=id_count+1;
872                               
873                        cre -> transition_map = transition_map;
874                       
875                        model_info->ContentModelData.push_back(cre);
876                        cm = cre;
877                }                       
878    }
879    ScanTo(NonWS);   
880
881        if (AtChar<C,'>'>(cur())) {
882                Advance(1);
883        }
884        else
885                Syntax_Error(NT_elementdecl);
886}
887template <CodeUnit_Base C>
888inline ContentModel * ParsingEngine<C>::Parse_RemainingMixed (){
889        CM_Mixed * r = new CM_Mixed();
890        Advance(7);  /* Skip "#PCDATA". */
891   
892    if (AtChar<C,')'>(cur())){
893        if (AtChar<C,'*'>(cur())) {
894                Advance(2);
895                }
896                else {
897                        Advance(1);
898                }
899    }
900    else{
901        ScanTo(NonWS);
902        int k = 0;
903        while (AtChar<C,'|'>(cur())){
904                        Advance(1);
905                        ScanTo(NonWS);
906                        int name_start = AbsPos();
907                        ScanTo(NameFollow);
908                        int lgth = AbsPos() - name_start;
909                        char * s = copy_string(GetCodeUnitPtr(name_start),lgth);
910                        int elemID = model_info->GlobalElementTable[s];
911                        if(elemID==0)
912                                Validity_Error(vErr_elementvalid);
913                        r->elements[elemID] = ++k;
914                        ScanTo(NonWS);
915                }
916                if (at_Para_star<C>(cur())) Advance(2);
917                else {
918                        Syntax_Error(NT_Mixed);
919                        exit(-1);
920        }
921    }
922    return r;
923}
924
925
926template <CodeUnit_Base C>
927inline Content_RE * ParsingEngine<C>::Parse_RemainingChildren (){
928        Content_RE * c1 = Parse_Cp();
929        Content_RE * r = c1;
930        ScanTo(NonWS);
931        if(AtChar<C,'|'>(cur())){
932                CRE_Choice * rslt = new CRE_Choice;
933                rslt->subCMs.push_back(c1);
934                Advance(1);
935                ScanTo(NonWS);
936                rslt->subCMs.push_back(Parse_Cp());
937                ScanTo(NonWS);
938                while(!AtChar<C,')'>(cur())){
939                        if(AtChar<C,'|'>(cur()))
940                                Advance(1);
941                        else
942                                Syntax_Error(NT_children);
943                        ScanTo(NonWS);
944                        rslt->subCMs.push_back(Parse_Cp());
945                        ScanTo(NonWS);
946                }
947                Advance(1);
948                rslt->Compile();
949                r = rslt;
950        }
951        else if(AtChar<C,','>(cur())){
952                CRE_Seq * rslt = new CRE_Seq;
953                rslt->subCMs.push_back(c1);
954                Advance(1);
955                ScanTo(NonWS);
956                rslt->subCMs.push_back(Parse_Cp());
957                ScanTo(NonWS);
958                while(!AtChar<C,')'>(cur())){
959                        if(AtChar<C,','>(cur()))
960                                Advance(1);
961                        else
962                                Syntax_Error(NT_children);
963                        ScanTo(NonWS);
964                        rslt->subCMs.push_back(Parse_Cp());
965                        ScanTo(NonWS);
966                }
967                Advance(1);
968                rslt->Compile();
969                r = rslt;
970        }       
971        else if(AtChar<C,')'>(cur())){
972                Advance(1);
973        }
974        else
975                Syntax_Error(NT_children);
976               
977        if (AtChar<C,'?'>(cur())) {
978                Advance(1);
979                r = new CRE_Opt(r);
980        }
981        else if (AtChar<C,'*'>(cur())) {
982                Advance(1);
983                r = new CRE_Star(r);
984        }
985        else if (AtChar<C,'+'>(cur())) {
986                Advance(1);
987                r = new CRE_Plus(r);
988        }
989
990        return r;
991}
992
993template <CodeUnit_Base C>
994inline Content_RE * ParsingEngine<C>::Parse_Cp (){
995        if (AtChar<C,'('>(cur())){
996                Advance(1);
997                ScanTo(NonWS);
998                Parse_RemainingChildren();
999        }
1000        else{
1001                int name_start = AbsPos();
1002                ScanTo(NameFollow);
1003                int lgth = AbsPos() - name_start;
1004                char * s = copy_string(GetCodeUnitPtr(name_start),lgth);
1005                int elemID = model_info->GlobalElementTable[s];
1006                if(elemID==0)
1007                        Validity_Error(vErr_elementvalid);
1008                CRE_Name * r = new CRE_Name(elemID);
1009
1010                if (AtChar<C,'?'>(cur())) {
1011                        Advance(1);
1012                        return new CRE_Opt(r);
1013                }
1014                else if (AtChar<C,'*'>(cur())) {
1015                        Advance(1);
1016                        return new CRE_Star(r);
1017                }
1018                else if (AtChar<C,'+'>(cur())) {
1019                        Advance(1);
1020                        return new CRE_Plus(r);
1021                }
1022                else return r;
1023        }
1024}
1025
1026template <CodeUnit_Base C>
1027inline void ParsingEngine<C>::Parse_AttlistDecl (){
1028       
1029        int old_abspos;
1030       
1031        int name_start;
1032        int lgth;
1033       
1034        int elemID;
1035        int attID;
1036       
1037        Advance(7); /* Skip "ATTLIST. */
1038        requireWS();
1039       
1040        name_start = AbsPos();
1041        ScanTo(NameFollow);
1042        lgth = AbsPos()-name_start;
1043        elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
1044       
1045        old_abspos = AbsPos();
1046        ScanTo(NonWS);
1047        while(!AtChar<C,'>'>(cur())) {
1048                if(old_abspos == AbsPos())
1049                Syntax_Error(NT_AttlistDecl);
1050               
1051        name_start = AbsPos();
1052                ScanTo(NameFollow);
1053                lgth = AbsPos()-name_start;
1054               
1055                attID = model_info->getOrInsertGlobalAttName(GetCodeUnitPtr(name_start), lgth);
1056                if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1057        ATT_info * this_info = new ATT_info;
1058        this_info->globalATT_id = attID;
1059        requireWS();
1060        if (at_CDATA<C>(cur())){
1061                Advance(5);
1062                this_info->attType = CDATA_att;
1063        }
1064        else if(at_ID<C>(cur())){
1065                Advance(2);
1066                this_info->attType = ID_att;
1067        }
1068        /* Make sure to check IDREFS before IDREF*/
1069        else if(at_IDREFS<C>(cur())){
1070                Advance(6);
1071                this_info->attType = IDREFS_att;
1072        }
1073        else if(at_IDREF<C>(cur())){
1074                Advance(5);
1075                this_info->attType = IDREF_att;
1076        }
1077        else if(at_ENTITY<C>(cur())){
1078                Advance(6);
1079                this_info->attType = ENTITY_att;
1080        }
1081        else if(at_ENTITIES<C>(cur())){
1082                Advance(8);
1083                this_info->attType = ENTITIES_att;
1084        }
1085        /* Make sure to check NMTOKENS before NMTOKEN*/
1086        else if(at_NMTOKENS<C>(cur())){
1087                Advance(8);
1088                this_info->attType = NMTOKENS_att;
1089        }
1090        else if(at_NMTOKEN<C>(cur())){
1091                Advance(7);
1092                this_info->attType = NMTOKEN_att;
1093        }
1094        else if(at_NOTATION<C>(cur())){ /* NotationType = 'NOTATION' S Enumeration
1095                                                                         when Nmtoken = Name */
1096                Advance(8);
1097                        requireWS();
1098                Parse_Notation(this_info);
1099                this_info->attType = NOTATION_att;
1100        }
1101        else if(AtChar<C,'('>(cur())){
1102                Parse_Enumeration(this_info);
1103                this_info->attType = enumeration_att;
1104        }
1105        else
1106                Syntax_Error(NT_AttlistDecl);
1107        requireWS();
1108        Parse_DefaultDecl(this_info);
1109
1110                ScanTo(NonWS);
1111                model_info->ElementAttributeData[elemID].push_back(this_info);
1112        }
1113
1114        Advance(1);
1115}
1116
1117template <CodeUnit_Base C>
1118inline void ParsingEngine<C>::Parse_Notation (ATT_info * this_info){
1119
1120        if(AtChar<C,'('>(cur()))
1121                Advance(1);
1122        else
1123                Syntax_Error(NT_NotationType);
1124        ScanTo(NonWS);
1125       
1126    int name_start = AbsPos();
1127        ScanTo(NameFollow);
1128        int     lgth = AbsPos()-name_start;
1129       
1130        char *s = new char[lgth+1];
1131        memcpy(s, GetCodeUnitPtr(name_start), lgth);
1132        s[lgth] = '\0';
1133
1134        /*Notation name is not in the global table!*/
1135        if(model_info->GlobalNotationTable[s]==0)
1136                Validity_Error(vErr_notatn);
1137       
1138        ScanTo(NonWS);
1139        while(AtChar<C,'|'>(cur())){
1140                Advance(1);
1141                ScanTo(NonWS);         
1142                name_start = AbsPos();
1143                ScanTo(NameFollow);
1144                lgth = AbsPos()-name_start;
1145       
1146                char *s = new char[lgth+1];
1147                memcpy(s, GetCodeUnitPtr(name_start), lgth);
1148                s[lgth] = '\0';
1149       
1150                if(model_info->GlobalNotationTable[s]==0)
1151                        Validity_Error(vErr_notatn);
1152                       
1153                ScanTo(NonWS);
1154        }
1155        if (AtChar<C,')'>(cur())) 
1156                Advance(1);
1157        else
1158                Syntax_Error(NT_NotationType);
1159}
1160
1161template <CodeUnit_Base C>
1162inline void ParsingEngine<C>::Parse_Enumeration (ATT_info * this_info){
1163
1164        int enumCount=0;
1165        if(AtChar<C,'('>(cur()))
1166                Advance(1);
1167        else
1168                Syntax_Error(NT_Enumeration);
1169        ScanTo(NonWS);
1170       
1171        int     name_start = AbsPos();
1172        ScanTo(NameFollow);
1173        int     lgth = AbsPos()-name_start;
1174       
1175        char *s = new char[lgth+1];
1176        memcpy(s, GetCodeUnitPtr(name_start), lgth);
1177        s[lgth] = '\0';
1178       
1179        this_info->enumValues[s]=++(enumCount);
1180       
1181        ScanTo(NonWS);
1182        while(AtChar<C,'|'>(cur())){
1183                Advance(1);
1184                ScanTo(NonWS);         
1185                name_start = AbsPos();
1186                ScanTo(NameFollow);
1187                lgth = AbsPos()-name_start;
1188       
1189                char *s = new char[lgth+1];
1190                memcpy(s, GetCodeUnitPtr(name_start), lgth);
1191                s[lgth] = '\0';
1192       
1193                int enumID = this_info->enumValues[s];
1194                if(enumID==0){ 
1195                        this_info->enumValues[s]=++(enumCount);
1196                        enumID = enumCount;
1197                }
1198                else if(!StrictWellFormedness){
1199                        Validity_Error(vErr_NoDuplicateTokens);
1200                }
1201                ScanTo(NonWS);
1202        }
1203        if (AtChar<C,')'>(cur())) 
1204                Advance(1);
1205        else
1206                Syntax_Error(NT_Enumeration);
1207}
1208
1209template <CodeUnit_Base C>
1210inline void ParsingEngine<C>::Parse_DefaultDecl (ATT_info * this_info){
1211        if(at_REQUIRED<C>(cur())){
1212                Advance(9);
1213                this_info->defaultKind = REQUIRED_att;
1214        }
1215        else if(at_IMPLIED<C>(cur())){
1216                Advance(8);
1217                this_info->defaultKind = IMPLIED_att;
1218        }
1219        else {
1220                if(at_FIXED<C>(cur())){
1221                        Advance(6);
1222                        requireWS();
1223                        this_info->defaultKind = FIXED_att;
1224                }
1225                else this_info->defaultKind = DEFAULT_att;
1226                if(AtQuote<C>(cur())){
1227                        int quot_start = AbsPos()+1;
1228                        Parse_AttValue();
1229                        /* need to normalize */
1230                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
1231                       
1232                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
1233                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
1234                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
1235                        }
1236                else
1237                        Syntax_Error(NT_DefaultDecl);
1238        }
1239}
1240
1241template <CodeUnit_Base C>
1242inline void ParsingEngine<C>::Parse_Entitydecl (){
1243       
1244        int name_start;
1245        int quot_start;
1246        int lgth;
1247        int old_abspos;
1248        char * s;
1249       
1250        Advance(6); /* Skip "ENTITY. */
1251        requireWS();
1252       
1253        if (AtChar<C,'%'>(cur())){
1254                Advance(1);
1255                requireWS();
1256               
1257                name_start = AbsPos();
1258                ScanTo(NameFollow);
1259                lgth = AbsPos()- name_start;
1260                s = new char[lgth+1];
1261                memcpy(s, GetCodeUnitPtr(name_start),lgth); 
1262                s[lgth] = '\0';
1263       
1264                PEntity_info * this_info = new PEntity_info;
1265                int entityID = model_info->GlobalPEntityTable[s];
1266                if(entityID==0){       
1267                        model_info->GlobalPEntityTable[s]=++(model_info->globalPEntityCount);
1268                        entityID = model_info->globalPEntityCount;
1269                        this_info->globalPEntity_id = entityID;
1270                }
1271                else
1272                        printf("Warning: Entity definition already exist!\n");
1273       
1274                requireWS();
1275                if(AtQuote<C>(cur())){
1276                Parse_PEntityValue(this_info);
1277                this_info->is_external = false;
1278        }
1279        else {
1280                this_info->is_external = true;
1281                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1282                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1283        }
1284        model_info->PEntityData.push_back(this_info);
1285        }
1286        else{
1287                name_start = AbsPos();
1288                ScanTo(NameFollow);
1289                lgth = AbsPos()- name_start;
1290                s = new char[lgth+1];
1291                memcpy(s, GetCodeUnitPtr(name_start),lgth); 
1292                s[lgth] = '\0';
1293       
1294                GEntity_info * this_info = new GEntity_info;
1295                int entityID = model_info->GlobalGEntityTable[s];
1296                if(entityID==0){       
1297                        model_info->GlobalGEntityTable[s]=++(model_info->globalGEntityCount);
1298                        entityID = model_info->globalGEntityCount;
1299                        this_info->globalGEntity_id = entityID;
1300                }
1301                else
1302                        printf("Warning: Entity definition already exist!\n");
1303                       
1304                requireWS();
1305               
1306                if(AtQuote<C>(cur())){
1307                Parse_GEntityValue(this_info);
1308                this_info->is_external = false;
1309        }
1310        else {
1311                this_info->is_external = true;
1312                Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1313                if (this_info->systemLiteral == NULL) Syntax_Error(NT_EntityDecl);
1314                        old_abspos = AbsPos();
1315                        ScanTo(NonWS);
1316                if(at_NDATA<C>(cur())){
1317                        if(old_abspos == AbsPos())
1318                                Syntax_Error(NT_EntityDecl);
1319                        else
1320                                Advance(5);
1321                        requireWS();
1322                        name_start = AbsPos();
1323                        ScanTo(NameFollow);
1324                        lgth = AbsPos() - name_start;
1325                                this_info->NDataName = copy_string(GetCodeUnitPtr(name_start),lgth);
1326                }
1327                }
1328        model_info->GEntityData.push_back(this_info);
1329        }
1330        ScanTo(NonWS);
1331        if (AtChar<C,'>'>(cur())){
1332                Advance(1);
1333        }
1334        else
1335                Syntax_Error(NT_EntityDecl);
1336}
1337
1338template <CodeUnit_Base C>
1339inline void ParsingEngine<C>::Parse_Notationdecl (){
1340
1341        int old_abspos;
1342        Advance(8); /* Skip "NOTATION. */
1343        requireWS();
1344       
1345        int name_start = AbsPos();
1346        ScanTo(NameFollow);
1347        int     lgth = AbsPos()-name_start;
1348       
1349        char *s = new char[lgth+1];
1350        memcpy(s, GetCodeUnitPtr(name_start), lgth);
1351        s[lgth] = '\0';
1352
1353        int notationID = model_info->GlobalNotationTable[s];
1354        if(notationID==0){     
1355                model_info->GlobalNotationTable[s]=++(model_info->globalNotationCount);
1356                notationID = model_info->globalNotationCount;
1357        }
1358        else /*Duplicate notation name!*/
1359                Validity_Error(vErr_NoDuplicateTokens);
1360        Notation_info * this_info = new Notation_info;
1361                       
1362    Parse_ExternalID(this_info->systemLiteral, this_info->pubidLiteral);
1363        ScanTo(NonWS);
1364        if (AtChar<C,'>'>(cur())) {
1365                Advance(1);
1366        }
1367        else
1368                Syntax_Error(NT_NotationDecl);
1369}
1370
1371template <CodeUnit_Base C>
1372inline void ParsingEngine<C>::requireWS(){
1373       
1374    int old_abspos = AbsPos(); 
1375    ScanTo(NonWS);
1376    if(old_abspos == AbsPos())
1377        Syntax_Error(NT_S);
1378}
1379
1380template <CodeUnit_Base C>
1381inline void ParsingEngine<C>::Parse_AttValue(){
1382       
1383        int     quoteCh = cur()[0];
1384        Advance(1); /* Skip " or ' */
1385
1386        ScanTo(Quote);                 
1387        while (cur()[0] != quoteCh){
1388                if (at_CharRef_Start<C>(cur())){
1389                        Parse_CharRef();
1390                        ScanTo(Quote);
1391                }
1392                else if (AtChar<C,'&'>(cur())){
1393                        Parse_EntityRef();
1394                        ScanTo(Quote);
1395                }
1396                else if (AtQuote<C>(cur())) {
1397                        Advance(1);
1398                        ScanTo(Quote);
1399                }
1400                else /* if (AtChar<C,'<'>(cur())) */
1401                        WF_Error(wfErr_CleanAttrVals);
1402        }
1403        Advance(1);
1404}
1405
1406template <CodeUnit_Base C>
1407inline void ParsingEngine<C>::Parse_GEntityValue(GEntity_info * this_info){
1408       
1409        int     quoteCh = cur()[0];
1410        Advance(1); /* Skip " or ' */
1411        this_info->is_simple = true;
1412        int quot_start = AbsPos();
1413        ScanTo(Quote);         
1414        char *  replText = copy_string(GetCodeUnitPtr(quot_start),AbsPos()-quot_start);
1415
1416        while (cur()[0] != quoteCh){
1417                if (at_CharRef_Start<C>(cur())){
1418                        strcat (replText,Replace_CharRef());
1419                        quot_start = AbsPos();
1420                        ScanTo(Quote);
1421                }
1422                else if (AtChar<C,'&'>(cur())){
1423                        strcat (replText,Replace_EntityRef(this_info->is_simple));
1424                        quot_start = AbsPos();
1425                        ScanTo(Quote);
1426                }
1427                else if (AtQuote<C>(cur())) {
1428                        quot_start = AbsPos();
1429                        Advance(1);
1430                        ScanTo(Quote);
1431
1432                }
1433                else { /* '<' found */
1434                        quot_start = AbsPos();
1435                        Advance(1);
1436                        ScanTo(Quote);
1437                        this_info->is_simple = false;
1438                }
1439                strcat (replText,copy_string(GetCodeUnitPtr(quot_start),AbsPos()-quot_start));                 
1440        }
1441        this_info->ReplacementText = replText;
1442        Advance(1);
1443}
1444
1445template <CodeUnit_Base C>
1446inline char * ParsingEngine<C>::Replace_EntityRef(bool& is_simple){
1447        Advance(1);
1448        int entity_start = AbsPos();
1449        ScanTo(NameFollow); 
1450        char * s = copy_string(GetCodeUnitPtr(entity_start),AbsPos()-entity_start);
1451        if (AtChar<C,';'>(cur()))
1452                Advance(1);
1453        else
1454                Syntax_Error(NT_EntityValue);
1455        int entityID = model_info->GlobalGEntityTable[s]; 
1456        if (entityID == 0)
1457                WF_Error(wfErr_wf_entdeclared);
1458        else{
1459                if (model_info->GEntityData[entityID-1]->is_simple == false)
1460                        is_simple = false;
1461                return model_info->GEntityData[entityID-1]->ReplacementText;
1462        }
1463       
1464}
1465
1466template <CodeUnit_Base C>
1467inline void ParsingEngine<C>::Parse_PEntityValue(PEntity_info * this_info){
1468}
1469
1470template <CodeUnit_Base C>
1471inline char * ParsingEngine<C>::Replace_CharRef(){
1472        Advance(1);
1473        int entity_start = AbsPos();
1474        ScanTo(NameFollow); 
1475        char * s = copy_string(GetCodeUnitPtr(entity_start),AbsPos()-entity_start);
1476        int entityID = model_info->GlobalGEntityTable[s]; 
1477        if (entityID == 0)
1478                WF_Error(wfErr_wf_entdeclared);
1479        else
1480                return model_info->GEntityData[entityID-1]->ReplacementText;   
1481       
1482}
1483
1484template <CodeUnit_Base C>
1485inline void ParsingEngine<C>::Parse_Prolog(){
1486        ScanTo(NonWS);
1487        int old_pos = AbsPos();
1488        while (!at_DOCTYPE_start<C>(cur())) {
1489                if (at_Comment_Start<C>(cur())) 
1490                        Parse_Comment();
1491                else if (at_PI_Start<C>(cur()))
1492                                Parse_PI();
1493                else{
1494                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1495                        return;
1496                }
1497                ScanTo(NonWS);
1498        }
1499        Parse_DocType();
1500        ScanTo(NonWS);
1501        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
1502                if (at_Comment_Start<C>(cur()))
1503                        Parse_Comment();
1504                else 
1505                        Parse_PI();
1506                ScanTo(NonWS);
1507        }
1508        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1509}
1510
1511template <CodeUnit_Base C>
1512inline void ParsingEngine<C>::Parse_ExtSubsetDecl() {
1513        int start_pos=AbsPos();
1514        while(!at_EOF()){
1515                if(at_condSect_start<C>(cur())){               
1516                        Advance(3);
1517                        ScanTo(NonWS);
1518                        if (at_INCLUDE<C>(cur())){
1519                                Advance(7);
1520                                ScanTo(NonWS);
1521                                if(AtChar<C,'['>(cur())){
1522                                        Advance(1);
1523                                        Parse_ExtSubsetDecl();
1524                                        if(at_CDATA_End<C>(cur()))
1525                                                Advance(3);
1526                                        else Syntax_Error(NT_includeSect);
1527                                }
1528                                else Syntax_Error(NT_includeSect);
1529                        }
1530                        else if (at_IGNORE<C>(cur())){
1531                                Advance(6);
1532                                ScanTo(NonWS);         
1533                                if(AtChar<C,'['>(cur())){
1534                                        int section_depth=1;
1535                                        Advance(1);
1536                                        while(!at_EOF()){
1537                                                ScanToMarkupStart();
1538                                                if(at_condSect_start<C>(cur())){
1539                                                        Advance(3);
1540                                                        section_depth++;
1541                                                }
1542                                                else if(at_CDATA_End<C>(cur())){
1543                                                        Advance(3);
1544                                                        section_depth--;
1545                                                }
1546                                                if(section_depth==0) return;                                   
1547                                        }
1548                                        Syntax_Error(NT_ignoreSectContents);   
1549                                }
1550                                else Syntax_Error(NT_ignoreSect);
1551                        }
1552                        else Syntax_Error(NT_conditionalSect);
1553                }
1554                else if (AtChar<C,'%'>(cur()))
1555                        Parse_PEReference();   
1556                else if (AtChar<C,'<'>(cur())){
1557                        Advance(1);
1558
1559                        if (AtChar<C,'?'>(cur())){
1560                                Parse_PI();
1561                        }
1562                        else if(AtChar<C,'!'>(cur())){
1563                                Advance(1);
1564                                if(at_DoubleHyphen<C>(cur()))
1565                                        Parse_Comment();
1566                                else if(at_ELEMENT<C>(cur()))
1567                                        Parse_Elementdecl();
1568                                else if(at_ATTLIST<C>(cur()))
1569                                        Parse_AttlistDecl();
1570                                else if(at_ENTITY<C>(cur()))
1571                                        Parse_Entitydecl();
1572                                else if(at_NOTATION<C>(cur()))
1573                                        Parse_Notationdecl();                                   
1574                                else{
1575                                        Syntax_Error(NT_markupdecl);   
1576                                }                                                               
1577                        }
1578                        else
1579                                Syntax_Error(NT_markupdecl); 
1580                }
1581                else
1582                        Syntax_Error(NT_extSubsetDecl); 
1583                ScanTo(NonWS);
1584        }
1585        ExtSubsetDecl_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
1586}
1587
1588       
1589/* Parse a valid start or empty element tag. */
1590template <CodeUnit_Base C>
1591inline int ParsingEngine<C>::Parse_ValidStartTag (bool& is_emptyStartTag){
1592        int att_name_start;
1593        int att_val_start;
1594        int att_name_end, att_val_end;
1595        unsigned char quoteCh;
1596        Advance(1);
1597       
1598        int name_start = AbsPos();
1599        ScanTo(NameFollow);  /* Name delimiter: WS, "/" or ">" */
1600        char * s = copy_string(GetCodeUnitPtr(name_start),AbsPos()-name_start);
1601        int elemID = model_info->GlobalElementTable[s];
1602       
1603        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
1604        /* The following test optimizes the most common case of a
1605        start tag with no attributes.  */
1606        if (AtChar<C,'>'>(cur())) {
1607                Advance(1);
1608                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1609        }
1610        else {
1611                ScanTo(NonWS);
1612                if (AtChar<C,'>'>(cur())) {
1613                        Advance(1);
1614                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1615                }
1616                else if (at_EmptyElementDelim<C>(cur())) {
1617                        Advance(2);
1618                        is_emptyStartTag = true;
1619                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1620                }
1621                else do {
1622                        /* Must be an attribute-value pair or error. */
1623                        att_name_start = AbsPos();
1624                        ScanTo(NameFollow);
1625                        att_name_end = AbsPos();
1626                        int lgth = att_name_end-att_name_start;
1627               
1628                        int attID = model_info->getOrInsertGlobalAttName(GetCodeUnitPtr(att_name_start), lgth);
1629                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
1630                        else {
1631                                if (LastAttOccurrence[attID] > text_or_markup_start) {
1632                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
1633                                        break;
1634                                }                       
1635                        }
1636                        LastAttOccurrence[attID] = att_name_start;
1637                        /* The following optimized tests handle the frequently occurring
1638                        case that there are no blanks on either side of the equals sign.
1639                        In many cases, the very first test handles 100% of actual
1640                        attribute-value pairs encountered. */
1641                        if (at_EqualsQuote<C>(cur())) Advance(1); 
1642                        else {
1643                                ScanTo(NonWS);
1644                                if (!AtChar<C,'='>(cur())) {
1645                                        Syntax_Error(NT_STag); 
1646                                        break;
1647                                }
1648                                ScanTo(NonWS);
1649                                if (!AtQuote<C>(cur())) {
1650                                        Syntax_Error(NT_STag); 
1651                                        break;
1652                                }
1653                        }
1654                        att_val_start = AbsPos()+1;
1655                        Parse_AttValue();
1656                        att_val_end = AbsPos()-1;
1657                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
1658                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
1659                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
1660                        }
1661                        else {
1662                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
1663                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
1664                        }
1665                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
1666                        if (AtChar<C,'>'>(cur())) {
1667                                Advance(1);
1668                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1669                                break;
1670                        }
1671                        else if (at_EmptyElementDelim<C>(cur())) {
1672                                Advance(2);
1673                                is_emptyStartTag = true;       
1674                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1675                                break;
1676                        }
1677                        ScanTo(NonWS);
1678                        if (AtChar<C,'>'>(cur())) {
1679                                Advance(1);
1680                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1681                                break;
1682                        }
1683                        else if (at_EmptyElementDelim<C>(cur())) {
1684                                Advance(2);
1685                                is_emptyStartTag = true;
1686                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1687                                break;
1688                        }
1689                        else if (AbsPos() == att_val_end + 1) { 
1690                                /* No WS following att value */
1691                                Syntax_Error(NT_STag);
1692                                break;
1693                        }
1694                } while (1);
1695        }
1696        return elemID;
1697}
1698
1699template <CodeUnit_Base C>
1700inline int ParsingEngine<C>::Parse_ValidElement() {
1701        bool is_emptyStartTag = false;
1702        int elemID = Parse_ValidStartTag(is_emptyStartTag);
1703#ifdef DEBUG
1704        printf("Parse_ValidElement: elemID = %d, is_emptyStartTag=%i\n",elemID, is_emptyStartTag);
1705#endif
1706        ContentModel * cm = model_info->ContentModelData[elemID-1];
1707        switch (cm->cm_type) {
1708                case cm_Empty:
1709                        if (!is_emptyStartTag) {
1710                                if (at_EndTag_Start<C>(cur())) {
1711                                        Parse_EndTag();
1712                                }
1713                                else {
1714                                        Validity_Error(vErr_elementvalid);
1715                                }
1716                        }
1717                        break;
1718                case cm_Any:           
1719                        if (!is_emptyStartTag) {
1720                                Parse_AnyContent();
1721                                Parse_EndTag();
1722                        }
1723                        break;
1724                case cm_Mixed:         
1725                        if (!is_emptyStartTag) {
1726                                Parse_MixedContent(((CM_Mixed *) cm)->elements);
1727                                Parse_EndTag();
1728                        }
1729                        break;
1730                case cm_RegExp:
1731                        CM_RegExp * cre = (CM_RegExp *) cm;
1732                        int content_state = 0;
1733                        if (!is_emptyStartTag) {
1734                                content_state = Parse_ValidContent(cre);
1735                                Parse_EndTag();                         
1736                        }
1737                        if (cre->transition_map[content_state][0]==0) {
1738                                Validity_Error(vErr_elementvalid);
1739                        }
1740        }
1741        return elemID;
1742}
1743
1744template <CodeUnit_Base C>
1745inline int ParsingEngine<C>::Parse_ValidContent(CM_RegExp * cre) {
1746        int cur_state = 0;
1747        do {
1748                ScanTo(NonWS);
1749                /* If non-null report WS  WS_action()? */
1750                if (at_EndTag_Start<C>(cur())) {
1751                        break;
1752                }
1753                else if (at_ElementTag_Start<C>(cur())) {
1754                        int elemID = Parse_ValidElement();
1755#ifdef DEBUG
1756                        printf("Content model state transition %i", cur_state);
1757#endif
1758                        cur_state = cre->transition_map[cur_state][elemID];
1759#ifdef DEBUG
1760                        printf("-> %i\n", cur_state);
1761#endif
1762                }
1763                else if (at_Comment_Start<C>(cur())) {
1764                        Parse_Comment();
1765                }
1766                else if (at_PI_Start<C>(cur())) {
1767                        Parse_PI();
1768                }
1769                else if (AtChar<C,'&'>(cur())) {
1770                        Parse_EntityRef();
1771                }
1772                else if (at_EOF()) {
1773                        break;
1774                }
1775                else {
1776                        Validity_Error(vErr_elementvalid);
1777                }
1778        } while(1);
1779        return cur_state;
1780}
1781
1782
1783template <CodeUnit_Base C>
1784inline void ParsingEngine<C>::Parse_AnyContent() {
1785        do {
1786                text_or_markup_start = AbsPos();
1787                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
1788                if (at_ElementTag_Start<C>(cur())) {
1789                        text_if_nonnull_action();
1790                        int elemID = Parse_ValidElement();
1791                }
1792                else if (at_EndTag_Start<C>(cur())) {
1793                        text_if_nonnull_action();
1794                        return;
1795                }
1796                else if (at_Comment_Start<C>(cur())) {
1797                        text_if_nonnull_action();
1798                        Parse_Comment();
1799                }
1800                else if (at_CharRef_Start<C>(cur())) {
1801                        text_if_nonnull_action();
1802                        Parse_CharRef();
1803                }
1804                else if (AtChar<C,'&'>(cur())) {
1805                        text_if_nonnull_action();
1806                        Parse_EntityRef();
1807                }
1808                else if (at_CDATA_Start<C>(cur())) {
1809                        text_if_nonnull_action();
1810                        Parse_CDATA();
1811                }
1812                else if (at_PI_Start<C>(cur())) {
1813                        text_if_nonnull_action();
1814                        Parse_PI();
1815                }
1816                else if (at_CDATA_End<C>(cur())) {
1817                        text_if_nonnull_action();
1818                        Advance(3);
1819                        Syntax_Error(NT_CharData);
1820                }
1821                else if (at_EOF()) {
1822                        text_if_nonnull_action();
1823                        return;
1824                }
1825                else {
1826                        Advance(1);
1827                        continue;
1828                }
1829        } while (1);
1830}
1831template <CodeUnit_Base C>
1832inline void ParsingEngine<C>::Parse_MixedContent(symbol_set_t elems) {
1833        do {
1834                text_or_markup_start = AbsPos();
1835                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
1836/*              if (AtChar<C,'<'>(cur())) {
1837                        text_if_nonnull_action();
1838                        Parse_Markup<C>();
1839                }*/
1840                if (at_ElementTag_Start<C>(cur())) {
1841                        text_if_nonnull_action();
1842                        int elemID = Parse_ValidElement();
1843                        if (elems[elemID] == 0) {
1844                                Validity_Error(vErr_elementvalid);
1845                        }
1846                }
1847                else if (at_EndTag_Start<C>(cur())) {
1848                        text_if_nonnull_action();
1849                        return;
1850                }
1851                else if (at_Comment_Start<C>(cur())) {
1852                        text_if_nonnull_action();
1853                        Parse_Comment();
1854                }
1855                else if (at_CharRef_Start<C>(cur())) {
1856                        text_if_nonnull_action();
1857                        Parse_CharRef();
1858                }
1859                else if (AtChar<C,'&'>(cur())) {
1860                        text_if_nonnull_action();
1861                        Parse_EntityRef();
1862                }
1863                else if (at_CDATA_Start<C>(cur())) {
1864                        text_if_nonnull_action();
1865                        Parse_CDATA();
1866                }
1867                else if (at_PI_Start<C>(cur())) {
1868                        text_if_nonnull_action();
1869                        Parse_PI();
1870                }
1871                else if (at_CDATA_End<C>(cur())) {
1872                        text_if_nonnull_action();
1873                        Advance(3);
1874                        Syntax_Error(NT_CharData);
1875                }
1876                else if (at_EOF()) {
1877                        text_if_nonnull_action();
1878                        return;
1879                }
1880                else {
1881                        Advance(1);
1882                        continue;
1883                }
1884        } while (1);
1885}
1886
1887
1888
1889template <CodeUnit_Base C>
1890inline void ParsingEngine<C>::Parse_DocumentContent() {
1891        int final_state = Parse_ValidContent(model_info->rootModel);
1892        if (model_info->rootModel->transition_map[final_state][0]==0) {
1893                Validity_Error(vErr_elementvalid);
1894        }
1895}
1896
Note: See TracBrowser for help on using the repository browser.