source: trunk/src/engine.c @ 111

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

Consolidation of error handling: xml_error.c

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