source: trunk/src/engine.c @ 98

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

Separate CharRef/EntityRef? routines

File size: 31.7 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
15#include <assert.h>
16#include <stdlib.h>
17#include <errno.h>
18#include <string.h>
19#include <string>
20#include <iostream>
21using namespace std;
22
23Parser_Interface * Parser_Interface::ParserFactory(char * filename, bool is_external) {
24       
25        int chars_read;
26        unsigned char signature[4];
27        FILE * infile;
28        infile = fopen(filename, "rb");
29        if (!infile) {
30                fprintf(stderr, "Error: cannot open %s for input.\n", filename);
31                exit(-1);
32        }
33        fread(signature,1,4,infile);
34        Model_Info * m = new Model_Info;
35        m->AnalyzeSignature(signature);
36        Byteplex * b = Byteplex::ByteplexFactory(m, infile);
37        b->InitializeBuffer(signature,4);
38
39        if (m->code_unit_base == ASCII) {
40                return new ParsingEngine<ASCII>(m, b, is_external);
41        }
42        else /* if (m->code_unit_base == EBCDIC) */ {
43                return new ParsingEngine<EBCDIC>(m, b, is_external);
44        }       
45}
46
47Parser_Interface::~Parser_Interface() {
48}
49
50
51bool Parser_Interface::has_ByteOrderMark() {
52        return model_info->BOM_units > 0;
53}
54
55XML_version Parser_Interface::get_version() {
56        return model_info->version;
57}
58
59XML_standalone Parser_Interface::standalone_status() {
60        return model_info->standalone;
61}
62
63bool Parser_Interface::has_EncodingDecl() {
64        return model_info->has_encoding_decl;
65}
66
67unsigned char * Parser_Interface::get_Encoding() {
68        return model_info->encoding;
69}
70
71unsigned char * Parser_Interface::GetCodeUnitPtr(int pos) {
72        int rel_pos = pos - buffer_base_pos;
73        return &((unsigned char *) (byteplex->src_buffer))[rel_pos * (int) model_info->code_unit_size];
74}
75
76
77
78
79template <CodeUnit_Base C>
80ParsingEngine<C>::ParsingEngine(Model_Info * m, Byteplex * b, bool is_external) : Parser_Interface () {
81
82        model_info = m;
83        byteplex = b;
84
85        byteplex->DoByteplex();
86        byteplex->PreparePseudoASCII_Stream();
87         StrictWellFormedness=false;
88        LastAttOccurrence.push_back(0);
89       
90        decl_parser = new XML_Decl_Parser<C>(byteplex);
91        int content_start = 0;
92        if(is_external == true)
93                content_start = decl_parser->ReadTextDeclaration(model_info);
94        else
95                content_start = decl_parser->ReadXMLInfo(model_info);
96       
97        bitplex = new Bitplex;
98        buf = (LexicalStreamSet *) simd_new(sizeof(LexicalStreamSet)/PACKSIZE);
99
100  /* Install sentinels for every lexical item stream*/
101#ifndef OPTIMIZE_SHORT_SCAN
102        BitBlock sentinel_value = simd_const_1(1);
103#endif
104#ifdef OPTIMIZE_SHORT_SCAN
105        BitBlock sentinel_value = sisd_sfli(simd_const_1(1), 8*sizeof(unsigned long));
106#endif
107        for (int j = minLexicalItem; j < LexicalItemCount; j++) {
108                buf->item_stream[j][BUFFER_BLOCKS] = sentinel_value;
109        }
110
111        buffer_base_pos = 0;
112        buffer_rel_pos = content_start;
113        buffer_limit_pos = min(BUFFER_SIZE, byteplex->units_in_buffer);
114        int blocks_in_buffer = (buffer_limit_pos + BLOCKSIZE - 1)/BLOCKSIZE;
115        x8data = byteplex->x8data;
116        lexer = Lexer<C>::LexerFactory(m, buf);
117        bitplex->TransposeToBitStreams(byteplex->x8data, blocks_in_buffer);
118        lexer->AnalyzeBuffer(bitplex->x8basis, buffer_limit_pos);
119}
120
121template <CodeUnit_Base C>
122ParsingEngine<C>::~ParsingEngine() {
123  model_info->~Model_Info();
124  byteplex->~Byteplex();
125  decl_parser->~XML_Decl_Parser<C>();
126  bitplex->~Bitplex();
127  simd_delete((SIMD_type *) buf);
128  lexer->~Lexer_Interface();
129}
130
131template <CodeUnit_Base C>
132inline void ParsingEngine<C>::AdvanceBuffers(int preserve_pos){
133        int advance_amt = min(preserve_pos, text_or_markup_start) - buffer_base_pos;
134        advance_amt &= -PACKSIZE; // maintain alignment
135        byteplex->AdvanceInputBuffer(advance_amt);
136        buffer_base_pos += advance_amt;
137        buffer_rel_pos -= advance_amt;
138        buffer_limit_pos = min(BUFFER_SIZE, byteplex->units_in_buffer);
139        int blocks_in_buffer = (buffer_limit_pos + BLOCKSIZE - 1)/BLOCKSIZE;
140        byteplex->DoByteplex();
141        byteplex->PreparePseudoASCII_Stream();
142        bitplex->TransposeToBitStreams(byteplex->x8data, blocks_in_buffer);
143        lexer->AnalyzeBuffer(bitplex->x8basis, buffer_limit_pos);
144}
145
146template <CodeUnit_Base C>
147inline unsigned char * ParsingEngine<C>::cur() const {
148  return &((unsigned char *) x8data)[buffer_rel_pos];
149}
150
151template <CodeUnit_Base C>
152inline int ParsingEngine<C>::AbsPos() const {
153  return buffer_base_pos + buffer_rel_pos;
154}
155
156template <CodeUnit_Base C>
157inline int ParsingEngine<C>::LengthFrom(int start_pos) const {
158  return buffer_base_pos + buffer_rel_pos - start_pos;
159}
160
161
162
163template <CodeUnit_Base C>
164inline int ParsingEngine<C>::BufferRelPos() const {
165  return buffer_rel_pos;
166}
167
168
169template <CodeUnit_Base C>
170inline bool ParsingEngine<C>::at_EOF() const {
171  return (buffer_rel_pos >= buffer_limit_pos) && 
172         (buffer_limit_pos < BUFFER_SIZE);
173}
174
175template <CodeUnit_Base C>
176inline void ParsingEngine<C>::Advance(int n) {
177        int preserve_pos;
178        buffer_rel_pos += n;
179#ifndef OMIT_BITBUFFER_LIMIT_TEST_IN_ADVANCE
180  if (buffer_rel_pos >= BUFFER_SIZE) {
181        FinalizeBuffer_action(preserve_pos);
182        AdvanceBuffers(preserve_pos);
183  }
184#endif
185}
186
187
188#ifndef OPTIMIZE_SHORT_SCAN
189template <CodeUnit_Base C>
190inline void ParsingEngine<C>::ScanTo(int item) {
191        int preserve_pos;
192  buffer_rel_pos = bitstream_scan(buf->item_stream[item], 
193                                      buffer_rel_pos);
194  while (buffer_rel_pos >= BUFFER_SIZE) {
195        FinalizeBuffer_action(preserve_pos);
196        AdvanceBuffers(preserve_pos);
197        buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
198  }
199}
200#endif
201
202template <CodeUnit_Base C>
203inline void ParsingEngine<C>::ScanToMarkupStart() {
204        int preserve_pos;
205        text_or_markup_start = AbsPos();
206        buffer_rel_pos = bitstream_scan(buf->item_stream[MarkupStart], buffer_rel_pos);
207        while (buffer_rel_pos >= BUFFER_SIZE) {
208                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
209                text_or_markup_start = AbsPos();
210                FinalizeBuffer_action(preserve_pos);
211                AdvanceBuffers(preserve_pos);
212                buffer_rel_pos = bitstream_scan(buf->item_stream[MarkupStart], buffer_rel_pos);
213        }
214}
215
216template <CodeUnit_Base C>
217inline void ParsingEngine<C>::ScanToCD_End_check() {
218        int preserve_pos;
219        buffer_rel_pos = bitstream_scan(buf->item_stream[CD_End_check], buffer_rel_pos);
220        while (buffer_rel_pos >= BUFFER_SIZE) {
221                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
222                text_or_markup_start = AbsPos();
223                FinalizeBuffer_action(preserve_pos);
224                AdvanceBuffers(preserve_pos);
225                buffer_rel_pos = bitstream_scan(buf->item_stream[CD_End_check], buffer_rel_pos);
226        }
227}
228
229#ifdef OPTIMIZE_SHORT_SCAN
230template <CodeUnit_Base C>
231inline void ParsingEngine<C>::ScanTo(int item) {
232  SIMD_type * stream = buf->item_stream[item];
233  unsigned long * bitstream_ptr = (unsigned long *) (((intptr_t) stream) + buffer_rel_pos/8);
234  unsigned long bitstream_slice = *bitstream_ptr >> buffer_rel_pos % 8;
235  if (bitstream_slice != 0) {
236    buffer_rel_pos += __builtin_ctzl(bitstream_slice);
237  }
238  else {
239    buffer_rel_pos = (buffer_rel_pos & -8) + 8*sizeof(unsigned long);
240    buffer_rel_pos += bitstream_scan0((SIMD_type *) &bitstream_ptr[1]);
241    while (buffer_rel_pos >= BUFFER_BLOCKS * BLOCKSIZE) {
242      buffer_rel_pos = BUFFER_BLOCKS * BLOCKSIZE;
243      FinalizeBuffer_action(preserve_pos);
244          AdvanceBuffers(preserve_pos);
245      buffer_rel_pos = bitstream_scan(buf->item_stream[item], buffer_rel_pos);
246    }
247  }
248}
249#endif
250
251template <CodeUnit_Base C>
252inline void ParsingEngine<C>::WF_Error (XML_Error errCode) {
253        ShowConstraintError(errCode);
254        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
255}
256       
257
258template <CodeUnit_Base C>
259inline void ParsingEngine<C>::Validity_Error (XML_Error errCode) {
260        ShowConstraintError(errCode);
261        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
262}
263       
264template <CodeUnit_Base C>
265inline void ParsingEngine<C>::Syntax_Error (XML_NonTerminal errNT) {
266        ShowSyntaxError(errNT);
267        Error_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
268}
269       
270
271/* Parse a comment beginning "<!--" */
272template <CodeUnit_Base C>
273inline void ParsingEngine<C>::Parse_Comment() {
274
275        Advance(4); /* Skip "<!--". */
276        ScanTo(Hyphen);
277        while (!at_DoubleHyphen<C>(cur())) {
278                Advance(2); /* Skip hyphen-nonhyphen pair */
279                ScanTo(Hyphen); 
280        }
281        if (at_Comment_End<C>(cur())) {
282                Advance(3); /* Skip "-->". */
283                Comment_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
284        }
285        else {
286                Advance(2);  /* "--" */
287                Syntax_Error(NT_Comment);
288        }
289}
290
291/* Parse an end tag beginning "</" */
292template <CodeUnit_Base C>
293inline void ParsingEngine<C>::Parse_EndTag() {
294        Advance(2); /* Skip "</". */
295        ScanTo(NameFollow);
296        if (AtChar<C,'>'>(cur())) {
297                Advance(1);
298                EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
299        }
300        else {
301                ScanTo(NonWS);
302                if (AtChar<C,'>'>(cur())) {
303                        Advance(1);
304                        EndTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
305                }
306                else Syntax_Error(NT_ETag);
307        }
308}
309
310/* Parse a CDATA section beginning "<![CDATA". */
311template <CodeUnit_Base C>
312inline void ParsingEngine<C>::Parse_CDATA() {
313        Advance(8); /* Skip "<![CDATA". */
314        if (!AtChar<C,'['>(cur())) {
315                Syntax_Error(NT_CDStart);
316        }
317        else { 
318                Advance(1);
319                CDATA_start_action(GetCodeUnitPtr(text_or_markup_start));
320                text_or_markup_start = AbsPos();
321                ScanTo(CD_End_check);
322                while (!at_CDATA_End<C>(cur())) {
323                        Advance(1);
324                        ScanTo(CD_End_check);
325                }
326                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
327                Advance(3); /* Skip "]]>". */
328                CDATA_end_action(GetCodeUnitPtr(AbsPos()));
329        }
330}
331
332template <CodeUnit_Base C>
333inline void ParsingEngine<C>::Parse_EntityRef() {
334        Advance(1);  // skip "&"
335        ScanTo(NameFollow);  /* Name delimiter */
336        if (!AtChar<C,';'>(cur())) {
337                Syntax_Error(NT_Reference);
338        }
339        else {
340                Advance(1);
341                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
342        }
343}
344
345template <CodeUnit_Base C>
346inline void ParsingEngine<C>::Parse_CharRef() {
347        Advance(2);  // skip "&#"
348        ScanTo(NameFollow);  /* Name delimiter */
349        if (!AtChar<C,';'>(cur())) {
350                Syntax_Error(NT_Reference);
351        }
352        else {
353                Advance(1);
354                Reference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
355        }
356}
357
358template <CodeUnit_Base C>
359inline void ParsingEngine<C>::Parse_PI (){
360        Advance(2); /* Skip "<?". */
361        int target_start = AbsPos();
362        // Check for illegal [Xx][Mm][Ll] target.
363        if (at_XxMmLll_WS<C>(cur())) {
364                Advance(4);
365                Syntax_Error(NT_PI);
366                return;
367        } 
368        ScanTo(NameFollow);  /* Name delimiter */
369        PI_Target_action(GetCodeUnitPtr(target_start), LengthFrom(target_start));
370        ScanTo(QMark);
371        while (!at_PI_End<C>(cur())) {
372                Advance(1);
373                ScanTo(QMark);
374        }
375        Advance(2); /* Skip "?>". */
376        PI_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
377}
378 
379/* Parse a start or empty element tag. */
380template <CodeUnit_Base C>
381inline void ParsingEngine<C>::Parse_StartTag (){
382        int att_name_start;
383        int att_val_start;
384        int att_name_end, att_val_end;
385        unsigned char quoteCh;
386        Advance(1);
387        ScanTo(NameFollow);  /* Name delimiter: WS, "/" or ">" */
388        ElementName_action(GetCodeUnitPtr(text_or_markup_start+1), LengthFrom(text_or_markup_start+1));
389        /* The following test optimizes the most common case of a
390        start tag with no attributes.  */
391        if (AtChar<C,'>'>(cur())) {
392                Advance(1);
393                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
394        }
395        else {
396                ScanTo(NonWS);
397                if (AtChar<C,'>'>(cur())) {
398                        Advance(1);
399                        StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
400                }
401                else if (at_EmptyElementDelim<C>(cur())) {
402                        Advance(2);
403                        EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
404                }
405                else do {
406                        /* Must be an attribute-value pair or error. */
407                        att_name_start = AbsPos();
408                        ScanTo(NameFollow);
409                        att_name_end = AbsPos();
410                        int lgth = att_name_end-att_name_start;
411               
412                        int attID = model_info->getOrInsertGlobalAttName(GetCodeUnitPtr(att_name_start), lgth);
413                        if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
414                        else {
415                                if (LastAttOccurrence[attID] > text_or_markup_start) {
416                                        WF_Error(wfErr_uniqattspec); /* Duplicate attribute. */
417                                        break;
418                                }                       
419                        }
420                        LastAttOccurrence[attID] = att_name_start;
421                        /* The following optimized tests handle the frequently occurring
422                        case that there are no blanks on either side of the equals sign.
423                        In many cases, the very first test handles 100% of actual
424                        attribute-value pairs encountered. */
425                        if (at_EqualsQuote<C>(cur())) Advance(1); 
426                        else {
427                                ScanTo(NonWS);
428                                if (!AtChar<C,'='>(cur())) {
429                                        Syntax_Error(NT_STag); 
430                                        break;
431                                }
432                                ScanTo(NonWS);
433                                if (!AtQuote<C>(cur())) {
434                                        Syntax_Error(NT_STag); 
435                                        break;
436                                }
437                        }
438                        att_val_start = AbsPos()+1;
439                        Parse_AttValue();
440                        att_val_end = AbsPos()-1;
441                        if (at_xmlns<C>(cur()+att_name_start-AbsPos())) {
442                                Namespace_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
443                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
444                        }
445                        else {
446                                AttributeValue_action(GetCodeUnitPtr(att_name_start), att_name_end - att_name_start,
447                                                 GetCodeUnitPtr(att_val_start), att_val_end - att_val_start);
448                        }
449                        /* Now check for end or repeat. Avoid whitespace scan if possible.*/
450                        if (AtChar<C,'>'>(cur())) {
451                                Advance(1);
452                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
453                                break;
454                        }
455                        else if (at_EmptyElementDelim<C>(cur())) {
456                                Advance(2);
457                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
458                                break;
459                        }
460                        ScanTo(NonWS);
461                        if (AtChar<C,'>'>(cur())) {
462                                Advance(1);
463                                StartTag_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
464                                break;
465                        }
466                        else if (at_EmptyElementDelim<C>(cur())) {
467                                Advance(2);
468                                EmptyElement_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
469                                break;
470                        }
471                        else if (AbsPos() == att_val_end + 1) { 
472                                /* No WS following att value */
473                                Syntax_Error(NT_STag);
474                                break;
475                        }
476                } while (1);
477        }
478}
479
480template <CodeUnit_Base C>
481inline void ParsingEngine<C>::text_if_nonnull_action(){
482        if (AbsPos() > text_or_markup_start) {
483                Text_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
484                text_or_markup_start = AbsPos();
485        }
486}
487
488template <CodeUnit_Base C>
489inline void ParsingEngine<C>::ParseContent() {
490        DocumentStart_action(); 
491        do {
492                text_or_markup_start = AbsPos();
493                ScanToMarkupStart(); /* '<', '&', or ']' for ']]>' test */
494/*              if (AtChar<C,'<'>(cur())) {
495                        text_if_nonnull_action();
496                        Parse_Markup<C>();
497                }*/
498                if (at_ElementTag_Start<C>(cur())) {
499                        text_if_nonnull_action();
500                        Parse_StartTag();
501                }
502                else if (at_EndTag_Start<C>(cur())) {
503                        text_if_nonnull_action();
504                        Parse_EndTag();
505                }
506                else if (at_Comment_Start<C>(cur())) {
507                        text_if_nonnull_action();
508                        Parse_Comment();
509                }
510                else if (at_CharRef_Start<C>(cur())) {
511                        text_if_nonnull_action();
512                        Parse_CharRef();
513                }
514                else if (AtChar<C,'&'>(cur())) {
515                        text_if_nonnull_action();
516                        Parse_EntityRef();
517                }
518                else if (at_CDATA_Start<C>(cur())) {
519                        text_if_nonnull_action();
520                        Parse_CDATA();
521                }
522                else if (at_PI_Start<C>(cur())) {
523                        text_if_nonnull_action();
524                        Parse_PI();
525                }
526                else if (at_CDATA_End<C>(cur())) {
527                        text_if_nonnull_action();
528                        Advance(3);
529                        Syntax_Error(NT_CharData);
530                }
531                else if (at_EOF()) {
532                        text_if_nonnull_action();
533                        break;
534                }
535                else {
536                        Advance(1);
537                        continue;
538                }
539        } while (1);
540        DocumentEnd_action();   
541}
542
543
544template <CodeUnit_Base C>
545inline void ParsingEngine<C>::Parse_DocType (){
546
547        int old_abspos, start_pos;
548        ScanTo(NonWS);
549        start_pos = AbsPos();
550       
551        if (at_DOCTYPE_start<C>(cur()))
552        Advance(9);
553        else{
554//              printf("No Document definition!\n");
555                return;
556        }
557        requireWS();
558       
559        ScanTo(NameFollow);
560       
561        old_abspos = AbsPos(); 
562    ScanTo(NonWS);
563    if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
564        if(old_abspos == AbsPos())
565                Syntax_Error(NT_doctypedecl);
566        Parse_ExternalID();
567    }
568   
569    ScanTo(NonWS);     
570
571        if (AtChar<C,'['>(cur())){
572                Advance(1);
573                Parse_IntSubset();
574                if (AtChar<C,']'>(cur()))
575                        Advance(1);
576                else
577                Syntax_Error(NT_doctypedecl);
578                ScanTo(NonWS);
579        }
580       
581        if (AtChar<C,'>'>(cur())){
582                Advance(1);   
583                Doctype_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
584        }
585}
586
587template <CodeUnit_Base C>
588inline void ParsingEngine<C>::Parse_ExternalID (){
589
590        if(at_SYSTEM<C>(cur())){
591                Advance(6);
592                requireWS();
593                Parse_MatchedQuote (); /*  SystemLiteral */
594        }
595        else if (at_PUBLIC<C>(cur())){
596                Advance(6);
597                requireWS();
598                Parse_MatchedQuote ();/*  PubidLiteral */
599                requireWS();
600                Parse_MatchedQuote ();/*  SystemLiteral */
601        }
602        else
603                Syntax_Error(NT_ExternalID); 
604}
605
606template <CodeUnit_Base C>
607inline void ParsingEngine<C>::Parse_MatchedQuote (){
608        unsigned char quoteCh;
609        if(AtQuote<C>(cur())){
610                quoteCh = cur()[0];
611                Advance(1);
612        }
613        ScanTo(Quote);                 
614        while (cur()[0] != quoteCh){
615                Advance(1);
616                ScanTo(Quote);
617        }
618        Advance(1);
619}
620
621template <CodeUnit_Base C>
622inline void ParsingEngine<C>::Parse_IntSubset (){
623       
624        while(1){
625                ScanTo(NonWS); 
626                text_or_markup_start = AbsPos();
627                if (AtChar<C,'%'>(cur()))
628                        Parse_PEReference();   
629                else if (AtChar<C,'<'>(cur())){
630                        Advance(1);
631
632                        if (AtChar<C,'?'>(cur())){
633                                Parse_PI();
634                        }
635                        else if(AtChar<C,'!'>(cur())){
636                                Advance(1);
637                                if(at_DoubleHyphen<C>(cur()))
638                                        Parse_Comment();
639                                else if(at_ELEMENT<C>(cur()))
640                                        Parse_Elementdecl();
641                                else if(at_ATTLIST<C>(cur()))
642                                        Parse_AttlistDecl();
643                                else if(at_ENTITY<C>(cur()))
644                                        Parse_Entitydecl();
645                                else if(at_NOTATION<C>(cur()))
646                                        Parse_Notationdecl();
647                                else{
648                                        Syntax_Error(NT_markupdecl);           
649                                }                                                               
650                        }
651                        else
652                                Syntax_Error(NT_markupdecl); 
653                }
654                else if (AtChar<C,']'>(cur())){
655                        break;
656                }
657                else
658                        Syntax_Error(NT_intSubset); 
659        }
660}
661
662
663template <CodeUnit_Base C>
664inline void ParsingEngine<C>::Parse_PEReference (){
665
666        Advance(1); /* Skip "%". */
667        ScanTo(NameFollow); 
668        if (AtChar<C,';'>(cur())) {
669                Advance(1);
670                PEReference_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
671        }
672        else
673                Syntax_Error(NT_PEReference);
674}
675
676
677template <CodeUnit_Base C>
678inline void ParsingEngine<C>::Parse_Elementdecl (){
679
680        Advance(7); /* Skip "<!ELEMENT". */
681
682    requireWS();
683    int name_start = AbsPos();
684        ScanTo(NameFollow);
685        int lgth = AbsPos() - name_start;
686        int elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
687        requireWS();
688       
689        /* Start parsing "contentspec"*/
690        if (at_EMPTY<C>(cur()))
691        Advance(5);
692    else if (at_ANY<C>(cur()))
693        Advance(3);
694    else {
695        if (AtChar<C,'('>(cur()))
696                        Advance(1);
697                ScanTo(NonWS);
698                if (at_PCDATA<C>(cur()))
699                        Parse_RemainingMixed();
700                else
701                        Parse_RemainingChildren();
702    }
703               
704        if (AtChar<C,'>'>(cur())) {
705                Advance(1);
706                Elementdecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
707        }
708        else
709                Syntax_Error(NT_elementdecl);
710}
711template <CodeUnit_Base C>
712inline void ParsingEngine<C>::Parse_RemainingMixed (){
713       
714        Advance(7);  /* Skip "#PCDATA". */
715   
716    if (AtChar<C,')'>(cur())){
717        if (AtChar<C,'*'>(cur()))
718                Advance(2);
719                else
720                        Advance(1);
721    }
722    else{
723        ScanTo(NonWS);
724        while(!at_Para_star<C>(cur())){
725                if (AtChar<C,'|'>(cur())){
726                                Advance(1);
727                                ScanTo(NonWS);
728                                ScanTo(NameFollow);
729                                ScanTo(NonWS);
730                }
731        }
732        Advance(2);
733    }
734}
735
736
737template <CodeUnit_Base C>
738inline void ParsingEngine<C>::Parse_RemainingChildren (){
739        Parse_Cp();
740        ScanTo(NonWS);
741        if(AtChar<C,'|'>(cur())){
742                Advance(1);
743                ScanTo(NonWS);
744                Parse_Cp();
745                ScanTo(NonWS);
746                while(!AtChar<C,')'>(cur())){
747                        if(AtChar<C,'|'>(cur()))
748                                Advance(1);
749                        ScanTo(NonWS);
750                        Parse_Cp();
751                        ScanTo(NonWS);
752                }
753                Advance(1);
754        }
755        else if(AtChar<C,','>(cur())){
756                Advance(1);
757                ScanTo(NonWS);
758                Parse_Cp();
759                ScanTo(NonWS);
760                while(!AtChar<C,')'>(cur())){
761                        if(AtChar<C,','>(cur()))
762                                Advance(1);
763                        ScanTo(NonWS);
764                        Parse_Cp();
765                        ScanTo(NonWS);
766                }
767                Advance(1);
768        }       
769        else if(AtChar<C,')'>(cur())){
770                Advance(1);
771        }
772        else
773                Syntax_Error(NT_children);
774               
775        if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
776                Advance(1);
777}
778
779template <CodeUnit_Base C>
780inline void ParsingEngine<C>::Parse_Cp (){
781        if (AtChar<C,'('>(cur())){
782                Advance(1);
783                ScanTo(NonWS);
784                Parse_RemainingChildren();
785        }
786        else{
787                ScanTo(NameFollow);
788                if (AtChar<C,'?'>(cur())||AtChar<C,'*'>(cur())||AtChar<C,'+'>(cur()))
789                        Advance(1);
790        }
791}
792
793template <CodeUnit_Base C>
794inline void ParsingEngine<C>::Parse_AttlistDecl (){
795       
796        int old_abspos;
797       
798        int name_start;
799        int lgth;
800       
801        int elemID;
802        int attID;
803       
804        Advance(7); /* Skip "ATTLIST. */
805        requireWS();
806       
807        name_start = AbsPos();
808        ScanTo(NameFollow);
809        lgth = AbsPos()-name_start;
810        elemID = model_info->getOrInsertGlobalElement(GetCodeUnitPtr(name_start), lgth);
811       
812        old_abspos = AbsPos();
813        ScanTo(NonWS);
814        while(!AtChar<C,'>'>(cur())) {
815                if(old_abspos == AbsPos())
816                Syntax_Error(NT_AttlistDecl);
817               
818        name_start = AbsPos();
819                ScanTo(NameFollow);
820                lgth = AbsPos()-name_start;
821               
822                attID = model_info->getOrInsertGlobalAttName(GetCodeUnitPtr(name_start), lgth);
823                if (attID >= LastAttOccurrence.size()) LastAttOccurrence.push_back(0);
824        ATT_info * this_info = new ATT_info;
825        this_info->globalATT_id = attID;
826        requireWS();
827        if (at_CDATA<C>(cur())){
828                Advance(5);
829                this_info->attType = CDATA_att;
830        }
831        else if(at_ID<C>(cur())){
832                Advance(2);
833                this_info->attType = ID_att;
834        }
835        /* Make sure to check IDREFS before IDREF*/
836        else if(at_IDREFS<C>(cur())){
837                Advance(6);
838                this_info->attType = IDREFS_att;
839        }
840        else if(at_IDREF<C>(cur())){
841                Advance(5);
842                this_info->attType = IDREF_att;
843        }
844        else if(at_ENTITY<C>(cur())){
845                Advance(6);
846                this_info->attType = ENTITY_att;
847        }
848        else if(at_ENTITIES<C>(cur())){
849                Advance(8);
850                this_info->attType = ENTITIES_att;
851        }
852        /* Make sure to check NMTOKENS before NMTOKEN*/
853        else if(at_NMTOKENS<C>(cur())){
854                Advance(8);
855                this_info->attType = NMTOKENS_att;
856        }
857        else if(at_NMTOKEN<C>(cur())){
858                Advance(7);
859                this_info->attType = NMTOKEN_att;
860        }
861        else if(at_NOTATION<C>(cur())){ /* NotationType = 'NOTATION' S Enumeration
862                                                                         when Nmtoken = Name */
863                Advance(8);
864                        requireWS();
865                Parse_Notation(this_info);
866                this_info->attType = NOTATION_att;
867        }
868        else if(AtChar<C,'('>(cur())){
869                Parse_Enumeration(this_info);
870                this_info->attType = enumeration_att;
871        }
872        else
873                Syntax_Error(NT_AttlistDecl);
874        requireWS();
875        Parse_DefaultDecl(this_info);
876
877                ScanTo(NonWS);
878                model_info->ElementAttributeData[elemID].push_back(this_info);
879        }
880
881        Advance(1);
882        AttlistDecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
883}
884
885template <CodeUnit_Base C>
886inline void ParsingEngine<C>::Parse_Notation (ATT_info * this_info){
887
888        if(AtChar<C,'('>(cur()))
889                Advance(1);
890        else
891                Syntax_Error(NT_NotationType);
892        ScanTo(NonWS);
893       
894    int name_start = AbsPos();
895        ScanTo(NameFollow);
896        int     lgth = AbsPos()-name_start;
897       
898        char *s = new char[lgth+1];
899        memcpy(s, GetCodeUnitPtr(name_start), lgth);
900        s[lgth] = '\0';
901
902        /*Notation name is not in the global table!*/
903        if(model_info->GlobalNotationTable[s]==0)
904                Validity_Error(vErr_notatn);
905       
906        ScanTo(NonWS);
907        while(AtChar<C,'|'>(cur())){
908                Advance(1);
909                ScanTo(NonWS);         
910                name_start = AbsPos();
911                ScanTo(NameFollow);
912                lgth = AbsPos()-name_start;
913       
914                char *s = new char[lgth+1];
915                memcpy(s, GetCodeUnitPtr(name_start), lgth);
916                s[lgth] = '\0';
917       
918                if(model_info->GlobalNotationTable[s]==0)
919                        Validity_Error(vErr_notatn);
920                       
921                ScanTo(NonWS);
922        }
923        if (AtChar<C,')'>(cur())) 
924                Advance(1);
925        else
926                Syntax_Error(NT_NotationType);
927}
928
929template <CodeUnit_Base C>
930inline void ParsingEngine<C>::Parse_Enumeration (ATT_info * this_info){
931
932        int enumCount=0;
933        if(AtChar<C,'('>(cur()))
934                Advance(1);
935        else
936                Syntax_Error(NT_Enumeration);
937        ScanTo(NonWS);
938       
939        int     name_start = AbsPos();
940        ScanTo(NameFollow);
941        int     lgth = AbsPos()-name_start;
942       
943        char *s = new char[lgth+1];
944        memcpy(s, GetCodeUnitPtr(name_start), lgth);
945        s[lgth] = '\0';
946       
947        this_info->enumValues[s]=++(enumCount);
948       
949        ScanTo(NonWS);
950        while(AtChar<C,'|'>(cur())){
951                Advance(1);
952                ScanTo(NonWS);         
953                name_start = AbsPos();
954                ScanTo(NameFollow);
955                lgth = AbsPos()-name_start;
956       
957                char *s = new char[lgth+1];
958                memcpy(s, GetCodeUnitPtr(name_start), lgth);
959                s[lgth] = '\0';
960       
961                int enumID = this_info->enumValues[s];
962                if(enumID==0){ 
963                        this_info->enumValues[s]=++(enumCount);
964                        enumID = enumCount;
965                }
966                else if(!StrictWellFormedness){
967                        Validity_Error(vErr_NoDuplicateTokens);
968                }
969                ScanTo(NonWS);
970        }
971        if (AtChar<C,')'>(cur())) 
972                Advance(1);
973        else
974                Syntax_Error(NT_Enumeration);
975}
976
977template <CodeUnit_Base C>
978inline void ParsingEngine<C>::Parse_DefaultDecl (ATT_info * this_info){
979        if(at_REQUIRED<C>(cur())){
980                Advance(9);
981                this_info->defaultKind = REQUIRED_att;
982        }
983        else if(at_IMPLIED<C>(cur())){
984                Advance(8);
985                this_info->defaultKind = IMPLIED_att;
986        }
987        else {
988                if(at_FIXED<C>(cur())){
989                        Advance(6);
990                        requireWS();
991                        this_info->defaultKind = FIXED_att;
992                }
993                else this_info->defaultKind = DEFAULT_att;
994                if(AtQuote<C>(cur())){
995                        int quot_start = AbsPos()+1;
996                        Parse_AttValue();
997                        /* need to normalize */
998                        this_info->defaultValueLgth = AbsPos() - quot_start - 1;
999                       
1000                        this_info->defaultValue = new unsigned char[this_info->defaultValueLgth+1];
1001                        memcpy(this_info->defaultValue, GetCodeUnitPtr(quot_start),this_info->defaultValueLgth); 
1002                        this_info->defaultValue[this_info->defaultValueLgth] = '\0';
1003                        }
1004                else
1005                        Syntax_Error(NT_DefaultDecl);
1006        }
1007}
1008
1009template <CodeUnit_Base C>
1010inline void ParsingEngine<C>::Parse_Entitydecl (){
1011       
1012        int name_start;
1013        int lgth;
1014        int old_abspos;
1015        Advance(6); /* Skip "ENTITY. */
1016        requireWS();
1017       
1018        if (AtChar<C,'%'>(cur())){
1019                Advance(1);
1020                requireWS();
1021               
1022                name_start = AbsPos();
1023                ScanTo(NameFollow);
1024                lgth = AbsPos()- name_start;
1025                char *s = new char[lgth+1];
1026                memcpy(s, GetCodeUnitPtr(name_start), lgth);
1027                s[lgth] = '\0';
1028       
1029                int entityID = model_info->GlobalEntityTable[s];
1030                if(entityID==0){       
1031                        model_info->GlobalEntityTable[s]=++(model_info->globalEntityCount);
1032                        entityID = model_info->globalEntityCount;
1033                }
1034                else
1035                        printf("Warning: Entity definition already exist!\n");
1036       
1037                requireWS();
1038                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
1039                Parse_ExternalID();     
1040        }
1041        else if(AtQuote<C>(cur())){
1042                Parse_AttValue(); /* Not parse PEReference*/
1043        }
1044        else
1045                Syntax_Error(NT_EntityDecl);
1046        }
1047        else{
1048                name_start = AbsPos();
1049                ScanTo(NameFollow);
1050                lgth = AbsPos()- name_start;
1051                char *s = new char[lgth+1];
1052                memcpy(s, GetCodeUnitPtr(name_start), lgth);
1053                s[lgth] = '\0';
1054       
1055                int entityID = model_info->GlobalEntityTable[s];
1056                if(entityID==0){       
1057                        model_info->GlobalEntityTable[s]=++(model_info->globalEntityCount);
1058                        entityID = model_info->globalEntityCount;
1059                }
1060                else
1061                        printf("Warning: Entity definition already exist!\n");
1062                       
1063                requireWS();
1064               
1065                if(at_SYSTEM<C>(cur())||at_PUBLIC<C>(cur())){
1066                Parse_ExternalID();
1067                ScanTo(NonWS);
1068                if(at_NDATA<C>(cur())){
1069                        if(old_abspos == AbsPos())
1070                                Syntax_Error(NT_EntityDecl);
1071                        else
1072                                Advance(5);
1073                        requireWS();
1074                        ScanTo(NameFollow);
1075                }
1076        }
1077        else if(AtQuote<C>(cur())){
1078                Parse_AttValue(); /* Not parse PEReference*/
1079        }
1080        else
1081                Syntax_Error(NT_EntityDecl);
1082        }
1083        ScanTo(NonWS);
1084        if (AtChar<C,'>'>(cur())){
1085                Advance(1);
1086                Entitydecl_action(GetCodeUnitPtr(name_start), lgth, 
1087                                  GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1088        }
1089        else
1090                Syntax_Error(NT_EntityDecl);
1091}
1092
1093template <CodeUnit_Base C>
1094inline void ParsingEngine<C>::Parse_Notationdecl (){
1095
1096        int old_abspos;
1097        Advance(8); /* Skip "NOTATION. */
1098        requireWS();
1099       
1100        int name_start = AbsPos();
1101        ScanTo(NameFollow);
1102        int     lgth = AbsPos()-name_start;
1103       
1104        char *s = new char[lgth+1];
1105        memcpy(s, GetCodeUnitPtr(name_start), lgth);
1106        s[lgth] = '\0';
1107
1108        int notationID = model_info->GlobalNotationTable[s];
1109        if(notationID==0){     
1110                model_info->GlobalNotationTable[s]=++(model_info->globalNotationCount);
1111                notationID = model_info->globalNotationCount;
1112        }
1113        else /*Duplicate notation name!*/
1114                Validity_Error(vErr_NoDuplicateTokens);
1115               
1116        requireWS();
1117        if(at_SYSTEM<C>(cur())){
1118                Advance(6);
1119                requireWS();
1120                Parse_MatchedQuote (); /*  SystemLiteral */
1121        }
1122        else if (at_PUBLIC<C>(cur())){
1123                Advance(6);
1124                requireWS();
1125                Parse_MatchedQuote (); /*  PubidLiteral */
1126                ScanTo(NonWS);
1127                if (!AtChar<C,'>'>(cur())){
1128                        if (old_abspos == AbsPos())
1129                                Syntax_Error(NT_NotationDecl);
1130                        Parse_MatchedQuote (); /*  SystemLiteral */
1131                }
1132        }
1133        else
1134                Syntax_Error(NT_NotationDecl);
1135        ScanTo(NonWS);
1136        if (AtChar<C,'>'>(cur())) {
1137                Advance(1);
1138                Notationdecl_action(GetCodeUnitPtr(text_or_markup_start), LengthFrom(text_or_markup_start));
1139        }
1140        else
1141                Syntax_Error(NT_NotationDecl);
1142}
1143
1144template <CodeUnit_Base C>
1145inline void ParsingEngine<C>::requireWS(){
1146       
1147    int old_abspos = AbsPos(); 
1148    ScanTo(NonWS);
1149    if(old_abspos == AbsPos())
1150        Syntax_Error(NT_S);
1151}
1152
1153template <CodeUnit_Base C>
1154inline void ParsingEngine<C>::Parse_AttValue(){
1155       
1156        int     quoteCh = cur()[0];
1157        Advance(1); /* Skip " or ' */
1158
1159        ScanTo(Quote);                 
1160        while (cur()[0] != quoteCh){
1161                if (at_CharRef_Start<C>(cur())){
1162                        Parse_CharRef();
1163                        ScanTo(Quote);
1164                }
1165                else if (AtChar<C,'&'>(cur())){
1166                        Parse_EntityRef();
1167                        ScanTo(Quote);
1168                }
1169                else if (AtQuote<C>(cur())) {
1170                        Advance(1);
1171                        ScanTo(Quote);
1172                }
1173                else /* if (AtChar<C,'<'>(cur())) */
1174                        WF_Error(wfErr_CleanAttrVals);
1175        }
1176        Advance(1);
1177}
1178
1179template <CodeUnit_Base C>
1180inline void ParsingEngine<C>::Parse_Prolog(){
1181        ScanTo(NonWS);
1182        int old_pos = AbsPos();
1183        while (!at_DOCTYPE_start<C>(cur())) {
1184                if (at_Comment_Start<C>(cur())) 
1185                        Parse_Comment();
1186                else if (at_PI_Start<C>(cur()))
1187                                Parse_PI();
1188                else{
1189                        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1190                        return;
1191                }
1192                ScanTo(NonWS);
1193        }
1194        Parse_DocType();
1195        ScanTo(NonWS);
1196        while(at_Comment_Start<C>(cur()) || at_PI_Start<C>(cur()) ){
1197                if (at_Comment_Start<C>(cur()))
1198                        Parse_Comment();
1199                else 
1200                        Parse_PI();
1201                ScanTo(NonWS);
1202        }
1203        Prolog_action(GetCodeUnitPtr(old_pos), LengthFrom(old_pos));
1204}
1205
1206template <CodeUnit_Base C>
1207inline void ParsingEngine<C>::ExtSubsetDecl_action(unsigned char * item, int lgth) {
1208}
1209
1210template <CodeUnit_Base C>
1211inline void ParsingEngine<C>::Parse_ExtSubsetDecl() {
1212        int start_pos=AbsPos();
1213        while(!at_EOF()){
1214                if(at_condSect_start<C>(cur())){               
1215                        Advance(3);
1216                        ScanTo(NonWS);
1217                        if (at_INCLUDE<C>(cur())){
1218                                Advance(7);
1219                                ScanTo(NonWS);
1220                                if(AtChar<C,'['>(cur())){
1221                                        Advance(1);
1222                                        Parse_ExtSubsetDecl();
1223                                        if(at_CDATA_End<C>(cur()))
1224                                                Advance(3);
1225                                        else Syntax_Error(NT_includeSect);
1226                                }
1227                                else Syntax_Error(NT_includeSect);
1228                        }
1229                        else if (at_IGNORE<C>(cur())){
1230                                Advance(6);
1231                                ScanTo(NonWS);         
1232                                if(AtChar<C,'['>(cur())){
1233                                        int section_depth=1;
1234                                        Advance(1);
1235                                        while(!at_EOF()){
1236                                                ScanToMarkupStart();
1237                                                if(at_condSect_start<C>(cur())){
1238                                                        Advance(3);
1239                                                        section_depth++;
1240                                                }
1241                                                else if(at_CDATA_End<C>(cur())){
1242                                                        Advance(3);
1243                                                        section_depth--;
1244                                                }
1245                                                if(section_depth==0) return;                                   
1246                                        }
1247                                        Syntax_Error(NT_ignoreSectContents);   
1248                                }
1249                                else Syntax_Error(NT_ignoreSect);
1250                        }
1251                        else Syntax_Error(NT_conditionalSect);
1252                }
1253                else if (AtChar<C,'%'>(cur()))
1254                        Parse_PEReference();   
1255                else if (AtChar<C,'<'>(cur())){
1256                        Advance(1);
1257
1258                        if (AtChar<C,'?'>(cur())){
1259                                Parse_PI();
1260                        }
1261                        else if(AtChar<C,'!'>(cur())){
1262                                Advance(1);
1263                                if(at_DoubleHyphen<C>(cur()))
1264                                        Parse_Comment();
1265                                else if(at_ELEMENT<C>(cur()))
1266                                        Parse_Elementdecl();
1267                                else if(at_ATTLIST<C>(cur()))
1268                                        Parse_AttlistDecl();
1269                                else if(at_ENTITY<C>(cur()))
1270                                        Parse_Entitydecl();
1271                                else if(at_NOTATION<C>(cur()))
1272                                        Parse_Notationdecl();                                   
1273                                else{
1274                                        Syntax_Error(NT_markupdecl);   
1275                                }                                                               
1276                        }
1277                        else
1278                                Syntax_Error(NT_markupdecl); 
1279                }
1280                else
1281                        Syntax_Error(NT_extSubsetDecl); 
1282                ScanTo(NonWS);
1283        }
1284        ExtSubsetDecl_action(GetCodeUnitPtr(start_pos), LengthFrom(start_pos));
1285}
Note: See TracBrowser for help on using the repository browser.