Parser.cpp

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

Generated on Sun Jan 27 13:04:15 2008 for ACEXML by doxygen 1.3.6