source: trunk/src/engine.c @ 108

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