Parser.cpp

Go to the documentation of this file.
00001 // Parser.cpp,v 1.42 2006/06/20 08:32:50 jwillemsen Exp
00002 
00003 #include "ACEXML/parser/parser/Parser.h"
00004 
00005 #if !defined (__ACEXML_INLINE__)
00006 # include "ACEXML/parser/parser/Parser.i"
00007 #endif /* __ACEXML_INLINE__ */
00008 
00009 #include "ace/ACE.h"
00010 #include "ACEXML/common/Transcode.h"
00011 #include "ACEXML/common/AttributesImpl.h"
00012 #include "ACEXML/common/StrCharStream.h"
00013 #include "ACEXML/common/StreamFactory.h"
00014 #include "ACEXML/parser/parser/ParserInternals.h"
00015 #include "ace/OS_NS_string.h"
00016 #include "ace/OS_NS_strings.h"
00017 
00018 static const ACEXML_Char default_attribute_type[] = ACE_TEXT ("CDATA");
00019 static const ACEXML_Char empty_string[] = { 0 };
00020 
00021 const ACEXML_Char
00022 ACEXML_Parser::simple_parsing_feature_[] = ACE_TEXT ("Simple");
00023 
00024 const ACEXML_Char
00025 ACEXML_Parser::namespaces_feature_[] = ACE_TEXT ("http://xml.org/sax/features/namespaces");
00026 
00027 const ACEXML_Char
00028 ACEXML_Parser::namespace_prefixes_feature_[] = ACE_TEXT ("http://xml.org/sax/features/namespace-prefixes");
00029 
00030 const ACEXML_Char
00031 ACEXML_Parser::validation_feature_[] = ACE_TEXT ("http://xml.org/sax/features/validation");
00032 
00033 ACEXML_Parser::ACEXML_Parser (void)
00034   :   dtd_handler_ (0),
00035       entity_resolver_ (0),
00036       content_handler_ (0),
00037       error_handler_ (0),
00038       doctype_ (0),
00039       current_ (0),
00040       alt_stack_ (MAXPATHLEN),
00041       nested_namespace_ (0),
00042       ref_state_ (ACEXML_ParserInt::INVALID),
00043       external_subset_ (0),
00044       external_entity_ (0),
00045       has_pe_refs_ (0),
00046       standalone_ (0),
00047       external_dtd_ (0),
00048       internal_dtd_ (0),
00049       simple_parsing_ (0),
00050       validate_ (1),
00051       namespaces_(1),
00052       namespace_prefixes_ (0)
00053 {
00054 }
00055 
00056 ACEXML_Parser::~ACEXML_Parser (void)
00057 {
00058 
00059 }
00060 
00061 int
00062 ACEXML_Parser::initialize(ACEXML_InputSource* input)
00063 {
00064   // Initialize namespace support
00065   if (this->xml_namespace_.init() == -1)
00066     {
00067       ACE_ERROR ((LM_ERROR,
00068                   ACE_TEXT ("Error initializing namespace support\n")));
00069       return -1;
00070     }
00071   for (int i = 0; i < 5; ++i)
00072     {
00073       if (this->predef_entities_.add_entity (ACEXML_ParserInt::predef_ent_[i],
00074                                              ACEXML_ParserInt::predef_val_[i])
00075           != 0)
00076         {
00077           ACE_ERROR ((LM_DEBUG,
00078                       ACE_TEXT ("Error adding entity %s to Manager\n"),
00079                       ACEXML_ParserInt::predef_ent_[i]));
00080           return -1;
00081         }
00082     }
00083   return this->switch_input (input, input->getSystemId());
00084 }
00085 
00086 void
00087 ACEXML_Parser::parse (const ACEXML_Char *systemId ACEXML_ENV_ARG_DECL)
00088   ACE_THROW_SPEC ((ACEXML_SAXException))
00089 {
00090   ACEXML_InputSource* input = 0;
00091   ACE_NEW (input, ACEXML_InputSource (systemId));
00092   this->parse (input ACEXML_ENV_ARG_PARAMETER);
00093 }
00094 
00095 void
00096 ACEXML_Parser::parse (ACEXML_InputSource *input ACEXML_ENV_ARG_DECL)
00097   ACE_THROW_SPEC ((ACEXML_SAXException))
00098 {
00099   if (input == 0)
00100     {
00101       this->fatal_error(ACE_TEXT ("Invalid input source")
00102                         ACEXML_ENV_ARG_PARAMETER);
00103       ACEXML_CHECK;
00104     }
00105   if (this->content_handler_ == 0)
00106     {
00107       this->fatal_error (ACE_TEXT ("No content handlers defined. Exiting..")
00108                          ACEXML_ENV_ARG_PARAMETER);
00109       ACEXML_CHECK;
00110     }
00111 
00112   if (this->validate_ && this->dtd_handler_ == 0)
00113     {
00114       this->fatal_error (ACE_TEXT ("No DTD handlers defined. Exiting..")
00115                          ACEXML_ENV_ARG_PARAMETER);
00116       ACEXML_CHECK;
00117     }
00118 
00119 
00120   if (this->initialize(input) == -1)
00121     {
00122       this->fatal_error (ACE_TEXT ("Failed to initialize parser state")
00123                          ACEXML_ENV_ARG_PARAMETER);
00124       ACEXML_CHECK;
00125     }
00126   // Set up Locator.
00127   this->content_handler_->setDocumentLocator (this->current_->getLocator());
00128 
00129   int xmldecl_defined = 0;
00130   ACEXML_Char fwd = this->get();  // Consume '<'
00131   if (fwd == '<' && this->peek() == '?')
00132     {
00133       this->get();      // Consume '?'
00134       fwd = this->peek();
00135       if (fwd == 'x' && !xmldecl_defined)
00136         {
00137           this->parse_xml_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00138           ACEXML_CHECK;
00139           xmldecl_defined = 1;
00140         }
00141     }
00142   // We need a XMLDecl in a Valid XML document
00143   if (this->validate_ && !xmldecl_defined)
00144     {
00145       this->fatal_error (ACE_TEXT ("Expecting an XMLDecl at the beginning of")
00146                          ACE_TEXT (" a valid document")
00147                          ACEXML_ENV_ARG_PARAMETER);
00148       ACEXML_CHECK;
00149     }
00150   this->content_handler_->startDocument (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00151   ACEXML_CHECK;
00152 
00153   int doctype_defined = 0;
00154   for (int prolog_done = 0; prolog_done == 0; )
00155     {
00156       // Expect a '<' only if we have encountered a XMLDecl, or we are
00157       // looping through Misc blocks.
00158       if (xmldecl_defined)
00159         {
00160           if (this->skip_whitespace () != '<')
00161             {
00162               this->fatal_error (ACE_TEXT ("Expecting '<' at the beginning of ")
00163                                  ACE_TEXT ("Misc section")
00164                                  ACEXML_ENV_ARG_PARAMETER);
00165               ACEXML_CHECK;
00166             }
00167           fwd = this->peek();
00168         }
00169       switch (fwd)
00170         {
00171           case '?':
00172             this->get();
00173             this->parse_processing_instruction (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00174             ACEXML_CHECK;
00175             xmldecl_defined = 1;
00176             break;
00177           case '!':
00178             this->get();
00179             fwd = this->peek ();
00180             if (fwd == 'D' && !doctype_defined)       // DOCTYPE
00181               {
00182                 // This will also take care of the trailing MISC block if any.
00183                 this->parse_doctypedecl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00184                 ACEXML_CHECK;
00185                 doctype_defined = 1;
00186                 // Now that we have a DOCTYPE Decl defined, we shouldn't
00187                 // accept XML Decl any longer
00188                 xmldecl_defined = 1;
00189               }
00190             else if (fwd == 'D')
00191               {
00192                 this->fatal_error (ACE_TEXT ("Duplicate DOCTYPE declaration")
00193                                    ACEXML_ENV_ARG_PARAMETER);
00194                 ACEXML_CHECK;
00195               }
00196             else if (fwd == '-')  // COMMENT
00197               {
00198                 if (this->parse_comment () < 0)
00199                   {
00200                     this->fatal_error(ACE_TEXT ("Invalid comment in document")
00201                                       ACEXML_ENV_ARG_PARAMETER);
00202                     ACEXML_CHECK;
00203                   }
00204                 xmldecl_defined = 1;
00205               }
00206             break;
00207           case 0:
00208             this->fatal_error (ACE_TEXT ("Unexpected end-of-file")
00209                                ACEXML_ENV_ARG_PARAMETER);
00210             ACEXML_CHECK;
00211           default:                // Root element begins
00212             prolog_done = 1;
00213             break;
00214         }
00215     }
00216 
00217   if (this->validate_ && !doctype_defined)
00218     {
00219       this->warning (ACE_TEXT ("No doctypeDecl in valid document")
00220                      ACEXML_ENV_ARG_PARAMETER);
00221       ACEXML_CHECK;
00222     }
00223 
00224   // Now parse root element.
00225   this->parse_element (1 ACEXML_ENV_ARG_PARAMETER);
00226   ACEXML_CHECK;
00227 
00228   this->content_handler_->endDocument (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00229   ACEXML_CHECK;
00230 
00231   // Reset the parser state
00232   this->reset();
00233 
00234 }
00235 
00236 int
00237 ACEXML_Parser::parse_doctypedecl (ACEXML_ENV_SINGLE_ARG_DECL)
00238   ACE_THROW_SPEC ((ACEXML_SAXException))
00239 {
00240   if (this->parse_token (ACE_TEXT ("DOCTYPE")) < 0)
00241     {
00242       this->fatal_error(ACE_TEXT ("Expecting keyword DOCTYPE in a doctypedecl")
00243                         ACEXML_ENV_ARG_PARAMETER);
00244       ACEXML_CHECK_RETURN (-1);
00245     }
00246 
00247   ACEXML_Char nextch = 0;
00248   if (this->skip_whitespace_count (&nextch) == 0)
00249     {
00250       this->fatal_error(ACE_TEXT ("Expecting a space between DOCTYPE keyword ")
00251                         ACE_TEXT ("and name") ACEXML_ENV_ARG_PARAMETER);
00252       ACEXML_CHECK_RETURN (-1);
00253     }
00254 
00255   this->doctype_ = this->parse_name ();
00256   if (this->doctype_ == 0)
00257     {
00258       this->fatal_error(ACE_TEXT ("Invalid DOCTYPE name")
00259                         ACEXML_ENV_ARG_PARAMETER);
00260       ACEXML_CHECK_RETURN (-1);
00261     }
00262   int count = this->skip_whitespace_count (&nextch);
00263 
00264   if (nextch == 'S' || nextch == 'P') // ExternalID defined
00265     {
00266       if (count == 0)
00267         {
00268           this->fatal_error(ACE_TEXT ("Expecting a space between DOCTYPE")
00269                             ACE_TEXT ("keyword and name")
00270                             ACEXML_ENV_ARG_PARAMETER);
00271           ACEXML_CHECK_RETURN (-1);
00272         }
00273       this->external_dtd_ = 1;
00274       this->parse_external_dtd (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00275       ACEXML_CHECK_RETURN (-1);
00276     }
00277 
00278   nextch = this->skip_whitespace ();
00279   switch (nextch)
00280     {
00281       case '[':
00282         this->internal_dtd_ = 1;  // Internal DTD definition
00283         this->parse_internal_dtd (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00284         ACEXML_CHECK_RETURN (-1);
00285         break;
00286       case '>':                   // End of DTD definition
00287         // This is an XML document without a doctypedecl.
00288         if (this->validate_ && !this->external_dtd_)
00289           {
00290             this->fatal_error (ACE_TEXT ("No DTD defined")
00291                                ACEXML_ENV_ARG_PARAMETER);
00292             ACEXML_CHECK_RETURN (-1);
00293           }
00294         return 0;
00295       case '0':
00296         this->fatal_error (ACE_TEXT ("Unexpected end-of-file")
00297                            ACEXML_ENV_ARG_PARAMETER);
00298         ACEXML_CHECK_RETURN (-1);
00299       default:
00300         break;
00301     }
00302 
00303   if (this->skip_whitespace() != '>')
00304     {
00305       this->fatal_error(ACE_TEXT ("Expecting '>' at end of doctypedecl")
00306                         ACEXML_ENV_ARG_PARAMETER);
00307       ACEXML_CHECK_RETURN (-1);
00308     }
00309   return 0;
00310 }
00311 
00312 int
00313 ACEXML_Parser::parse_internal_dtd (ACEXML_ENV_SINGLE_ARG_DECL)
00314   ACE_THROW_SPEC ((ACEXML_SAXException))
00315 {
00316   this->ref_state_ = ACEXML_ParserInt::IN_INT_DTD;
00317   ACEXML_Char nextch = this->skip_whitespace ();
00318   do {
00319     switch (nextch)
00320       {
00321         case '<':
00322           nextch = this->get();
00323           switch (nextch)
00324             {
00325               case '!':
00326                 this->parse_markup_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00327                 ACEXML_CHECK_RETURN (-1);
00328                 break;
00329               case '?':
00330                 this->parse_processing_instruction (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00331                 ACEXML_CHECK_RETURN (-1);
00332                 break;
00333               default:
00334                 this->fatal_error (ACE_TEXT ("Invalid internal subset")
00335                                    ACEXML_ENV_ARG_PARAMETER);
00336                 ACEXML_CHECK_RETURN (-1);
00337                 break;
00338             }
00339           break;
00340         case '%':
00341           this->has_pe_refs_ = 1;
00342           this->parse_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00343           ACEXML_CHECK_RETURN (-1);
00344           break;
00345         case ']':                 // End of internal definitions.
00346           return 0;
00347         case '&':
00348           this->fatal_error (ACE_TEXT ("Invalid Reference in internal DTD")
00349                              ACEXML_ENV_ARG_PARAMETER);
00350           ACEXML_CHECK_RETURN (-1);
00351           break;
00352         case 0:
00353           this->pop_context (0 ACEXML_ENV_ARG_PARAMETER);
00354           ACEXML_CHECK_RETURN (-1);
00355           break;
00356         default:
00357           this->fatal_error (ACE_TEXT ("Invalid content in internal subset")
00358                              ACEXML_ENV_ARG_PARAMETER);
00359           ACEXML_CHECK_RETURN (-1);
00360       };
00361     nextch = this->skip_whitespace ();
00362   } while (1);
00363 
00364   ACE_NOTREACHED (return -1);
00365 }
00366 
00367 int
00368 ACEXML_Parser::parse_external_dtd (ACEXML_ENV_SINGLE_ARG_DECL)
00369   ACE_THROW_SPEC ((ACEXML_SAXException))
00370 {
00371   this->ref_state_ = ACEXML_ParserInt::IN_EXT_DTD;
00372   ACEXML_Char* publicId = 0;
00373   ACEXML_Char* systemId = 0;
00374   if (this->parse_external_id (publicId, systemId
00375                                ACEXML_ENV_ARG_PARAMETER) != 0)
00376     {
00377       this->fatal_error (ACE_TEXT ("Error in parsing ExternalID")
00378                          ACEXML_ENV_ARG_PARAMETER);
00379       ACEXML_CHECK_RETURN (-1);
00380     }
00381   if (this->validate_)
00382     {
00383       ACEXML_Char* uri = this->normalize_systemid (systemId);
00384       ACE_Auto_Basic_Array_Ptr<ACEXML_Char> cleanup_uri (uri);
00385       ACEXML_InputSource* ip = 0;
00386       if (this->entity_resolver_)
00387         {
00388           ip = this->entity_resolver_->resolveEntity (publicId,
00389                                                       (uri ? uri : systemId)
00390                                                       ACEXML_ENV_ARG_PARAMETER);
00391           ACEXML_CHECK_RETURN (-1);
00392         }
00393       if (ip)
00394         {
00395           if (this->switch_input (ip, (uri ? uri : systemId), publicId) != 0)
00396             return -1;
00397         }
00398       else
00399         {
00400           ACEXML_StreamFactory factory;
00401           ACEXML_CharStream* cstream = factory.create_stream (uri ?
00402                                                               uri: systemId);
00403           if (!cstream) {
00404             this->fatal_error (ACE_TEXT ("Invalid input source")
00405                                ACEXML_ENV_ARG_PARAMETER);
00406             ACEXML_CHECK_RETURN (-1);
00407           }
00408           if (this->switch_input (cstream, systemId, publicId) != 0)
00409             return -1;
00410         }
00411       this->parse_external_subset (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00412       ACEXML_CHECK_RETURN (-1);
00413     }
00414   return 0;
00415 }
00416 
00417 
00418 int
00419 ACEXML_Parser::parse_external_subset (ACEXML_ENV_SINGLE_ARG_DECL)
00420   ACE_THROW_SPEC ((ACEXML_SAXException))
00421 {
00422   this->ref_state_ = ACEXML_ParserInt::IN_EXT_DTD;
00423   this->external_subset_ = 1;
00424   int nrelems = 0;
00425   ACEXML_Char nextch = this->skip_whitespace();
00426   do {
00427     switch (nextch)
00428       {
00429         case '<':
00430           nextch = this->get();
00431           switch (nextch)
00432             {
00433               case '!':
00434                 nextch = this->peek();
00435                 if (nextch == '[')
00436                   this->parse_conditional_section (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00437                 else
00438                   this->parse_markup_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00439                 ACEXML_CHECK_RETURN (-1);
00440                 break;
00441               case '?':
00442                 nextch = this->peek();
00443                 if (nextch == 'x')
00444                   this->parse_text_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00445                 else
00446                   this->parse_processing_instruction (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00447                 ACEXML_CHECK_RETURN (-1);
00448                 break;
00449               default:
00450                 this->fatal_error (ACE_TEXT ("Invalid content in external DTD")
00451                                    ACEXML_ENV_ARG_PARAMETER);
00452                 ACEXML_CHECK_RETURN (-1);
00453             }
00454           break;
00455         case '%':
00456           this->parse_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00457           ACEXML_CHECK_RETURN (-1);
00458           break;
00459         case 0:
00460           nrelems = this->pop_context (0 ACEXML_ENV_ARG_PARAMETER);
00461           ACEXML_CHECK_RETURN (-1);
00462           if (nrelems == 1)
00463             return 0;
00464           break;
00465         default:
00466           this->fatal_error (ACE_TEXT ("Invalid content in external DTD")
00467                              ACEXML_ENV_ARG_PARAMETER);
00468           ACEXML_CHECK_RETURN (-1);
00469       }
00470     nextch = this->skip_whitespace();
00471   } while (1);
00472 }
00473 
00474 int
00475 ACEXML_Parser::parse_conditional_section (ACEXML_ENV_SINGLE_ARG_DECL)
00476   ACE_THROW_SPEC ((ACEXML_SAXException))
00477 {
00478   ACEXML_Char ch = this->get ();
00479   int include = 0;
00480   if (ch != '[')
00481     {
00482       this->fatal_error(ACE_TEXT ("Internal Parser Error")
00483                         ACEXML_ENV_ARG_PARAMETER);
00484       ACEXML_CHECK_RETURN (-1);
00485     }
00486   ch = this->skip_whitespace();
00487   if (ch == '%')
00488     {
00489       this->parse_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00490       ACEXML_CHECK_RETURN (-1);
00491       ch = this->skip_whitespace();
00492     }
00493   if (ch == 'I')
00494     {
00495       ch = this->get();
00496       switch (ch)
00497         {
00498           case 'N':
00499             if (this->parse_token (ACE_TEXT ("CLUDE")) < 0)
00500               {
00501                 this->fatal_error (ACE_TEXT ("Expecting keyword INCLUDE in ")
00502                                    ACE_TEXT ("conditionalSect")
00503                                    ACEXML_ENV_ARG_PARAMETER);
00504                 ACEXML_CHECK_RETURN (-1);
00505               }
00506             include = 1;
00507             break;
00508           case 'G':
00509             if (this->parse_token (ACE_TEXT ("GNORE")) < 0)
00510               {
00511                 this->fatal_error (ACE_TEXT ("Expecting keyword IGNORE in ")
00512                                    ACE_TEXT ("conditionalSect")
00513                                    ACEXML_ENV_ARG_PARAMETER);
00514                 ACEXML_CHECK_RETURN (-1);
00515               }
00516             include = 0;
00517             break;
00518           default:
00519             this->fatal_error (ACE_TEXT ("Invalid conditionalSect")
00520                                ACEXML_ENV_ARG_PARAMETER);
00521             ACEXML_CHECK_RETURN (-1);
00522         }
00523       ACEXML_Char fwd = '\xFF';
00524       this->skip_whitespace_count (&fwd);
00525       if (fwd == 0)
00526         {
00527           this->get(); // Consume the 0
00528           this->pop_context (0 ACEXML_ENV_ARG_PARAMETER);
00529           ACEXML_CHECK_RETURN (-1);
00530         }
00531     }
00532   else
00533     {
00534       this->fatal_error (ACE_TEXT ("Invalid conditionalSect")
00535                          ACEXML_ENV_ARG_PARAMETER);
00536       ACEXML_CHECK_RETURN (-1);
00537     }
00538   if (this->skip_whitespace() != '[')
00539     {
00540       this->fatal_error (ACE_TEXT ("Expecting '[' in conditionalSect")
00541                          ACEXML_ENV_ARG_PARAMETER);
00542       ACEXML_CHECK_RETURN (-1);
00543     }
00544   if (include)
00545     this->parse_includesect (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00546   else
00547     this->parse_ignoresect (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00548   ACEXML_CHECK_RETURN (-1);
00549   return 0;
00550 }
00551 
00552 int
00553 ACEXML_Parser::parse_ignoresect (ACEXML_ENV_SINGLE_ARG_DECL)
00554   ACE_THROW_SPEC ((ACEXML_SAXException))
00555 {
00556   ACEXML_Char nextch = this->skip_whitespace();
00557   int count = 0;
00558   int done = 0;
00559   do {
00560     switch (nextch)
00561       {
00562         case '<':
00563           if (this->peek() == '!')
00564             {
00565               this->get();
00566               if (this->peek() == '[')
00567                 {
00568                   this->get();
00569                   count++;
00570                 }
00571             }
00572           break;
00573         case ']':
00574           if (this->peek() == ']')
00575             {
00576               this->get();
00577               if (this->peek() == '>')
00578                 {
00579                   this->get();
00580                   if (count)
00581                     {
00582                       --count;
00583                       break;
00584                     }
00585                   done = 1;
00586                 }
00587             }
00588           break;
00589         case 0: // [VC: Proper Conditional Section/PE Nesting]
00590           if (count != 0)
00591             {
00592               this->fatal_error (ACE_TEXT ("Invalid Conditional Section/PE ")
00593                                  ACE_TEXT ("Nesting ")
00594                                  ACEXML_ENV_ARG_PARAMETER);
00595               ACEXML_CHECK_RETURN (-1);
00596             }
00597         default:
00598           break;
00599       }
00600     if (done)
00601       break;
00602     nextch = this->get();
00603   } while (1);
00604 
00605   return 0;
00606 }
00607 
00608 int
00609 ACEXML_Parser::parse_includesect (ACEXML_ENV_SINGLE_ARG_DECL)
00610   ACE_THROW_SPEC ((ACEXML_SAXException))
00611 {
00612   ACEXML_Char nextch = this->skip_whitespace();
00613   do {
00614     switch (nextch)
00615       {
00616         case '<':
00617           nextch = this->get();
00618           switch (nextch)
00619             {
00620               case '!':
00621                 nextch = this->peek();
00622                 if (nextch == '[')
00623                   this->parse_conditional_section (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00624                 else
00625                   this->parse_markup_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00626                 ACEXML_CHECK_RETURN (-1);
00627                 break;
00628               case '?':
00629                 nextch = this->peek();
00630                 this->parse_processing_instruction (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00631                 ACEXML_CHECK_RETURN (-1);
00632                 break;
00633               default:
00634                 this->fatal_error (ACE_TEXT ("Invalid includeSect")
00635                                    ACEXML_ENV_ARG_PARAMETER);
00636                 ACEXML_CHECK_RETURN (-1);
00637             }
00638           break;
00639         case '%':
00640           this->parse_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00641           ACEXML_CHECK_RETURN (-1);
00642           break;
00643         case 0: // [VC: Proper Conditional Section/PE Nesting]
00644           this->fatal_error (ACE_TEXT ("Invalid Conditional Section/PE ")
00645                              ACE_TEXT ("Nesting ")
00646                              ACEXML_ENV_ARG_PARAMETER);
00647           ACEXML_CHECK_RETURN (-1);
00648         case ']':
00649           if (this->peek() == ']')
00650             {
00651               nextch = this->get();
00652               if (this->peek() == '>')
00653                 {
00654                   nextch = this->get();
00655                   return 0;
00656                 }
00657             }
00658         default:
00659           this->fatal_error (ACE_TEXT ("Invalid includeSect")
00660                              ACEXML_ENV_ARG_PARAMETER);
00661           ACEXML_CHECK_RETURN (-1);
00662       }
00663     nextch = this->skip_whitespace();
00664   } while (1);
00665 }
00666 
00667 int
00668 ACEXML_Parser::parse_markup_decl (ACEXML_ENV_SINGLE_ARG_DECL)
00669   ACE_THROW_SPEC ((ACEXML_SAXException))
00670 {
00671   ACEXML_Char nextch = this->peek ();
00672   switch (nextch)
00673     {
00674       case 'E':         // An ELEMENT or ENTITY decl
00675         this->get ();
00676         nextch = this->peek ();
00677         switch (nextch)
00678           {
00679             case 'L':
00680               this->parse_element_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00681               ACEXML_CHECK_RETURN (-1);
00682               break;
00683             case 'N':
00684               this->parse_entity_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00685               ACEXML_CHECK_RETURN (-1);
00686               break;
00687             default:
00688               this->fatal_error(ACE_TEXT ("Expecting keyword ELEMENT/ENTITY")
00689                                 ACEXML_ENV_ARG_PARAMETER);
00690               ACEXML_CHECK_RETURN (-1);
00691           }
00692         break;
00693 
00694       case 'A':         // An ATTLIST decl
00695         this->parse_attlist_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00696         ACEXML_CHECK_RETURN (-1);
00697         break;
00698 
00699       case 'N':         // A NOTATION decl
00700         this->parse_notation_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
00701         ACEXML_CHECK_RETURN (-1);
00702         break;
00703 
00704       case '-':         // a comment.
00705         if (this->parse_comment () < 0)
00706           {
00707             this->fatal_error(ACE_TEXT ("Invalid comment")
00708                               ACEXML_ENV_ARG_PARAMETER);
00709             ACEXML_CHECK_RETURN (-1);
00710           }
00711         break;
00712       case 0: //  [VC: Proper Declaration/PE Nesting]
00713         this->fatal_error (ACE_TEXT ("Unexpected end-of-file")
00714                            ACEXML_ENV_ARG_PARAMETER);
00715         ACEXML_CHECK_RETURN (-1);
00716       default:
00717         this->fatal_error (ACE_TEXT ("Invalid markupDecl")
00718                            ACEXML_ENV_ARG_PARAMETER);
00719         ACEXML_CHECK_RETURN (-1);
00720     }
00721   return 0;
00722 }
00723 
00724 int
00725 ACEXML_Parser::parse_external_id (ACEXML_Char *&publicId,
00726                                   ACEXML_Char *&systemId
00727                                   ACEXML_ENV_ARG_DECL)
00728   ACE_THROW_SPEC ((ACEXML_SAXException))
00729 {
00730   publicId = systemId = 0;
00731   ACEXML_Char nextch = this->get ();
00732   ACEXML_Char fwd = 0;
00733   switch (nextch)
00734     {
00735       case 'S':                   // External SYSTEM id.
00736         if (this->parse_token (ACE_TEXT ("YSTEM")) < 0 ||
00737             this->skip_whitespace_count () < 1)
00738           {
00739             this->fatal_error(ACE_TEXT ("Expecting keyword SYSTEM")
00740                               ACEXML_ENV_ARG_PARAMETER);
00741             ACEXML_CHECK_RETURN (-1);
00742           }
00743         if (this->parse_system_literal (systemId) != 0)
00744           {
00745             this->fatal_error(ACE_TEXT ("Invalid systemLiteral")
00746                               ACEXML_ENV_ARG_PARAMETER);
00747             ACEXML_CHECK_RETURN (-1);
00748           }
00749         break;
00750       case 'P': // External PUBLIC id or previously defined PUBLIC id.
00751         if (this->parse_token (ACE_TEXT ("UBLIC")) < 0 ||
00752             this->skip_whitespace_count () < 1)
00753           {
00754             this->fatal_error(ACE_TEXT ("Expecing keyword PUBLIC")
00755                               ACEXML_ENV_ARG_PARAMETER);
00756             ACEXML_CHECK_RETURN (-1);
00757           }
00758         if (this->parse_pubid_literal (publicId) != 0)
00759           {
00760             this->fatal_error(ACE_TEXT ("Invalid PubidLiteral")
00761                               ACEXML_ENV_ARG_PARAMETER);
00762             ACEXML_CHECK_RETURN (-1);
00763           }
00764         this->skip_whitespace_count(&fwd);
00765         if (fwd == '\'' || fwd == '"')
00766           {
00767             if (this->parse_system_literal (systemId) != 0)
00768               {
00769                 this->fatal_error(ACE_TEXT ("Invalid systemLiteral")
00770                                   ACEXML_ENV_ARG_PARAMETER);
00771                 ACEXML_CHECK_RETURN (-1);
00772               }
00773           }
00774         else if (this->ref_state_ != ACEXML_ParserInt::IN_NOTATION)
00775           {
00776             this->fatal_error(ACE_TEXT ("Expecting systemLiteral after a ")
00777                               ACE_TEXT ("PUBLIC keyword")
00778                               ACEXML_ENV_ARG_PARAMETER);
00779             ACEXML_CHECK_RETURN (-1);
00780           }
00781         break;
00782       default:
00783         this->fatal_error(ACE_TEXT ("Invalid system/public Literal")
00784                           ACEXML_ENV_ARG_PARAMETER);
00785         ACEXML_CHECK_RETURN (-1);
00786     }
00787   return 0;
00788 }
00789 
00790 ACEXML_Char*
00791 ACEXML_Parser::normalize_systemid (const ACEXML_Char* systemId)
00792 {
00793   if (ACE_OS::strstr (systemId, ACE_TEXT("ftp://")) != 0 ||
00794       ACE_OS::strstr (systemId, ACE_TEXT ("http://")) != 0 ||
00795       ACE_OS::strstr (systemId, ACE_TEXT ("file://")) != 0)
00796     return 0;
00797   else
00798     {
00799       ACEXML_Char* normalized_uri = 0;
00800       const ACEXML_Char* baseURI = this->current_->getLocator()->getSystemId();
00801       ACE_ASSERT (baseURI);
00802       const ACEXML_Char* temp = 0;
00803       if (ACE_OS::strstr (baseURI, ACE_TEXT ("http://")) != 0)
00804         // baseURI is a HTTP URL and systemId is relative. Note that this
00805         // is not compliant with RFC2396. Caveat Emptor !
00806         temp = ACE_OS::strrchr (baseURI, '/');
00807       else
00808         // baseURI is a local file and systemId is relative
00809         // Unlike the HTTP one, this will work always.
00810         temp = ACE_OS::strrchr (baseURI,ACE_DIRECTORY_SEPARATOR_CHAR);
00811       if (temp)
00812         {
00813           size_t pos = temp - baseURI + 1;
00814           size_t len = pos + ACE_OS::strlen (systemId) + 1;
00815           ACE_NEW_RETURN (normalized_uri, ACEXML_Char[len], 0);
00816           ACE_OS::strncpy (normalized_uri, baseURI, pos);
00817           ACE_OS::strcpy (normalized_uri + pos, systemId);
00818           return normalized_uri;
00819         }
00820       return 0;
00821     }
00822 }
00823 
00824 void
00825 ACEXML_Parser::parse_element (int is_root ACEXML_ENV_ARG_DECL)
00826   ACE_THROW_SPEC ((ACEXML_SAXException))
00827 {
00828   // Parse STag.
00829   const ACEXML_Char *startname = this->parse_name ();
00830   if (startname == 0)
00831     {
00832       this->fatal_error (ACE_TEXT ("Unexpected end-of-file")
00833                          ACEXML_ENV_ARG_PARAMETER);
00834       return;
00835     }
00836   if (is_root && this->doctype_ != 0
00837       && ACE_OS::strcmp (startname, this->doctype_) != 0)
00838     {
00839       this->fatal_error (ACE_TEXT ("Root element different from DOCTYPE")
00840                          ACEXML_ENV_ARG_PARAMETER);
00841       return ;
00842     }
00843   ACEXML_AttributesImpl attributes;
00844   ACEXML_Char ch;
00845   int ns_flag = 0;   // Push only one namespace context onto the stack
00846                      // if there are multiple namespaces declared.
00847 
00848   const ACEXML_Char* ns_uri = 0;
00849   const ACEXML_Char* ns_lname = 0; // namespace URI and localName
00850   for (int start_element_done = 0; start_element_done == 0;)
00851     {
00852       ch = this->skip_whitespace ();
00853 
00854       switch (ch)
00855         {
00856           case 0:
00857             this->fatal_error(ACE_TEXT ("Internal Parser error")
00858                               ACEXML_ENV_ARG_PARAMETER);
00859             return;
00860           case '/':
00861             if (this->get () != '>')
00862               {
00863                 this->fatal_error(ACE_TEXT ("Expecting '>' at end of element ")
00864                                   ACE_TEXT ("definition")
00865                                   ACEXML_ENV_ARG_PARAMETER);
00866                 return;
00867               }
00868             this->xml_namespace_.processName(startname, ns_uri,
00869                                              ns_lname, 0);
00870             this->prefix_mapping (this->xml_namespace_.getPrefix(ns_uri),
00871                                   ns_uri, 1
00872                                   ACEXML_ENV_ARG_PARAMETER);
00873             ACEXML_CHECK;
00874             this->content_handler_->startElement(ns_uri, ns_lname,
00875                                                  startname, &attributes
00876                                                  ACEXML_ENV_ARG_PARAMETER);
00877             ACEXML_CHECK;
00878             this->content_handler_->endElement (ns_uri, ns_lname, startname
00879                                                 ACEXML_ENV_ARG_PARAMETER);
00880             ACEXML_CHECK;
00881             this->prefix_mapping (this->xml_namespace_.getPrefix(ns_uri),
00882                                   ns_uri, 0
00883                                   ACEXML_ENV_ARG_PARAMETER);
00884             ACEXML_CHECK;
00885             if (ns_flag)
00886               {
00887                 this->xml_namespace_.popContext ();
00888                 this->nested_namespace_--;
00889               }
00890             return;
00891           case '>':
00892             this->xml_namespace_.processName (startname, ns_uri,
00893                                               ns_lname, 0);
00894             this->prefix_mapping (this->xml_namespace_.getPrefix(ns_uri),
00895                                   ns_uri, 1
00896                                   ACEXML_ENV_ARG_PARAMETER);
00897             ACEXML_CHECK;
00898             this->content_handler_->startElement(ns_uri, ns_lname, startname,
00899                                                  &attributes
00900                                                  ACEXML_ENV_ARG_PARAMETER);
00901             ACEXML_CHECK;
00902             start_element_done = 1;
00903             break;
00904           default:
00905             ACEXML_Char *attvalue = 0;
00906             ACEXML_Char *attname = this->parse_name (ch);
00907 
00908             if (attname == 0 ||
00909                 this->skip_equal () != 0 ||
00910                 this->parse_attvalue (attvalue ACEXML_ENV_ARG_PARAMETER) != 0)
00911               {
00912                 this->fatal_error(ACE_TEXT ("Error reading attribute value")
00913                                   ACEXML_ENV_ARG_PARAMETER);
00914                 return;
00915               }
00916 
00917             // Handling new namespace if any. Notice that the order of
00918             // namespace declaration does matter.
00919             if (ACE_OS::strncmp (attname, ACE_TEXT("xmlns"), 5) == 0)
00920               {
00921                 if (this->namespaces_)
00922                   {
00923                     if (!ns_flag)
00924                       {
00925                         this->xml_namespace_.pushContext ();
00926                         this->nested_namespace_++;
00927                         ns_flag = 1;
00928                       }
00929 
00930                     ACEXML_Char* name = ACE_OS::strchr (attname, ':');
00931                     const ACEXML_Char* ns_name = (name == 0)?
00932                                                  empty_string:name+1;
00933                     if (this->xml_namespace_.declarePrefix (ns_name,
00934                                                             attvalue) == -1)
00935                       {
00936                         this->fatal_error(ACE_TEXT ("Duplicate definition of ")
00937                                           ACE_TEXT ("prefix")
00938                                           ACEXML_ENV_ARG_PARAMETER);
00939                         return;
00940                       }
00941                   }
00942                 if (this->namespace_prefixes_)
00943                   {
00944                     // Namespace_prefixes_feature_ is required. So add the
00945                     // xmlns:foo to the list of attributes.
00946                     if (attributes.addAttribute (ACE_TEXT (""), ACE_TEXT (""),
00947                                                  attname,
00948                                                  default_attribute_type,
00949                                                  attvalue) == -1)
00950                       {
00951                         this->fatal_error(ACE_TEXT ("Duplicate attribute ")
00952                                           ACE_TEXT ("definition. Hint: Try ")
00953                                           ACE_TEXT ("setting namespace_prefix")
00954                                           ACE_TEXT ("es feature to 0")
00955                                           ACEXML_ENV_ARG_PARAMETER);
00956                         return;
00957                       }
00958                   }
00959                 if (!this->namespaces_ && !this->namespace_prefixes_)
00960                   {
00961                     this->fatal_error(ACE_TEXT ("One of namespaces or ")
00962                                       ACE_TEXT ("namespace_prefixes should be")
00963                                       ACE_TEXT (" declared")
00964                                       ACEXML_ENV_ARG_PARAMETER);
00965                     return;
00966                   }
00967               }
00968             else
00969               {
00970                 const ACEXML_Char *uri, *lName;
00971                 this->xml_namespace_.processName (attname, uri, lName, 1);
00972                 if (attributes.addAttribute (uri, lName, attname,
00973                                              default_attribute_type,
00974                                              attvalue) == -1)
00975                   {
00976                     this->fatal_error(ACE_TEXT ("Duplicate attribute ")
00977                                       ACE_TEXT ("definition")
00978                                       ACEXML_ENV_ARG_PARAMETER);
00979                     return;
00980                   }
00981               }
00982             break;
00983         }
00984     }
00985   if (this->parse_content (startname, ns_uri, ns_lname, ns_flag
00986                            ACEXML_ENV_ARG_PARAMETER) != 0)
00987     return;
00988 }
00989 
00990 int
00991 ACEXML_Parser::parse_content (const ACEXML_Char* startname,
00992                               const ACEXML_Char*& ns_uri,
00993                               const ACEXML_Char*& ns_lname, int ns_flag ACEXML_ENV_ARG_DECL)
00994   ACE_THROW_SPEC ((ACEXML_SAXException))
00995 {
00996   ACEXML_Char *cdata;
00997   size_t cdata_length = 0;
00998 
00999   // Parse element contents.
01000   while (1)
01001     {
01002       ACEXML_Char ch = this->get ();
01003       switch (ch)
01004         {
01005           case 0:
01006             this->pop_context (1 ACEXML_ENV_ARG_PARAMETER);
01007             ACEXML_CHECK_RETURN (-1);
01008             break;
01009           case '<':
01010             // Push out old 'characters' event.
01011             if (cdata_length != 0)
01012               {
01013                 cdata = this->obstack_.freeze ();
01014                 this->content_handler_->characters (cdata, 0, cdata_length
01015                                                     ACEXML_ENV_ARG_PARAMETER);
01016                 ACEXML_CHECK_RETURN (-1);
01017                 this->obstack_.unwind (cdata);
01018                 cdata_length = 0;
01019               }
01020             ch = this->peek();
01021             switch (ch)
01022               {
01023                 case '!':             // a comment or a CDATA section.
01024                   this->get ();       // consume '!'
01025                   ch = this->peek ();
01026                   if (ch == '-')      // a comment
01027                     {
01028                       if (this->parse_comment () < 0)
01029                         {
01030                           this->fatal_error(ACE_TEXT ("Invalid comment in ")
01031                                             ACE_TEXT ("document")
01032                                             ACEXML_ENV_ARG_PARAMETER);
01033                           ACEXML_CHECK_RETURN (-1);
01034                         }
01035                     }
01036                   else if (ch == '[') // a CDATA section.
01037                     {
01038                       this->parse_cdata (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01039                       ACEXML_CHECK_RETURN (-1);
01040                     }
01041                   else
01042                     {
01043                       this->fatal_error(ACE_TEXT ("Expecting a CDATA section ")
01044                                         ACE_TEXT ("or a comment section")
01045                                         ACEXML_ENV_ARG_PARAMETER);
01046                       ACEXML_CHECK_RETURN (-1);
01047                     }
01048                   break;
01049                 case '?':             // a PI.
01050                   this->get();        // consume the '?'
01051                   this->parse_processing_instruction
01052                     (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01053                   ACEXML_CHECK_RETURN (-1);
01054                   break;
01055                 case '/':             // an ETag.
01056                   {
01057                     this->get ();       // consume '/'
01058                     ACEXML_Char* endname = this->parse_name ();
01059                     if (endname == 0 ||
01060                         ACE_OS::strcmp (startname, endname) != 0)
01061                       {
01062                         this->fatal_error(ACE_TEXT ("Name in ETag doesn't ")
01063                                           ACE_TEXT ("match name in STag")
01064                                           ACEXML_ENV_ARG_PARAMETER);
01065                         ACEXML_CHECK_RETURN (-1);
01066                       }
01067                     if (this->skip_whitespace () != '>')
01068                       {
01069                         this->fatal_error(ACE_TEXT ("Expecting '>' at end ")
01070                                           ACE_TEXT ("of element")
01071                                           ACEXML_ENV_ARG_PARAMETER);
01072                         return -1;
01073                       }
01074                     this->content_handler_->endElement (ns_uri, ns_lname,
01075                                                         endname
01076                                                         ACEXML_ENV_ARG_PARAMETER);
01077                     ACEXML_CHECK_RETURN (-1);
01078                     this->prefix_mapping (this->xml_namespace_.getPrefix(ns_uri),
01079                                           ns_uri, 0
01080                                           ACEXML_ENV_ARG_PARAMETER);
01081                     ACEXML_CHECK_RETURN (-1);
01082                     if (this->namespaces_ && ns_flag)
01083                       {
01084                     if (this->nested_namespace_ >= 1)
01085                       {
01086                         this->xml_namespace_.popContext ();
01087                         this->nested_namespace_--;
01088                       }
01089                       }
01090                     return 0;
01091                   }
01092                 default:              // a new nested element?
01093                   this->parse_element (0 ACEXML_ENV_ARG_PARAMETER);
01094                   ACEXML_CHECK_RETURN (-1);
01095                   break;
01096               }
01097             break;
01098           case '&':
01099             if (this->peek () == '#')
01100               {
01101                 ACEXML_Char buf[7];
01102                 size_t len = 0;
01103                 do
01104                   {
01105                     len = sizeof (buf);
01106                     if (this->parse_char_reference (buf, len) != 0)
01107                       {
01108                         // [WFC: Legal Character]
01109                         this->fatal_error (ACE_TEXT ("Invalid CharRef")
01110                                            ACEXML_ENV_ARG_PARAMETER);
01111                         ACEXML_CHECK_RETURN (-1);
01112                       }
01113                   } while (buf[0] == '&' && this->peek() == '#');
01114                   for (size_t j = 0; j < len; ++j)
01115                     this->obstack_.grow (buf[j]);
01116                 cdata_length += len;
01117               }
01118             else
01119               {
01120                 this->ref_state_ = ACEXML_ParserInt::IN_CONTENT;
01121                 int length = this->parse_entity_reference(ACEXML_ENV_SINGLE_ARG_PARAMETER);
01122                 ACEXML_CHECK_RETURN (-1);
01123                 if (length == 1)
01124                   cdata_length++;
01125               }
01126             break;
01127           case '\x20': case '\x0D': case '\x0A': case '\x09':
01128 //             if (this->validate_)
01129 //               {
01130 //                 // Flush out any non-whitespace characters
01131 //                 if (cdata_length != 0)
01132 //                   {
01133 //                     cdata = this->obstack_.freeze ();
01134 //                     this->content_handler_->characters(cdata, 0, cdata_length
01135 //                                                        ACEXML_ENV_ARG_PARAMETER);
01136 //                     ACEXML_CHECK_RETURN (-1);
01137 //                     this->obstack_.unwind (cdata);
01138 //                     cdata_length = 0;
01139 //                   }
01140 //                 ++cdata_length;
01141 //                 this->obstack_.grow (ch);
01142 //                 while (1)
01143 //                   {
01144 //                     ch = this->peek();
01145 //                     if (ch == '\x20' || ch == '\x0D' || ch == '\x0A' ||
01146 //                         ch == '\x09')
01147 //                       {
01148 //                         ch = this->get();
01149 //                         this->obstack_.grow (ch);
01150 //                         continue;
01151 //                       }
01152 //                     break;
01153 //                   }
01154 //                 cdata = this->obstack_.freeze ();
01155 //                 this->content_handler_->ignorableWhitespace (cdata, 0,
01156 //                                                              cdata_length
01157 //                                                              ACEXML_ENV_ARG_PARAMETER);
01158 //                 ACEXML_CHECK_RETURN (-1);
01159 //                 this->obstack_.unwind (cdata);
01160 //                 cdata_length = 0;
01161 //                 break;
01162 //               }
01163             // Fall thru...
01164           default:
01165             ++cdata_length;
01166             this->obstack_.grow (ch);
01167         }
01168     }
01169   ACE_NOTREACHED (return 0;)
01170 }
01171 
01172 
01173 int
01174 ACEXML_Parser::parse_cdata (ACEXML_ENV_SINGLE_ARG_DECL)
01175   ACE_THROW_SPEC ((ACEXML_SAXException))
01176 {
01177   if (this->parse_token (ACE_TEXT ("[CDATA[")) < 0)
01178     {
01179       this->fatal_error(ACE_TEXT ("Expecting '[CDATA[' at beginning of CDATA ")
01180                         ACE_TEXT ("section")
01181                         ACEXML_ENV_ARG_PARAMETER);
01182       ACEXML_CHECK_RETURN (-1);
01183     }
01184 
01185   ACEXML_Char ch;
01186   int datalen = 0;
01187   ACEXML_Char *cdata = 0;
01188   while (1)
01189     {
01190       ch = this->get ();
01191       // Anything goes except the sequence "]]>".
01192       if (ch == ']' && this->peek() == ']')
01193         {
01194           ACEXML_Char temp = ch;
01195           ch = this->get();
01196           if (ch == ']' && this->peek() == '>')
01197             {
01198               ch = this->get();
01199               cdata = this->obstack_.freeze ();
01200               this->content_handler_->characters (cdata, 0, datalen
01201                                                   ACEXML_ENV_ARG_PARAMETER);
01202               ACEXML_CHECK_RETURN (-1);
01203               this->obstack_.unwind(cdata);
01204               return 0;
01205             }
01206           this->obstack_.grow (temp);
01207           ++datalen;
01208         }
01209       this->obstack_.grow (ch);
01210       ++datalen;
01211     };
01212   ACE_NOTREACHED (return -1);
01213 }
01214 
01215 
01216 int
01217 ACEXML_Parser::parse_entity_decl (ACEXML_ENV_SINGLE_ARG_DECL)
01218   ACE_THROW_SPEC ((ACEXML_SAXException))
01219 {
01220   ACEXML_Char nextch = 0;
01221 
01222   if ((this->parse_token (ACE_TEXT ("NTITY")) < 0) ||
01223       this->skip_whitespace_count (&nextch) == 0)
01224     {
01225       this->fatal_error (ACE_TEXT ("Expecting keyword ENTITY followed by a ")
01226                          ACE_TEXT ("space") ACEXML_ENV_ARG_PARAMETER);
01227       ACEXML_CHECK_RETURN (-1);
01228     }
01229 
01230   int is_GEDecl = 1;
01231   if (nextch == '%')            // This is a PEDecl.
01232     {
01233       is_GEDecl = 0;
01234       this->get ();             // consume the '%'
01235       if (this->skip_whitespace_count (&nextch) == 0)
01236         {
01237           this->fatal_error (ACE_TEXT ("Expecting space between % and ")
01238                              ACE_TEXT ("entity name")
01239                              ACEXML_ENV_ARG_PARAMETER);
01240           ACEXML_CHECK_RETURN (-1);
01241         }
01242     }
01243 
01244   ACEXML_Char *entity_name = this->parse_name ();
01245   if (entity_name == 0)
01246     {
01247       this->fatal_error (ACE_TEXT ("Invalid entity name")
01248                          ACEXML_ENV_ARG_PARAMETER);
01249       ACEXML_CHECK_RETURN (-1);
01250     }
01251 
01252   if (this->skip_whitespace_count (&nextch) == 0)
01253     {
01254       this->fatal_error (ACE_TEXT ("Expecting space between entity name and ")
01255                          ACE_TEXT ("entityDef")
01256                          ACEXML_ENV_ARG_PARAMETER);
01257       ACEXML_CHECK_RETURN (-1);
01258     }
01259   int retval = 0;
01260   if (nextch == '\'' || nextch == '"')
01261     {
01262       ACEXML_Char *entity_value = 0;
01263       if (this->parse_entity_value (entity_value
01264                                     ACEXML_ENV_ARG_PARAMETER) != 0)
01265         {
01266           this->fatal_error(ACE_TEXT ("Invalid EntityValue")
01267                             ACEXML_ENV_ARG_PARAMETER);
01268           ACEXML_CHECK_RETURN (-1);
01269         }
01270       if (is_GEDecl)
01271         retval = this->internal_GE_.add_entity (entity_name,
01272                                                 entity_value);
01273       else
01274         retval = this->internal_PE_.add_entity (entity_name,
01275                                                 entity_value);
01276       if (retval < 0)
01277         {
01278           this->fatal_error (ACE_TEXT ("Internal Parser Error in adding")
01279                              ACE_TEXT ("Entity to map")
01280                              ACEXML_ENV_ARG_PARAMETER);
01281           ACEXML_CHECK_RETURN (-1);
01282         }
01283       else if (retval == 1)
01284         {
01285           this->warning (ACE_TEXT ("Duplicate entity found")
01286                          ACEXML_ENV_ARG_PARAMETER);
01287           ACEXML_CHECK_RETURN (-1);
01288         }
01289     }
01290   else
01291     {
01292       ACEXML_Char *systemid, *publicid;
01293 
01294       this->parse_external_id (publicid, systemid
01295                                ACEXML_ENV_ARG_PARAMETER);
01296       ACEXML_CHECK_RETURN (-1);
01297       if (systemid == 0)
01298         {
01299           this->fatal_error(ACE_TEXT ("Invalid SystemLiteral")
01300                             ACEXML_ENV_ARG_PARAMETER);
01301           ACEXML_CHECK_RETURN (-1);
01302         }
01303       this->skip_whitespace_count (&nextch);
01304       if (nextch == 'N')        // NDATA section followed
01305         {
01306           if (is_GEDecl == 0)
01307             {
01308               this->fatal_error(ACE_TEXT ("Invalid NDataDecl in PEDef")
01309                                 ACEXML_ENV_ARG_PARAMETER);
01310               ACEXML_CHECK_RETURN (-1);
01311             }
01312 
01313           if ((this->parse_token (ACE_TEXT ("NDATA")) < 0) ||
01314               this->skip_whitespace_count (&nextch) == 0)
01315             {
01316               this->fatal_error(ACE_TEXT ("Expecting keyword NDATA followed ")
01317                                 ACE_TEXT ("by a space") ACEXML_ENV_ARG_PARAMETER);
01318               ACEXML_CHECK_RETURN (-1);
01319             }
01320 
01321           ACEXML_Char *ndata = this->parse_name ();
01322           if (this->validate_) // [VC: Notation Declared]
01323             {
01324               if (!this->notations_.resolve_entity (ndata))
01325                 {
01326                   this->fatal_error (ACE_TEXT ("Undeclared Notation name")
01327                                      ACEXML_ENV_ARG_PARAMETER);
01328                   ACEXML_CHECK_RETURN (-1);
01329                 }
01330               this->dtd_handler_->unparsedEntityDecl(entity_name, publicid,
01331                                                      systemid, ndata
01332                                                      ACEXML_ENV_ARG_PARAMETER);
01333               ACEXML_CHECK_RETURN (-1);
01334             }
01335         }
01336       else
01337         {
01338           if (is_GEDecl)
01339             retval = this->external_GE_.add_entity (entity_name,
01340                                                     systemid);
01341           else
01342             retval = this->external_PE_.add_entity (entity_name,
01343                                                     systemid);
01344           if (retval < 0)
01345             {
01346               this->fatal_error(ACE_TEXT ("Internal Parser Error")
01347                                 ACEXML_ENV_ARG_PARAMETER);
01348               ACEXML_CHECK_RETURN (-1);
01349             }
01350           else if (retval == 1)
01351             this->warning(ACE_TEXT ("Duplicate external entity")
01352                           ACEXML_ENV_ARG_PARAMETER);
01353           if (is_GEDecl)
01354             retval = this->external_GE_.add_entity (entity_name,
01355                                                     publicid);
01356           else
01357             retval = this->external_PE_.add_entity (entity_name,
01358                                                     publicid);
01359           if (retval < 0)
01360             {
01361               this->fatal_error(ACE_TEXT ("Internal Parser Error")
01362                                 ACEXML_ENV_ARG_PARAMETER);
01363               ACEXML_CHECK_RETURN (-1);
01364             }
01365           else if (retval == 1)
01366             this->warning (ACE_TEXT ("Duplicate entity definition")
01367                            ACEXML_ENV_ARG_PARAMETER);
01368         }
01369     }
01370 
01371   // End of ENTITY definition
01372   if (this->skip_whitespace() != '>')
01373     {
01374       this->fatal_error(ACE_TEXT ("Expecting '>' at end of entityDef")
01375                         ACEXML_ENV_ARG_PARAMETER);
01376       ACEXML_CHECK_RETURN (-1);
01377     }
01378   return 0;
01379 }
01380 
01381 int
01382 ACEXML_Parser::parse_attlist_decl (ACEXML_ENV_SINGLE_ARG_DECL)
01383   ACE_THROW_SPEC ((ACEXML_SAXException))
01384 {
01385   if (this->parse_token (ACE_TEXT ("ATTLIST")) < 0)
01386     {
01387       this->fatal_error(ACE_TEXT ("Expecting keyword 'ATTLIST'")
01388                         ACEXML_ENV_ARG_PARAMETER);
01389       ACEXML_CHECK_RETURN (-1);
01390     }
01391   int count = check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01392   ACEXML_CHECK_RETURN (-1);
01393   if (!count)
01394     {
01395       this->fatal_error(ACE_TEXT ("Expecting space between ATTLIST and ")
01396                         ACE_TEXT ("element name") ACEXML_ENV_ARG_PARAMETER);
01397       ACEXML_CHECK_RETURN (-1);
01398     }
01399 
01400   ACEXML_Char *element_name = this->parse_name ();
01401   if (element_name == 0)
01402     {
01403       this->fatal_error(ACE_TEXT ("Invalid element Name in attlistDecl")
01404                         ACEXML_ENV_ARG_PARAMETER);
01405       ACEXML_CHECK_RETURN (-1);
01406     }
01407   ACEXML_Char fwd = 0;
01408   count = this->skip_whitespace_count (&fwd);
01409   // Parse AttDef*
01410   while (fwd != '>')
01411     {
01412       if (!this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER)
01413           && !count)
01414         this->fatal_error(ACE_TEXT ("Expecting space between element ")
01415                           ACE_TEXT ("name and AttDef")
01416                           ACEXML_ENV_ARG_PARAMETER);
01417       ACEXML_CHECK_RETURN (-1);
01418       this->skip_whitespace_count (&fwd);
01419       if (fwd == '>')
01420         break;
01421 
01422       count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01423       ACEXML_CHECK_RETURN (-1);
01424 
01425       this->parse_attname (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01426       ACEXML_CHECK_RETURN (-1);
01427 
01428       count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01429       ACEXML_CHECK_RETURN (-1);
01430       if (!count)
01431         {
01432           this->fatal_error(ACE_TEXT ("Expecting space between AttName and ")
01433                             ACE_TEXT ("AttType") ACEXML_ENV_ARG_PARAMETER);
01434           ACEXML_CHECK_RETURN (-1);
01435         }
01436       this->parse_atttype (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01437       ACEXML_CHECK_RETURN (-1);
01438 
01439       count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01440       ACEXML_CHECK_RETURN (-1);
01441       if (!count)
01442         {
01443           this->fatal_error(ACE_TEXT ("Expecting space between AttType and")
01444                             ACE_TEXT (" DefaultDecl")
01445                             ACEXML_ENV_ARG_PARAMETER);
01446           ACEXML_CHECK_RETURN (-1);
01447         }
01448       this->parse_defaultdecl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01449       ACEXML_CHECK_RETURN (-1);
01450 
01451       count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01452       ACEXML_CHECK_RETURN (-1);
01453       this->skip_whitespace_count(&fwd);
01454     }
01455   this->get ();                 // consume closing '>'
01456   return 0;
01457 }
01458 
01459 
01460 int
01461 ACEXML_Parser::check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_DECL)
01462 {
01463   ACEXML_Char fwd = '\xFF';
01464   // Skip any leading whitespaces and store the number of such chars skipped
01465   int count = this->skip_whitespace_count (&fwd);
01466   if (fwd == 0)
01467     {
01468       this->get(); // Consume the 0
01469       this->pop_context (0 ACEXML_ENV_ARG_PARAMETER);
01470       ACEXML_CHECK_RETURN (-1);
01471       fwd = this->peek();
01472     }
01473   if (fwd == '%')
01474     {
01475       this->get();  // Consume the %
01476       if (this->external_subset_)
01477         {
01478           this->parse_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01479           ACEXML_CHECK_RETURN (-1);
01480         }
01481       else
01482         {
01483           this->fatal_error(ACE_TEXT ("Illegal PERef within markupDecl")
01484                             ACEXML_ENV_ARG_PARAMETER);
01485           ACEXML_CHECK_RETURN (-1);
01486         }
01487     }
01488   if (count)
01489     {
01490       // We have atleast one whitespace. So just skip any more whitespaces
01491       // and return the count
01492       this->skip_whitespace_count();
01493       return count;
01494     }
01495   return this->skip_whitespace_count();
01496 }
01497 
01498 ACEXML_Char*
01499 ACEXML_Parser::parse_attname (ACEXML_ENV_SINGLE_ARG_DECL)
01500   ACE_THROW_SPEC ((ACEXML_SAXException))
01501 {
01502   // Parse attribute name
01503   ACEXML_Char *att_name = this->parse_name ();
01504   if (att_name == 0)
01505     {
01506       this->fatal_error(ACE_TEXT ("Invalid AttName")
01507                         ACEXML_ENV_ARG_PARAMETER);
01508       ACEXML_CHECK_RETURN (0);
01509     }
01510   return att_name;
01511 }
01512 
01513 int
01514 ACEXML_Parser::parse_defaultdecl (ACEXML_ENV_SINGLE_ARG_DECL)
01515   ACE_THROW_SPEC ((ACEXML_SAXException))
01516 {
01517   // DefaultDecl ::=  '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)? AttValue)
01518   ACEXML_Char nextch = this->peek ();
01519   ACEXML_Char *fixed_attr = 0;
01520   switch (nextch)
01521     {
01522       case '#':
01523         this->get ();         // consume the '#'
01524         switch (this->get ())
01525           {
01526             case 'R':
01527               if (this->parse_token (ACE_TEXT ("EQUIRED")) < 0)
01528                 {
01529                   this->fatal_error(ACE_TEXT ("Expecting keyword REQUIRED")
01530                                     ACEXML_ENV_ARG_PARAMETER);
01531                   ACEXML_CHECK_RETURN (-1);
01532                 }
01533               // We now know this attribute is required
01534               // @@ Set up the validator as such.
01535               break;
01536             case 'I':
01537               if (this->parse_token (ACE_TEXT ("MPLIED")) < 0)
01538                 {
01539                   this->fatal_error(ACE_TEXT ("Expecting keyword IMPLIED")
01540                                     ACEXML_ENV_ARG_PARAMETER);
01541                   ACEXML_CHECK_RETURN (-1);
01542                 }
01543               // We now know this attribute is implied.
01544               // @@ Set up the validator as such.
01545               break;
01546             case 'F':
01547               if (this->parse_token (ACE_TEXT ("IXED")) < 0 ||
01548                   this->skip_whitespace_count () == 0)
01549                 {
01550                   this->fatal_error(ACE_TEXT ("Expecting keyword FIXED")
01551                                     ACEXML_ENV_ARG_PARAMETER);
01552                   ACEXML_CHECK_RETURN (-1);
01553                 }
01554               // We now know this attribute is fixed.
01555               if (this->parse_attvalue (fixed_attr
01556                                         ACEXML_ENV_ARG_PARAMETER) != 0)
01557                 {
01558                   this->fatal_error(ACE_TEXT ("Invalid Default AttValue")
01559                                     ACEXML_ENV_ARG_PARAMETER);
01560                   ACEXML_CHECK_RETURN (-1);
01561                 }
01562               // @@ set up validator
01563               break;
01564             default:
01565               this->fatal_error (ACE_TEXT ("Invalid DefaultDecl")
01566                                  ACEXML_ENV_ARG_PARAMETER);
01567               ACEXML_CHECK_RETURN (-1);
01568           }
01569         break;
01570       case '\'':
01571       case '"':
01572         if (this->parse_attvalue (fixed_attr ACEXML_ENV_ARG_PARAMETER) != 0)
01573           {
01574             this->fatal_error(ACE_TEXT ("Invalid AttValue")
01575                               ACEXML_ENV_ARG_PARAMETER);
01576             ACEXML_CHECK_RETURN (-1);
01577           }
01578         // @@ set up validator
01579         break;
01580       default:
01581         this->fatal_error (ACE_TEXT ("Invalid DefaultDecl")
01582                            ACEXML_ENV_ARG_PARAMETER);
01583         ACEXML_CHECK_RETURN (-1);
01584         break;
01585     }
01586   return 0;
01587 }
01588 
01589 int
01590 ACEXML_Parser::parse_tokenized_type (ACEXML_ENV_SINGLE_ARG_DECL)
01591   ACE_THROW_SPEC ((ACEXML_SAXException))
01592 {
01593   ACEXML_Char ch = this->get();
01594   switch (ch)
01595     {
01596       case 'I':
01597         if (this->get () == 'D')
01598           {
01599             if (this->peek() != 'R' && this->is_whitespace (this->peek()))
01600               {
01601                 // We have successfully identified the type of the
01602                 // attribute as ID
01603                 // @@ Set up validator as such.
01604                 break;
01605               }
01606             if (this->parse_token (ACE_TEXT ("REF")) == 0)
01607               {
01608                 if (this->peek() != 'S' && this->is_whitespace (this->peek()))
01609                   {
01610                     // We have successfully identified the type of
01611                     // the attribute as IDREF
01612                     // @@ Set up validator as such.
01613                     break;
01614                   }
01615                 else if (this->peek() == 'S'
01616                          && this->get() // consume the 'S'
01617                          && this->is_whitespace (this->peek()))
01618                   {
01619                     // We have successfully identified the type of
01620                     // the attribute as IDREFS
01621                     // @@ Set up validator as such.
01622                     break;
01623                   }
01624               }
01625           }
01626         // Admittedly, this error message is not precise enough
01627         this->fatal_error(ACE_TEXT ("Expecting keyword `ID', `IDREF', or")
01628                           ACE_TEXT ("`IDREFS'") ACEXML_ENV_ARG_PARAMETER);
01629         ACEXML_CHECK_RETURN (-1);
01630       case 'E':               // ENTITY or ENTITIES
01631         if (this->parse_token (ACE_TEXT ("NTIT")) == 0)
01632           {
01633             ACEXML_Char nextch = this->get ();
01634             if (nextch == 'Y')
01635               {
01636                 // We have successfully identified the type of
01637                 // the attribute as ENTITY
01638                 // @@ Set up validator as such.
01639               }
01640             else if (this->parse_token (ACE_TEXT ("IES")) == 0)
01641               {
01642                 // We have successfully identified the type of
01643                 // the attribute as ENTITIES
01644                 // @@ Set up validator as such.
01645               }
01646             if (this->is_whitespace (this->peek()))
01647               {
01648                 // success
01649                 break;
01650               }
01651           }
01652         // Admittedly, this error message is not precise enough
01653         this->fatal_error(ACE_TEXT ("Expecting keyword `ENTITY', or")
01654                           ACE_TEXT ("`ENTITIES'") ACEXML_ENV_ARG_PARAMETER);
01655         ACEXML_CHECK_RETURN (-1);
01656       case 'M':
01657         if (this->parse_token (ACE_TEXT ("TOKEN")) == 0)
01658           {
01659             if (this->is_whitespace (this->peek()))
01660               {
01661                 // We have successfully identified the type of
01662                 // the attribute as NMTOKEN
01663                 // @@ Set up validator as such.
01664                 break;
01665               }
01666             else if (this->peek() == 'S'
01667                      && this->get()
01668                      && this->is_whitespace (this->peek()))
01669               {
01670                 // We have successfully identified the type of
01671                 // the attribute as NMTOKENS
01672                 // @@ Set up validator as such.
01673                 break;
01674               }
01675           }
01676         this->fatal_error(ACE_TEXT ("Expecting keyword `NMTOKEN' or `NMTO")
01677                           ACE_TEXT ("KENS'") ACEXML_ENV_ARG_PARAMETER);
01678         ACEXML_CHECK_RETURN (-1);
01679         break;
01680       default:
01681         this->fatal_error (ACE_TEXT ("Internal Parser Error")
01682                            ACEXML_ENV_ARG_PARAMETER);
01683         ACEXML_CHECK_RETURN (-1);
01684         break;
01685     }
01686   return 0;
01687 }
01688 
01689 
01690 /**
01691  * AttType    ::=    StringType | TokenizedType | EnumeratedType
01692  * StringType ::=    'CDATA'
01693  * TokenizedType    ::=    'ID'       [VC: ID]
01694  *                                    [VC: One ID per Element Type]
01695  *                                    [VC: ID Attribute Default]
01696  *                       | 'IDREF' [VC: IDREF]
01697  *                       | 'IDREFS' [VC: IDREF]
01698  *                       | 'ENTITY' [VC: Entity Name]
01699  *                       | 'ENTITIES' [VC: Entity Name]
01700  *                       | 'NMTOKEN' [VC: Name Token]
01701  *                       | 'NMTOKENS'
01702  *
01703  * EnumeratedType  ::=    NotationType | Enumeration
01704  * NotationType    ::=   'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
01705  *                                  [VC: Notation Attributes]
01706  *                                  [VC: One Notation Per Element Type]
01707  *                                  [VC: No Notation on Empty Element]
01708  * Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
01709  *                                  [VC: Enumeration]
01710  */
01711 int
01712 ACEXML_Parser::parse_atttype (ACEXML_ENV_SINGLE_ARG_DECL)
01713   ACE_THROW_SPEC ((ACEXML_SAXException))
01714 {
01715   ACEXML_Char nextch = this->peek();
01716   switch (nextch)
01717     {
01718       case 'C':               // CDATA
01719         if (this->parse_token (ACE_TEXT ("CDATA")) < 0)
01720           {
01721             this->fatal_error(ACE_TEXT ("Expecting keyword 'CDATA'")
01722                               ACEXML_ENV_ARG_PARAMETER);
01723             ACEXML_CHECK_RETURN (-1);
01724           }
01725         // Else, we have successfully identified the type of the
01726         // attribute as CDATA
01727         // @@ Set up validator appropriately here.
01728         break;
01729       case 'I': case 'E':      // ID, IDREF, IDREFS, ENTITY or ENTITIES
01730         this->parse_tokenized_type (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01731         ACEXML_CHECK_RETURN (-1);
01732         break;
01733       case 'N':             // NMTOKEN, NMTOKENS, or NOTATION
01734         this->get();
01735         nextch = this->peek();
01736         if (nextch != 'M' && nextch != 'O')
01737           {
01738             this->fatal_error (ACE_TEXT ("Expecting keyword 'NMTOKEN', ")
01739                                ACE_TEXT ("'NMTOKENS' or 'NOTATION'")
01740                                ACEXML_ENV_ARG_PARAMETER);
01741             ACEXML_CHECK_RETURN (-1);
01742           }
01743         if (nextch == 'M')
01744           {
01745             this->parse_tokenized_type (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01746             ACEXML_CHECK_RETURN (-1);
01747             break;
01748           }
01749         else                   // NOTATION
01750           {
01751             if (this->parse_token (ACE_TEXT ("OTATION")) < 0)
01752               {
01753                 this->fatal_error(ACE_TEXT ("Expecting keyword `NOTATION'")
01754                                   ACEXML_ENV_ARG_PARAMETER);
01755                 ACEXML_CHECK_RETURN (-1);
01756               }
01757             int count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01758             ACEXML_CHECK_RETURN (-1);
01759             if (!count)
01760               {
01761                 this->fatal_error (ACE_TEXT ("Expecting space between keyword ")
01762                                    ACE_TEXT ("NOTATION and '('")
01763                                    ACEXML_ENV_ARG_PARAMETER);
01764                 ACEXML_CHECK_RETURN (-1);
01765               }
01766             if (this->get () != '(')
01767               {
01768                 this->fatal_error(ACE_TEXT ("Expecting '(' in NotationType")
01769                                   ACEXML_ENV_ARG_PARAMETER);
01770                 ACEXML_CHECK_RETURN (-1);
01771               }
01772             this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01773             ACEXML_CHECK_RETURN (-1);
01774             do {
01775               this->skip_whitespace_count();
01776               ACEXML_Char *notation_name = this->parse_name ();
01777               if (notation_name == 0)
01778                 {
01779                   this->fatal_error(ACE_TEXT ("Invalid notation name")
01780                                     ACEXML_ENV_ARG_PARAMETER);
01781                   ACEXML_CHECK_RETURN (-1);
01782                 }
01783               // @@ get another notation name, set up validator as such
01784               this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01785               ACEXML_CHECK_RETURN (-1);
01786               nextch = this->get();
01787             } while (nextch == '|');
01788             if (nextch != ')')
01789               {
01790                 this->fatal_error (ACE_TEXT ("Expecting a ')' after a ")
01791                                    ACE_TEXT ("NotationType declaration")
01792                                    ACEXML_ENV_ARG_PARAMETER);
01793                 ACEXML_CHECK_RETURN (-1);
01794               }
01795           }
01796         break;
01797       case '(':               // EnumeratedType - Enumeration
01798         this->get();
01799         this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01800         ACEXML_CHECK_RETURN (-1);
01801         do {
01802           this->skip_whitespace_count();
01803           ACEXML_Char *token_name = this->parse_nmtoken ();
01804           if (token_name == 0)
01805             {
01806               this->fatal_error(ACE_TEXT ("Invalid enumeration name")
01807                                 ACEXML_ENV_ARG_PARAMETER);
01808               ACEXML_CHECK_RETURN (-1);
01809             }
01810           // @@ get another nmtoken, set up validator as such
01811           this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01812           ACEXML_CHECK_RETURN (-1);
01813           nextch = this->get();
01814         } while (nextch == '|');
01815         if (nextch != ')')
01816           {
01817             this->fatal_error (ACE_TEXT ("Expecting a ')' after a ")
01818                                ACE_TEXT ("Enumeration declaration")
01819                                ACEXML_ENV_ARG_PARAMETER);
01820             ACEXML_CHECK_RETURN (-1);
01821           }
01822         break;
01823       default:
01824         {
01825           this->fatal_error(ACE_TEXT ("Invalid AttType")
01826                             ACEXML_ENV_ARG_PARAMETER);
01827           ACEXML_CHECK_RETURN (-1);
01828         }
01829         ACE_NOTREACHED (break);
01830     }
01831   return 0;
01832 }
01833 
01834 int
01835 ACEXML_Parser::parse_notation_decl (ACEXML_ENV_SINGLE_ARG_DECL)
01836   ACE_THROW_SPEC ((ACEXML_SAXException))
01837 {
01838   if (this->parse_token (ACE_TEXT ("NOTATION")) < 0)
01839     {
01840       this->fatal_error(ACE_TEXT ("Expecting Keyword 'NOTATION'")
01841                         ACEXML_ENV_ARG_PARAMETER);
01842       ACEXML_CHECK_RETURN (-1);
01843     }
01844   int count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01845   ACEXML_CHECK_RETURN (-1);
01846   if (!count)
01847     {
01848       this->fatal_error (ACE_TEXT ("Expecting a space between keyword NOTATION")
01849                          ACE_TEXT (" and notation name")
01850                          ACEXML_ENV_ARG_PARAMETER);
01851       ACEXML_CHECK_RETURN (-1);
01852     }
01853   ACEXML_Char *notation = this->parse_name ();
01854   if (notation == 0)
01855     {
01856       this->fatal_error(ACE_TEXT ("Invalid Notation name")
01857                         ACEXML_ENV_ARG_PARAMETER);
01858       ACEXML_CHECK_RETURN (-1);
01859     }
01860   count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01861   ACEXML_CHECK_RETURN (-1);
01862   if (!count)
01863     {
01864       this->fatal_error (ACE_TEXT ("Expecting a space between notation name ")
01865                          ACE_TEXT ("and ExternalID/PublicID")
01866                          ACEXML_ENV_ARG_PARAMETER);
01867       ACEXML_CHECK_RETURN (-1);
01868     }
01869 
01870   ACEXML_Char *systemid, *publicid;
01871 
01872   // Gross hack but otherwise we need to go around a lot of loops to parse,
01873   // When the ExternalID starts with 'PUBLIC' we cannot distinguish a
01874   // PublicId from a ExternalID by looking using a one character read-ahead
01875   ACEXML_ParserInt::ReferenceState temp = this->ref_state_;
01876   this->ref_state_ = ACEXML_ParserInt::IN_NOTATION;
01877 
01878   this->parse_external_id (publicid, systemid
01879                            ACEXML_ENV_ARG_PARAMETER);
01880   ACEXML_CHECK_RETURN (-1);
01881   // Restore the original value.
01882   this->ref_state_ = temp;
01883 
01884   // [VC: Unique Notation Name]
01885   if (systemid && this->notations_.add_entity (notation, systemid) != 0
01886       && this->validate_)
01887     {
01888       this->fatal_error(ACE_TEXT ("Internal Parser Error")
01889                         ACEXML_ENV_ARG_PARAMETER);
01890       ACEXML_CHECK_RETURN (-1);
01891     }
01892   if (publicid)
01893     {
01894       int retval = this->notations_.add_entity (notation, publicid);
01895       if (retval != 0 && !systemid && this->validate_)
01896         {
01897           this->fatal_error(ACE_TEXT ("Internal Parser Error")
01898                             ACEXML_ENV_ARG_PARAMETER);
01899           ACEXML_CHECK_RETURN (-1);
01900         }
01901     }
01902 
01903   if (this->skip_whitespace() != '>')
01904     {
01905       this->fatal_error(ACE_TEXT ("Expecting '>' at end of NotationDecl")
01906                         ACEXML_ENV_ARG_PARAMETER);
01907       ACEXML_CHECK_RETURN (-1);
01908     }
01909 
01910   if (this->validate_ && this->dtd_handler_)
01911     {
01912       this->dtd_handler_->notationDecl (notation,
01913                                         publicid,
01914                                         systemid ACEXML_ENV_ARG_PARAMETER);
01915       ACEXML_CHECK_RETURN (-1);
01916     }
01917   return 0;
01918 }
01919 
01920 int
01921 ACEXML_Parser::parse_element_decl (ACEXML_ENV_SINGLE_ARG_DECL)
01922   ACE_THROW_SPEC ((ACEXML_SAXException))
01923 {
01924   if (this->parse_token (ACE_TEXT ("LEMENT")) < 0)
01925     {
01926       this->fatal_error (ACE_TEXT ("Expecting keyword ELEMENT")
01927                          ACEXML_ENV_ARG_PARAMETER);
01928       ACEXML_CHECK_RETURN (-1);
01929     }
01930   int count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01931   ACEXML_CHECK_RETURN (-1);
01932   if (!count)
01933     {
01934       this->fatal_error (ACE_TEXT ("Expecting a space between keyword ELEMENT")
01935                          ACE_TEXT (" and element name")
01936                          ACEXML_ENV_ARG_PARAMETER);
01937       ACEXML_CHECK_RETURN (-1);
01938     }
01939   ACEXML_Char *element_name = this->parse_name ();
01940   if (element_name == 0)
01941     {
01942       this->fatal_error (ACE_TEXT ("Invalid element name")
01943                          ACEXML_ENV_ARG_PARAMETER);
01944       ACEXML_CHECK_RETURN (-1);
01945     }
01946   count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01947   ACEXML_CHECK_RETURN (-1);
01948   if (!count)
01949     {
01950       this->fatal_error (ACE_TEXT ("Expecting a space between element name ")
01951                          ACE_TEXT ("and element definition")
01952                          ACEXML_ENV_ARG_PARAMETER);
01953       ACEXML_CHECK_RETURN (-1);
01954     }
01955   ACEXML_Char nextch = this->peek();
01956   switch (nextch)
01957     {
01958       case 'E':                   // EMPTY
01959         if (this->parse_token (ACE_TEXT ("EMPTY")) < 0)
01960           {
01961             this->fatal_error (ACE_TEXT ("Expecting keyword EMPTY")
01962                                ACEXML_ENV_ARG_PARAMETER);
01963             ACEXML_CHECK_RETURN (-1);
01964           }
01965         break;
01966       case 'A':                   // ANY
01967         if (this->parse_token (ACE_TEXT ("ANY")) < 0)
01968           {
01969             this->fatal_error (ACE_TEXT ("Expecting keyword ANY")
01970                                ACEXML_ENV_ARG_PARAMETER);
01971             ACEXML_CHECK_RETURN (-1);
01972           }
01973         break;
01974       case '(':                   // children
01975         this->parse_children_definition (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01976         ACEXML_CHECK_RETURN (-1);
01977         break;
01978       default:                    // error
01979         this->fatal_error (ACE_TEXT ("Invalid element definition")
01980                            ACEXML_ENV_ARG_PARAMETER);
01981         ACEXML_CHECK_RETURN (-1);
01982     }
01983   count = this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
01984   ACEXML_CHECK_RETURN (-1);
01985   if (this->skip_whitespace () != '>')
01986     {
01987       this->fatal_error (ACE_TEXT ("Expecting '>' after element defintion")
01988                          ACEXML_ENV_ARG_PARAMETER);
01989       ACEXML_CHECK_RETURN (-1);
01990     }
01991   return 0;
01992 }
01993 
01994 
01995 int
01996 ACEXML_Parser::parse_children_definition (ACEXML_ENV_SINGLE_ARG_DECL)
01997   ACE_THROW_SPEC ((ACEXML_SAXException))
01998 {
01999   this->get ();                 // consume the '('
02000   this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02001   ACEXML_CHECK_RETURN (-1);
02002   int subelement_number = 0;
02003   ACEXML_Char nextch = this->peek();
02004   switch (nextch)
02005     {
02006       case '#':                   // Mixed element,
02007         if (this->parse_token (ACE_TEXT ("#PCDATA")) < 0)
02008           {
02009             this->fatal_error(ACE_TEXT ("Expecting keyword '#PCDATA'")
02010                               ACEXML_ENV_ARG_PARAMETER);
02011             ACEXML_CHECK_RETURN (-1);
02012           }
02013         this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02014         ACEXML_CHECK_RETURN (-1);
02015         nextch = this->get();
02016         while (nextch == '|')
02017           {
02018             this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02019             ACEXML_CHECK_RETURN (-1);
02020             ACEXML_Char *name = this->parse_name ();
02021             // @@ name will be used in the Validator later.
02022             ACE_UNUSED_ARG (name);
02023             ++subelement_number;
02024             // @@ Install Mixed element name into the validator.
02025             this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02026             ACEXML_CHECK_RETURN (-1);
02027             nextch = this->skip_whitespace();
02028           }
02029         if (nextch != ')' ||
02030             (subelement_number && this->get () != '*'))
02031           {
02032             this->fatal_error(ACE_TEXT ("Expecing ')' or ')*' at end of Mixed")
02033                               ACE_TEXT (" element") ACEXML_ENV_ARG_PARAMETER);
02034             ACEXML_CHECK_RETURN (-1);
02035           }
02036         // @@ close the element definition in the validator.
02037         break;
02038       default:
02039         int status = this->parse_child (1 ACEXML_ENV_ARG_PARAMETER);
02040         ACEXML_CHECK_RETURN (-1);
02041         if (status != 0)
02042           return -1;
02043     }
02044 
02045   // Check for trailing '?', '*', '+'
02046   nextch = this->peek ();
02047   switch (nextch)
02048     {
02049       case '?':
02050         // @@ Consume the character and inform validator as such,
02051         this->get ();
02052         break;
02053       case '*':
02054         // @@ Consume the character and inform validator as such,
02055         this->get ();
02056         break;
02057       case '+':
02058         // @@ Consume the character and inform validator as such,
02059         this->get ();
02060         break;
02061       default:
02062         break;                    // not much to do.
02063     }
02064 
02065   return 0;
02066 }
02067 
02068 int
02069 ACEXML_Parser::parse_child (int skip_open_paren ACEXML_ENV_ARG_DECL)
02070   ACE_THROW_SPEC ((ACEXML_SAXException))
02071 {
02072   // Conditionally consume the open paren.
02073   if (skip_open_paren == 0 && this->get () != '(')
02074     {
02075       this->fatal_error(ACE_TEXT ("Expecting '(' at beginning of children")
02076                         ACEXML_ENV_ARG_PARAMETER);
02077       ACEXML_CHECK_RETURN (-1);
02078     }
02079 
02080   ACEXML_Char node_type = 0;
02081   ACEXML_Char nextch;
02082 
02083   do {
02084     this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02085     ACEXML_CHECK_RETURN (-1);
02086     this->skip_whitespace_count (&nextch);
02087     switch (nextch)
02088       {
02089         case '(':
02090           this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02091           ACEXML_CHECK_RETURN (-1);
02092           this->parse_child (0 ACEXML_ENV_ARG_PARAMETER);
02093           ACEXML_CHECK_RETURN (-1);
02094           break;
02095         default:
02096           this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02097           ACEXML_CHECK_RETURN (-1);
02098           // must be an element name here.
02099           ACEXML_Char *subelement = this->parse_name ();
02100           if (subelement == 0)
02101             {
02102               this->fatal_error(ACE_TEXT ("Invalid subelement name")
02103                                 ACEXML_ENV_ARG_PARAMETER);
02104               ACEXML_CHECK_RETURN (-1);
02105             }
02106           // Check for trailing '?', '*', '+'
02107           nextch = this->peek ();
02108           switch (nextch)
02109             {
02110               case '?':
02111                 // @@ Consume the character and inform validator as such,
02112                 this->get ();
02113                 break;
02114               case '*':
02115                 // @@ Consume the character and inform validator as such,
02116                 this->get ();
02117                 break;
02118               case '+':
02119                 // @@ Consume the character and inform validator as such,
02120                 this->get ();
02121                 break;
02122               default:
02123                 break;                    // not much to do.
02124             }
02125 
02126           // @@ Inform validator of the new element here.
02127           break;
02128       }
02129     this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02130     ACEXML_CHECK_RETURN (-1);
02131     this->skip_whitespace_count (&nextch);
02132     switch (nextch)
02133       {
02134         case '|':
02135           switch (node_type)
02136             {
02137               case 0:
02138                 node_type = '|';
02139                 // @@ inform validator of this new type??
02140                 break;
02141               case '|':
02142                 break;
02143               default:
02144                 this->fatal_error (ACE_TEXT ("Expecting `,', `|', or `)' ")
02145                                    ACE_TEXT ("while defining an element")
02146                                    ACEXML_ENV_ARG_PARAMETER);
02147                 ACEXML_CHECK_RETURN (-1);
02148             }
02149           break;
02150         case ',':
02151           switch (node_type)
02152             {
02153               case 0:
02154                 node_type = ',';
02155                 // @@ inform validator of this new type??
02156                 break;
02157               case ',':
02158                 break;
02159               default:
02160                 this->fatal_error (ACE_TEXT ("Expecting `,', `|', or `)' ")
02161                                    ACE_TEXT ("while defining an element")
02162                                    ACEXML_ENV_ARG_PARAMETER);
02163                 ACEXML_CHECK_RETURN (-1);
02164             }
02165           break;
02166         case ')':
02167           break;
02168         default:
02169           this->fatal_error (ACE_TEXT ("Expecting `,', `|', or `)' ")
02170                              ACE_TEXT ("while defining an element")
02171                              ACEXML_ENV_ARG_PARAMETER);
02172           ACEXML_CHECK_RETURN (-1);
02173       }
02174     nextch = this->get();  // Consume the `,' or `|' or `)'
02175     if (nextch == ')')
02176       break;
02177     this->check_for_PE_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02178     ACEXML_CHECK_RETURN (-1);
02179     this->skip_whitespace_count (&nextch);
02180   } while (nextch != ')');
02181 
02182   // Check for trailing '?', '*', '+'
02183   nextch = this->peek ();
02184   switch (nextch)
02185     {
02186       case '?':
02187         // @@ Consume the character and inform validator as such,
02188         this->get ();
02189         break;
02190       case '*':
02191         // @@ Consume the character and inform validator as such,
02192         this->get ();
02193         break;
02194       case '+':
02195         // @@ Consume the character and inform validator as such,
02196         this->get ();
02197         break;
02198       default:
02199         break;                    // not much to do.
02200     }
02201 
02202 
02203   return 0;
02204 }
02205 
02206 int
02207 ACEXML_Parser::parse_char_reference (ACEXML_Char *buf, size_t& len)
02208 {
02209   if (len < 7)   // Max size of a CharRef plus terminating '\0'
02210     return -1;
02211   ACEXML_Char ch = this->get();
02212   if (ch != '#')      // Internal error.
02213     return -1;
02214   int hex = 0;
02215   ch = this->peek();
02216   if (ch == 'x')
02217     {
02218       hex = 1;
02219       this->get ();
02220     }
02221   size_t i = 0;
02222   int more_digit = 0;
02223   ch = this->get ();
02224   for ( ; i < len &&
02225           (this->isNormalDigit (ch) || (hex ? this->isCharRef(ch): 0)); ++i)
02226     {
02227       buf[i] = ch;
02228       ch = this->get();
02229       ++more_digit;
02230     }
02231   if (ch != ';' || !more_digit)
02232     return -1;
02233   buf[i] = 0;
02234   ACEXML_UCS4 sum = (ACEXML_UCS4) ACE_OS::strtol (buf, 0, (hex ? 16 : 10));
02235   // [WFC: Legal Character]
02236   if (!this->isChar (sum))
02237     return -1;
02238   int clen;
02239 #if defined (ACE_USES_WCHAR)
02240 #  if (ACE_SIZEOF_WCHAR == 2)    // UTF-16
02241   if ((clen = ACEXML_Transcoder::ucs42utf16 (sum, buf, len)) < 0)
02242     return -1;
02243 #  elif (ACE_SIZEOF_WCHAR == 4)  // UCS 4
02244   buf [0] = sum;
02245   buf [1] = 0;
02246   clen = 2;
02247 #  endif /* ACE_SIZEOF_WCHAR */
02248 
02249 #else                          // or UTF-8
02250   if ((clen = ACEXML_Transcoder::ucs42utf8 (sum, buf, len)) < 0)
02251     return -1;
02252 #endif
02253   buf [clen] = 0;
02254   len = clen;
02255   return 0;
02256 }
02257 
02258 ACEXML_Char*
02259 ACEXML_Parser::parse_reference_name (void)
02260 {
02261   ACEXML_Char ch = this->get ();
02262   if (!this->isLetter (ch) && (ch != '_' || ch != ':'))
02263     return 0;
02264   while (ch) {
02265     this->alt_stack_.grow (ch);
02266     ch = this->peek ();
02267     if (!this->isNameChar (ch))
02268       break;
02269     ch = this->get ();
02270   };
02271   if (ch != ';')
02272     return 0;
02273   ch = this->get();
02274   return this->alt_stack_.freeze ();
02275 }
02276 
02277 int
02278 ACEXML_Parser::parse_attvalue (ACEXML_Char *&str ACEXML_ENV_ARG_DECL)
02279   ACE_THROW_SPEC ((ACEXML_SAXException))
02280 {
02281   ACEXML_Char quote = this->get ();
02282   if (quote != '\'' && quote != '"')  // Not a quoted string.
02283     return -1;
02284   ACEXML_Char ch = this->get ();
02285   while (1)
02286     {
02287       if (ch == quote)
02288         {
02289           ACEXML_Char* temp = this->obstack_.freeze ();
02290           // If the attribute type is not CDATA, then the XML processor
02291           // must further process the normalized attribute value by
02292           // discarding any leading and trailing space (#x20) characters,
02293           // and by replacing sequences of space (#x20) characters by a
02294           // single space (#x20) character.
02295 
02296           //           if (atttype != CDATA) {
02297           //             ACEXML_Char* start = temp;
02298           //             ACEXML_Char* end = temp + ACE_OS::strlen (temp);
02299           //             while (*start == '\x20')
02300           //               start++;
02301           //             if (start == end) // String which is all spaces
02302           //               str = start;
02303           //             while (*start != 0)
02304           //               {
02305           //                 this->obstack_.grow (*start);
02306           //                 start++;
02307           //                 while (*start == '\x20')
02308           //                   start++;
02309           //               }
02310           //             str = this->obstack_.freeze();
02311           //           }
02312           str = temp;
02313           return 0;
02314         }
02315       switch (ch)
02316         {
02317           case '&':
02318             if (this->peek () == '#')
02319               {
02320                 ACEXML_Char buf[7];
02321                 size_t len = sizeof (buf);
02322                 if (this->parse_char_reference (buf, len) != 0)
02323                   {
02324                     // [WFC: Legal Character]
02325                     this->fatal_error (ACE_TEXT ("Invalid CharacterRef")
02326                                        ACEXML_ENV_ARG_PARAMETER);
02327                     ACEXML_CHECK_RETURN (-1);
02328                   }
02329                 for (size_t j = 0; j < len; ++j)
02330                   this->obstack_.grow (buf[j]);
02331               }
02332             else
02333               {
02334                 this->ref_state_ = ACEXML_ParserInt::IN_ATT_VALUE;
02335                 this->parse_entity_reference (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02336                 ACEXML_CHECK_RETURN (-1);
02337               }
02338             break;
02339           case '\x20': case '\x0D': case '\x0A': case '\x09':
02340             this->obstack_.grow ('\x20');
02341             break;
02342           case '<': // [WFC: No < in Attribute Values]
02343             this->fatal_error (ACE_TEXT ("Illegal '<' in AttValue")
02344                                ACEXML_ENV_ARG_PARAMETER);
02345             ACEXML_CHECK_RETURN (-1);
02346             break;
02347           case 0:
02348             this->pop_context (1 ACEXML_ENV_ARG_PARAMETER);
02349             ACEXML_CHECK_RETURN (-1);
02350             break;
02351           default:
02352             this->obstack_.grow (ch);
02353             break;
02354         }
02355       ch = this->get();
02356     }
02357 }
02358 
02359 
02360 
02361 int
02362 ACEXML_Parser::parse_entity_reference (ACEXML_ENV_SINGLE_ARG_DECL)
02363   ACE_THROW_SPEC ((ACEXML_SAXException))
02364 {
02365   ACEXML_Char* replace = this->parse_reference_name ();
02366   if (replace == 0)
02367     {
02368       this->fatal_error (ACE_TEXT ("Invalid Reference name")
02369                          ACEXML_ENV_ARG_PARAMETER);
02370       ACEXML_CHECK_RETURN (-1);
02371     }
02372 
02373   //  [WFC: Parsed Entity]
02374   if (this->unparsed_entities_.resolve_entity (replace)) {
02375     this->fatal_error (ACE_TEXT ("EntityRef refers to unparsed entity")
02376                        ACEXML_ENV_ARG_PARAMETER);
02377     ACEXML_CHECK_RETURN (-1);
02378   }
02379   // Look in the internal general entities set first.
02380   const ACEXML_Char* entity = this->internal_GE_.resolve_entity(replace);
02381 
02382   // Look in the predefined entities.
02383   if (!entity)
02384     {
02385       entity = this->predef_entities_.resolve_entity (replace);
02386       if (entity)
02387         {
02388           // Special case to return the length in case of predefined entities
02389           this->obstack_.grow (*entity);
02390           return 1;
02391         }
02392     }
02393 
02394   if (!this->validate_)
02395     {
02396       if (this->standalone_)
02397         {
02398           // [WFC: Entity Declared]
02399           this->fatal_error (ACE_TEXT ("Undeclared Entity reference")
02400                              ACEXML_ENV_ARG_PARAMETER);
02401           ACEXML_CHECK_RETURN (-1);
02402         }
02403       else
02404         {
02405           this->content_handler_->skippedEntity (replace
02406                                                  ACEXML_ENV_ARG_PARAMETER);
02407           ACEXML_CHECK_RETURN (-1);
02408           return 0;
02409         }
02410     }
02411 
02412   // No match in internal subset
02413   if (!entity
02414           // or No DTDs
02415       && (!(this->internal_dtd_ || this->external_dtd_)
02416           // or Only Internal DTD and no parameter entity references
02417           || (this->internal_dtd_ && !this->external_dtd_
02418               && !this->has_pe_refs_)
02419           // or Standalone = 'yes'
02420           || this->standalone_))
02421     {
02422       // [WFC: Entity Declared]
02423       this->fatal_error (ACE_TEXT ("Undeclared Entity reference")
02424                          ACEXML_ENV_ARG_PARAMETER);
02425       ACEXML_CHECK_RETURN (-1);
02426     }
02427 
02428   ACEXML_Char* systemId = 0;
02429   ACEXML_Char* publicId = 0;
02430   if (!entity)
02431     {
02432       if (this->external_GE_.resolve_entity (replace, systemId, publicId) < 0)
02433         {
02434           this->fatal_error (ACE_TEXT ("Undeclared Entity reference")
02435                              ACEXML_ENV_ARG_PARAMETER);
02436           ACEXML_CHECK_RETURN (-1);
02437         }
02438       if (this->ref_state_ == ACEXML_ParserInt::IN_ATT_VALUE)
02439         {
02440           this->fatal_error (ACE_TEXT ("External EntityRef in Attribute Value")
02441                              ACEXML_ENV_ARG_PARAMETER);
02442           ACEXML_CHECK_RETURN (-1);
02443         }
02444       this->external_entity_++;
02445     }
02446 
02447 
02448   // [WFC: No Recursion]
02449   ACEXML_Char* ref_name = replace;
02450   int present = this->GE_reference_.insert (ref_name);
02451   if (present == 1 || present == -1)
02452     {
02453       while (this->GE_reference_.pop(ref_name) != -1)
02454         ;
02455       this->fatal_error (ACE_TEXT ("Recursion in resolving entity")
02456                          ACEXML_ENV_ARG_PARAMETER);
02457       ACEXML_CHECK_RETURN (-1);
02458     }
02459 
02460   if (!this->external_entity_)
02461     {
02462       ACEXML_StrCharStream* str = 0;
02463       ACE_NEW_RETURN (str, ACEXML_StrCharStream, -1);
02464       if (str->open (entity, replace) < 0
02465           || this->switch_input (str, replace) != 0)
02466         {
02467           this->fatal_error (ACE_TEXT ("Unable to create internal input ")
02468                              ACE_TEXT ("stream")
02469                              ACEXML_ENV_ARG_PARAMETER);
02470           ACEXML_CHECK_RETURN (-1);
02471         }
02472       return 0;
02473     }
02474   else
02475     {
02476       ACEXML_Char* uri = this->normalize_systemid (systemId);
02477       ACE_Auto_Basic_Array_Ptr<ACEXML_Char> cleanup_uri (uri);
02478       ACEXML_InputSource* ip = 0;
02479       if (this->entity_resolver_)
02480         {
02481           ip = this->entity_resolver_->resolveEntity (publicId,
02482                                                       (uri ? uri : systemId)
02483                                                       ACEXML_ENV_ARG_PARAMETER);
02484           ACEXML_CHECK_RETURN (-1);
02485           if (ip)
02486             {
02487               if (this->switch_input (ip, (uri ? uri : systemId),
02488                                       publicId) != 0)
02489                 {
02490                   this->fatal_error (ACE_TEXT ("Internal Parser Error")
02491                                      ACEXML_ENV_ARG_PARAMETER);
02492                   ACEXML_CHECK_RETURN (-1);
02493                 }
02494               return 0;
02495             }
02496         }
02497       ACEXML_StreamFactory factory;
02498       ACEXML_CharStream* cstream = factory.create_stream (uri ? uri: systemId);
02499       if (!cstream) {
02500         this->fatal_error (ACE_TEXT ("Invalid input source")
02501                            ACEXML_ENV_ARG_PARAMETER);
02502         ACEXML_CHECK_RETURN (-1);
02503       }
02504       if (this->switch_input (cstream, systemId, publicId) != 0)
02505         {
02506           this->fatal_error (ACE_TEXT ("Internal Parser Error")
02507                              ACEXML_ENV_ARG_PARAMETER);
02508           ACEXML_CHECK_RETURN (-1);
02509         }
02510     }
02511   return 0;
02512 }
02513 
02514 int
02515 ACEXML_Parser::parse_PE_reference (ACEXML_ENV_SINGLE_ARG_DECL)
02516   ACE_THROW_SPEC ((ACEXML_SAXException))
02517 {
02518   ACEXML_Char* replace = this->parse_reference_name ();
02519   if (replace == 0)
02520     {
02521       this->fatal_error (ACE_TEXT ("Invalid PEReference name")
02522                          ACEXML_ENV_ARG_PARAMETER);
02523       ACEXML_CHECK_RETURN (-1);
02524     }
02525 
02526   // Look in the internal general entities set first.
02527   const ACEXML_Char* entity = this->internal_PE_.resolve_entity(replace);
02528 
02529   if (!entity &&                     // No match in internal
02530       (!this->external_dtd_ ||       // or No External DTDs
02531        this->standalone_))           // or Standalone
02532     {
02533       // [VC: Entity Declared]
02534       this->fatal_error (ACE_TEXT ("Undefined Internal PEReference")
02535                          ACEXML_ENV_ARG_PARAMETER);
02536       ACEXML_CHECK_RETURN (-1);
02537     }
02538 
02539   ACEXML_Char* systemId = 0;
02540   ACEXML_Char* publicId = 0;
02541   if (!entity && this->validate_)
02542     {
02543       if (this->external_PE_.resolve_entity (replace, systemId, publicId) < 0)
02544         {
02545           this->fatal_error (ACE_TEXT ("Undefined PEReference")
02546                              ACEXML_ENV_ARG_PARAMETER);
02547           ACEXML_CHECK_RETURN (-1);
02548         }
02549       this->external_entity_++;
02550     }
02551 
02552   // [WFC: No Recursion]
02553   ACEXML_Char* ref_name = replace;
02554   int present = this->PE_reference_.insert (ref_name);
02555   if (present == 1 || present == -1)
02556     {
02557       while (this->PE_reference_.pop(ref_name) != -1)
02558         ;
02559       this->fatal_error (ACE_TEXT ("Recursion in resolving entity")
02560                          ACEXML_ENV_ARG_PARAMETER);
02561       ACEXML_CHECK_RETURN (-1);
02562     }
02563 
02564   if (entity && !this->external_entity_)
02565     {
02566       ACEXML_StrCharStream* sstream = 0;
02567       ACEXML_String str (entity);
02568       if (this->ref_state_ != ACEXML_ParserInt::IN_ENTITY_VALUE)
02569         {
02570           const ACEXML_Char* ch = ACE_TEXT (" ");
02571           str = ch + str + ch;
02572         }
02573       //  ACE_DEBUG ((LM_DEBUG,
02574       //             ACE_TEXT ("Entity is %s\n Replacement Text is : %s\n"),
02575       //             replace, str.c_str()));
02576       ACE_NEW_RETURN (sstream, ACEXML_StrCharStream, -1);
02577       if (sstream->open (str.c_str(), replace) < 0
02578           || this->switch_input (sstream, replace) != 0)
02579         {
02580           this->fatal_error (ACE_TEXT ("Error in switching InputSource")
02581                              ACEXML_ENV_ARG_PARAMETER);
02582           ACEXML_CHECK_RETURN (-1);
02583         }
02584       return 0;
02585     }
02586   else if (this->external_entity_ && this->validate_)
02587     {
02588       ACEXML_Char* uri = this->normalize_systemid (systemId);
02589       ACE_Auto_Basic_Array_Ptr<ACEXML_Char> cleanup_uri (uri);
02590       ACEXML_InputSource* ip = 0;
02591       if (this->entity_resolver_)
02592         {
02593           ip = this->entity_resolver_->resolveEntity (publicId,
02594                                                       (uri ? uri : systemId)
02595                                                       ACEXML_ENV_ARG_PARAMETER);
02596           ACEXML_CHECK_RETURN (-1);
02597         }
02598       if (ip)
02599         {
02600           if (this->switch_input (ip, (uri ? uri : systemId), publicId) != 0)
02601             {
02602               this->fatal_error (ACE_TEXT ("Error in switching InputSource")
02603                                  ACEXML_ENV_ARG_PARAMETER);
02604               ACEXML_CHECK_RETURN (-1);
02605             }
02606           return 0;
02607         }
02608       else
02609         {
02610           ACEXML_StreamFactory factory;
02611           ACEXML_CharStream* cstream = factory.create_stream (uri ? uri: systemId);
02612           if (!cstream) {
02613             this->fatal_error (ACE_TEXT ("Invalid input source")
02614                                ACEXML_ENV_ARG_PARAMETER);
02615             ACEXML_CHECK_RETURN (-1);
02616           }
02617           if (this->switch_input (cstream, systemId, publicId) != 0)
02618             {
02619               this->fatal_error (ACE_TEXT ("Error in switching InputSource")
02620                                  ACEXML_ENV_ARG_PARAMETER);
02621               ACEXML_CHECK_RETURN (-1);
02622             }
02623           if (this->ref_state_ == ACEXML_ParserInt::IN_ENTITY_VALUE)
02624             {
02625               ACEXML_Char less, mark;
02626               if (this->peek() == '<')
02627                 {
02628                   less = this->get();
02629                   if (this->peek() == '?')
02630                     {
02631                       mark = this->get();
02632                       if (this->peek() == 'x')
02633                         {
02634                           this->parse_text_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
02635                           ACEXML_CHECK_RETURN (-1);
02636                         }
02637                       else
02638                         {
02639                           this->obstack_.grow (less);
02640                           this->obstack_.grow (mark);
02641                         }
02642                     }
02643                   this->obstack_.grow (less);
02644                 }
02645             }
02646           return 0;
02647         }
02648     }
02649   this->fatal_error (ACE_TEXT ("Undefined PEReference")
02650                      ACEXML_ENV_ARG_PARAMETER);
02651   ACEXML_CHECK_RETURN (-1);
02652   return -1;
02653 }
02654 
02655 int
02656 ACEXML_Parser::parse_entity_value (ACEXML_Char *&str
02657                                    ACEXML_ENV_ARG_DECL)
02658   ACE_THROW_SPEC ((ACEXML_SAXException))
02659 {
02660   ACEXML_ParserInt::ReferenceState temp = this->ref_state_;
02661   ACEXML_Char quote = this->get ();
02662   if (quote != '\'' && quote != '"')  // Not a quoted string.
02663     return -1;
02664   ACEXML_Char ch = this->get ();
02665   while (1)
02666     {
02667       if (ch == quote)
02668         {
02669           str = this->obstack_.freeze ();
02670           this->ref_state_ = temp;
02671           return 0;
02672         }
02673       switch (ch)
02674         {
02675           case '&':
02676             if (this->peek () == '#')
02677               {
02678                 if (!this->external_entity_)
02679                   {
02680                     ACEXML_Char buf[7];
02681                     size_t len = sizeof (buf);
02682                     if (this->parse_char_reference (buf, len) != 0)
02683                       {
02684                         // [WFC: Legal Character]
02685                         this->fatal_error (ACE_TEXT ("Invalid character ")
02686                                            ACE_TEXT ("reference")
02687                                            ACEXML_ENV_ARG_PARAMETER);
02688                         return -1;
02689                       }
02690                     for (size_t j = 0; j < len; ++j)
02691                       this->obstack_.grow (buf[j]);
02692                     break;
02693                   }
02694               }
02695             this->obstack_.grow (ch);
02696             break;
02697           case '%':
02698             if (!this->external_entity_)
02699               {
02700                 this->ref_state_ = ACEXML_ParserInt::IN_ENTITY_VALUE;
02701                 this->parse_PE_reference(ACEXML_ENV_SINGLE_ARG_PARAMETER);
02702                 ACEXML_CHECK_RETURN (-1);
02703                 break;
02704               }
02705             this->obstack_.grow (ch);
02706             break;
02707           case 0:
02708             this->pop_context (0 ACEXML_ENV_ARG_PARAMETER);
02709             ACEXML_CHECK_RETURN (-1);
02710             break;
02711           default:
02712             this->obstack_.grow (ch);
02713             break;
02714         }
02715       ch = this->get();
02716     }
02717 }
02718 
02719 ACEXML_Char *
02720 ACEXML_Parser::parse_name (ACEXML_Char ch)
02721 {
02722   if (ch == 0)
02723     ch = this->get ();
02724   if (!this->isLetter (ch) && ch != '_' && ch != ':')
02725     return 0;
02726   while (ch) {
02727     this->obstack_.grow (ch);
02728     ch = this->peek ();
02729     if (!this->isNameChar (ch))
02730       break;
02731     ch = this->get ();
02732   };
02733   return this->obstack_.freeze ();
02734 }
02735 
02736 ACEXML_Char*
02737 ACEXML_Parser::parse_nmtoken (ACEXML_Char ch)
02738 {
02739   if (ch == 0)
02740     ch = this->get ();
02741   if (!this->isNameChar (ch))
02742     return 0;
02743   while (ch) {
02744     this->obstack_.grow (ch);
02745     ch = this->peek ();
02746     if (!this->isNameChar (ch))
02747       break;
02748     ch = this->get ();
02749   };
02750   return this->obstack_.freeze ();
02751 }
02752 
02753 int
02754 ACEXML_Parser::parse_version_num (ACEXML_Char*& str)
02755 {
02756   ACEXML_Char quote = this->get ();
02757   if (quote != '\'' && quote != '"')  // Not a quoted string.
02758     return -1;
02759   int numchars = 0;
02760   while (1)
02761     {
02762       ACEXML_Char ch = this->get ();
02763       if (ch == quote && !numchars)
02764         return -1;
02765       else if (ch == quote)
02766         {
02767           str = this->obstack_.freeze ();
02768           return 0;
02769         }
02770       // [26]    VersionNum ::= ([a-zA-Z0-9_.:] | '-')+
02771       if (ch == '-' || ((ch >= 'a' && ch <= 'z') ||
02772                         (ch >= 'A' && ch <= 'Z') ||
02773                         (ch >= '0' && ch <= '9') ||
02774                         (ch == '_' || ch == '.' || ch == ':')))
02775         {
02776           this->obstack_.grow (ch);
02777           numchars++;
02778         }
02779       else
02780         return -1;
02781     }
02782 }
02783 
02784 int
02785 ACEXML_Parser::parse_system_literal (ACEXML_Char*& str)
02786 {
02787   const ACEXML_Char quote = this->get();
02788   if (quote != '\'' && quote != '"')  // Not a quoted string.
02789     return -1;
02790   while (1)
02791     {
02792       ACEXML_Char ch = this->get ();
02793       if (ch == quote)
02794         {
02795           str = this->obstack_.freeze ();
02796           return 0;
02797         }
02798       switch (ch)
02799         {
02800           case '\x00': case '\x01': case '\x02': case '\x03': case '\x04':
02801           case '\x05': case '\x06': case '\x07': case '\x08': case '\x09':
02802           case '\x0A': case '\x0B': case '\x0C': case '\x0D': case '\x0E':
02803           case '\x0F': case '\x10': case '\x11': case '\x12': case '\x13':
02804           case '\x14': case '\x15': case '\x16': case '\x17': case '\x18':
02805           case '\x19': case '\x1A': case '\x1B': case '\x1C': case '\x1D':
02806           case '\x1E': case '\x1F': case '\x7F': case '\x20': case '<':
02807           case '>': case '#': case '%':
02808             ACE_ERROR ((LM_ERROR,
02809                         ACE_TEXT ("Invalid char %c in SystemLiteral\n"), ch));
02810             return -1;
02811           default:
02812             this->obstack_.grow (ch);
02813         }
02814     }
02815 }
02816 
02817 int
02818 ACEXML_Parser::parse_pubid_literal (ACEXML_Char*& str)
02819 {
02820   const ACEXML_Char quote = this->get();
02821   if (quote != '\'' && quote != '"')  // Not a quoted string.
02822     return -1;
02823   while (1)
02824     {
02825       ACEXML_Char ch = this->get ();
02826       if (ch == quote)
02827         {
02828           str = this->obstack_.freeze ();
02829           return 0;
02830         }
02831       else if (this->isPubidChar (ch))
02832         this->obstack_.grow (ch);
02833       else
02834         return -1;
02835     }
02836 }
02837 
02838 int
02839 ACEXML_Parser::parse_encname (ACEXML_Char*& str)
02840 {
02841   const ACEXML_Char quote = this->get ();
02842   if (quote != '\'' && quote != '"')  // Not a quoted string.
02843     return -1;
02844   int numchars = 0;
02845   while (1)
02846     {
02847       ACEXML_Char ch = this->get ();
02848       if (ch == quote && !numchars)
02849         return -1;
02850       else if (ch == quote)
02851         {
02852           str = this->obstack_.freeze ();
02853           return 0;
02854         }
02855       // [81]    EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
02856       if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
02857           && !numchars)
02858         return -1;
02859       if (ch == '-' || ((ch >= 'a' && ch <= 'z') ||
02860                         (ch >= 'A' && ch <= 'Z') ||
02861                         (ch >= '0' && ch <= '9') ||
02862                         (ch == '_' || ch == '.')))
02863         {
02864           this->obstack_.grow (ch);
02865           numchars++;
02866         }
02867       else
02868         return -1;
02869     }
02870 }
02871 
02872 int
02873 ACEXML_Parser::parse_sddecl (ACEXML_Char*& str)
02874 {
02875   ACEXML_Char quote = this->get ();
02876   if (quote != '\'' && quote != '"')  // Not a quoted string.
02877     return -1;
02878   int numchars = 0;
02879   while (1)
02880     {
02881       ACEXML_Char ch = this->get ();
02882       if (ch == quote && numchars < 2)
02883         return -1;
02884       else if (ch == quote)
02885         {
02886           str = this->obstack_.freeze ();
02887           return 0;
02888         }
02889       // [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
02890       //                                   | ('"' ('yes' | 'no') '"'))
02891       switch (ch)
02892         {
02893           case 'y': case 'e': case 's': case 'n': case 'o':
02894             this->obstack_.grow (ch);
02895             numchars++;
02896             break;
02897           default:
02898             return -1;
02899         }
02900     }
02901 }
02902 
02903 void
02904 ACEXML_Parser::prefix_mapping (const ACEXML_Char* prefix,
02905                                const ACEXML_Char* uri,
02906                                int start ACEXML_ENV_ARG_DECL)
02907   ACE_THROW_SPEC ((ACEXML_SAXException))
02908 {
02909   if (this->namespaces_)
02910     {
02911       const ACEXML_Char* temp = (prefix == 0) ? empty_string : prefix;
02912       if (start) {
02913         this->content_handler_->startPrefixMapping (temp, uri
02914                                                     ACEXML_ENV_ARG_PARAMETER);
02915         ACEXML_CHECK;
02916       }
02917       else
02918         {
02919           this->content_handler_->endPrefixMapping(temp
02920                                                    ACEXML_ENV_ARG_PARAMETER);
02921           ACEXML_CHECK;
02922         }
02923     }
02924 }
02925 
02926 int
02927 ACEXML_Parser::switch_input (ACEXML_CharStream* cstream,
02928                              const ACEXML_Char* systemId,
02929                              const ACEXML_Char* publicId)
02930 {
02931   ACEXML_InputSource* input = 0;
02932   ACE_NEW_RETURN (input, ACEXML_InputSource (cstream), -1);
02933   return this->switch_input (input, systemId, publicId);
02934 }
02935 
02936 int
02937 ACEXML_Parser::switch_input (ACEXML_InputSource* input,
02938                              const ACEXML_Char* systemId,
02939                              const ACEXML_Char* publicId)
02940 {
02941   ACEXML_LocatorImpl* locator = 0;
02942   if (!systemId)
02943     systemId = input->getSystemId();
02944   ACE_NEW_RETURN (locator, ACEXML_LocatorImpl (systemId, publicId), -1);
02945   ACEXML_Parser_Context* new_context = 0;
02946   ACE_NEW_RETURN (new_context, ACEXML_Parser_Context(input, locator), -1);
02947   if (this->push_context (new_context) != 0)
02948     {
02949       ACE_ERROR ((LM_ERROR, "Unable to switch input streams"));
02950       delete new_context;
02951       return -1;
02952     }
02953   this->current_ = new_context;
02954   this->content_handler_->setDocumentLocator (this->current_->getLocator());
02955   return 0;
02956 }
02957 
02958 int
02959 ACEXML_Parser::push_context (ACEXML_Parser_Context* context)
02960 {
02961   if (this->ctx_stack_.push (context) < 0)
02962     {
02963       ACE_ERROR ((LM_ERROR, "Unable to push input source onto the stack"));
02964       return -1;
02965     }
02966   return 0;
02967 }
02968 
02969 int
02970 ACEXML_Parser::pop_context (int GE_ref ACEXML_ENV_ARG_DECL)
02971 {
02972   size_t nrelems = this->ctx_stack_.size();
02973   if (nrelems <= 1)
02974     {
02975       this->fatal_error(ACE_TEXT ("Unexpected end-of-file")
02976                         ACEXML_ENV_ARG_PARAMETER);
02977       ACEXML_CHECK_RETURN (-1);
02978     }
02979 
02980   ACEXML_Parser_Context* temp = 0;
02981   int retval = this->ctx_stack_.pop (temp);
02982   if (retval != 0)
02983     {
02984       this->fatal_error (ACE_TEXT ("Unable to pop element of the input stack")
02985                          ACEXML_ENV_ARG_PARAMETER);
02986       ACEXML_CHECK_RETURN (-1);
02987     }
02988   delete temp;
02989   if (this->ctx_stack_.top (this->current_) != 0)
02990     {
02991       this->fatal_error (ACE_TEXT ("Unable to read top element of input stack")
02992                          ACEXML_ENV_ARG_PARAMETER);
02993       ACEXML_CHECK_RETURN (-1);
02994     }
02995   ACEXML_Char* reference = 0;
02996   if (GE_ref == 1 && this->GE_reference_.size() > 0)
02997     {
02998       if (this->GE_reference_.pop (reference) < 0)
02999         {
03000           this->fatal_error (ACE_TEXT ("Internal Parser Error")
03001                              ACEXML_ENV_ARG_PARAMETER);
03002           ACEXML_CHECK_RETURN (-1);
03003         }
03004     }
03005   else if (GE_ref == 0 && this->PE_reference_.size() > 0)
03006     {
03007       if (this->PE_reference_.pop (reference) < 0)
03008         {
03009           this->fatal_error (ACE_TEXT ("Internal Parser Error")
03010                              ACEXML_ENV_ARG_PARAMETER);
03011           ACEXML_CHECK_RETURN (-1);
03012         }
03013     }
03014   nrelems = this->ctx_stack_.size();
03015 
03016   if (this->external_entity_ && (GE_ref == 0 || GE_ref == 1))
03017     this->external_entity_--;
03018 
03019   this->content_handler_->setDocumentLocator (this->current_->getLocator());
03020 
03021   return nrelems;
03022 }
03023 
03024 int
03025 ACEXML_Parser::getFeature (const ACEXML_Char *name ACEXML_ENV_ARG_DECL)
03026   ACE_THROW_SPEC ((ACEXML_SAXNotRecognizedException,
03027                    ACEXML_SAXNotSupportedException))
03028 {
03029   if (ACE_OS::strcmp (name, ACEXML_Parser::simple_parsing_feature_) == 0)
03030     {
03031       return this->simple_parsing_;
03032     }
03033   else if (ACE_OS::strcmp (name, ACEXML_Parser::namespaces_feature_) == 0)
03034     {
03035       return this->namespaces_;
03036     }
03037   else if (ACE_OS::strcmp (name,
03038                            ACEXML_Parser::namespace_prefixes_feature_) == 0)
03039     {
03040       return this->namespace_prefixes_;
03041     }
03042   else if (ACE_OS::strcmp (name, ACEXML_Parser::validation_feature_) == 0)
03043     {
03044       return this->validate_;
03045     }
03046   ACEXML_THROW_RETURN (ACEXML_SAXNotRecognizedException (name), -1);
03047 }
03048 
03049 
03050 
03051 void
03052 ACEXML_Parser::setFeature (const ACEXML_Char *name,
03053                            int boolean_value ACEXML_ENV_ARG_DECL)
03054   ACE_THROW_SPEC ((ACEXML_SAXNotRecognizedException,
03055                    ACEXML_SAXNotSupportedException))
03056 {
03057   if (ACE_OS::strcmp (name, ACEXML_Parser::simple_parsing_feature_) == 0)
03058     {
03059       this->simple_parsing_ = (boolean_value == 0 ? 0 : 1);
03060       return;
03061     }
03062   else if (ACE_OS::strcmp (name, ACEXML_Parser::namespaces_feature_) == 0)
03063     {
03064       this->namespaces_ = (boolean_value == 0 ? 0 : 1);
03065       return;
03066     }
03067   else if (ACE_OS::strcmp (name,
03068                            ACEXML_Parser::namespace_prefixes_feature_) == 0)
03069     {
03070       this->namespace_prefixes_ = (boolean_value == 0 ? 0 : 1);
03071       return;
03072     }
03073   else if (ACE_OS::strcmp (name, ACEXML_Parser::validation_feature_) == 0)
03074     {
03075       this->validate_ = (boolean_value == 0 ? 0 : 1);
03076       return;
03077     }
03078 
03079   ACEXML_THROW (ACEXML_SAXNotRecognizedException (name));
03080 }
03081 
03082 void *
03083 ACEXML_Parser::getProperty (const ACEXML_Char *name ACEXML_ENV_ARG_DECL)
03084   ACE_THROW_SPEC ((ACEXML_SAXNotRecognizedException,
03085                    ACEXML_SAXNotSupportedException))
03086 {
03087   ACEXML_THROW_RETURN (ACEXML_SAXNotSupportedException (name), 0);
03088 }
03089 
03090 void
03091 ACEXML_Parser::setProperty (const ACEXML_Char *name,
03092                             void *value ACEXML_ENV_ARG_DECL)
03093   ACE_THROW_SPEC ((ACEXML_SAXNotRecognizedException,
03094                    ACEXML_SAXNotSupportedException))
03095 {
03096   ACE_UNUSED_ARG (value);
03097 
03098   ACEXML_THROW (ACEXML_SAXNotSupportedException (name));
03099 }
03100 
03101 void
03102 ACEXML_Parser::error (const ACEXML_Char* msg ACEXML_ENV_ARG_DECL)
03103   ACE_THROW_SPEC ((ACEXML_SAXException))
03104 {
03105   ACEXML_SAXParseException* exception = 0;
03106   ACE_NEW_NORETURN (exception, ACEXML_SAXParseException (msg));
03107   if (this->error_handler_)
03108       this->error_handler_->error (*exception ACEXML_ENV_ARG_PARAMETER);
03109   else
03110     ACEXML_ENV_RAISE (exception);
03111   return;
03112 }
03113 
03114 void
03115 ACEXML_Parser::warning (const ACEXML_Char* msg ACEXML_ENV_ARG_DECL)
03116   ACE_THROW_SPEC ((ACEXML_SAXException))
03117 {
03118   ACEXML_SAXParseException* exception = 0;
03119   ACE_NEW_NORETURN (exception, ACEXML_SAXParseException (msg));
03120   if (this->error_handler_)
03121     this->error_handler_->warning (*exception ACEXML_ENV_ARG_PARAMETER);
03122   delete exception;
03123   return;
03124 }
03125 
03126 void
03127 ACEXML_Parser::fatal_error (const ACEXML_Char* msg ACEXML_ENV_ARG_DECL)
03128   ACE_THROW_SPEC ((ACEXML_SAXException))
03129 {
03130   ACEXML_SAXParseException* exception = 0;
03131   ACE_NEW_NORETURN (exception, ACEXML_SAXParseException (msg));
03132   if (this->error_handler_)
03133     this->error_handler_->fatalError (*exception ACEXML_ENV_ARG_PARAMETER);
03134   this->reset();
03135   ACEXML_ENV_RAISE (exception);
03136   return;
03137 }
03138 
03139 void
03140 ACEXML_Parser::parse_version_info (ACEXML_ENV_SINGLE_ARG_DECL)
03141   ACE_THROW_SPEC ((ACEXML_SAXException))
03142 {
03143   ACEXML_Char* astring;
03144   if (this->parse_token (ACE_TEXT("ersion")) < 0
03145       || this->skip_equal () != 0
03146       || this->parse_version_num (astring) != 0)
03147     {
03148       this->fatal_error (ACE_TEXT ("Invalid VersionInfo specification")
03149                          ACEXML_ENV_ARG_PARAMETER);
03150       return;
03151     }
03152   if (ACE_OS::strcmp (astring, ACE_TEXT ("1.0")) != 0)
03153     {
03154       this->fatal_error (ACE_TEXT ("ACEXML Parser supports XML version 1.0 ")
03155                          ACE_TEXT ("documents only") ACEXML_ENV_ARG_PARAMETER);
03156       return;
03157     }
03158 }
03159 
03160 void
03161 ACEXML_Parser::parse_encoding_decl (ACEXML_ENV_SINGLE_ARG_DECL)
03162   ACE_THROW_SPEC ((ACEXML_SAXException))
03163 {
03164   ACEXML_Char* astring = 0;
03165   if ((this->parse_token (ACE_TEXT("ncoding")) < 0)
03166       || this->skip_equal () != 0
03167       || this->parse_encname (astring) != 0)
03168     {
03169       this->fatal_error (ACE_TEXT ("Invalid EncodingDecl specification")
03170                          ACEXML_ENV_ARG_PARAMETER);
03171       ACEXML_CHECK;
03172     }
03173   const ACEXML_Char* encoding = this->current_->getInputSource()->getEncoding();
03174   if (encoding != 0 && ACE_OS::strcmp (astring, encoding) != 0)
03175     {
03176       ACE_ERROR ((LM_ERROR, ACE_TEXT ("Detected Encoding is %s ")
03177                   ACE_TEXT (": Declared Encoding is %s\n"),
03178                   encoding, astring));
03179       this->warning (ACE_TEXT ("Declared encoding differs from detected ")
03180                      ACE_TEXT ("encoding") ACEXML_ENV_ARG_PARAMETER);
03181     }
03182 }
03183 
03184 int
03185 ACEXML_Parser::parse_text_decl (ACEXML_ENV_SINGLE_ARG_DECL)
03186   ACE_THROW_SPEC ((ACEXML_SAXException))
03187 {
03188   // Read xml
03189   if (this->parse_token (ACE_TEXT("xml")) < 0)
03190     {
03191       this->fatal_error(ACE_TEXT ("Expecting keyword 'xml' in TextDecl")
03192                         ACEXML_ENV_ARG_PARAMETER);
03193       ACEXML_CHECK_RETURN (-1);
03194     }
03195 
03196   ACEXML_Char fwd = this->skip_whitespace();
03197   // Read version
03198   if (fwd == 'v')
03199     {
03200       this->parse_version_info (ACEXML_ENV_SINGLE_ARG_PARAMETER);
03201       ACEXML_CHECK_RETURN (-1);
03202       fwd = this->skip_whitespace();
03203     }
03204 
03205   if (fwd == 'e')
03206     {
03207       this->parse_encoding_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
03208       ACEXML_CHECK_RETURN (-1);
03209       fwd = this->skip_whitespace();
03210     }
03211   else
03212     {
03213       this->fatal_error (ACE_TEXT ("Missing encodingDecl in TextDecl")
03214                          ACEXML_ENV_ARG_PARAMETER);
03215       ACEXML_CHECK_RETURN (-1);
03216     }
03217 
03218   if (fwd == '?' && this->get() == '>')
03219     return 0;
03220   // All the rules fail. So return an error.
03221   this->fatal_error (ACE_TEXT ("Invalid TextDecl") ACEXML_ENV_ARG_PARAMETER);
03222   ACEXML_CHECK_RETURN (-1);
03223   return -1;
03224 }
03225 
03226 void
03227 ACEXML_Parser::parse_xml_decl (ACEXML_ENV_SINGLE_ARG_DECL)
03228   ACE_THROW_SPEC ((ACEXML_SAXException))
03229 {
03230   // Read <?xml
03231   if (this->parse_token (ACE_TEXT("xml")) < 0)
03232     {
03233       this->fatal_error(ACE_TEXT ("Expecting keyword xml in XMLDecl")
03234                         ACEXML_ENV_ARG_PARAMETER);
03235       ACEXML_CHECK;
03236     }
03237 
03238   ACEXML_Char fwd = this->skip_whitespace();
03239 
03240   // Read version
03241   if (fwd != 'v')
03242     {
03243       this->fatal_error (ACE_TEXT ("Expecting VersionInfo declaration")
03244                          ACEXML_ENV_ARG_PARAMETER);
03245       ACEXML_CHECK;
03246     }
03247 
03248   this->parse_version_info (ACEXML_ENV_SINGLE_ARG_PARAMETER);
03249   ACEXML_CHECK;
03250 
03251   fwd = this->skip_whitespace();
03252   if (fwd != '?')
03253     {
03254       if (fwd == 'e')
03255         {
03256           this->parse_encoding_decl (ACEXML_ENV_SINGLE_ARG_PARAMETER);
03257           ACEXML_CHECK;
03258           fwd = this->skip_whitespace();
03259         }
03260       if (fwd == 's')
03261         {
03262           ACEXML_Char* astring;
03263           if ((this->parse_token (ACE_TEXT("tandalone")) == 0) &&
03264               this->skip_equal () == 0 &&
03265               this->parse_sddecl (astring) == 0)
03266             {
03267               if (ACE_OS::strcmp (astring, ACE_TEXT ("yes")) == 0)
03268                 this->standalone_ = 1;
03269               fwd = this->skip_whitespace();
03270             }
03271         }
03272     }
03273   if (fwd == '?' && this->get() == '>')
03274     return;
03275   // All the rules fail. So return an error.
03276   this->fatal_error (ACE_TEXT ("Invalid XMLDecl declaration")
03277                      ACEXML_ENV_ARG_PARAMETER);
03278   ACEXML_CHECK;
03279 }
03280 
03281 int
03282 ACEXML_Parser::parse_comment (void)
03283 {
03284   int state = 0;
03285 
03286   if (this->get () != '-' ||    // Skip the opening "<!--"
03287       this->get () != '-' ||    // completely.
03288       this->get () == '-')      // and at least something not '-'.
03289     return -1;
03290 
03291   while (state < 3)
03292     // Waiting for the trailing three character '-->'. Notice that
03293     // according to the spec, '--->' is not a valid closing comment
03294     // sequence. But we'll let it pass anyway.
03295     {
03296       ACEXML_Char fwd = this->get ();
03297       if ((fwd == '-' && state < 2) ||
03298           (fwd == '>' && state == 2))
03299         state += 1;
03300       else
03301         state = 0;              // Reset parse state.
03302     }
03303   return 0;
03304 }
03305 
03306 int
03307 ACEXML_Parser::parse_processing_instruction (ACEXML_ENV_SINGLE_ARG_DECL)
03308   ACE_THROW_SPEC ((ACEXML_SAXException))
03309 {
03310   const ACEXML_Char *pitarget = this->parse_name ();
03311   ACEXML_Char *instruction = 0;
03312 
03313   if (!ACE_OS::strcasecmp (ACE_TEXT ("xml"), pitarget))
03314     {
03315       // Invalid PITarget name.
03316       this->fatal_error(ACE_TEXT ("PI can't have 'xml' in PITarget")
03317                         ACEXML_ENV_ARG_PARAMETER);
03318       ACEXML_CHECK_RETURN (-1);
03319     }
03320 
03321   int state = 0;
03322 
03323   ACEXML_Char ch = this->skip_whitespace();
03324   while (state < 2)
03325     {
03326       switch (ch)
03327         {
03328           case '?':
03329             if (state == 0)
03330               state = 1;
03331             break;
03332           case '>':
03333             if (state == 1)
03334               {
03335                 instruction = this->obstack_.freeze ();
03336                 this->content_handler_->processingInstruction (pitarget,
03337                                                                instruction
03338                                                                ACEXML_ENV_ARG_PARAMETER);
03339                 ACEXML_CHECK_RETURN (-1);
03340                 this->obstack_.unwind (const_cast<ACEXML_Char*> (pitarget));
03341                 return 0;
03342               }
03343             break;
03344           case 0x0A:
03345             // Fall thru...
03346           default:
03347             if (state == 1)
03348               this->obstack_.grow ('?');
03349             this->obstack_.grow (ch);
03350             state = 0;
03351         }
03352       ch = this->get ();
03353     }
03354   return -1;
03355 }
03356 
03357 void
03358 ACEXML_Parser::reset (void)
03359 {
03360   this->doctype_ = 0;
03361   if (this->ctx_stack_.pop (this->current_) == -1)
03362     ACE_ERROR ((LM_ERROR,
03363                 ACE_TEXT ("Mismatched push/pop of Context stack")));
03364   if (this->current_)
03365     {
03366       this->current_->getInputSource()->getCharStream()->rewind();
03367 
03368       this->current_->setInputSource (0);
03369       delete this->current_;
03370       this->current_ = 0;
03371     }
03372 
03373   ACEXML_Char* temp = 0;
03374   while (this->GE_reference_.pop (temp) != -1)
03375     ;
03376   while (this->PE_reference_.pop (temp) != -1)
03377     ;
03378   this->obstack_.release();
03379   this->alt_stack_.release();
03380   this->xml_namespace_.reset();
03381   this->nested_namespace_ = 0;
03382   this->internal_GE_.reset();
03383   this->external_GE_.reset();
03384   this->unparsed_entities_.reset();
03385   this->predef_entities_.reset();
03386   this->internal_PE_.reset();
03387   this->external_PE_.reset();
03388   this->notations_.reset();
03389   this->ref_state_ = ACEXML_ParserInt::INVALID;
03390   this->external_subset_ = 0;
03391   this->external_entity_ = 0;
03392   this->has_pe_refs_ = 0;
03393   this->standalone_ = 0;
03394   this->external_dtd_ = 0;
03395   this->internal_dtd_ = 0;
03396 }
03397 

Generated on Thu Nov 9 11:45:38 2006 for ACEXML by doxygen 1.3.6