source: trunk/src/engine.c @ 180

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

Adding boolean more parameter to Text_Action.

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