1 //@copyright_begin
2 // ================================================================
3 // Copyright Notice
4 // Copyright (C) 1998-2004 by Joe Linoff
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining
7 // a copy of this software and associated documentation files (the
8 // "Software"), to deal in the Software without restriction, including
9 // without limitation the rights to use, copy, modify, merge, publish,
10 // distribute, sublicense, and/or sell copies of the Software, and to
11 // permit persons to whom the Software is furnished to do so, subject to
12 // the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be
15 // included in all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 // IN NO EVENT SHALL JOE LINOFF BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 // OTHER DEALINGS IN THE SOFTWARE.
24 //
25 // Comments and suggestions are always welcome.
26 // Please report bugs to http://ccdoc.sourceforge.net/ccdoc
27 // ================================================================
28 //@copyright_end
29 #include "statement.h"
30 #include "log.h"
31 #include <algorithm>
32 #include <cstdio>
33 #include <cstring>
34
35 // ================================================================
36 // This variable allows the header version
37 // to be queried at runtime.
38 // ================================================================
39 namespace {
40 char ccdoc_rcsid[] = "$Id: statement.cc,v 1.15 2004/09/30 04:52:36 jlinoff Exp $";
41 }
42
43 // ================================================================
44 // String manager.
45 // ================================================================
46 namespace {
47 ccdoc::strmgr s_strmgr;
48 }
get_strmgr()49 ccdoc::strmgr& ccdoc::statement::base::get_strmgr()
50 {
51 // Make sure that all of the terse strings in are
52 // the string table. This guarantees that the db
53 // write will work correctly in terse mode.
54 s_strmgr.get("pub");
55 s_strmgr.get("pro");
56 s_strmgr.get("pri");
57
58 s_strmgr.get("unk");
59 s_strmgr.get("ign");
60 s_strmgr.get("att");
61 s_strmgr.get("atf");
62 s_strmgr.get("enu");
63 s_strmgr.get("ext");
64 s_strmgr.get("frc");
65 s_strmgr.get("frf");
66 s_strmgr.get("fct");
67 s_strmgr.get("con");
68 s_strmgr.get("des");
69 s_strmgr.get("opr");
70 s_strmgr.get("cls");
71 s_strmgr.get("clx");
72 s_strmgr.get("cod");
73 s_strmgr.get("cop");
74 s_strmgr.get("cos");
75 s_strmgr.get("m00");
76 s_strmgr.get("m01");
77 s_strmgr.get("m0n");
78 s_strmgr.get("mnn");
79 s_strmgr.get("mif");
80 s_strmgr.get("miv");
81 s_strmgr.get("met");
82 s_strmgr.get("nsp");
83 s_strmgr.get("nsx");
84 s_strmgr.get("pkg");
85 s_strmgr.get("str");
86 s_strmgr.get("stx");
87 s_strmgr.get("tyf");
88 s_strmgr.get("tyv");
89 s_strmgr.get("uni");
90 s_strmgr.get("unx");
91 s_strmgr.get("var");
92 s_strmgr.get("vaf");
93
94 return s_strmgr;
95 }
96 // ================================================================
97 // Constructor
98 // ================================================================
base()99 ccdoc::statement::base::base()
100 : m_comment(0),
101 m_file(0),
102 m_id(0),
103 m_extern(0),
104 m_lineno(0),
105 m_parent(0),
106 m_type(STMT_IGNORE),
107 m_access(STMT_PUBLIC),
108 m_tag(0),
109 m_sorted(true),
110 m_static(false),
111 m_template(false),
112 m_next(0)
113 {
114 set_id(0);
115 set_file(0);
116 set_extern(0);
117 }
118 // ================================================================
119 // Copy Constructor
120 // ================================================================
base(const base & x)121 ccdoc::statement::base::base(const base& x)
122 : m_children(x.m_children),
123 m_comment(x.m_comment),
124 m_file(x.m_file),
125 m_id(x.m_id),
126 m_extern(x.m_extern),
127 m_lineno(x.m_lineno),
128 m_parent(x.m_parent),
129 m_tokens(x.m_tokens),
130 m_type(x.m_type),
131 m_access(x.m_access),
132 m_tag(x.m_tag),
133 m_sorted(x.m_sorted),
134 m_static(x.m_static),
135 m_template(x.m_template),
136 m_next(x.m_next)
137 {
138 }
139 // ================================================================
140 // Copy operator
141 // ================================================================
142 ccdoc::statement::base&
operator =(const base & x)143 ccdoc::statement::base::operator=(const base& x)
144 {
145 m_access = x.m_access;
146 m_children = x.m_children;
147 m_comment = x.m_comment;
148 m_file = x.m_file;
149 m_id = x.m_id;
150 m_extern = x.m_extern;
151 m_lineno = x.m_lineno;
152 m_tag = x.m_tag;
153 m_parent = x.m_parent;
154 m_sorted = x.m_sorted;
155 m_static = x.m_static;
156 m_template = x.m_template;
157 m_tokens = x.m_tokens;
158 m_type = x.m_type;
159
160 return *this;
161 }
162 // ================================================================
163 // Destructor
164 // ================================================================
~base()165 ccdoc::statement::base::~base()
166 {
167 if( m_parent ) {
168 m_parent->remove_child(this);
169 m_parent = 0;
170 }
171 if( m_comment ) {
172 m_comment->set_comment(0);
173 m_comment = 0;
174 }
175 if( m_children.size() ) {
176 // Make a copy of the children vector
177 // to avoid messing up the iterator.
178 stmts_t vec = m_children;
179 m_children.clear();
180 stmts_itr_t itr = vec.begin();
181 for(;itr!=vec.end();++itr) {
182 base* child = *itr;
183 delete child;
184 }
185 }
186 }
187 // ================================================================
188 // Clear
189 // ================================================================
clear()190 void ccdoc::statement::base::clear()
191 {
192 m_access = STMT_PUBLIC;
193 m_comment = 0;
194 m_children.clear();
195 set_file(0);
196 set_id(0);
197 set_extern(0);
198 m_lineno = 0;
199 m_tag = 0;
200 m_parent = 0;
201 m_tokens.clear();
202 m_type = STMT_IGNORE;
203 m_sorted = false;
204 m_static = false;
205 m_template = false;
206 set_id(0);
207 }
208 // ================================================================
209 // Set string.
210 // ================================================================
set_string(const char * value)211 const char* ccdoc::statement::base::set_string(const char* value)
212 {
213 if(value) {
214 string key = value;
215 const string& p = s_strmgr.get(key);
216 return p.c_str();
217 }
218 return set_string("");
219 }
220 // ================================================================
221 // Set file.
222 // ================================================================
set_file(const char * file)223 void ccdoc::statement::base::set_file(const char* file)
224 {
225 m_file = set_string(file);
226 }
227 // ================================================================
228 // Set the external linkage type.
229 // ================================================================
set_extern(const char * x)230 void ccdoc::statement::base::set_extern(const char* x)
231 {
232 m_extern = set_string(x);
233 }
234 // ================================================================
235 // Set id.
236 // ================================================================
set_id(const char * id)237 void ccdoc::statement::base::set_id(const char* id)
238 {
239 m_id = set_string(id);
240 if( m_parent )
241 m_parent->m_sorted = false;
242 }
243 // ================================================================
244 // Set id.
245 // ================================================================
set_id(const string & id)246 void ccdoc::statement::base::set_id(const string& id)
247 {
248 set_id(id.c_str());
249 }
250 // ================================================================
251 // add token
252 // ================================================================
add_token(const char * str)253 void ccdoc::statement::base::add_token(const char* str)
254 {
255 if(str) {
256 const string& p = s_strmgr.get(str);
257 m_tokens.push_back( p.c_str() );
258 }
259 }
260 // ================================================================
261 // Set tokens.
262 // ================================================================
set_tokens(strs_t & vec)263 void ccdoc::statement::base::set_tokens(strs_t& vec)
264 {
265 m_tokens.clear();
266 strs_itr_t itr = vec.begin();
267 for(;itr!=vec.end();++itr) {
268 string& str = *itr;
269 const string& p = s_strmgr.get(str);
270 m_tokens.push_back( p.c_str() );
271 }
272 }
273 // ================================================================
274 // Get parents.
275 // ================================================================
get_parents(base::stmts_t & parents) const276 void ccdoc::statement::base::get_parents(base::stmts_t& parents) const
277 {
278 if(parents.size())
279 parents.clear();
280 base* stmt = get_parent();
281 while(stmt) {
282 parents.push_back(stmt);
283 stmt = stmt->get_parent();
284 }
285 reverse(parents.begin(),parents.end());
286 }
287 // ================================================================
288 // Get parents, don't include packages.
289 // ================================================================
get_parents_no_pkgs(stmts_t & parents) const290 void ccdoc::statement::base::get_parents_no_pkgs(stmts_t& parents) const
291 {
292 if(parents.size())
293 parents.clear();
294 if( get_type() != STMT_PACKAGE ) {
295 base* stmt = get_parent();
296 while(stmt) {
297 if( stmt->get_type() == STMT_PACKAGE )
298 break;
299 parents.push_back(stmt);
300 stmt = stmt->get_parent();
301 }
302 reverse(parents.begin(),parents.end());
303 }
304 }
305 // ================================================================
306 // Set parent.
307 // ================================================================
set_parent(base * parent)308 void ccdoc::statement::base::set_parent(base* parent)
309 {
310 if(m_parent) {
311 m_parent->remove_child(this);
312 }
313 m_parent = parent;
314 if(m_parent) {
315 m_parent->add_child(this);
316 }
317 }
318 // ================================================================
319 // Insert before.
320 // ================================================================
insert_before(base * stmt)321 void ccdoc::statement::base::insert_before(base* stmt)
322 {
323 // Insert this after stmt in it's child list.
324 if( stmt ) {
325 if( m_parent ) {
326 m_parent->remove_child(this);
327 }
328 if( stmt->m_parent ) {
329 stmts_t& vec = stmt->m_parent->m_children;
330 stmts_itr_t itr = vec.begin();
331 for(;itr!=m_children.end();++itr) {
332 if( stmt == *itr ) {
333 m_sorted = false;
334 vec.insert(itr,this);
335 m_parent = stmt->m_parent;
336 return;
337 }
338 }
339 }
340 }
341 }
342 // ================================================================
343 // Insert after.
344 // ================================================================
insert_after(base * stmt)345 void ccdoc::statement::base::insert_after(base* stmt)
346 {
347 // Insert this after stmt in it's child list.
348 if( stmt ) {
349 if( m_parent ) {
350 m_parent->remove_child(this);
351 }
352 if( stmt->m_parent ) {
353 stmts_t& vec = stmt->m_parent->m_children;
354 stmts_itr_t itr = vec.begin();
355 for(;itr!=m_children.end();++itr) {
356 if( stmt == *itr ) {
357 ++itr;
358 m_sorted = false;
359 if( itr != m_children.end() ) {
360 vec.insert(itr,this);
361 }
362 else {
363 vec.push_back(this);
364 }
365 m_parent = stmt->m_parent;
366 return;
367 }
368 }
369 }
370 }
371 }
372 // ================================================================
373 // Add a child.
374 // ================================================================
add_child(base * child)375 void ccdoc::statement::base::add_child(base* child)
376 {
377 if(child && find_child(child) == false) {
378 if( m_sorted &&
379 m_children.size() &&
380 strcmp(m_children.back()->get_id(),child->get_id())>0 )
381 m_sorted = false;
382 m_children.push_back(child);
383 child->m_parent = this;
384 }
385 }
386 // ================================================================
387 // Remove a child.
388 // ================================================================
remove_child(base * child)389 void ccdoc::statement::base::remove_child(base* child)
390 {
391 if(child) {
392 stmts_itr_t itr = m_children.begin();
393 for(;itr!=m_children.end();++itr) {
394 if( *itr == child ) {
395 child->m_parent = 0;
396 m_children.erase(itr);
397 return;
398 }
399 }
400 }
401 }
402 // ================================================================
403 // Get all children, load them into a vector.
404 // ================================================================
get_all_children(stmts_t & children) const405 void ccdoc::statement::base::get_all_children(stmts_t& children) const
406 {
407 stmts_citr_t itr = m_children.begin();
408 for(;itr!=m_children.end();++itr) {
409 statement::base* stmt = *itr;
410 children.push_back(stmt);
411 stmt->get_all_children(children);
412 }
413 }
414 // ================================================================
415 // Get a child by a type and an id name.
416 // ================================================================
417 ccdoc::statement::base*
get_child_by_id_type(const char * id,TYPE t) const418 ccdoc::statement::base::get_child_by_id_type(const char* id,TYPE t) const
419 {
420 if(id) {
421 stmts_citr_t itr = m_children.begin();
422 for(;itr!=m_children.end();++itr) {
423 statement::base* stmt = *itr;
424 if( stmt->get_type() == t && !::strcmp(stmt->get_id(),id) )
425 return stmt;
426 }
427 }
428 return 0;
429 }
430 // ================================================================
431 // Get a child by a type and an id name.
432 // ================================================================
433 ccdoc::statement::base*
get_child_by_id_type(const string & id,TYPE t) const434 ccdoc::statement::base::get_child_by_id_type(const string& id,TYPE t) const
435 {
436 return get_child_by_id_type(id.c_str(),t);
437 }
438 // ================================================================
439 // Get a child by an id name.
440 // ================================================================
441 ccdoc::statement::base*
get_child_by_id(const char * id) const442 ccdoc::statement::base::get_child_by_id(const char* id) const
443 {
444 if(id) {
445 stmts_citr_t itr = m_children.begin();
446 for(;itr!=m_children.end();++itr) {
447 statement::base* stmt = *itr;
448 if( !::strcmp(stmt->get_id(),id) )
449 return stmt;
450 }
451 }
452 return 0;
453 }
454 // ================================================================
455 // Get a child by an id name.
456 // ================================================================
457 ccdoc::statement::base*
get_child_by_id(const string & id) const458 ccdoc::statement::base::get_child_by_id(const string& id) const
459 {
460 return get_child_by_id(id.c_str());
461 }
462 // ================================================================
463 // Find a child.
464 // ================================================================
find_child(base * child) const465 bool ccdoc::statement::base::find_child(base* child) const
466 {
467 if(child) {
468 stmts_citr_t itr = m_children.begin();
469 for(;itr!=m_children.end();++itr) {
470 if( *itr == child )
471 return true;
472 }
473 }
474 return false;
475 }
476 // ================================================================
477 // Get children by an id name.
478 // ================================================================
get_children_by_id(stmts_t & vec,const char * id)479 bool ccdoc::statement::base::get_children_by_id(stmts_t& vec,
480 const char* id)
481 {
482 bool st = false;
483 if(id) {
484 stmts_itr_t itr = search(id);
485 for(;itr!=m_children.end();++itr) {
486 statement::base* stmt = *itr;
487 if( !::strcmp(stmt->get_id(),id) ) {
488 st = true;
489 vec.push_back(stmt);
490 }
491 else {
492 break;
493 }
494 }
495 }
496 return st;
497 }
498 // ================================================================
499 // Get children by an id name.
500 // ================================================================
get_children_by_id(stmts_t & vec,const string & id)501 bool ccdoc::statement::base::get_children_by_id(stmts_t& vec,
502 const string& id)
503 {
504 return get_children_by_id(vec,id.c_str());
505 }
506 // ================================================================
507 // Get hier id.
508 // ================================================================
get_hier_id(string & id) const509 void ccdoc::statement::base::get_hier_id(string& id) const
510 {
511 id = "";
512 if(get_parent()) {
513 strs_t vec;
514 const base* x = this;
515 while( x ) {
516 vec.push_back(x->get_id());
517 x = x->get_parent();
518 }
519
520 strs_ritr_t itr = vec.rbegin();
521 for(;itr!=vec.rend();++itr) {
522 id += "::";
523 id += *itr;
524 }
525 }
526 }
527 // ================================================================
528 // Get hier id, don't include packages.
529 // ================================================================
get_hier_id_no_pkgs(string & id) const530 void ccdoc::statement::base::get_hier_id_no_pkgs(string& id) const
531 {
532 id = "";
533 if(get_parent()) {
534 strs_t vec;
535 const base* x = this;
536 while( x ) {
537 if( x->get_type() == STMT_PACKAGE )
538 break;
539 vec.push_back(x->get_id());
540 x = x->get_parent();
541 }
542
543 if( vec.size() ) {
544 strs_ritr_t itr = vec.rbegin();
545 if( itr != vec.rend() )
546 id += *itr;
547 for(++itr;itr!=vec.rend();++itr) {
548 id += "::";
549 id += *itr;
550 }
551 }
552 }
553 }
554 // ================================================================
555 // Get the access name.
556 // ================================================================
get_access_name(ACCESS a)557 const char* ccdoc::statement::base::get_access_name(ACCESS a)
558 {
559 switch(a) {
560 case STMT_PUBLIC: return "public";
561 case STMT_PROTECTED: return "protected";
562 case STMT_PRIVATE: return "private";
563 default: break;
564 }
565 return "unknown";
566 }
567 // ================================================================
568 // Get the terse access name.
569 // ================================================================
get_terse_access_name(ACCESS a)570 const char* ccdoc::statement::base::get_terse_access_name(ACCESS a)
571 {
572 switch(a) {
573 case STMT_PUBLIC: return "pub";
574 case STMT_PROTECTED: return "pro";
575 case STMT_PRIVATE: return "pri";
576 default: break;
577 }
578 return "unknown";
579 }
580 // ================================================================
581 // Get the terse access name.
582 // ================================================================
583 ccdoc::statement::base::ACCESS
get_terse_access(const string & token)584 ccdoc::statement::base::get_terse_access(const string& token)
585 {
586 if( token == "pro" ) return STMT_PROTECTED;
587 if( token == "pri" ) return STMT_PRIVATE;
588 return STMT_PUBLIC;
589 }
590 // ================================================================
591 // Get the full type name in lower case with static prepended.
592 // ================================================================
get_type_name2() const593 string ccdoc::statement::base::get_type_name2() const
594 {
595 string name;
596
597 // Issue 0144:
598 if( m_static )
599 name += "static ";
600
601 // Issue 0122:
602 if( m_template )
603 name += "template ";
604
605 name += get_type_name1();
606 return name;
607 }
608 // ================================================================
609 // Get the full type name in lower case.
610 // ================================================================
get_type_name1(TYPE t)611 const char* ccdoc::statement::base::get_type_name1(TYPE t)
612 {
613 switch(t) {
614 case STMT_ATTRIBUTE: return "attribute";
615 case STMT_ATTRIBUTE_FUNCTION: return "attribute";
616 case STMT_ENUM: return "enum";
617 case STMT_FRIEND_FUNCTION: return "friend";
618 case STMT_FUNCTION: return "function";
619 case STMT_FUNCTION_OPERATOR: return "operator";
620 case STMT_CLASS_BEGIN: return "class";
621 case STMT_MACRODEF_0_0: return "macro";
622 case STMT_MACRODEF_0_1: return "macro";
623 case STMT_MACRODEF_0_N: return "macro";
624 case STMT_MACRODEF_N_N: return "macro";
625 case STMT_MACROINST_FUNCTION: return "macroinst";
626 case STMT_MACROINST_VARIABLE: return "macroinst";
627 case STMT_METHOD: return "method";
628 case STMT_METHOD_CONSTRUCTOR: return "constructor";
629 case STMT_METHOD_DESTRUCTOR: return "destructor";
630 case STMT_METHOD_OPERATOR: return "operator";
631 case STMT_NAMESPACE_BEGIN: return "namespace";
632 case STMT_PACKAGE: return "package";
633 case STMT_STRUCT_BEGIN: return "struct";
634 case STMT_TYPEDEF_FUNCTION: return "typedef";
635 case STMT_TYPEDEF_VARIABLE: return "typedef";
636 case STMT_UNION_BEGIN: return "union";
637 case STMT_VARIABLE: return "variable";
638 case STMT_VARIABLE_FUNCTION: return "variable";
639 default: break;
640 }
641 return get_type_name(t);
642 }
643 // ================================================================
644 // Get the type name.
645 // ================================================================
get_type_name(TYPE t)646 const char* ccdoc::statement::base::get_type_name(TYPE t)
647 {
648 switch(t) {
649 case STMT_IGNORE: return "IGNORE";
650 case STMT_ATTRIBUTE: return "ATTRIBUTE";
651 case STMT_ATTRIBUTE_FUNCTION: return "ATTRIBUTE_FUNCTION";
652 case STMT_ENUM: return "ENUM";
653 case STMT_EXTERN: return "EXTERN";
654 case STMT_FRIEND_CLASS: return "FRIEND_CLASS";
655 case STMT_FRIEND_FUNCTION: return "FRIEND_FUNCTION";
656 case STMT_FUNCTION: return "FUNCTION";
657 case STMT_FUNCTION_OPERATOR: return "FUNCTION_OPERATOR";
658 case STMT_CLASS_BEGIN: return "CLASS_BEGIN";
659 case STMT_CLASS_END: return "CLASS_END";
660 case STMT_COMMENT_PKGDOC: return "COMMENT_PKGDOC";
661 case STMT_COMMENT_PKGDOC_URL: return "COMMENT_PKGDOC_URL";
662 case STMT_COMMENT_PREFIX: return "COMMENT_PREFIX";
663 case STMT_COMMENT_SUFFIX: return "COMMENT_SUFFIX";
664 case STMT_MACRODEF_0_0: return "MACRODEF_0_0";
665 case STMT_MACRODEF_0_1: return "MACRODEF_0_1";
666 case STMT_MACRODEF_0_N: return "MACRODEF_0_N";
667 case STMT_MACRODEF_N_N: return "MACRODEF_N_N";
668 case STMT_MACROINST_FUNCTION: return "MACROINST_FUNCTION";
669 case STMT_MACROINST_VARIABLE: return "MACROINST_VARIABLE";
670 case STMT_METHOD: return "METHOD";
671 case STMT_METHOD_CONSTRUCTOR: return "METHOD_CONSTRUCTOR";
672 case STMT_METHOD_DESTRUCTOR: return "METHOD_DESTRUCTOR";
673 case STMT_METHOD_OPERATOR: return "METHOD_OPERATOR";
674 case STMT_NAMESPACE_BEGIN: return "NAMESPACE_BEGIN";
675 case STMT_NAMESPACE_END: return "NAMESPACE_END";
676 case STMT_PACKAGE: return "PACKAGE";
677 case STMT_STRUCT_BEGIN: return "STRUCT_BEGIN";
678 case STMT_STRUCT_END: return "STRUCT_END";
679 case STMT_TYPEDEF_FUNCTION: return "TYPEDEF_FUNCTION";
680 case STMT_TYPEDEF_VARIABLE: return "TYPEDEF_VARIABLE";
681 case STMT_UNION_BEGIN: return "UNION_BEGIN";
682 case STMT_UNION_END: return "UNION_END";
683 case STMT_VARIABLE: return "VARIABLE";
684 case STMT_VARIABLE_FUNCTION: return "VARIABLE_FUNCTION";
685 default: break;
686 }
687 return "UNKNOWN";
688 }
689 // ================================================================
690 // Get the terse type name.
691 // ================================================================
get_terse_type_name(TYPE t)692 const char* ccdoc::statement::base::get_terse_type_name(TYPE t)
693 {
694 switch(t) {
695 case STMT_IGNORE: return "ign";
696 case STMT_ATTRIBUTE: return "att";
697 case STMT_ATTRIBUTE_FUNCTION: return "atf";
698 case STMT_ENUM: return "enu";
699 case STMT_EXTERN: return "ext";
700 case STMT_FRIEND_CLASS: return "frc";
701 case STMT_FRIEND_FUNCTION: return "frf";
702 case STMT_FUNCTION: return "fct";
703 case STMT_FUNCTION_OPERATOR: return "opr";
704 case STMT_CLASS_BEGIN: return "cls";
705 case STMT_CLASS_END: return "clx";
706 case STMT_COMMENT_PKGDOC: return "cod";
707 case STMT_COMMENT_PKGDOC_URL: return "cou";
708 case STMT_COMMENT_PREFIX: return "cop";
709 case STMT_COMMENT_SUFFIX: return "cos";
710 case STMT_MACRODEF_0_0: return "m00";
711 case STMT_MACRODEF_0_1: return "m01";
712 case STMT_MACRODEF_0_N: return "m0n";
713 case STMT_MACRODEF_N_N: return "mnn";
714 case STMT_MACROINST_FUNCTION: return "mif";
715 case STMT_MACROINST_VARIABLE: return "miv";
716 case STMT_METHOD: return "met";
717 case STMT_METHOD_CONSTRUCTOR: return "con";
718 case STMT_METHOD_DESTRUCTOR: return "des";
719 case STMT_METHOD_OPERATOR: return "mop";
720 case STMT_NAMESPACE_BEGIN: return "nsp";
721 case STMT_NAMESPACE_END: return "nsx";
722 case STMT_PACKAGE: return "pkg";
723 case STMT_STRUCT_BEGIN: return "str";
724 case STMT_STRUCT_END: return "stx";
725 case STMT_TYPEDEF_FUNCTION: return "tyf";
726 case STMT_TYPEDEF_VARIABLE: return "tyv";
727 case STMT_UNION_BEGIN: return "uni";
728 case STMT_UNION_END: return "unx";
729 case STMT_VARIABLE: return "var";
730 case STMT_VARIABLE_FUNCTION: return "vaf";
731 default: break;
732 }
733 return "unk";
734 }
735 // ================================================================
736 // Get the terse type name.
737 // ================================================================
738 ccdoc::statement::base::TYPE
get_terse_type(const string & token)739 ccdoc::statement::base::get_terse_type(const string& token)
740 {
741 if(token == "ign" ) return STMT_IGNORE ;
742 if(token == "att" ) return STMT_ATTRIBUTE ;
743 if(token == "atf" ) return STMT_ATTRIBUTE_FUNCTION ;
744 if(token == "enu" ) return STMT_ENUM ;
745 if(token == "ext" ) return STMT_EXTERN ;
746 if(token == "frc" ) return STMT_FRIEND_CLASS ;
747 if(token == "frf" ) return STMT_FRIEND_FUNCTION ;
748 if(token == "fct" ) return STMT_FUNCTION ;
749 if(token == "opr" ) return STMT_FUNCTION_OPERATOR ;
750 if(token == "cls" ) return STMT_CLASS_BEGIN ;
751 if(token == "clx" ) return STMT_CLASS_END ;
752 if(token == "cod" ) return STMT_COMMENT_PKGDOC ;
753 if(token == "cou" ) return STMT_COMMENT_PKGDOC_URL ;
754 if(token == "cop" ) return STMT_COMMENT_PREFIX ;
755 if(token == "cos" ) return STMT_COMMENT_SUFFIX ;
756 if(token == "m00" ) return STMT_MACRODEF_0_0 ;
757 if(token == "m01" ) return STMT_MACRODEF_0_1 ;
758 if(token == "m0n" ) return STMT_MACRODEF_0_N ;
759 if(token == "mnn" ) return STMT_MACRODEF_N_N ;
760 if(token == "mif" ) return STMT_MACROINST_FUNCTION ;
761 if(token == "miv" ) return STMT_MACROINST_VARIABLE ;
762 if(token == "met" ) return STMT_METHOD ;
763 if(token == "con" ) return STMT_METHOD_CONSTRUCTOR ;
764 if(token == "des" ) return STMT_METHOD_DESTRUCTOR ;
765 if(token == "mop" ) return STMT_METHOD_OPERATOR ;
766 if(token == "nsp" ) return STMT_NAMESPACE_BEGIN ;
767 if(token == "nsx" ) return STMT_NAMESPACE_END ;
768 if(token == "pkg" ) return STMT_PACKAGE ;
769 if(token == "str" ) return STMT_STRUCT_BEGIN ;
770 if(token == "stx" ) return STMT_STRUCT_END ;
771 if(token == "tyf" ) return STMT_TYPEDEF_FUNCTION ;
772 if(token == "tyv" ) return STMT_TYPEDEF_VARIABLE ;
773 if(token == "uni" ) return STMT_UNION_BEGIN ;
774 if(token == "unx" ) return STMT_UNION_END ;
775 if(token == "var" ) return STMT_VARIABLE ;
776 if(token == "vaf" ) return STMT_VARIABLE_FUNCTION ;
777 return STMT_IGNORE;
778 }
779 // ================================================================
780 // Get depth.
781 // ================================================================
get_depth() const782 unsigned ccdoc::statement::base::get_depth() const
783 {
784 // The top always returns zero.
785 unsigned depth = 0;
786 base* stmt = get_parent();
787 while(stmt) {
788 depth++;
789 stmt = stmt->get_parent();
790 }
791 return depth;
792 }
793 // ================================================================
794 // Get depth.
795 // ================================================================
get_depth_no_pkgs() const796 unsigned ccdoc::statement::base::get_depth_no_pkgs() const
797 {
798 // The top always returns zero.
799 unsigned depth = 0;
800 base* stmt = get_parent();
801 while(stmt && stmt->get_type() != STMT_PACKAGE ) {
802 depth++;
803 stmt = stmt->get_parent();
804 }
805 return depth;
806 }
807 // ================================================================
808 // Get the matching begin statement.
809 // ================================================================
810 ccdoc::statement::base*
get_matching_begin() const811 ccdoc::statement::base::get_matching_begin() const
812 {
813 switch( get_type() ) {
814 case STMT_CLASS_END:
815 return get_matching_begin(STMT_CLASS_BEGIN);
816 break;
817 case STMT_STRUCT_END:
818 return get_matching_begin(STMT_STRUCT_BEGIN);
819 break;
820 case STMT_UNION_END:
821 return get_matching_begin(STMT_UNION_BEGIN);
822 break;
823 default:
824 break;
825 }
826 return 0;
827 }
828 // ================================================================
829 // Get the matching begin statement.
830 // ================================================================
831 ccdoc::statement::base*
get_matching_begin(TYPE t) const832 ccdoc::statement::base::get_matching_begin(TYPE t) const
833 {
834 unsigned depth = get_depth();
835 base* parent = get_parent();
836 if( parent ) {
837 stmts_t& vec = parent->get_children();
838 stmts_itr_t itr = vec.begin();
839 for(;itr!=vec.end();++itr) {
840 if( *itr == this ) {
841 // Found the end statement.
842 // Now back up to the enclosing begin.
843 for(;itr!=vec.begin();--itr) {
844 base* begin = *itr;
845 if( begin->get_type() == t && begin->get_depth() == depth )
846 return begin;
847 }
848 break;
849 }
850 }
851 }
852 return 0;
853 }
854 // ================================================================
855 // Local sort compare.
856 // ================================================================
857 namespace
858 {
compare_stmts(const ccdoc::statement::base * a,const ccdoc::statement::base * b)859 bool compare_stmts(const ccdoc::statement::base* a,
860 const ccdoc::statement::base* b)
861 {
862 return strcmp(a->get_id(),b->get_id()) < 0;
863 }
864 }
865 // ================================================================
866 // Sort
867 // ================================================================
sort_children()868 void ccdoc::statement::base::sort_children()
869 {
870 if( !m_sorted ) {
871 stable_sort(m_children.begin(),m_children.end(),compare_stmts);
872 m_sorted = true;
873 }
874 }
875 // ================================================================
876 // Binary search
877 // ================================================================
878 ccdoc::statement::base::stmts_itr_t
search(const char * name)879 ccdoc::statement::base::search(const char* name)
880 {
881 if( name ) {
882 if( m_children.size() ) {
883 if( !m_sorted )
884 sort_children();
885
886 // Check the first record.
887 base* stmt = m_children[0];
888 if( !strcmp(stmt->get_id(),name) ) {
889 return m_children.begin();
890 }
891
892 // Check all of the other records.
893 unsigned top = m_children.size()-1;
894 unsigned bot = 0;
895 unsigned cnt = 0;
896 while( top>bot ) {
897 unsigned delta = top-bot;
898 unsigned mid = bot + ((delta+1)/2);
899 stmt = m_children[mid];
900 int cmp = strcmp(stmt->get_id(),name);
901 if( cmp == 0 ) {
902 stmts_itr_t itr = m_children.begin();
903 if( mid ) {
904 itr += mid;
905 // Backup to the 1st one (duplicates are allowed).
906 stmts_itr_t itr1 = itr;
907 for(;;) {
908 --itr1;
909 stmt = *itr1;
910 if( strcmp(stmt->get_id(),name) ) {
911 ++itr1;
912 itr = itr1;
913 break;
914 }
915 if( itr1 == m_children.begin() ) {
916 // The names match but we are at the beginning.
917 itr = itr1;
918 break;
919 }
920 }
921 }
922 return itr;
923 }
924 if( cmp > 0 ) {
925 top = mid;
926 }
927 else {
928 bot = mid;
929 }
930 if(++cnt>32)
931 break;
932 }
933 }
934 }
935 return m_children.end();
936 }
937 // ================================================================
938 // Binary search
939 // ================================================================
940 ccdoc::statement::base::stmts_itr_t
search(const string & name)941 ccdoc::statement::base::search(const string& name)
942 {
943 return search(name.c_str());
944 }
945 // ================================================================
946 // is_rptmac1_id
947 // ================================================================
is_rptmac1_id() const948 bool ccdoc::statement::base::is_rptmac1_id() const
949 {
950 return is_rptmac1_id(get_id());
951 }
952 // ================================================================
953 // is_rptmac1_id
954 // ================================================================
is_rptmac1_id(const char * id)955 bool ccdoc::statement::base::is_rptmac1_id(const char* id)
956 {
957 if( !id )
958 return false;
959
960 // ================================================
961 // In heuristic mode ignore all macro definitions
962 // that have the following characteristics:
963 // - Prefixes:
964 // dll_,DLL_
965 // include_,INCLUDE_,
966 // included_,INCLUDED_,
967 // - Suffixes:
968 // _dll,_DLL
969 // _h,_H,
970 // _hh,_HH,
971 // _include,_INCLUDE,
972 // _included,_INCLUDED,
973 // _included_,_INCLUDED_,
974 // More heuristics will be added over time as
975 // requested.
976 // ================================================
977
978 // ================================================
979 // Define the search strings.
980 // ================================================
981 const char* prefixes[] = {
982 "dll_" , "DLL_" ,
983 "include_" , "INCLUDE_" ,
984 "included_", "INCLUDED_",
985 0 };
986 const char* suffixes[] = {
987 "_dll" , "_DLL" ,
988 "_h" , "_H" ,
989 "_hh" , "_HH" ,
990 "_include" , "_INCLUDE" ,
991 "_included" , "_INCLUDED" ,
992 "_included_", "_INCLUDED_",
993 0 };
994 // ================================================
995 // Check the prefixes.
996 // ================================================
997 {for(int i=0;prefixes[i];++i) {
998 const char* p1 = id;
999 const char* p2 = prefixes[i];
1000 for(;*p1 && *p2 && *p1 == *p2;++p1,++p2)
1001 ;
1002 if( *p2 == 0 )
1003 return true;
1004 }}
1005 // ================================================
1006 // Check the suffixes.
1007 // ================================================
1008 {for(int i=0;suffixes[i];++i) {
1009 const char* p1 = id;
1010 const char* p1e = p1;
1011 const char* p2 = suffixes[i];
1012 const char* p2e = p2;
1013
1014 // Point to the end of the strings.
1015 for(;*p1e;++p1e)
1016 ;
1017 for(;*p2e;++p2e)
1018 ;
1019
1020 // Compare backwards.
1021 for(;p1e!=p1 && p2e!=p2 && *p1e == *p2e;--p1e,--p2e)
1022 ;
1023 if( p2e == p2 && *p1e == *p2e )
1024 return true;
1025 }}
1026 return false;
1027 }
1028 // ================================================================
1029 // Debug dump
1030 // ================================================================
debug_dump(const char * prefix)1031 void ccdoc::statement::base::debug_dump(const char* prefix)
1032 {
1033 string p;
1034 if(prefix)
1035 p = prefix;
1036
1037 string hid;
1038 get_hier_id(hid);
1039
1040 s_log << p << "stmt: begin: ================================================\n";
1041 s_log << p << "stmt: id: '" << get_id() << "'\n";
1042 s_log << p << "stmt: hid: '" << hid << "'\n";
1043 s_log << p << "stmt: type: " << get_type_name() << "\n";
1044 s_log << p << "stmt: access: " << get_access_name() << "\n";
1045 s_log << p << "stmt: depth: " << get_depth() << "\n";
1046
1047 s_log << p << "stmt: file: '" << get_file() << "'\n";
1048 s_log << p << "stmt: lineno: " << get_lineno() << "\n";
1049 s_log << p << "stmt: extern: '" << get_extern() << "'\n";
1050
1051 if( m_comment ) {
1052 m_comment->get_hier_id(hid);
1053 s_log << p << "stmt: ctype: " << m_comment->get_type_name() << "'\n";
1054 s_log << p << "stmt: cid: '" << hid << "'\n";
1055 }
1056 else {
1057 s_log << p << "stmt: ctype:\n";
1058 s_log << p << "stmt: cid: ''\n";
1059 }
1060
1061 // Children
1062 s_log << p << "stmt: nch: " << m_children.size() << "\n";
1063 if( m_children.size() ) {
1064 stmts_itr_t itr = m_children.begin();
1065 for(int i=0;itr!=m_children.end();++itr,++i) {
1066 s_log << p << "stmt: child[" << i << "]: "
1067 << (*itr)->get_type_name()
1068 << ": '"
1069 ;
1070 (*itr)->get_hier_id(hid);
1071 s_log << hid << "'\n";
1072 }
1073 }
1074
1075 switch( m_type ) {
1076 case STMT_COMMENT_PKGDOC:
1077 case STMT_COMMENT_PKGDOC_URL:
1078 case STMT_COMMENT_PREFIX:
1079 case STMT_COMMENT_SUFFIX:
1080 {
1081 s_log << p << "stmt: ccdoc_begin\n";
1082 cstrs_itr_t itr = m_tokens.begin();
1083 for(;itr!=m_tokens.end();++itr) {
1084 s_log << p << "stmt: token: '" << (*itr);
1085 s_log << "'\n";
1086 }
1087 s_log << p << "stmt: ccdoc_end\n";
1088 break;
1089 }
1090 case STMT_CLASS_END:
1091 case STMT_NAMESPACE_END:
1092 case STMT_STRUCT_END:
1093 case STMT_UNION_END:
1094 // Ignore hier-id and tokens for end statements.
1095 break;
1096 default:
1097 {
1098 s_log << p << "stmt: tokens:";
1099 cstrs_itr_t itr = m_tokens.begin();
1100 for(;itr!=m_tokens.end();++itr) {
1101 s_log << " " << (*itr);
1102 }
1103 s_log << "\n";
1104 break;
1105 }
1106 }
1107 s_log << p << "stmt: end\n";
1108 }
1109 // ================================================================
1110 //
1111 // Comment class.
1112 //
1113 // ================================================================
1114 // ================================================================
1115 // Constructor
1116 // ================================================================
comment()1117 ccdoc::statement::comment::comment()
1118 : m_stmt(0),
1119 m_suffix(false)
1120 {
1121 }
1122 // ================================================================
1123 // Constructor
1124 // ================================================================
comment(base * stmt)1125 ccdoc::statement::comment::comment(base* stmt)
1126 : m_stmt(stmt),
1127 m_suffix(false)
1128 {
1129 if(stmt) {
1130 set(stmt->get_tokens());
1131 }
1132 }
1133 // ================================================================
1134 // Destructor
1135 // ================================================================
~comment()1136 ccdoc::statement::comment::~comment()
1137 {
1138 }
1139 // ================================================================
1140 // Set
1141 // ================================================================
set(const base::cstrs_t & tokens)1142 void ccdoc::statement::comment::set(const base::cstrs_t& tokens)
1143 {
1144 base::cstrs_citr_t i = tokens.begin();
1145 base::cstrs_citr_t e = tokens.end();
1146
1147 string token;
1148 if(!set(token,i,e,"@{" )) return;
1149
1150 if(!set(token,i,e,"@file")) return;
1151 if(!set(token,i,e,"2")) return;
1152 if(!set(token,i,e)) return;
1153 add_file(token);
1154 if(!set(token,i,e)) return;
1155 add_lineno(token);
1156
1157 if(!set_scalar(token,i,e,"@type")) return;
1158 m_suffix = token == "@suffix";
1159
1160 if(!set (m_short_desc,i,e,"@short_desc")) return;
1161 if(!set (m_long_desc ,i,e,"@long_desc")) return;
1162 if(!set (m_params ,i,e,"@params","@param")) return;
1163 if(!set (m_returns ,i,e,"@returns")) return;
1164 if(!set (m_exceptions,i,e,"@exceptions","@exception")) return;
1165 if(!set (m_deprecated,i,e,"@deprecated")) return;
1166 if(!set (m_authors ,i,e,"@authors")) return;
1167 if(!set_scalar(m_version ,i,e,"@version")) return;
1168 if(!set (m_sees ,i,e,"@sees","@see")) return;
1169 if(!set_scalar(m_since ,i,e,"@since")) return;
1170 if(!set_scalar(m_source ,i,e,"@source")) return;
1171 if(!set (m_pkg ,i,e,"@pkg")) return;
1172 if(!set (m_pkgdoc ,i,e,"@pkgdoc")) return;
1173 if(!set (m_todo ,i,e,"@todo")) return; // Issue 0120
1174 if(!set (token ,i,e,"@}")) return;
1175 }
1176 // ================================================================
1177 // Set scalar token
1178 // ================================================================
set_scalar(string & var,base::cstrs_citr_t & i,base::cstrs_citr_t & e,const char * match)1179 bool ccdoc::statement::comment::set_scalar(string& var,
1180 base::cstrs_citr_t& i,
1181 base::cstrs_citr_t& e,
1182 const char* match)
1183 {
1184 string token;
1185 if(!set(token,i,e,match)) return false;
1186 if(!set(token,i,e)) return false;
1187 if( token == "1" ) {
1188 if(!set(var,i,e)) return false;
1189 }
1190 else if( token != "0" ) {
1191 // Issue 0053
1192 s_log.warning() << "Internal comment parsing error";
1193 if(m_stmt) {
1194 s_log << " at line " << m_stmt->get_lineno()
1195 << " in " << m_stmt->get_file();
1196 }
1197 s_log << ".\n"
1198 << "\tExpected 0 or 1 for the number of " << match << " arguments.\n"
1199 << "\tThis comment will be ignored.\n"
1200 << s_log.enable();
1201 clear();
1202 return false;
1203 }
1204 return true;
1205 }
1206 // ================================================================
1207 // Set token
1208 // ================================================================
set(string & token,base::cstrs_citr_t & i,base::cstrs_citr_t & e,const char * match)1209 bool ccdoc::statement::comment::set(string& token,
1210 base::cstrs_citr_t& i,
1211 base::cstrs_citr_t& e,
1212 const char* match)
1213 {
1214 if(i == e) {
1215 s_log.warning() << "Internal comment parsing error, empty list";
1216 if(m_stmt) {
1217 // Issue 0053
1218 s_log << " at line " << m_stmt->get_lineno()
1219 << " in " << m_stmt->get_file();
1220 }
1221 s_log << ".\n"
1222 << "\tUnexpected EOF for '" << token <<"'.\n"
1223 << "\tThis comment will be ignored.\n"
1224 << s_log.enable();
1225 clear();
1226 return false;
1227 }
1228 if( match && *match && ::strcmp(*i,match) ) {
1229 // Match failed, report a warning.
1230 s_log.warning() << "Internal comment parsing error, match failed";
1231 if(m_stmt) {
1232 // Issue 0053
1233 s_log << " at line " << m_stmt->get_lineno()
1234 << " in " << m_stmt->get_file();
1235 }
1236 s_log << ".\n"
1237 << "\tExpected token '" << match << "' but found '" << *i << "'.\n"
1238 << "\tThis comment will be ignored.\n"
1239 << s_log.enable();
1240 clear();
1241 return false;
1242 }
1243 token = *i;
1244 ++i;
1245 return true;
1246 }
1247 // ================================================================
1248 // Set token
1249 // ================================================================
set(base::strs_t & vec,base::cstrs_citr_t & i,base::cstrs_citr_t & e,const char * match)1250 bool ccdoc::statement::comment::set(base::strs_t& vec,
1251 base::cstrs_citr_t& i,
1252 base::cstrs_citr_t& e,
1253 const char* match)
1254 {
1255 string token;
1256 if(!set(token,i,e,match)) return false;
1257 if(!set(token,i,e)) return false;
1258 unsigned k = atoi(token.c_str());
1259 for(unsigned j=0;j<k;++j) {
1260 if(!set(token,i,e)) return false;
1261 vec.push_back(token);
1262 }
1263 return true;
1264 }
1265 // ================================================================
1266 // Set token
1267 // ================================================================
set(base::strss_t & vecvec,base::cstrs_citr_t & i,base::cstrs_citr_t & e,const char * match,const char * match1)1268 bool ccdoc::statement::comment::set(base::strss_t& vecvec,
1269 base::cstrs_citr_t& i,
1270 base::cstrs_citr_t& e,
1271 const char* match,
1272 const char* match1)
1273 {
1274 string token;
1275 if(!set(token,i,e,match)) return false;
1276 if(!set(token,i,e)) return false;
1277 unsigned k = atoi(token.c_str());
1278 for(unsigned j=0;j<k;++j) {
1279 base::strs_t vec;
1280 if(!set(vec,i,e,match1)) return false;
1281 vecvec.push_back(vec);
1282 }
1283 return true;
1284 }
1285 // ================================================================
1286 // Get.
1287 // ================================================================
get(base::strs_t & tokens)1288 void ccdoc::statement::comment::get(base::strs_t& tokens)
1289 {
1290
1291 tokens.push_back("@{");
1292 tokens.push_back("@file");
1293 tokens.push_back("2");
1294 tokens.push_back(m_file);
1295 tokens.push_back(m_lineno);
1296 tokens.push_back("@type");
1297 tokens.push_back("1");
1298 if( m_suffix ) {
1299 tokens.push_back("@suffix");
1300 }
1301 else {
1302 tokens.push_back("@prefix");
1303 }
1304 get( tokens, m_short_desc, "@short_desc" );
1305 get( tokens, m_long_desc, "@long_desc" );
1306 get( tokens, m_params, "@param" );
1307 get( tokens, m_returns, "@returns" );
1308 get( tokens, m_exceptions, "@exception" );
1309 get( tokens, m_deprecated, "@deprecated" );
1310 get( tokens, m_authors, "@authors" );
1311 if( m_version.size() ) {
1312 tokens.push_back("@version");
1313 tokens.push_back( "1" );
1314 tokens.push_back( m_version );
1315 }
1316 else {
1317 tokens.push_back("@version");
1318 tokens.push_back("0");
1319 }
1320 get( tokens, m_sees, "@see" );
1321
1322 tokens.push_back("@since");
1323 if( m_since.size() ) {
1324 tokens.push_back("1");
1325 tokens.push_back(m_since);
1326 }
1327 else {
1328 tokens.push_back("0");
1329 }
1330
1331 tokens.push_back("@source");
1332 if( m_source.size() ) {
1333 tokens.push_back("1");
1334 tokens.push_back(m_source);
1335 }
1336 else {
1337 tokens.push_back("0");
1338 }
1339 get( tokens, m_pkg, "@pkg" );
1340 get( tokens, m_pkgdoc, "@pkgdoc" );
1341 get( tokens, m_todo, "@todo" ); // Issue 0120
1342 tokens.push_back("@}");
1343 }
1344 // ================================================================
1345 // Get.
1346 // ================================================================
get(base::strs_t & tokens,const base::strs_t & vec,const char * type)1347 void ccdoc::statement::comment::get(base::strs_t& tokens,
1348 const base::strs_t& vec,
1349 const char* type)
1350 {
1351 if(vec.size()) {
1352 char nbuf[16];
1353 sprintf(nbuf,"%d",vec.size());
1354
1355 tokens.push_back(type);
1356 tokens.push_back(nbuf);
1357
1358 base::strs_citr_t itr = vec.begin();
1359 for(;itr!=vec.end();++itr) {
1360 tokens.push_back(*itr);
1361 }
1362 }
1363 else {
1364 tokens.push_back(type);
1365 tokens.push_back("0");
1366 }
1367 }
1368 // ================================================================
1369 // Insert tokens
1370 // ================================================================
get(base::strs_t & tokens,base::strss_t & vecvec,const char * type)1371 void ccdoc::statement::comment::get(base::strs_t& tokens,
1372 base::strss_t& vecvec,
1373 const char* type)
1374 {
1375 string x = type;
1376 x += "s";
1377 if( vecvec.size() ) {
1378 tokens.push_back(x);
1379 char nbuf[16];
1380 sprintf(nbuf,"%d",vecvec.size());
1381 tokens.push_back(nbuf);
1382 base::strss_itr_t itr = vecvec.begin();
1383 for(;itr!=vecvec.end();++itr) {
1384 base::strs_t& vec = *itr;
1385
1386 sprintf(nbuf,"%d",vec.size());
1387
1388 tokens.push_back(type);
1389 tokens.push_back(nbuf);
1390
1391 base::strs_citr_t itr1 = vec.begin();
1392 for(;itr1!=vec.end();++itr1) {
1393 tokens.push_back(*itr1);
1394 }
1395 }
1396 }
1397 else {
1398 tokens.push_back(x);
1399 tokens.push_back("0");
1400 }
1401 }
1402 // ================================================================
1403 // Empty?
1404 // ================================================================
empty() const1405 bool ccdoc::statement::comment::empty() const
1406 {
1407 if(m_authors.size()) return false;
1408 if(m_exceptions.size()) return false;
1409 if(m_long_desc.size()) return false;
1410 if(m_params.size()) return false;
1411 if(m_pkg.size()) return false;
1412 if(m_pkgdoc.size()) return false;
1413 if(m_returns.size()) return false;
1414 if(m_sees.size()) return false;
1415 if(m_short_desc.size()) return false;
1416 if(m_since.size()) return false;
1417 if(m_source.size()) return false;
1418 if(m_version.size()) return false;
1419 return true;
1420 }
1421 // ================================================================
1422 // Clear
1423 // ================================================================
clear()1424 void ccdoc::statement::comment::clear()
1425 {
1426 m_authors.clear();
1427 m_exceptions.clear();
1428 m_long_desc.clear();
1429 m_params.clear();
1430 m_pkg.clear();
1431 m_pkgdoc.clear();
1432 m_returns.clear();
1433 m_sees.clear();
1434 m_short_desc.clear();
1435 m_since = "";
1436 m_source = "";
1437 m_version = "";
1438 }
1439 // ================================================================
1440 // Add since
1441 // ================================================================
add_since(const string & name)1442 void ccdoc::statement::comment::add_since(const string& name)
1443 {
1444 m_since=name;
1445 }
1446 // ================================================================
1447 // Add source
1448 // ================================================================
add_source(const string & name)1449 void ccdoc::statement::comment::add_source(const string& name)
1450 {
1451 m_source=name;
1452 }
1453 // ================================================================
1454 // Add version
1455 // ================================================================
add_version(const string & name)1456 void ccdoc::statement::comment::add_version(const string& name)
1457 {
1458 m_version=name;
1459 }
1460 // ================================================================
1461 // Add author
1462 // ================================================================
add_author(const string & name)1463 void ccdoc::statement::comment::add_author(const string& name)
1464 {
1465 m_authors.push_back(name);
1466 }
1467 // ================================================================
1468 // Add deprecated
1469 // ================================================================
add_deprecated(const string & desc)1470 void ccdoc::statement::comment::add_deprecated(const string& desc)
1471 {
1472 m_deprecated.push_back(desc);
1473 }
1474 // ================================================================
1475 // Add exception
1476 // ================================================================
add_new_exception(const string & name,const string & desc)1477 void ccdoc::statement::comment::add_new_exception(const string& name,
1478 const string& desc)
1479 {
1480 base::strs_t vec;
1481 vec.push_back(name);
1482 vec.push_back(desc);
1483 m_exceptions.push_back(vec);
1484 }
1485 // ================================================================
1486 // Add exception
1487 // ================================================================
add_new_exception(const string & name)1488 void ccdoc::statement::comment::add_new_exception(const string& name)
1489 {
1490 base::strs_t vec;
1491 vec.push_back(name);
1492 m_exceptions.push_back(vec);
1493 }
1494 // ================================================================
1495 // Add exception
1496 // ================================================================
add_exception_desc(const string & desc)1497 void ccdoc::statement::comment::add_exception_desc(const string& desc)
1498 {
1499 if( m_exceptions.size() ) {
1500 base::strs_t& vec = m_exceptions.back();
1501 vec.push_back(desc);
1502 }
1503 }
1504 // ================================================================
1505 // Add file
1506 // ================================================================
add_file(const string & name)1507 void ccdoc::statement::comment::add_file(const string& name)
1508 {
1509 m_file = name;
1510 }
1511 // ================================================================
1512 // Add lineno
1513 // ================================================================
add_lineno(const string & name)1514 void ccdoc::statement::comment::add_lineno(const string& name)
1515 {
1516 m_lineno = name;
1517 }
1518 // ================================================================
1519 // Add long desc
1520 // ================================================================
add_long_desc(const string & desc)1521 void ccdoc::statement::comment::add_long_desc(const string& desc)
1522 {
1523 m_long_desc.push_back(desc);
1524 }
1525 // ================================================================
1526 // Add params desc
1527 // ================================================================
add_new_param(const string & name)1528 void ccdoc::statement::comment::add_new_param(const string& name)
1529 {
1530 base::strs_t vec;
1531 vec.push_back(name);
1532 m_params.push_back(vec);
1533 }
1534 // ================================================================
1535 // Add params desc
1536 // ================================================================
add_new_param(const string & name,const string & desc)1537 void ccdoc::statement::comment::add_new_param(const string& name,
1538 const string& desc)
1539 {
1540 base::strs_t vec;
1541 vec.push_back(name);
1542 vec.push_back(desc);
1543 m_params.push_back(vec);
1544 }
1545 // ================================================================
1546 // Add params desc
1547 // ================================================================
add_param_desc(const string & desc)1548 void ccdoc::statement::comment::add_param_desc(const string& desc)
1549 {
1550 if( m_params.size() ) {
1551 base::strs_t& vec = m_params.back();
1552 vec.push_back(desc);
1553 }
1554 }
1555 // ================================================================
1556 // Add pkg
1557 // ================================================================
add_pkg(const string & desc)1558 void ccdoc::statement::comment::add_pkg(const string& desc)
1559 {
1560 m_pkg.push_back(desc);
1561 }
1562 // ================================================================
1563 // Add pkgdoc
1564 // ================================================================
add_pkgdoc(const string & desc)1565 void ccdoc::statement::comment::add_pkgdoc(const string& desc)
1566 {
1567 m_pkgdoc.push_back(desc);
1568 }
1569 // ================================================================
1570 // Add pkgdoc_tid
1571 // ================================================================
add_pkgdoc_tid(const string & desc)1572 void ccdoc::statement::comment::add_pkgdoc_tid(const string& desc)
1573 {
1574 // The package doc tag is always inserted at the
1575 // beginning of the pkgdoc vector as @tid <name>.
1576 base::strs_t vec;
1577 vec.push_back("@tid");
1578 vec.push_back(desc);
1579 base::strs_itr_t itr = m_pkgdoc.begin();
1580 for(;itr!=m_pkgdoc.end();++itr) {
1581 vec.push_back(*itr);
1582 }
1583 m_pkgdoc.clear();
1584 m_pkgdoc = vec;
1585 }
1586 // ================================================================
1587 // Add returns
1588 // ================================================================
add_returns(const string & desc)1589 void ccdoc::statement::comment::add_returns(const string& desc)
1590 {
1591 m_returns.push_back(desc);
1592 }
1593 // ================================================================
1594 // Add sees desc
1595 // ================================================================
add_new_see(const string & name)1596 void ccdoc::statement::comment::add_new_see(const string& name)
1597 {
1598 base::strs_t vec;
1599 vec.push_back(name);
1600 m_sees.push_back(vec);
1601 }
1602 // ================================================================
1603 // Add sees desc
1604 // ================================================================
add_new_see(const string & name,const string & desc)1605 void ccdoc::statement::comment::add_new_see(const string& name,
1606 const string& desc)
1607 {
1608 base::strs_t vec;
1609 vec.push_back(name);
1610 vec.push_back(desc);
1611 m_sees.push_back(vec);
1612 }
1613 // ================================================================
1614 // Add sees desc
1615 // ================================================================
add_see_desc(const string & desc)1616 void ccdoc::statement::comment::add_see_desc(const string& desc)
1617 {
1618 if( m_sees.size() ) {
1619 base::strs_t& vec = m_sees.back();
1620 vec.push_back(desc);
1621 }
1622 }
1623 // ================================================================
1624 // Add short desc
1625 // ================================================================
add_short_desc(const string & desc)1626 void ccdoc::statement::comment::add_short_desc(const string& desc)
1627 {
1628 m_short_desc.push_back(desc);
1629 }
1630 // ================================================================
1631 // Add todo
1632 // ================================================================
add_todo(const string & desc)1633 void ccdoc::statement::comment::add_todo(const string& desc)
1634 {
1635 m_todo.push_back(desc);
1636 }
1637 // ================================================================
1638 // Get the pkgdoc url.
1639 // ================================================================
get_pkgdoc_url() const1640 const string& ccdoc::statement::comment::get_pkgdoc_url() const
1641 {
1642 base::strs_citr_t itr = m_pkgdoc.begin();
1643 for(;itr!=m_pkgdoc.end();++itr) {
1644 if( *itr == "@url" ) {
1645 ++itr;
1646 if( itr!=m_pkgdoc.end())
1647 return *itr;
1648 break;
1649 }
1650 }
1651 static string null;
1652 return null;
1653 }
1654 // ================================================================
1655 // Get the pkgdoc tid.
1656 // ================================================================
get_pkgdoc_tid() const1657 const string& ccdoc::statement::comment::get_pkgdoc_tid() const
1658 {
1659 base::strs_citr_t itr = m_pkgdoc.begin();
1660 for(;itr!=m_pkgdoc.end();++itr) {
1661 if( *itr == "@tid" ) {
1662 ++itr;
1663 if( itr!=m_pkgdoc.end())
1664 return *itr;
1665 break;
1666 }
1667 }
1668 static string null;
1669 return null;
1670 }
1671