source: trunk/src/engine.c @ 129

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

UTF-8 validation.

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