xref: /AOO41X/main/autodoc/source/parser_i/idoc/docu_pe2.cxx (revision a87170c6c4927a10cb9e9ab51807dd00321307a2)
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 
SapiDocu_PE(ParserInfo & io_rPositionInfo)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 
~SapiDocu_PE()67 SapiDocu_PE::~SapiDocu_PE()
68 {
69 }
70 
71 void
ProcessToken(DYN csi::dsapi::Token & let_drToken)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
Process_AtTag(const Tok_AtTag & i_rToken)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
Process_HtmlTag(const Tok_HtmlTag & i_rToken)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
Process_XmlConst(const Tok_XmlConst & i_rToken)186 SapiDocu_PE::Process_XmlConst( const Tok_XmlConst & i_rToken )
187 {
188     (this->*fCurTokenAddFunction)(*new DT_MupConst(i_rToken.Text()));
189 }
190 
191 void
Process_XmlLink_BeginTag(const Tok_XmlLink_BeginTag & i_rToken)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
Process_XmlLink_EndTag(const Tok_XmlLink_EndTag & i_rToken)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
Process_XmlFormat_BeginTag(const Tok_XmlFormat_BeginTag & i_rToken)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
Process_XmlFormat_EndTag(const Tok_XmlFormat_EndTag & i_rToken)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
Process_Word(const Tok_Word & i_rToken)291 SapiDocu_PE::Process_Word( const Tok_Word & i_rToken )
292 {
293     (this->*fCurTokenAddFunction)(*new DT_TextToken(i_rToken.Text()));
294 }
295 
296 void
Process_Comma()297 SapiDocu_PE::Process_Comma()
298 {
299     csv_assert(1==7);
300 //  (this->*fCurTokenAddFunction)(*new DT_Comma(i_rToken.Text()));
301 }
302 
303 void
Process_DocuEnd()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
Process_EOL()313 SapiDocu_PE::Process_EOL()
314 {
315     (this->*fCurTokenAddFunction)(*new DT_EOL);
316 }
317 
318 void
Process_White()319 SapiDocu_PE::Process_White()
320 {
321     (this->*fCurTokenAddFunction)(*new DT_White);
322 }
323 
324 DYN ary::doc::OldIdlDocu *
ReleaseJustParsedDocu()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
IsComplete() const337 SapiDocu_PE::IsComplete() const
338 {
339     return eState == st_complete;
340 }
341 
342 void
AddDocuToken2Void(DYN ary::inf::DocuToken & let_drNewToken)343 SapiDocu_PE::AddDocuToken2Void( DYN ary::inf::DocuToken & let_drNewToken )
344 {
345     delete &let_drNewToken;
346 }
347 
348 void
AddDocuToken2Short(DYN ary::inf::DocuToken & let_drNewToken)349 SapiDocu_PE::AddDocuToken2Short( DYN ary::inf::DocuToken & let_drNewToken )
350 {
351     csv_assert(pDocu);
352     pDocu->AddToken2Short(let_drNewToken);
353 }
354 
355 void
AddDocuToken2Description(DYN ary::inf::DocuToken & let_drNewToken)356 SapiDocu_PE::AddDocuToken2Description( DYN ary::inf::DocuToken & let_drNewToken )
357 {
358     csv_assert(pDocu);
359     pDocu->AddToken2Description(let_drNewToken);
360 }
361 
362 void
AddDocuToken2Deprecated(DYN ary::inf::DocuToken & let_drNewToken)363 SapiDocu_PE::AddDocuToken2Deprecated( DYN ary::inf::DocuToken & let_drNewToken )
364 {
365     csv_assert(pDocu);
366     pDocu->AddToken2DeprecatedText(let_drNewToken);
367 }
368 
369 void
AddDocuToken2CurAtTag(DYN ary::inf::DocuToken & let_drNewToken)370 SapiDocu_PE::AddDocuToken2CurAtTag( DYN ary::inf::DocuToken & let_drNewToken )
371 {
372     csv_assert(pCurAtTag);
373     pCurAtTag->AddToken(let_drNewToken);
374 }
375 
376 void
SetCurParameterAtTagName(DYN ary::inf::DocuToken & let_drNewToken)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
SetCurSeeAlsoAtTagLinkText(DYN ary::inf::DocuToken & let_drNewToken)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
SetCurSeeAlsoAtTagLinkText_2(DYN ary::inf::DocuToken & let_drNewToken)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
SetCurSeeAlsoAtTagLinkText_3(DYN ary::inf::DocuToken & let_drNewToken)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: \"OpenOffice <major>.<minor>[.<micro> if micro is not 0]\".");
495 
496 void
SetCurSinceAtTagVersion_OOo(DYN ary::inf::DocuToken & let_drNewToken)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     if (sVersion != "OpenOffice")
512     {
513         Cerr() << "Version information in @since tag has incorrect format.\n"
514                << "Found: \"" << sVersion << "\"\n"
515                << C_sSinceFormat
516                << Endl();
517         exit(1);
518     }
519 
520     const autodoc::CommandLine &
521         rCommandLine = autodoc::CommandLine::Get_();
522     if (NOT rCommandLine.DoesTransform_SinceTag())
523         pCurAtTag->AddToken(let_drNewToken);
524 
525     fCurTokenAddFunction = &SapiDocu_PE::SetCurSinceAtTagVersion_Number;
526 }
527 
528 void
SetCurSinceAtTagVersion_Number(DYN ary::inf::DocuToken & let_drNewToken)529 SapiDocu_PE::SetCurSinceAtTagVersion_Number( DYN ary::inf::DocuToken & let_drNewToken )
530 {
531     csv_assert(pCurAtTag);
532 
533     DT_TextToken * pToken = dynamic_cast< DT_TextToken* >(&let_drNewToken);
534     if (pToken == 0)
535     {
536         if (dynamic_cast< DT_White* >(&let_drNewToken) != 0)
537         {
538             String &
539                 sValue = pCurAtTag->Access_Text().Access_TextOfFirstToken();
540             StreamLock
541                 sHelp(1000);
542             sValue = sHelp() << sValue << " " << c_str;
543         }
544 
545         delete &let_drNewToken;
546         return;
547     }
548 
549     const String
550         sVersion(pToken->GetText());
551     if (NOT CheckVersionSyntax_Number(sVersion))
552     {
553         Cerr() << "Version information in @since tag has incorrect format.\n"
554                << "Found: \"" << sVersion << "\"\n"
555                << C_sSinceFormat
556                << Endl();
557         exit(1);
558     }
559 
560     const autodoc::CommandLine &
561         rCommandLine = autodoc::CommandLine::Get_();
562     if ( rCommandLine.DoesTransform_SinceTag())
563     {
564         pCurAtTag->AddToken(let_drNewToken);
565 
566         if (rCommandLine.DisplayOf_SinceTagValue(sVersion).empty())
567         {
568             // This is the numbered part, but we don't know it.
569             delete &let_drNewToken;
570 
571             StreamLock
572                 sl(200);
573             sl()
574                 << "Since-value '"
575                 << sVersion
576                 << "' not found in translation table.";
577             throw X_Docu("since", sl().c_str());
578         }
579     }
580     else
581     {
582         AddDocuToken2SinceAtTag(let_drNewToken);
583     }
584     fCurTokenAddFunction = &SapiDocu_PE::AddDocuToken2SinceAtTag;
585 }
586 
587 void
AddDocuToken2SinceAtTag(DYN ary::inf::DocuToken & let_drNewToken)588 SapiDocu_PE::AddDocuToken2SinceAtTag( DYN ary::inf::DocuToken & let_drNewToken )
589 {
590     csv_assert(pCurAtTag);
591     String &
592         sValue = pCurAtTag->Access_Text().Access_TextOfFirstToken();
593     StreamLock
594         sHelp(1000);
595 
596     DT_TextToken *
597         pToken = dynamic_cast< DT_TextToken* >(&let_drNewToken);
598     if (pToken != 0)
599     {
600         sValue = sHelp() << sValue << pToken->GetText() << c_str;
601     }
602     else if (dynamic_cast< DT_White* >(&let_drNewToken) != 0)
603     {
604         sValue = sHelp() << sValue << " " << c_str;
605     }
606     delete &let_drNewToken;
607 }
608 
609 bool
CheckVersionSyntax_Number(const String & i_versionPart2)610 SapiDocu_PE::CheckVersionSyntax_Number(const String & i_versionPart2)
611 {
612     if (i_versionPart2.length () == 0)
613         return false;
614 
615     const char
616         pt = '.';
617     unsigned int countDigit = 0;
618     unsigned int countPoint = 0;
619     const char *
620         pFirstPoint = 0;
621     const char *
622         pLastPoint = 0;
623 
624     for ( const char * p = i_versionPart2.begin();
625           *p != 0;
626           ++p )
627     {
628         if ( std::isdigit(*p) )
629             ++countDigit;
630         else if (*p == pt)
631         {
632             if (countPoint == 0)
633                 pFirstPoint = p;
634             pLastPoint = p;
635             ++countPoint;
636         }
637     }
638 
639     if (    countDigit + countPoint == i_versionPart2.length()         // only digits and points
640         AND pFirstPoint != 0 AND countPoint < 3                         // 1 or 2 points
641         AND pFirstPoint + 1 != pLastPoint                               // there are digits between two points
642         AND *i_versionPart2.begin() != pt AND *(pLastPoint + 1) != 0    // points are surrounded by digits
643         AND (*(pLastPoint + 1) != '0' OR pLastPoint == pFirstPoint) )   // the first micro-digit is not 0
644     {
645         return true;
646     }
647     return false;
648 }
649 
650 const char *
AtTagTitle(const Tok_AtTag & i_rToken)651 AtTagTitle( const Tok_AtTag & i_rToken )
652 {
653     switch (i_rToken.Id())
654     {
655         case Tok_AtTag::author:     return "";
656         case Tok_AtTag::see:        return "See also";
657         case Tok_AtTag::param:      return "Parameters";
658         case Tok_AtTag::e_return:   return "Returns";
659         case Tok_AtTag::e_throw:    return "Throws";
660         case Tok_AtTag::example:    return "Example";
661         case Tok_AtTag::deprecated: return "Deprecated";
662         case Tok_AtTag::suspicious: return "";
663         case Tok_AtTag::missing:    return "";
664         case Tok_AtTag::incomplete: return "";
665         case Tok_AtTag::version:    return "";
666         case Tok_AtTag::guarantees: return "Guarantees";
667         case Tok_AtTag::exception:  return "Exception";
668         case Tok_AtTag::since:      return "Since version";
669         default:
670             //  See below.
671             ;
672     }
673     return i_rToken.Text();
674 }
675 
676 
677 
678 }   // namespace dsapi
679 }   // namespace csi
680 
681