| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| #include <precomp.h> |
| #include <s2_dsapi/docu_pe2.hxx> |
| |
| |
| // NOT FULLY DEFINED SERVICES |
| #include <cctype> |
| #include <ary/doc/d_oldidldocu.hxx> |
| #include <ary_i/d_token.hxx> |
| #include <parser/parserinfo.hxx> |
| #include <adc_cl.hxx> |
| #include <adc_msg.hxx> |
| #include <../parser/inc/x_docu.hxx> |
| #include <s2_dsapi/dsapitok.hxx> |
| #include <s2_dsapi/tk_atag2.hxx> |
| #include <s2_dsapi/tk_html.hxx> |
| #include <s2_dsapi/tk_docw2.hxx> |
| #include <s2_dsapi/tk_xml.hxx> |
| |
| |
| #ifdef UNX |
| #define strnicmp strncasecmp |
| #endif |
| |
| |
| namespace csi |
| { |
| namespace dsapi |
| { |
| |
| |
| const char * AtTagTitle( |
| const Tok_AtTag & i_rToken ); |
| |
| |
| SapiDocu_PE::SapiDocu_PE(ParserInfo & io_rPositionInfo) |
| : pDocu(0), |
| eState(e_none), |
| pPositionInfo(&io_rPositionInfo), |
| fCurTokenAddFunction(&SapiDocu_PE::AddDocuToken2Void), |
| pCurAtTag(0), |
| sCurDimAttribute(), |
| sCurAtSeeType_byXML(200) |
| { |
| } |
| |
| SapiDocu_PE::~SapiDocu_PE() |
| { |
| } |
| |
| void |
| SapiDocu_PE::ProcessToken( DYN csi::dsapi::Token & let_drToken ) |
| { |
| if (IsComplete()) |
| { |
| pDocu = 0; |
| eState = e_none; |
| } |
| |
| if ( eState == e_none ) |
| { |
| pDocu = new ary::doc::OldIdlDocu; |
| eState = st_short; |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2Short; |
| } |
| |
| csv_assert(pDocu); |
| |
| let_drToken.Trigger(*this); |
| delete &let_drToken; |
| } |
| |
| void |
| SapiDocu_PE::Process_AtTag( const Tok_AtTag & i_rToken ) |
| { |
| if (NOT pCurAtTag) |
| { |
| eState = st_attags; |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; |
| } |
| else |
| { |
| csv_assert(eState == st_attags); |
| pDocu->AddAtTag(*pCurAtTag.Release()); |
| } |
| |
| if (i_rToken.Id() == Tok_AtTag::param) |
| { |
| pCurAtTag = new DT_ParameterAtTag; |
| fCurTokenAddFunction = &SapiDocu_PE::SetCurParameterAtTagName; |
| } |
| else if (i_rToken.Id() == Tok_AtTag::see) |
| { |
| pCurAtTag = new DT_SeeAlsoAtTag; |
| fCurTokenAddFunction = &SapiDocu_PE::SetCurSeeAlsoAtTagLinkText; |
| } |
| else if (i_rToken.Id() == Tok_AtTag::deprecated) |
| { |
| pDocu->SetDeprecated(); |
| pCurAtTag = new DT_StdAtTag(""); // Dummy that will not be used. |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2Deprecated; |
| } |
| else if (i_rToken.Id() == Tok_AtTag::since) |
| { |
| pCurAtTag = new DT_SinceAtTag; |
| fCurTokenAddFunction = &SapiDocu_PE::SetCurSinceAtTagVersion_OOo; |
| } |
| else |
| { |
| pCurAtTag = new DT_StdAtTag( AtTagTitle(i_rToken) ); |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; |
| } |
| } |
| |
| void |
| SapiDocu_PE::Process_HtmlTag( const Tok_HtmlTag & i_rToken ) |
| { |
| if (eState == st_short AND i_rToken.IsParagraphStarter()) |
| { |
| eState = st_description; |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2Description; |
| } |
| |
| // Workaround special for some errors in API docu: |
| if ( strnicmp("<true",i_rToken.Text(),5 ) == 0 ) |
| { |
| if ( strcmp("<TRUE/>",i_rToken.Text()) != 0 ) |
| TheMessages().Out_InvalidConstSymbol( i_rToken.Text(), |
| pPositionInfo->CurFile(), |
| pPositionInfo->CurLine() ); |
| (this->*fCurTokenAddFunction)( *new DT_TextToken("<b>true</b>") ); |
| return; |
| } |
| else if ( strnicmp("<false",i_rToken.Text(),6 ) == 0 ) |
| { |
| if ( strcmp("<FALSE/>",i_rToken.Text()) != 0 ) |
| TheMessages().Out_InvalidConstSymbol( i_rToken.Text(), |
| pPositionInfo->CurFile(), |
| pPositionInfo->CurLine() ); |
| (this->*fCurTokenAddFunction)( *new DT_TextToken("<b>false</b>") ); |
| return; |
| } |
| else if ( strnicmp("<NULL",i_rToken.Text(),5 ) == 0 ) |
| { |
| if ( strcmp("<NULL/>",i_rToken.Text()) != 0 ) |
| TheMessages().Out_InvalidConstSymbol( i_rToken.Text(), |
| pPositionInfo->CurFile(), |
| pPositionInfo->CurLine() ); |
| (this->*fCurTokenAddFunction)( *new DT_TextToken("<b>null</b>") ); |
| return; |
| } |
| else if ( strnicmp("<void",i_rToken.Text(),5 ) == 0 ) |
| { |
| if ( strcmp("<void/>",i_rToken.Text()) != 0 ) |
| TheMessages().Out_InvalidConstSymbol( i_rToken.Text(), |
| pPositionInfo->CurFile(), |
| pPositionInfo->CurLine() ); |
| (this->*fCurTokenAddFunction)( *new DT_TextToken("<b>void</b>") ); |
| return; |
| } |
| |
| (this->*fCurTokenAddFunction)( *new DT_Style(i_rToken.Text(),false) ); |
| } |
| |
| void |
| SapiDocu_PE::Process_XmlConst( const Tok_XmlConst & i_rToken ) |
| { |
| (this->*fCurTokenAddFunction)(*new DT_MupConst(i_rToken.Text())); |
| } |
| |
| void |
| SapiDocu_PE::Process_XmlLink_BeginTag( const Tok_XmlLink_BeginTag & i_rToken ) |
| { |
| switch (i_rToken.Id()) |
| { |
| case Tok_XmlLink_Tag::e_const: |
| (this->*fCurTokenAddFunction)(*new DT_Style("<b>",false)); |
| break; |
| case Tok_XmlLink_Tag::member: |
| (this->*fCurTokenAddFunction)(*new DT_MupMember(i_rToken.Scope())); |
| break; |
| case Tok_XmlLink_Tag::type: |
| (this->*fCurTokenAddFunction)(*new DT_MupType(i_rToken.Scope())); |
| break; |
| default: |
| // Do nothing. |
| ; |
| } |
| |
| if ( i_rToken.Dim().length() > 0 ) |
| sCurDimAttribute = i_rToken.Dim(); |
| else |
| sCurDimAttribute.clear(); |
| } |
| |
| void |
| SapiDocu_PE::Process_XmlLink_EndTag( const Tok_XmlLink_EndTag & i_rToken ) |
| { |
| switch (i_rToken.Id()) |
| { |
| case Tok_XmlLink_Tag::e_const: |
| (this->*fCurTokenAddFunction)(*new DT_Style("</b>",false)); |
| break; |
| case Tok_XmlLink_Tag::member: |
| (this->*fCurTokenAddFunction)(*new DT_MupMember(true)); |
| break; |
| case Tok_XmlLink_Tag::type: |
| (this->*fCurTokenAddFunction)(*new DT_MupType(true)); |
| break; |
| default: |
| // Do nothing. |
| ; |
| } |
| if ( sCurDimAttribute.length() > 0 ) |
| { |
| (this->*fCurTokenAddFunction)( *new DT_TextToken(sCurDimAttribute.c_str()) ); |
| sCurDimAttribute.clear(); |
| } |
| } |
| |
| void |
| SapiDocu_PE::Process_XmlFormat_BeginTag( const Tok_XmlFormat_BeginTag & i_rToken ) |
| { |
| switch (i_rToken.Id()) |
| { |
| case Tok_XmlFormat_Tag::code: |
| (this->*fCurTokenAddFunction)(*new DT_Style("<code>",false)); |
| break; |
| case Tok_XmlFormat_Tag::listing: |
| (this->*fCurTokenAddFunction)(*new DT_Style("<pre>",true)); |
| break; |
| case Tok_XmlFormat_Tag::atom: |
| (this->*fCurTokenAddFunction)(*new DT_Style("<code>",true)); |
| break; |
| default: |
| // Do nothing. |
| ; |
| } |
| if ( i_rToken.Dim().length() > 0 ) |
| sCurDimAttribute = i_rToken.Dim(); |
| else |
| sCurDimAttribute.clear(); |
| } |
| |
| void |
| SapiDocu_PE::Process_XmlFormat_EndTag( const Tok_XmlFormat_EndTag & i_rToken ) |
| { |
| switch (i_rToken.Id()) |
| { |
| case Tok_XmlFormat_Tag::code: |
| (this->*fCurTokenAddFunction)(*new DT_Style("</code>",false)); |
| break; |
| case Tok_XmlFormat_Tag::listing: |
| (this->*fCurTokenAddFunction)(*new DT_Style("</pre>",true)); |
| break; |
| case Tok_XmlFormat_Tag::atom: |
| (this->*fCurTokenAddFunction)(*new DT_Style("</code>",true)); |
| break; |
| default: |
| // Do nothing. |
| ; |
| } |
| if ( sCurDimAttribute.length() > 0 ) |
| { |
| (this->*fCurTokenAddFunction)( *new DT_TextToken(sCurDimAttribute.c_str()) ); |
| sCurDimAttribute.clear(); |
| } |
| } |
| |
| void |
| SapiDocu_PE::Process_Word( const Tok_Word & i_rToken ) |
| { |
| (this->*fCurTokenAddFunction)(*new DT_TextToken(i_rToken.Text())); |
| } |
| |
| void |
| SapiDocu_PE::Process_Comma() |
| { |
| csv_assert(1==7); |
| // (this->*fCurTokenAddFunction)(*new DT_Comma(i_rToken.Text())); |
| } |
| |
| void |
| SapiDocu_PE::Process_DocuEnd() |
| { |
| eState = st_complete; |
| if (pCurAtTag) |
| pDocu->AddAtTag(*pCurAtTag.Release()); |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2Void; |
| } |
| |
| void |
| SapiDocu_PE::Process_EOL() |
| { |
| (this->*fCurTokenAddFunction)(*new DT_EOL); |
| } |
| |
| void |
| SapiDocu_PE::Process_White() |
| { |
| (this->*fCurTokenAddFunction)(*new DT_White); |
| } |
| |
| DYN ary::doc::OldIdlDocu * |
| SapiDocu_PE::ReleaseJustParsedDocu() |
| { |
| if (IsComplete()) |
| { |
| eState = e_none; |
| return pDocu.Release(); |
| } |
| return 0; |
| } |
| |
| |
| bool |
| SapiDocu_PE::IsComplete() const |
| { |
| return eState == st_complete; |
| } |
| |
| void |
| SapiDocu_PE::AddDocuToken2Void( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| delete &let_drNewToken; |
| } |
| |
| void |
| SapiDocu_PE::AddDocuToken2Short( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pDocu); |
| pDocu->AddToken2Short(let_drNewToken); |
| } |
| |
| void |
| SapiDocu_PE::AddDocuToken2Description( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pDocu); |
| pDocu->AddToken2Description(let_drNewToken); |
| } |
| |
| void |
| SapiDocu_PE::AddDocuToken2Deprecated( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pDocu); |
| pDocu->AddToken2DeprecatedText(let_drNewToken); |
| } |
| |
| void |
| SapiDocu_PE::AddDocuToken2CurAtTag( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pCurAtTag); |
| pCurAtTag->AddToken(let_drNewToken); |
| } |
| |
| void |
| SapiDocu_PE::SetCurParameterAtTagName( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| if (let_drNewToken.IsWhiteOnly()) |
| { |
| delete &let_drNewToken; |
| return; |
| } |
| |
| csv_assert(pCurAtTag); |
| DT_TextToken * dpText = dynamic_cast< DT_TextToken* >(&let_drNewToken); |
| if (dpText != 0) |
| pCurAtTag->SetName(dpText->GetText()); |
| else |
| pCurAtTag->SetName("parameter ?"); |
| delete &let_drNewToken; |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; |
| } |
| |
| void |
| SapiDocu_PE::SetCurSeeAlsoAtTagLinkText( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pCurAtTag); |
| |
| if (let_drNewToken.IsWhiteOnly()) |
| { |
| delete &let_drNewToken; |
| return; |
| } |
| |
| DT_TextToken * pText = dynamic_cast< DT_TextToken* >(&let_drNewToken); |
| if (pText != 0) |
| pCurAtTag->SetName(pText->GetText()); |
| else |
| { |
| DT_MupType * |
| pTypeBegin = dynamic_cast< DT_MupType* >(&let_drNewToken); |
| DT_MupMember * |
| pMemberBegin = dynamic_cast< DT_MupMember* >(&let_drNewToken); |
| if (pTypeBegin != 0 OR pMemberBegin != 0) |
| { |
| sCurAtSeeType_byXML.reset(); |
| |
| sCurAtSeeType_byXML |
| << ( pTypeBegin != 0 |
| ? pTypeBegin->Scope() |
| : pMemberBegin->Scope() ); |
| |
| if (sCurAtSeeType_byXML.tellp() > 0) |
| { |
| sCurAtSeeType_byXML |
| << "::"; |
| } |
| delete &let_drNewToken; |
| fCurTokenAddFunction = &SapiDocu_PE::SetCurSeeAlsoAtTagLinkText_2; |
| return; |
| } |
| else |
| { |
| pCurAtTag->SetName("? (no identifier found)"); |
| } |
| } |
| delete &let_drNewToken; |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; |
| } |
| |
| void |
| SapiDocu_PE::SetCurSeeAlsoAtTagLinkText_2( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pCurAtTag); |
| |
| if (let_drNewToken.IsWhiteOnly()) |
| { |
| delete &let_drNewToken; |
| return; |
| } |
| |
| DT_TextToken * |
| pText = dynamic_cast< DT_TextToken* >(&let_drNewToken); |
| if (pText != 0) |
| { |
| sCurAtSeeType_byXML |
| << pText->GetText(); |
| pCurAtTag->SetName(sCurAtSeeType_byXML.c_str()); |
| } |
| else |
| { |
| pCurAtTag->SetName("? (no identifier found)"); |
| } |
| sCurAtSeeType_byXML.reset(); |
| delete &let_drNewToken; |
| fCurTokenAddFunction = &SapiDocu_PE::SetCurSeeAlsoAtTagLinkText_3; |
| } |
| |
| void |
| SapiDocu_PE::SetCurSeeAlsoAtTagLinkText_3( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pCurAtTag); |
| |
| if (let_drNewToken.IsWhiteOnly()) |
| { |
| delete &let_drNewToken; |
| return; |
| } |
| |
| /// Could emit warning, but don't because this parser is obsolete. |
| // Tok_XmlLink_BeginTag * |
| // pLinkEnd = dynamic_cast< Tok_XmlLink_EndTag* >(&let_drNewToken); |
| // if (pLinkEnd == 0) |
| // { |
| // warn_aboutMissingClosingTag(); |
| // } |
| |
| delete &let_drNewToken; |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; |
| } |
| |
| const String |
| C_sSinceFormat("Correct version format: \"OpenOffice <major>.<minor>[.<micro> if micro is not 0]\"."); |
| |
| void |
| SapiDocu_PE::SetCurSinceAtTagVersion_OOo( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pCurAtTag); |
| |
| DT_TextToken * pToken = dynamic_cast< DT_TextToken* >(&let_drNewToken); |
| if (pToken == 0) |
| { |
| delete &let_drNewToken; |
| return; |
| } |
| |
| const String |
| sVersion(pToken->GetText()); |
| // if (NOT CheckVersionSyntax_OOo(sVersion)) |
| if (sVersion != "OpenOffice") |
| { |
| Cerr() << "Version information in @since tag has incorrect format.\n" |
| << "Found: \"" << sVersion << "\"\n" |
| << C_sSinceFormat |
| << Endl(); |
| exit(1); |
| } |
| |
| const autodoc::CommandLine & |
| rCommandLine = autodoc::CommandLine::Get_(); |
| if (NOT rCommandLine.DoesTransform_SinceTag()) |
| pCurAtTag->AddToken(let_drNewToken); |
| |
| fCurTokenAddFunction = &SapiDocu_PE::SetCurSinceAtTagVersion_Number; |
| } |
| |
| void |
| SapiDocu_PE::SetCurSinceAtTagVersion_Number( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pCurAtTag); |
| |
| DT_TextToken * pToken = dynamic_cast< DT_TextToken* >(&let_drNewToken); |
| if (pToken == 0) |
| { |
| if (dynamic_cast< DT_White* >(&let_drNewToken) != 0) |
| { |
| String & |
| sValue = pCurAtTag->Access_Text().Access_TextOfFirstToken(); |
| StreamLock |
| sHelp(1000); |
| sValue = sHelp() << sValue << " " << c_str; |
| } |
| |
| delete &let_drNewToken; |
| return; |
| } |
| |
| const String |
| sVersion(pToken->GetText()); |
| if (NOT CheckVersionSyntax_Number(sVersion)) |
| { |
| Cerr() << "Version information in @since tag has incorrect format.\n" |
| << "Found: \"" << sVersion << "\"\n" |
| << C_sSinceFormat |
| << Endl(); |
| exit(1); |
| } |
| |
| const autodoc::CommandLine & |
| rCommandLine = autodoc::CommandLine::Get_(); |
| if ( rCommandLine.DoesTransform_SinceTag()) |
| { |
| pCurAtTag->AddToken(let_drNewToken); |
| |
| if (rCommandLine.DisplayOf_SinceTagValue(sVersion).empty()) |
| { |
| // This is the numbered part, but we don't know it. |
| delete &let_drNewToken; |
| |
| StreamLock |
| sl(200); |
| sl() |
| << "Since-value '" |
| << sVersion |
| << "' not found in translation table."; |
| throw X_Docu("since", sl().c_str()); |
| } |
| } |
| else |
| { |
| AddDocuToken2SinceAtTag(let_drNewToken); |
| } |
| fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2SinceAtTag; |
| } |
| |
| void |
| SapiDocu_PE::AddDocuToken2SinceAtTag( DYN ary::inf::DocuToken & let_drNewToken ) |
| { |
| csv_assert(pCurAtTag); |
| String & |
| sValue = pCurAtTag->Access_Text().Access_TextOfFirstToken(); |
| StreamLock |
| sHelp(1000); |
| |
| DT_TextToken * |
| pToken = dynamic_cast< DT_TextToken* >(&let_drNewToken); |
| if (pToken != 0) |
| { |
| sValue = sHelp() << sValue << pToken->GetText() << c_str; |
| } |
| else if (dynamic_cast< DT_White* >(&let_drNewToken) != 0) |
| { |
| sValue = sHelp() << sValue << " " << c_str; |
| } |
| delete &let_drNewToken; |
| } |
| |
| bool |
| SapiDocu_PE::CheckVersionSyntax_Number(const String & i_versionPart2) |
| { |
| if (i_versionPart2.length () == 0) |
| return false; |
| |
| const char |
| pt = '.'; |
| unsigned int countDigit = 0; |
| unsigned int countPoint = 0; |
| const char * |
| pFirstPoint = 0; |
| const char * |
| pLastPoint = 0; |
| |
| for ( const char * p = i_versionPart2.begin(); |
| *p != 0; |
| ++p ) |
| { |
| if ( std::isdigit(*p) ) |
| ++countDigit; |
| else if (*p == pt) |
| { |
| if (countPoint == 0) |
| pFirstPoint = p; |
| pLastPoint = p; |
| ++countPoint; |
| } |
| } |
| |
| if ( countDigit + countPoint == i_versionPart2.length() // only digits and points |
| AND pFirstPoint != 0 AND countPoint < 3 // 1 or 2 points |
| AND pFirstPoint + 1 != pLastPoint // there are digits between two points |
| AND *i_versionPart2.begin() != pt AND *(pLastPoint + 1) != 0 // points are surrounded by digits |
| AND (*(pLastPoint + 1) != '0' OR pLastPoint == pFirstPoint) ) // the first micro-digit is not 0 |
| { |
| return true; |
| } |
| return false; |
| } |
| |
| const char * |
| AtTagTitle( const Tok_AtTag & i_rToken ) |
| { |
| switch (i_rToken.Id()) |
| { |
| case Tok_AtTag::author: return ""; |
| case Tok_AtTag::see: return "See also"; |
| case Tok_AtTag::param: return "Parameters"; |
| case Tok_AtTag::e_return: return "Returns"; |
| case Tok_AtTag::e_throw: return "Throws"; |
| case Tok_AtTag::example: return "Example"; |
| case Tok_AtTag::deprecated: return "Deprecated"; |
| case Tok_AtTag::suspicious: return ""; |
| case Tok_AtTag::missing: return ""; |
| case Tok_AtTag::incomplete: return ""; |
| case Tok_AtTag::version: return ""; |
| case Tok_AtTag::guarantees: return "Guarantees"; |
| case Tok_AtTag::exception: return "Exception"; |
| case Tok_AtTag::since: return "Since version"; |
| default: |
| // See below. |
| ; |
| } |
| return i_rToken.Text(); |
| } |
| |
| |
| |
| } // namespace dsapi |
| } // namespace csi |
| |