source: trunk/src/engine.c @ 110

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

Rename constraint errors XML_Error -> XML_Constraint.

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