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