1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 #include <precomp.h> 23 #include <s2_dsapi/docu_pe2.hxx> 24 25 26 // NOT FULLY DEFINED SERVICES 27 #include <cctype> 28 #include <ary/doc/d_oldidldocu.hxx> 29 #include <ary_i/d_token.hxx> 30 #include <parser/parserinfo.hxx> 31 #include <adc_cl.hxx> 32 #include <adc_msg.hxx> 33 #include <../parser/inc/x_docu.hxx> 34 #include <s2_dsapi/dsapitok.hxx> 35 #include <s2_dsapi/tk_atag2.hxx> 36 #include <s2_dsapi/tk_html.hxx> 37 #include <s2_dsapi/tk_docw2.hxx> 38 #include <s2_dsapi/tk_xml.hxx> 39 40 41 #ifdef UNX 42 #define strnicmp strncasecmp 43 #endif 44 45 46 namespace csi 47 { 48 namespace dsapi 49 { 50 51 52 const char * AtTagTitle( 53 const Tok_AtTag & i_rToken ); 54 55 56 SapiDocu_PE::SapiDocu_PE(ParserInfo & io_rPositionInfo) 57 : pDocu(0), 58 eState(e_none), 59 pPositionInfo(&io_rPositionInfo), 60 fCurTokenAddFunction(&SapiDocu_PE::AddDocuToken2Void), 61 pCurAtTag(0), 62 sCurDimAttribute(), 63 sCurAtSeeType_byXML(200) 64 { 65 } 66 67 SapiDocu_PE::~SapiDocu_PE() 68 { 69 } 70 71 void 72 SapiDocu_PE::ProcessToken( DYN csi::dsapi::Token & let_drToken ) 73 { 74 if (IsComplete()) 75 { 76 pDocu = 0; 77 eState = e_none; 78 } 79 80 if ( eState == e_none ) 81 { 82 pDocu = new ary::doc::OldIdlDocu; 83 eState = st_short; 84 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2Short; 85 } 86 87 csv_assert(pDocu); 88 89 let_drToken.Trigger(*this); 90 delete &let_drToken; 91 } 92 93 void 94 SapiDocu_PE::Process_AtTag( const Tok_AtTag & i_rToken ) 95 { 96 if (NOT pCurAtTag) 97 { 98 eState = st_attags; 99 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; 100 } 101 else 102 { 103 csv_assert(eState == st_attags); 104 pDocu->AddAtTag(*pCurAtTag.Release()); 105 } 106 107 if (i_rToken.Id() == Tok_AtTag::param) 108 { 109 pCurAtTag = new DT_ParameterAtTag; 110 fCurTokenAddFunction = &SapiDocu_PE::SetCurParameterAtTagName; 111 } 112 else if (i_rToken.Id() == Tok_AtTag::see) 113 { 114 pCurAtTag = new DT_SeeAlsoAtTag; 115 fCurTokenAddFunction = &SapiDocu_PE::SetCurSeeAlsoAtTagLinkText; 116 } 117 else if (i_rToken.Id() == Tok_AtTag::deprecated) 118 { 119 pDocu->SetDeprecated(); 120 pCurAtTag = new DT_StdAtTag(""); // Dummy that will not be used. 121 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2Deprecated; 122 } 123 else if (i_rToken.Id() == Tok_AtTag::since) 124 { 125 pCurAtTag = new DT_SinceAtTag; 126 fCurTokenAddFunction = &SapiDocu_PE::SetCurSinceAtTagVersion_OOo; 127 } 128 else 129 { 130 pCurAtTag = new DT_StdAtTag( AtTagTitle(i_rToken) ); 131 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; 132 } 133 } 134 135 void 136 SapiDocu_PE::Process_HtmlTag( const Tok_HtmlTag & i_rToken ) 137 { 138 if (eState == st_short AND i_rToken.IsParagraphStarter()) 139 { 140 eState = st_description; 141 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2Description; 142 } 143 144 // Workaround special for some errors in API docu: 145 if ( strnicmp("<true",i_rToken.Text(),5 ) == 0 ) 146 { 147 if ( strcmp("<TRUE/>",i_rToken.Text()) != 0 ) 148 TheMessages().Out_InvalidConstSymbol( i_rToken.Text(), 149 pPositionInfo->CurFile(), 150 pPositionInfo->CurLine() ); 151 (this->*fCurTokenAddFunction)( *new DT_TextToken("<b>true</b>") ); 152 return; 153 } 154 else if ( strnicmp("<false",i_rToken.Text(),6 ) == 0 ) 155 { 156 if ( strcmp("<FALSE/>",i_rToken.Text()) != 0 ) 157 TheMessages().Out_InvalidConstSymbol( i_rToken.Text(), 158 pPositionInfo->CurFile(), 159 pPositionInfo->CurLine() ); 160 (this->*fCurTokenAddFunction)( *new DT_TextToken("<b>false</b>") ); 161 return; 162 } 163 else if ( strnicmp("<NULL",i_rToken.Text(),5 ) == 0 ) 164 { 165 if ( strcmp("<NULL/>",i_rToken.Text()) != 0 ) 166 TheMessages().Out_InvalidConstSymbol( i_rToken.Text(), 167 pPositionInfo->CurFile(), 168 pPositionInfo->CurLine() ); 169 (this->*fCurTokenAddFunction)( *new DT_TextToken("<b>null</b>") ); 170 return; 171 } 172 else if ( strnicmp("<void",i_rToken.Text(),5 ) == 0 ) 173 { 174 if ( strcmp("<void/>",i_rToken.Text()) != 0 ) 175 TheMessages().Out_InvalidConstSymbol( i_rToken.Text(), 176 pPositionInfo->CurFile(), 177 pPositionInfo->CurLine() ); 178 (this->*fCurTokenAddFunction)( *new DT_TextToken("<b>void</b>") ); 179 return; 180 } 181 182 (this->*fCurTokenAddFunction)( *new DT_Style(i_rToken.Text(),false) ); 183 } 184 185 void 186 SapiDocu_PE::Process_XmlConst( const Tok_XmlConst & i_rToken ) 187 { 188 (this->*fCurTokenAddFunction)(*new DT_MupConst(i_rToken.Text())); 189 } 190 191 void 192 SapiDocu_PE::Process_XmlLink_BeginTag( const Tok_XmlLink_BeginTag & i_rToken ) 193 { 194 switch (i_rToken.Id()) 195 { 196 case Tok_XmlLink_Tag::e_const: 197 (this->*fCurTokenAddFunction)(*new DT_Style("<b>",false)); 198 break; 199 case Tok_XmlLink_Tag::member: 200 (this->*fCurTokenAddFunction)(*new DT_MupMember(i_rToken.Scope())); 201 break; 202 case Tok_XmlLink_Tag::type: 203 (this->*fCurTokenAddFunction)(*new DT_MupType(i_rToken.Scope())); 204 break; 205 default: 206 // Do nothing. 207 ; 208 } 209 210 if ( i_rToken.Dim().length() > 0 ) 211 sCurDimAttribute = i_rToken.Dim(); 212 else 213 sCurDimAttribute.clear(); 214 } 215 216 void 217 SapiDocu_PE::Process_XmlLink_EndTag( const Tok_XmlLink_EndTag & i_rToken ) 218 { 219 switch (i_rToken.Id()) 220 { 221 case Tok_XmlLink_Tag::e_const: 222 (this->*fCurTokenAddFunction)(*new DT_Style("</b>",false)); 223 break; 224 case Tok_XmlLink_Tag::member: 225 (this->*fCurTokenAddFunction)(*new DT_MupMember(true)); 226 break; 227 case Tok_XmlLink_Tag::type: 228 (this->*fCurTokenAddFunction)(*new DT_MupType(true)); 229 break; 230 default: 231 // Do nothing. 232 ; 233 } 234 if ( sCurDimAttribute.length() > 0 ) 235 { 236 (this->*fCurTokenAddFunction)( *new DT_TextToken(sCurDimAttribute.c_str()) ); 237 sCurDimAttribute.clear(); 238 } 239 } 240 241 void 242 SapiDocu_PE::Process_XmlFormat_BeginTag( const Tok_XmlFormat_BeginTag & i_rToken ) 243 { 244 switch (i_rToken.Id()) 245 { 246 case Tok_XmlFormat_Tag::code: 247 (this->*fCurTokenAddFunction)(*new DT_Style("<code>",false)); 248 break; 249 case Tok_XmlFormat_Tag::listing: 250 (this->*fCurTokenAddFunction)(*new DT_Style("<pre>",true)); 251 break; 252 case Tok_XmlFormat_Tag::atom: 253 (this->*fCurTokenAddFunction)(*new DT_Style("<code>",true)); 254 break; 255 default: 256 // Do nothing. 257 ; 258 } 259 if ( i_rToken.Dim().length() > 0 ) 260 sCurDimAttribute = i_rToken.Dim(); 261 else 262 sCurDimAttribute.clear(); 263 } 264 265 void 266 SapiDocu_PE::Process_XmlFormat_EndTag( const Tok_XmlFormat_EndTag & i_rToken ) 267 { 268 switch (i_rToken.Id()) 269 { 270 case Tok_XmlFormat_Tag::code: 271 (this->*fCurTokenAddFunction)(*new DT_Style("</code>",false)); 272 break; 273 case Tok_XmlFormat_Tag::listing: 274 (this->*fCurTokenAddFunction)(*new DT_Style("</pre>",true)); 275 break; 276 case Tok_XmlFormat_Tag::atom: 277 (this->*fCurTokenAddFunction)(*new DT_Style("</code>",true)); 278 break; 279 default: 280 // Do nothing. 281 ; 282 } 283 if ( sCurDimAttribute.length() > 0 ) 284 { 285 (this->*fCurTokenAddFunction)( *new DT_TextToken(sCurDimAttribute.c_str()) ); 286 sCurDimAttribute.clear(); 287 } 288 } 289 290 void 291 SapiDocu_PE::Process_Word( const Tok_Word & i_rToken ) 292 { 293 (this->*fCurTokenAddFunction)(*new DT_TextToken(i_rToken.Text())); 294 } 295 296 void 297 SapiDocu_PE::Process_Comma() 298 { 299 csv_assert(1==7); 300 // (this->*fCurTokenAddFunction)(*new DT_Comma(i_rToken.Text())); 301 } 302 303 void 304 SapiDocu_PE::Process_DocuEnd() 305 { 306 eState = st_complete; 307 if (pCurAtTag) 308 pDocu->AddAtTag(*pCurAtTag.Release()); 309 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2Void; 310 } 311 312 void 313 SapiDocu_PE::Process_EOL() 314 { 315 (this->*fCurTokenAddFunction)(*new DT_EOL); 316 } 317 318 void 319 SapiDocu_PE::Process_White() 320 { 321 (this->*fCurTokenAddFunction)(*new DT_White); 322 } 323 324 DYN ary::doc::OldIdlDocu * 325 SapiDocu_PE::ReleaseJustParsedDocu() 326 { 327 if (IsComplete()) 328 { 329 eState = e_none; 330 return pDocu.Release(); 331 } 332 return 0; 333 } 334 335 336 bool 337 SapiDocu_PE::IsComplete() const 338 { 339 return eState == st_complete; 340 } 341 342 void 343 SapiDocu_PE::AddDocuToken2Void( DYN ary::inf::DocuToken & let_drNewToken ) 344 { 345 delete &let_drNewToken; 346 } 347 348 void 349 SapiDocu_PE::AddDocuToken2Short( DYN ary::inf::DocuToken & let_drNewToken ) 350 { 351 csv_assert(pDocu); 352 pDocu->AddToken2Short(let_drNewToken); 353 } 354 355 void 356 SapiDocu_PE::AddDocuToken2Description( DYN ary::inf::DocuToken & let_drNewToken ) 357 { 358 csv_assert(pDocu); 359 pDocu->AddToken2Description(let_drNewToken); 360 } 361 362 void 363 SapiDocu_PE::AddDocuToken2Deprecated( DYN ary::inf::DocuToken & let_drNewToken ) 364 { 365 csv_assert(pDocu); 366 pDocu->AddToken2DeprecatedText(let_drNewToken); 367 } 368 369 void 370 SapiDocu_PE::AddDocuToken2CurAtTag( DYN ary::inf::DocuToken & let_drNewToken ) 371 { 372 csv_assert(pCurAtTag); 373 pCurAtTag->AddToken(let_drNewToken); 374 } 375 376 void 377 SapiDocu_PE::SetCurParameterAtTagName( DYN ary::inf::DocuToken & let_drNewToken ) 378 { 379 if (let_drNewToken.IsWhiteOnly()) 380 { 381 delete &let_drNewToken; 382 return; 383 } 384 385 csv_assert(pCurAtTag); 386 DT_TextToken * dpText = dynamic_cast< DT_TextToken* >(&let_drNewToken); 387 if (dpText != 0) 388 pCurAtTag->SetName(dpText->GetText()); 389 else 390 pCurAtTag->SetName("parameter ?"); 391 delete &let_drNewToken; 392 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; 393 } 394 395 void 396 SapiDocu_PE::SetCurSeeAlsoAtTagLinkText( DYN ary::inf::DocuToken & let_drNewToken ) 397 { 398 csv_assert(pCurAtTag); 399 400 if (let_drNewToken.IsWhiteOnly()) 401 { 402 delete &let_drNewToken; 403 return; 404 } 405 406 DT_TextToken * pText = dynamic_cast< DT_TextToken* >(&let_drNewToken); 407 if (pText != 0) 408 pCurAtTag->SetName(pText->GetText()); 409 else 410 { 411 DT_MupType * 412 pTypeBegin = dynamic_cast< DT_MupType* >(&let_drNewToken); 413 DT_MupMember * 414 pMemberBegin = dynamic_cast< DT_MupMember* >(&let_drNewToken); 415 if (pTypeBegin != 0 OR pMemberBegin != 0) 416 { 417 sCurAtSeeType_byXML.reset(); 418 419 sCurAtSeeType_byXML 420 << ( pTypeBegin != 0 421 ? pTypeBegin->Scope() 422 : pMemberBegin->Scope() ); 423 424 if (sCurAtSeeType_byXML.tellp() > 0) 425 { 426 sCurAtSeeType_byXML 427 << "::"; 428 } 429 delete &let_drNewToken; 430 fCurTokenAddFunction = &SapiDocu_PE::SetCurSeeAlsoAtTagLinkText_2; 431 return; 432 } 433 else 434 { 435 pCurAtTag->SetName("? (no identifier found)"); 436 } 437 } 438 delete &let_drNewToken; 439 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; 440 } 441 442 void 443 SapiDocu_PE::SetCurSeeAlsoAtTagLinkText_2( DYN ary::inf::DocuToken & let_drNewToken ) 444 { 445 csv_assert(pCurAtTag); 446 447 if (let_drNewToken.IsWhiteOnly()) 448 { 449 delete &let_drNewToken; 450 return; 451 } 452 453 DT_TextToken * 454 pText = dynamic_cast< DT_TextToken* >(&let_drNewToken); 455 if (pText != 0) 456 { 457 sCurAtSeeType_byXML 458 << pText->GetText(); 459 pCurAtTag->SetName(sCurAtSeeType_byXML.c_str()); 460 } 461 else 462 { 463 pCurAtTag->SetName("? (no identifier found)"); 464 } 465 sCurAtSeeType_byXML.reset(); 466 delete &let_drNewToken; 467 fCurTokenAddFunction = &SapiDocu_PE::SetCurSeeAlsoAtTagLinkText_3; 468 } 469 470 void 471 SapiDocu_PE::SetCurSeeAlsoAtTagLinkText_3( DYN ary::inf::DocuToken & let_drNewToken ) 472 { 473 csv_assert(pCurAtTag); 474 475 if (let_drNewToken.IsWhiteOnly()) 476 { 477 delete &let_drNewToken; 478 return; 479 } 480 481 /// Could emit warning, but don't because this parser is obsolete. 482 // Tok_XmlLink_BeginTag * 483 // pLinkEnd = dynamic_cast< Tok_XmlLink_EndTag* >(&let_drNewToken); 484 // if (pLinkEnd == 0) 485 // { 486 // warn_aboutMissingClosingTag(); 487 // } 488 489 delete &let_drNewToken; 490 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2CurAtTag; 491 } 492 493 const String 494 C_sSinceFormat("Correct version format: \"OOo <major>.<minor>[.<micro> if micro is not 0]\"."); 495 496 void 497 SapiDocu_PE::SetCurSinceAtTagVersion_OOo( DYN ary::inf::DocuToken & let_drNewToken ) 498 { 499 csv_assert(pCurAtTag); 500 501 DT_TextToken * pToken = dynamic_cast< DT_TextToken* >(&let_drNewToken); 502 if (pToken == 0) 503 { 504 delete &let_drNewToken; 505 return; 506 } 507 508 const String 509 sVersion(pToken->GetText()); 510 if (NOT CheckVersionSyntax_OOo(sVersion)) 511 { 512 Cerr() << "Version information in @since tag has incorrect format.\n" 513 << "Found: \"" << sVersion << "\"\n" 514 << C_sSinceFormat 515 << Endl(); 516 exit(1); 517 } 518 519 const autodoc::CommandLine & 520 rCommandLine = autodoc::CommandLine::Get_(); 521 if (NOT rCommandLine.DoesTransform_SinceTag()) 522 pCurAtTag->AddToken(let_drNewToken); 523 524 fCurTokenAddFunction = &SapiDocu_PE::SetCurSinceAtTagVersion_Number; 525 } 526 527 void 528 SapiDocu_PE::SetCurSinceAtTagVersion_Number( DYN ary::inf::DocuToken & let_drNewToken ) 529 { 530 csv_assert(pCurAtTag); 531 532 DT_TextToken * pToken = dynamic_cast< DT_TextToken* >(&let_drNewToken); 533 if (pToken == 0) 534 { 535 if (dynamic_cast< DT_White* >(&let_drNewToken) != 0) 536 { 537 String & 538 sValue = pCurAtTag->Access_Text().Access_TextOfFirstToken(); 539 StreamLock 540 sHelp(1000); 541 sValue = sHelp() << sValue << " " << c_str; 542 } 543 544 delete &let_drNewToken; 545 return; 546 } 547 548 const String 549 sVersion(pToken->GetText()); 550 if (NOT CheckVersionSyntax_Number(sVersion)) 551 { 552 Cerr() << "Version information in @since tag has incorrect format.\n" 553 << "Found: \"" << sVersion << "\"\n" 554 << C_sSinceFormat 555 << Endl(); 556 exit(1); 557 } 558 559 const autodoc::CommandLine & 560 rCommandLine = autodoc::CommandLine::Get_(); 561 if ( rCommandLine.DoesTransform_SinceTag()) 562 { 563 pCurAtTag->AddToken(let_drNewToken); 564 565 if (rCommandLine.DisplayOf_SinceTagValue(sVersion).empty()) 566 { 567 // This is the numbered part, but we don't know it. 568 delete &let_drNewToken; 569 570 StreamLock 571 sl(200); 572 sl() 573 << "Since-value '" 574 << sVersion 575 << "' not found in translation table."; 576 throw X_Docu("since", sl().c_str()); 577 } 578 } 579 else 580 { 581 AddDocuToken2SinceAtTag(let_drNewToken); 582 } 583 fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2SinceAtTag; 584 } 585 586 void 587 SapiDocu_PE::AddDocuToken2SinceAtTag( DYN ary::inf::DocuToken & let_drNewToken ) 588 { 589 csv_assert(pCurAtTag); 590 String & 591 sValue = pCurAtTag->Access_Text().Access_TextOfFirstToken(); 592 StreamLock 593 sHelp(1000); 594 595 DT_TextToken * 596 pToken = dynamic_cast< DT_TextToken* >(&let_drNewToken); 597 if (pToken != 0) 598 { 599 sValue = sHelp() << sValue << pToken->GetText() << c_str; 600 } 601 else if (dynamic_cast< DT_White* >(&let_drNewToken) != 0) 602 { 603 sValue = sHelp() << sValue << " " << c_str; 604 } 605 delete &let_drNewToken; 606 } 607 608 bool 609 SapiDocu_PE::CheckVersionSyntax_OOo(const String & i_versionPart1) 610 { 611 return i_versionPart1 == "OOo" 612 OR i_versionPart1 == "OpenOffice.org"; 613 } 614 615 bool 616 SapiDocu_PE::CheckVersionSyntax_Number(const String & i_versionPart2) 617 { 618 if (i_versionPart2.length () == 0) 619 return false; 620 621 const char 622 pt = '.'; 623 unsigned int countDigit = 0; 624 unsigned int countPoint = 0; 625 const char * 626 pFirstPoint = 0; 627 const char * 628 pLastPoint = 0; 629 630 for ( const char * p = i_versionPart2.begin(); 631 *p != 0; 632 ++p ) 633 { 634 if ( std::isdigit(*p) ) 635 ++countDigit; 636 else if (*p == pt) 637 { 638 if (countPoint == 0) 639 pFirstPoint = p; 640 pLastPoint = p; 641 ++countPoint; 642 } 643 } 644 645 if ( countDigit + countPoint == i_versionPart2.length() // only digits and points 646 AND pFirstPoint != 0 AND countPoint < 3 // 1 or 2 points 647 AND pFirstPoint + 1 != pLastPoint // there are digits between two points 648 AND *i_versionPart2.begin() != pt AND *(pLastPoint + 1) != 0 // points are surrounded by digits 649 AND (*(pLastPoint + 1) != '0' OR pLastPoint == pFirstPoint) ) // the first micro-digit is not 0 650 { 651 return true; 652 } 653 return false; 654 } 655 656 const char * 657 AtTagTitle( const Tok_AtTag & i_rToken ) 658 { 659 switch (i_rToken.Id()) 660 { 661 case Tok_AtTag::author: return ""; 662 case Tok_AtTag::see: return "See also"; 663 case Tok_AtTag::param: return "Parameters"; 664 case Tok_AtTag::e_return: return "Returns"; 665 case Tok_AtTag::e_throw: return "Throws"; 666 case Tok_AtTag::example: return "Example"; 667 case Tok_AtTag::deprecated: return "Deprecated"; 668 case Tok_AtTag::suspicious: return ""; 669 case Tok_AtTag::missing: return ""; 670 case Tok_AtTag::incomplete: return ""; 671 case Tok_AtTag::version: return ""; 672 case Tok_AtTag::guarantees: return "Guarantees"; 673 case Tok_AtTag::exception: return "Exception"; 674 case Tok_AtTag::since: return "Since version"; 675 default: 676 // See below. 677 ; 678 } 679 return i_rToken.Text(); 680 } 681 682 683 684 } // namespace dsapi 685 } // namespace csi 686 687