]>
Commit | Line | Data |
---|---|---|
cecfc5e7 VZ |
1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // Name: HelpGen.cpp | |
3 | // Purpose: Main program file for HelpGen | |
4 | // Author: Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> | |
5 | // Modified by: | |
6 | // Created: 06/01/99 | |
7 | // RCS-ID: $Id$ | |
8 | // Copyright: (c) 1999 VZ | |
9 | // Licence: GPL | |
10 | ///////////////////////////////////////////////////////////////////////////// | |
11 | ||
12 | /* | |
13 | TODO (+ means fixed) | |
14 | ||
15 | (i) small fixes in the current version | |
59734eb5 | 16 | |
cecfc5e7 VZ |
17 | +1. Quote special TeX characters like '&' and '_' (=> derive from wxFile) |
18 | 2. Document typedefs | |
19 | 3. Document global variables | |
20 | 4. Document #defines | |
ed38ec7e | 21 | +5. Program options |
cecfc5e7 VZ |
22 | |
23 | (ii) plans for version 2 | |
24 | 1. Use wxTextFile for direct file access to avoid one scan method problems | |
ed38ec7e | 25 | 2. Use command line parsrer class for the options |
59734eb5 | 26 | |
cecfc5e7 VZ |
27 | */ |
28 | ||
29 | // ============================================================================= | |
30 | // declarations | |
31 | // ============================================================================= | |
32 | ||
33 | // ----------------------------------------------------------------------------- | |
34 | // headers | |
35 | // ----------------------------------------------------------------------------- | |
36 | ||
37 | // wxWindows | |
38 | #include "wx/wxprec.h" | |
39 | ||
40 | #ifndef WX_PRECOMP | |
41 | #include <wx/string.h> | |
42 | #include <wx/log.h> | |
ed38ec7e | 43 | #include <wx/dynarray.h> |
cecfc5e7 VZ |
44 | #endif // WX_PRECOMP |
45 | ||
3d05544e JS |
46 | #include <wx/file.h> |
47 | ||
cecfc5e7 VZ |
48 | // C++ parsing classes |
49 | #include "cjparser.h" | |
50 | ||
51 | // standard headers | |
52 | #include <stdio.h> | |
53 | #include <time.h> | |
54 | ||
55 | // ----------------------------------------------------------------------------- | |
56 | // private functions | |
57 | // ----------------------------------------------------------------------------- | |
58 | ||
ed38ec7e VZ |
59 | // return the label for the given function name (i.e. argument of \label) |
60 | static wxString MakeLabel(const char *classname, const char *funcname = NULL); | |
61 | ||
62 | // return the whole \helpref{arg}{arg_label} string | |
63 | static wxString MakeHelpref(const char *argument); | |
64 | ||
cecfc5e7 VZ |
65 | // quotes special TeX characters in place |
66 | static void TeXFilter(wxString* str); | |
67 | ||
ed38ec7e VZ |
68 | // get all comments associated with this context |
69 | static wxString GetAllComments(const spContext& ctx); | |
70 | ||
71 | // get the string with current time (returns pointer to static buffer) | |
72 | // timeFormat is used for the call of strftime(3) | |
3d05544e JS |
73 | #ifdef GetCurrentTime |
74 | #undef GetCurrentTime | |
75 | #endif | |
76 | ||
ed38ec7e VZ |
77 | static const char *GetCurrentTime(const char *timeFormat); |
78 | ||
cecfc5e7 VZ |
79 | // ----------------------------------------------------------------------------- |
80 | // private classes | |
81 | // ----------------------------------------------------------------------------- | |
82 | ||
83 | // add a function which sanitazes the string before writing it to the file | |
84 | class wxTeXFile : public wxFile | |
85 | { | |
86 | public: | |
59734eb5 | 87 | wxTeXFile() { } |
cecfc5e7 VZ |
88 | |
89 | bool WriteTeX(const wxString& s) | |
90 | { | |
91 | wxString t(s); | |
92 | TeXFilter(&t); | |
93 | ||
94 | return wxFile::Write(t); | |
95 | } | |
59734eb5 VZ |
96 | |
97 | private: | |
98 | wxTeXFile(const wxTeXFile&); | |
99 | wxTeXFile& operator=(const wxTeXFile&); | |
cecfc5e7 VZ |
100 | }; |
101 | ||
102 | class HelpGenVisitor : public spVisitor | |
103 | { | |
104 | public: | |
105 | // ctor | |
59734eb5 VZ |
106 | HelpGenVisitor(const wxString& directoryOut) : m_directoryOut(directoryOut) |
107 | { | |
108 | Reset(); | |
109 | } | |
cecfc5e7 VZ |
110 | |
111 | virtual void VisitFile( spFile& fl ); | |
112 | virtual void VisitClass( spClass& cl ); | |
113 | virtual void VisitEnumeration( spEnumeration& en ); | |
114 | virtual void VisitTypeDef( spTypeDef& td ); | |
59734eb5 | 115 | virtual void VisitPreprocessorLine( spPreprocessorLine& pd ); |
cecfc5e7 VZ |
116 | virtual void VisitAttribute( spAttribute& attr ); |
117 | virtual void VisitOperation( spOperation& op ); | |
118 | virtual void VisitParameter( spParameter& param ); | |
119 | ||
120 | void EndVisit(); | |
121 | ||
122 | // shut up g++ warning (ain't it stupid?) | |
123 | virtual ~HelpGenVisitor() { } | |
124 | ||
125 | protected: | |
126 | // (re)initialize the state | |
127 | void Reset(); | |
128 | ||
129 | // insert documentation for enums/typedefs coming immediately before the | |
130 | // class declaration into the class documentation | |
131 | void InsertTypedefDocs(); | |
132 | void InsertEnumDocs(); | |
133 | ||
134 | // write the headers for corresponding sections (only once) | |
135 | void InsertDataStructuresHeader(); | |
136 | void InsertMethodsHeader(); | |
59734eb5 | 137 | |
cecfc5e7 VZ |
138 | // terminate the function documentation if it was started |
139 | void CloseFunction(); | |
140 | ||
59734eb5 VZ |
141 | wxString m_directoryOut; // directory for the output |
142 | wxTeXFile m_file; // file we're writing to now | |
cecfc5e7 VZ |
143 | |
144 | // state variables | |
145 | bool m_inClass, // TRUE after file successfully opened | |
146 | m_inTypesSection, // enums & typedefs go there | |
147 | m_inMethodSection, // functions go here | |
148 | m_isFirstParam, // first parameter of current function? | |
149 | m_inFunction; // we're parsing a function declaration | |
150 | ||
151 | // holders for "saved" documentation | |
152 | wxString m_textStoredEnums, | |
153 | m_textStoredTypedefs, | |
154 | m_textStoredFunctionComment; | |
ed38ec7e | 155 | |
59734eb5 | 156 | // headers included by this file |
ed38ec7e | 157 | wxArrayString m_headers; |
59734eb5 VZ |
158 | |
159 | private: | |
160 | HelpGenVisitor(const HelpGenVisitor&); | |
161 | HelpGenVisitor& operator=(const HelpGenVisitor&); | |
cecfc5e7 VZ |
162 | }; |
163 | ||
164 | // ----------------------------------------------------------------------------- | |
165 | // private functions | |
166 | // ----------------------------------------------------------------------------- | |
167 | ||
168 | // ============================================================================= | |
169 | // implementation | |
170 | // ============================================================================= | |
171 | ||
ed38ec7e VZ |
172 | // this function never returns |
173 | static void usage() | |
174 | { | |
59734eb5 | 175 | wxLogError("usage: HelpGen [-q|-v] [-o outdir] <header files...>\n"); |
ed38ec7e VZ |
176 | |
177 | exit(1); | |
178 | } | |
179 | ||
cecfc5e7 VZ |
180 | int main(int argc, char **argv) |
181 | { | |
182 | if ( argc < 2 ) { | |
ed38ec7e | 183 | usage(); |
cecfc5e7 VZ |
184 | } |
185 | ||
59734eb5 VZ |
186 | wxString directoryOut; |
187 | ||
ed38ec7e VZ |
188 | int first; |
189 | for ( first = 1; (first < argc) && argv[first][0] == '-'; first++ ) { | |
59734eb5 VZ |
190 | // all options have one letter |
191 | if ( argv[first][2] == '\0' ) { | |
192 | switch ( argv[first][1] ) { | |
193 | case 'v': | |
194 | // be verbose | |
195 | wxLog::GetActiveTarget()->SetVerbose(); | |
196 | continue; | |
197 | ||
198 | case 'q': | |
199 | // be quiet | |
200 | wxLog::GetActiveTarget()->SetVerbose(false); | |
201 | continue; | |
202 | ||
203 | case 'o': | |
204 | first++; | |
205 | if ( first >= argc ) { | |
206 | wxLogError("-o option requires an argument."); | |
207 | ||
208 | break; | |
209 | } | |
210 | ||
211 | directoryOut = argv[first]; | |
212 | if ( !!directoryOut ) { | |
213 | // terminate with a '/' if it doesn't have it | |
214 | switch ( directoryOut.Last() ) { | |
215 | case '/': | |
216 | #ifdef __WXMSW__ | |
217 | case '\\': | |
218 | #endif | |
219 | break; | |
ed38ec7e | 220 | |
59734eb5 VZ |
221 | default: |
222 | directoryOut += '/'; | |
223 | } | |
224 | } | |
225 | //else: it's empty, do nothing | |
226 | ||
227 | continue; | |
ed38ec7e | 228 | |
59734eb5 VZ |
229 | default: |
230 | break; | |
231 | } | |
ed38ec7e | 232 | } |
59734eb5 VZ |
233 | |
234 | // only get here after a break from switch or from else branch of if | |
235 | wxLogError("unknown option '%s'", argv[first]); | |
236 | ||
237 | usage(); | |
ed38ec7e | 238 | } |
cecfc5e7 VZ |
239 | |
240 | // create a parser object and a visitor derivation | |
241 | CJSourceParser parser; | |
59734eb5 | 242 | HelpGenVisitor visitor(directoryOut); |
cecfc5e7 VZ |
243 | |
244 | // parse all files | |
ed38ec7e | 245 | for ( int i = first; i < argc; i++ ) { |
cecfc5e7 VZ |
246 | spContext *ctxTop = parser.ParseFile(argv[i]); |
247 | if ( !ctxTop ) { | |
248 | wxLogWarning("File '%s' couldn't be processed.", argv[i]); | |
249 | } | |
250 | else { | |
251 | ((spFile *)ctxTop)->mFileName = argv[i]; | |
252 | visitor.VisitAll(*ctxTop); | |
253 | visitor.EndVisit(); | |
254 | } | |
255 | } | |
256 | ||
257 | return 0; | |
258 | } | |
259 | ||
260 | // ----------------------------------------------------------------------------- | |
261 | // HelpGenVisitor implementation | |
262 | // ----------------------------------------------------------------------------- | |
263 | ||
cecfc5e7 VZ |
264 | void HelpGenVisitor::Reset() |
265 | { | |
266 | m_inClass = | |
267 | m_inFunction = | |
268 | m_inTypesSection = | |
269 | m_inMethodSection = false; | |
ed38ec7e VZ |
270 | |
271 | m_textStoredTypedefs = | |
272 | m_textStoredEnums = | |
273 | m_textStoredFunctionComment = ""; | |
274 | m_headers.Empty(); | |
cecfc5e7 VZ |
275 | } |
276 | ||
277 | void HelpGenVisitor::InsertTypedefDocs() | |
278 | { | |
279 | m_file.WriteTeX(m_textStoredTypedefs); | |
280 | m_textStoredTypedefs.Empty(); | |
281 | } | |
282 | ||
283 | void HelpGenVisitor::InsertEnumDocs() | |
284 | { | |
285 | m_file.WriteTeX(m_textStoredEnums); | |
286 | m_textStoredEnums.Empty(); | |
287 | } | |
288 | ||
289 | void HelpGenVisitor::InsertDataStructuresHeader() | |
290 | { | |
291 | if ( !m_inTypesSection ) { | |
292 | m_inTypesSection = true; | |
293 | ||
294 | m_file.WriteTeX("\\wxheading{Data structures}\n\n"); | |
295 | } | |
296 | } | |
297 | ||
298 | void HelpGenVisitor::InsertMethodsHeader() | |
299 | { | |
300 | if ( !m_inMethodSection ) { | |
301 | m_inMethodSection = true; | |
302 | ||
303 | m_file.WriteTeX( "\\latexignore{\\rtfignore{\\wxheading{Members}}}\n\n"); | |
304 | } | |
305 | } | |
306 | ||
307 | void HelpGenVisitor::CloseFunction() | |
308 | { | |
309 | if ( m_inFunction ) { | |
310 | m_inFunction = false; | |
311 | ||
312 | wxString totalText; | |
313 | if ( m_isFirstParam ) { | |
314 | // no params found | |
315 | totalText << "\\void"; | |
316 | } | |
317 | ||
318 | totalText << "}\n\n"; | |
319 | ||
320 | if ( !m_textStoredFunctionComment.IsEmpty() ) | |
321 | totalText << m_textStoredFunctionComment << '\n'; | |
322 | ||
323 | m_file.WriteTeX(totalText); | |
324 | } | |
325 | } | |
326 | ||
327 | void HelpGenVisitor::EndVisit() | |
328 | { | |
329 | CloseFunction(); | |
ed38ec7e VZ |
330 | |
331 | wxLogInfo("%s: finished parsing the current file.", | |
332 | GetCurrentTime("%H:%M:%S")); | |
cecfc5e7 VZ |
333 | } |
334 | ||
335 | void HelpGenVisitor::VisitFile( spFile& file ) | |
336 | { | |
ed38ec7e VZ |
337 | wxLogInfo("%s: started to parse classes from file '%s'...", |
338 | GetCurrentTime("%H:%M:%S"), file.mFileName.c_str()); | |
cecfc5e7 VZ |
339 | } |
340 | ||
341 | void HelpGenVisitor::VisitClass( spClass& cl ) | |
342 | { | |
343 | wxString name = cl.GetName(); | |
344 | ||
345 | // the file name is built from the class name by removing the leading "wx" | |
346 | // if any and converting it to the lower case | |
59734eb5 VZ |
347 | wxString filename = m_directoryOut; |
348 | if ( name(0, 2) == "wx" ) { | |
349 | filename << name.c_str() + 2; | |
350 | } | |
351 | else { | |
352 | filename << name; | |
cecfc5e7 VZ |
353 | } |
354 | ||
355 | filename.MakeLower(); | |
356 | filename += ".tex"; | |
357 | ||
358 | m_inClass = m_file.Open(filename, wxFile::write); | |
359 | if ( !m_inClass ) { | |
360 | wxLogError("Can't generate documentation for the class '%s'.", | |
361 | name.c_str()); | |
362 | ||
363 | return; | |
364 | } | |
365 | ||
366 | m_inMethodSection = | |
367 | m_inTypesSection = false; | |
368 | ||
369 | wxLogInfo("Created new file '%s' for class '%s'.", | |
370 | filename.c_str(), name.c_str()); | |
371 | ||
372 | // the entire text we're writing to file | |
373 | wxString totalText; | |
374 | ||
375 | // write out the header | |
376 | { | |
cecfc5e7 | 377 | wxString header; |
59734eb5 VZ |
378 | header.Printf("%%\n" |
379 | "%% automatically generated by HelpGen from\n" | |
380 | "%% %s at %s\n" | |
381 | "%%\n" | |
382 | "\n" | |
383 | "\n" | |
cecfc5e7 | 384 | "\\section{\\class{%s}}\\label{%s}\n", |
ed38ec7e | 385 | filename.c_str(), GetCurrentTime("%d/%b/%y %H:%M:%S"), |
cecfc5e7 VZ |
386 | name.c_str(), wxString(name).MakeLower().c_str()); |
387 | ||
388 | totalText << header << '\n'; | |
389 | } | |
390 | ||
ed38ec7e VZ |
391 | // if the header includes other headers they must be related to it... try to |
392 | // automatically generate the "See also" clause | |
393 | if ( !m_headers.IsEmpty() ) { | |
394 | // correspondence between wxWindows headers and class names | |
395 | static const char *headers[] = { | |
396 | "object", | |
397 | "defs", | |
398 | "string", | |
399 | "dynarray", | |
59734eb5 | 400 | "file", |
ed38ec7e VZ |
401 | "time", |
402 | }; | |
403 | ||
404 | // NULL here means not to insert anything in "See also" for the | |
405 | // corresponding header | |
406 | static const char *classes[] = { | |
407 | NULL, | |
408 | NULL, | |
409 | NULL, | |
410 | NULL, | |
411 | "wxFile", | |
412 | "wxTime", | |
413 | }; | |
414 | ||
415 | wxASSERT_MSG( WXSIZEOF(headers) == WXSIZEOF(classes), | |
416 | "arrays must be in sync!" ); | |
417 | ||
418 | wxArrayInt interestingClasses; | |
419 | ||
420 | size_t count = m_headers.Count(), index; | |
421 | for ( size_t n = 0; n < count; n++ ) { | |
422 | wxString baseHeaderName = m_headers[n].Before('.'); | |
423 | if ( baseHeaderName(0, 3) != "wx/" ) | |
424 | continue; | |
425 | ||
426 | baseHeaderName.erase(0, 3); | |
427 | for ( index = 0; index < WXSIZEOF(headers); index++ ) { | |
428 | if ( Stricmp(baseHeaderName, headers[index]) == 0 ) | |
429 | break; | |
430 | } | |
431 | ||
432 | if ( (index < WXSIZEOF(headers)) && classes[index] ) { | |
433 | // interesting header | |
434 | interestingClasses.Add(index); | |
435 | } | |
436 | } | |
437 | ||
438 | if ( !interestingClasses.IsEmpty() ) { | |
439 | // do generate "See also" clause | |
440 | totalText << "\\wxheading{See also:}\n\n"; | |
441 | ||
442 | count = interestingClasses.Count(); | |
443 | for ( index = 0; index < count; index++ ) { | |
444 | if ( index > 0 ) | |
445 | totalText << ", "; | |
446 | ||
447 | totalText << MakeHelpref(classes[interestingClasses[index]]); | |
448 | } | |
449 | ||
450 | totalText << "\n\n"; | |
451 | } | |
452 | } | |
453 | ||
cecfc5e7 VZ |
454 | // the comment before the class generally explains what is it for so put it |
455 | // in place of the class description | |
456 | if ( cl.HasComments() ) { | |
ed38ec7e | 457 | wxString comment = GetAllComments(cl); |
cecfc5e7 VZ |
458 | |
459 | totalText << '\n' << comment << '\n'; | |
460 | } | |
461 | ||
462 | // derived from section | |
463 | wxString derived = "\\wxheading{Derived from}\n\n"; | |
464 | ||
465 | const StrListT& baseClasses = cl.mSuperClassNames; | |
466 | if ( baseClasses.size() == 0 ) { | |
467 | derived << "No base class"; | |
468 | } | |
469 | else { | |
470 | bool first = true; | |
471 | for ( StrListT::const_iterator i = baseClasses.begin(); | |
472 | i != baseClasses.end(); | |
473 | i++ ) { | |
474 | if ( !first ) { | |
475 | // separate from the previous one | |
476 | derived << "\\\\\n"; | |
477 | } | |
478 | else { | |
479 | first = false; | |
480 | } | |
481 | ||
482 | wxString baseclass = *i; | |
dface61c | 483 | derived << "\\helpref{" << baseclass << "}"; |
59734eb5 | 484 | derived << "{" << baseclass.MakeLower() << "}"; |
cecfc5e7 VZ |
485 | } |
486 | } | |
487 | totalText << derived << "\n\n"; | |
488 | ||
489 | // write all this to file | |
490 | m_file.WriteTeX(totalText); | |
491 | ||
492 | // if there were any enums/typedefs before, insert their documentation now | |
493 | InsertDataStructuresHeader(); | |
494 | InsertTypedefDocs(); | |
495 | InsertEnumDocs(); | |
496 | } | |
497 | ||
498 | void HelpGenVisitor::VisitEnumeration( spEnumeration& en ) | |
499 | { | |
500 | CloseFunction(); | |
501 | ||
502 | if ( m_inMethodSection ) { | |
503 | // FIXME that's a bug, but tell the user aboit it nevertheless... we | |
504 | // should be smart enough to process even the enums which come after the | |
505 | // functions | |
506 | wxLogWarning("enum '%s' ignored, please put it before the class " | |
507 | "methods.", en.GetName().c_str()); | |
508 | return; | |
509 | } | |
510 | ||
511 | // simply copy the enum text in the docs | |
ed38ec7e | 512 | wxString enumeration = GetAllComments(en); |
cecfc5e7 VZ |
513 | enumeration << "{\\small \\begin{verbatim}\n" |
514 | << en.mEnumContent | |
515 | << "\n\\end{verbatim}}\n"; | |
516 | ||
517 | // remember for later use if we're not inside a class yet | |
518 | if ( !m_inClass ) { | |
519 | if ( !m_textStoredEnums.IsEmpty() ) { | |
520 | m_textStoredEnums << '\n'; | |
521 | } | |
522 | ||
523 | m_textStoredEnums << enumeration; | |
524 | } | |
525 | else { | |
526 | // write the header for this section if not done yet | |
527 | InsertDataStructuresHeader(); | |
528 | ||
529 | enumeration << '\n'; | |
530 | m_file.WriteTeX(enumeration); | |
531 | } | |
532 | } | |
533 | ||
534 | void HelpGenVisitor::VisitTypeDef( spTypeDef& td ) | |
535 | { | |
536 | CloseFunction(); | |
537 | ||
ed38ec7e VZ |
538 | if ( m_inMethodSection ) { |
539 | // FIXME that's a bug, but tell the user aboit it nevertheless... | |
540 | wxLogWarning("typedef '%s' ignored, please put it before the class " | |
541 | "methods.", td.GetName().c_str()); | |
542 | return; | |
543 | } | |
544 | ||
545 | wxString typedefdoc; | |
546 | typedefdoc << "{\\small \\begin{verbatim}\n" | |
547 | << "typedef " << td.mOriginalType << ' ' << td.GetName() | |
548 | << "\n\\end{verbatim}}\n" | |
549 | << GetAllComments(td); | |
550 | ||
551 | // remember for later use if we're not inside a class yet | |
552 | if ( !m_inClass ) { | |
553 | if ( !m_textStoredTypedefs.IsEmpty() ) { | |
554 | m_textStoredTypedefs << '\n'; | |
555 | } | |
556 | ||
557 | m_textStoredTypedefs << typedefdoc; | |
558 | } | |
559 | else { | |
560 | // write the header for this section if not done yet | |
561 | InsertDataStructuresHeader(); | |
562 | ||
563 | typedefdoc << '\n'; | |
564 | m_file.WriteTeX(typedefdoc); | |
565 | } | |
566 | } | |
567 | ||
568 | void HelpGenVisitor::VisitPreprocessorLine( spPreprocessorLine& pd ) | |
569 | { | |
570 | switch ( pd.GetStatementType() ) { | |
571 | case SP_PREP_DEF_INCLUDE_FILE: | |
572 | m_headers.Add(pd.CPP_GetIncludedFileNeme()); | |
573 | break; | |
574 | ||
575 | case SP_PREP_DEF_DEFINE_SYMBOL: | |
576 | // TODO decide if it's a constant and document it if it is | |
577 | break; | |
578 | } | |
cecfc5e7 VZ |
579 | } |
580 | ||
581 | void HelpGenVisitor::VisitAttribute( spAttribute& attr ) | |
582 | { | |
583 | CloseFunction(); | |
584 | ||
585 | // only document the public member variables | |
586 | if ( !m_inClass || !attr.IsPublic() ) | |
587 | return; | |
588 | ||
ed38ec7e | 589 | wxLogWarning("Ignoring member variable '%s'.", attr.GetName().c_str()); |
cecfc5e7 VZ |
590 | } |
591 | ||
592 | void HelpGenVisitor::VisitOperation( spOperation& op ) | |
593 | { | |
594 | CloseFunction(); | |
595 | ||
596 | if ( !m_inClass || !op.IsInClass() ) { | |
597 | // FIXME that's a bug too | |
598 | wxLogWarning("skipped global function '%s'.", op.GetName().c_str()); | |
599 | ||
600 | return; | |
601 | } | |
602 | ||
603 | if ( op.mVisibility == SP_VIS_PRIVATE ) { | |
604 | // FIXME should we document protected functions? | |
605 | return; | |
606 | } | |
607 | ||
608 | InsertMethodsHeader(); | |
609 | ||
610 | // save state info | |
611 | m_inFunction = | |
612 | m_isFirstParam = true; | |
613 | ||
ed38ec7e | 614 | m_textStoredFunctionComment = GetAllComments(op); |
cecfc5e7 VZ |
615 | |
616 | // start function documentation | |
617 | wxString totalText; | |
618 | const char *funcname = op.GetName().c_str(); | |
619 | const char *classname = op.GetClass().GetName().c_str(); | |
59734eb5 | 620 | |
cecfc5e7 VZ |
621 | // check for the special case of dtor |
622 | wxString dtor; | |
623 | if ( (funcname[0] == '~') && (strcmp(funcname + 1, classname) == 0) ) { | |
624 | dtor.Printf("\\destruct{%s}", classname); | |
625 | funcname = dtor; | |
626 | } | |
627 | ||
59734eb5 VZ |
628 | totalText.Printf("\n" |
629 | "\\membersection{%s::%s}\\label{%s}\n" | |
630 | "\n" | |
ed38ec7e | 631 | "\\%sfunc{%s%s}{%s}{", |
cecfc5e7 VZ |
632 | classname, funcname, |
633 | MakeLabel(classname, funcname).c_str(), | |
634 | op.mIsConstant ? "const" : "", | |
ed38ec7e | 635 | op.mIsVirtual ? "virtual " : "", |
cecfc5e7 VZ |
636 | op.mRetType.c_str(), |
637 | funcname); | |
638 | ||
639 | m_file.WriteTeX(totalText); | |
640 | } | |
641 | ||
642 | void HelpGenVisitor::VisitParameter( spParameter& param ) | |
643 | { | |
644 | if ( !m_inFunction ) | |
645 | return; | |
646 | ||
647 | wxString totalText; | |
648 | if ( m_isFirstParam ) { | |
649 | m_isFirstParam = false; | |
650 | } | |
651 | else { | |
652 | totalText << ", "; | |
653 | } | |
59734eb5 | 654 | |
cecfc5e7 VZ |
655 | totalText << "\\param{" << param.mType << " }{" << param.GetName(); |
656 | wxString defvalue = param.mInitVal; | |
657 | if ( !defvalue.IsEmpty() ) { | |
658 | totalText << " = " << defvalue; | |
659 | } | |
59734eb5 | 660 | |
cecfc5e7 VZ |
661 | totalText << '}'; |
662 | ||
663 | m_file.WriteTeX(totalText); | |
664 | } | |
665 | ||
666 | // ----------------------------------------------------------------------------- | |
667 | // global function implementation | |
668 | // ----------------------------------------------------------------------------- | |
669 | ||
670 | static wxString MakeLabel(const char *classname, const char *funcname) | |
671 | { | |
672 | wxString label(classname); | |
ed38ec7e | 673 | if ( funcname && funcname[0] == '\\' ) { |
cecfc5e7 VZ |
674 | // we may have some special TeX macro - so far only \destruct exists, |
675 | // but may be later others will be added | |
676 | static const char *macros[] = { "destruct" }; | |
677 | static const char *replacement[] = { "dtor" }; | |
59734eb5 | 678 | |
cecfc5e7 VZ |
679 | size_t n; |
680 | for ( n = 0; n < WXSIZEOF(macros); n++ ) { | |
681 | if ( strncmp(funcname + 1, macros[n], strlen(macros[n])) == 0 ) { | |
682 | // found | |
683 | break; | |
684 | } | |
685 | } | |
686 | ||
687 | if ( n == WXSIZEOF(macros) ) { | |
688 | wxLogWarning("unknown function name '%s' - leaving as is.", | |
689 | funcname); | |
690 | } | |
691 | else { | |
692 | funcname = replacement[n]; | |
693 | } | |
694 | } | |
695 | ||
ed38ec7e VZ |
696 | if ( funcname ) |
697 | label << funcname; | |
cecfc5e7 VZ |
698 | |
699 | label.MakeLower(); | |
700 | ||
701 | return label; | |
702 | } | |
703 | ||
ed38ec7e VZ |
704 | static wxString MakeHelpref(const char *argument) |
705 | { | |
706 | wxString helpref; | |
707 | helpref << "\\helpref{" << argument << "}{" << MakeLabel(argument) << '}'; | |
708 | ||
709 | return helpref; | |
710 | } | |
711 | ||
cecfc5e7 VZ |
712 | static void TeXFilter(wxString* str) |
713 | { | |
714 | // FIXME may be done much more quickly | |
715 | str->Replace("&", "\\&"); | |
716 | str->Replace("_", "\\_"); | |
717 | } | |
718 | ||
ed38ec7e VZ |
719 | static wxString GetAllComments(const spContext& ctx) |
720 | { | |
59734eb5 VZ |
721 | wxString comments; |
722 | const MCommentListT& commentsList = ctx.GetCommentList(); | |
723 | for ( MCommentListT::const_iterator i = commentsList.begin(); | |
724 | i != commentsList.end(); | |
725 | i++ ) { | |
726 | wxString comment = (*i)->GetText(); | |
727 | ||
728 | // don't take comments like "// ----------" &c | |
729 | comment.Trim(FALSE); | |
730 | if ( !!comment && | |
731 | comment == wxString(comment[0u], comment.length() - 1) + '\n' ) | |
732 | comments << "\n"; | |
733 | else | |
734 | comments << comment; | |
ed38ec7e VZ |
735 | } |
736 | ||
59734eb5 | 737 | return comments; |
ed38ec7e VZ |
738 | } |
739 | ||
740 | static const char *GetCurrentTime(const char *timeFormat) | |
741 | { | |
742 | static char s_timeBuffer[128]; | |
743 | time_t timeNow; | |
744 | struct tm *ptmNow; | |
745 | ||
746 | time(&timeNow); | |
747 | ptmNow = localtime(&timeNow); | |
748 | ||
749 | strftime(s_timeBuffer, WXSIZEOF(s_timeBuffer), timeFormat, ptmNow); | |
750 | ||
751 | return s_timeBuffer; | |
752 | } | |
753 | ||
cecfc5e7 | 754 | /* vi: set tw=80 et ts=4 sw=4: */ |