Root/
Source at commit 1322 created 12 years 8 months ago. By meklort, Add doxygen to utils folder | |
---|---|
1 | /******************************************************************************␊ |
2 | *␊ |
3 | * Copyright (C) 1997-2011 by Dimitri van Heesch.␊ |
4 | *␊ |
5 | * Permission to use, copy, modify, and distribute this software and its␊ |
6 | * documentation under the terms of the GNU General Public License is hereby ␊ |
7 | * granted. No representations are made about the suitability of this software ␊ |
8 | * for any purpose. It is provided "as is" without express or implied warranty.␊ |
9 | * See the GNU General Public License for more details.␊ |
10 | *␊ |
11 | * Documents produced by Doxygen are derivative works derived from the␊ |
12 | * input used in their production; they are not affected by this license.␊ |
13 | *␊ |
14 | */␊ |
15 | ␊ |
16 | #include "docsets.h"␊ |
17 | #include "config.h"␊ |
18 | #include "message.h"␊ |
19 | #include "doxygen.h"␊ |
20 | #include <qfile.h>␊ |
21 | ␊ |
22 | ␊ |
23 | DocSets::DocSets() : m_nodes(17), m_scopes(17)␊ |
24 | {␊ |
25 | m_nf = 0;␊ |
26 | m_tf = 0;␊ |
27 | m_dc = 0;␊ |
28 | m_id = 0;␊ |
29 | m_nodes.setAutoDelete(TRUE);␊ |
30 | }␊ |
31 | ␊ |
32 | DocSets::~DocSets()␊ |
33 | {␊ |
34 | delete m_nf;␊ |
35 | delete m_tf;␊ |
36 | }␊ |
37 | ␊ |
38 | void DocSets::initialize()␊ |
39 | {␊ |
40 | // -- get config options␊ |
41 | QCString projectName = Config_getString("PROJECT_NAME");␊ |
42 | if (projectName.isEmpty()) projectName="root";␊ |
43 | QCString bundleId = Config_getString("DOCSET_BUNDLE_ID");␊ |
44 | if (bundleId.isEmpty()) bundleId="org.doxygen.Project";␊ |
45 | QCString feedName = Config_getString("DOCSET_FEEDNAME");␊ |
46 | if (feedName.isEmpty()) feedName="FeedName";␊ |
47 | QCString publisherId = Config_getString("DOCSET_PUBLISHER_ID");␊ |
48 | if (publisherId.isEmpty()) publisherId="PublisherId";␊ |
49 | QCString publisherName = Config_getString("DOCSET_PUBLISHER_NAME");␊ |
50 | if (publisherName.isEmpty()) publisherName="PublisherName";␊ |
51 | ␊ |
52 | // -- write Makefile␊ |
53 | {␊ |
54 | QCString mfName = Config_getString("HTML_OUTPUT") + "/Makefile";␊ |
55 | QFile makefile(mfName);␊ |
56 | if (!makefile.open(IO_WriteOnly))␊ |
57 | {␊ |
58 | err("Could not open file %s for writing\n",mfName.data());␊ |
59 | exit(1);␊ |
60 | }␊ |
61 | FTextStream ts(&makefile);␊ |
62 | ␊ |
63 | ts << "DOCSET_NAME=" << bundleId << ".docset\n" ␊ |
64 | "DOCSET_CONTENTS=$(DOCSET_NAME)/Contents\n"␊ |
65 | "DOCSET_RESOURCES=$(DOCSET_CONTENTS)/Resources\n"␊ |
66 | "DOCSET_DOCUMENTS=$(DOCSET_RESOURCES)/Documents\n"␊ |
67 | "DESTDIR=~/Library/Developer/Shared/Documentation/DocSets\n"␊ |
68 | "XCODE_INSTALL=$(shell xcode-select -print-path)\n"␊ |
69 | "\n"␊ |
70 | "all: docset\n"␊ |
71 | "\n"␊ |
72 | "docset:\n"␊ |
73 | "\tmkdir -p $(DOCSET_DOCUMENTS)\n"␊ |
74 | "\tcp Nodes.xml $(DOCSET_RESOURCES)\n"␊ |
75 | "\tcp Tokens.xml $(DOCSET_RESOURCES)\n"␊ |
76 | "\tcp Info.plist $(DOCSET_CONTENTS)\n"␊ |
77 | "\ttar --exclude $(DOCSET_NAME) \\\n"␊ |
78 | "\t --exclude Nodes.xml \\\n"␊ |
79 | "\t --exclude Tokens.xml \\\n"␊ |
80 | "\t --exclude Info.plist \\\n"␊ |
81 | "\t --exclude Makefile -c -f - . \\\n"␊ |
82 | "\t | (cd $(DOCSET_DOCUMENTS); tar xvf -)\n"␊ |
83 | "\t$(XCODE_INSTALL)/usr/bin/docsetutil index $(DOCSET_NAME)\n"␊ |
84 | "\trm -f $(DOCSET_DOCUMENTS)/Nodes.xml\n"␊ |
85 | "\trm -f $(DOCSET_DOCUMENTS)/Info.plist\n"␊ |
86 | "\trm -f $(DOCSET_DOCUMENTS)/Makefile\n"␊ |
87 | "\trm -f $(DOCSET_RESOURCES)/Nodes.xml\n"␊ |
88 | "\trm -f $(DOCSET_RESOURCES)/Tokens.xml\n"␊ |
89 | "\n"␊ |
90 | "install: docset\n"␊ |
91 | "\tmkdir -p $(DESTDIR)\n"␊ |
92 | "\tcp -R $(DOCSET_NAME) $(DESTDIR)\n"␊ |
93 | "\n"␊ |
94 | "uninstall:\n"␊ |
95 | "\trm -rf $(DESTDIR)/$(DOCSET_NAME)\n"␊ |
96 | "\n"␊ |
97 | "always:\n";␊ |
98 | }␊ |
99 | ␊ |
100 | // -- write Info.plist␊ |
101 | {␊ |
102 | QCString plName = Config_getString("HTML_OUTPUT") + "/Info.plist";␊ |
103 | QFile plist(plName);␊ |
104 | if (!plist.open(IO_WriteOnly))␊ |
105 | {␊ |
106 | err("Could not open file %s for writing\n",plName.data());␊ |
107 | exit(1);␊ |
108 | }␊ |
109 | FTextStream ts(&plist);␊ |
110 | ␊ |
111 | ts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" ␊ |
112 | "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"\n" ␊ |
113 | "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" ␊ |
114 | "<plist version=\"1.0\">\n" ␊ |
115 | "<dict>\n" ␊ |
116 | " <key>CFBundleName</key>\n" ␊ |
117 | " <string>" << projectName << "</string>\n" ␊ |
118 | " <key>CFBundleIdentifier</key>\n"␊ |
119 | " <string>" << bundleId << ".docset</string>\n" ␊ |
120 | " <key>DocSetFeedName</key>\n" ␊ |
121 | " <string>" << feedName << "</string>\n"␊ |
122 | " <key>DocSetPublisherIdentifier</key>\n"␊ |
123 | " <string>" << publisherId << "</string>\n"␊ |
124 | " <key>DocSetPublisherName</key>\n"␊ |
125 | " <string>" << publisherName << "</string>\n"␊ |
126 | "</dict>\n"␊ |
127 | "</plist>\n";␊ |
128 | }␊ |
129 | ␊ |
130 | // -- start Nodes.xml␊ |
131 | QCString notes = Config_getString("HTML_OUTPUT") + "/Nodes.xml";␊ |
132 | m_nf = new QFile(notes);␊ |
133 | if (!m_nf->open(IO_WriteOnly))␊ |
134 | {␊ |
135 | err("Could not open file %s for writing\n",notes.data());␊ |
136 | exit(1);␊ |
137 | }␊ |
138 | QCString indexName=Config_getBool("GENERATE_TREEVIEW")?"main":"index";␊ |
139 | m_nts.setDevice(m_nf);␊ |
140 | m_nts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;␊ |
141 | m_nts << "<DocSetNodes version=\"1.0\">" << endl;␊ |
142 | m_nts << " <TOC>" << endl;␊ |
143 | m_nts << " <Node>" << endl;␊ |
144 | m_nts << " <Name>Root</Name>" << endl;␊ |
145 | m_nts << " <Path>" << indexName << Doxygen::htmlFileExtension << "</Path>" << endl;␊ |
146 | m_nts << " <Subnodes>" << endl;␊ |
147 | m_dc = 1;␊ |
148 | m_firstNode.resize(m_dc);␊ |
149 | m_firstNode.at(0)=TRUE;␊ |
150 | ␊ |
151 | QCString tokens = Config_getString("HTML_OUTPUT") + "/Tokens.xml";␊ |
152 | m_tf = new QFile(tokens);␊ |
153 | if (!m_tf->open(IO_WriteOnly))␊ |
154 | {␊ |
155 | err("Could not open file %s for writing\n",tokens.data());␊ |
156 | exit(1);␊ |
157 | }␊ |
158 | m_tts.setDevice(m_tf);␊ |
159 | m_tts << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl;␊ |
160 | m_tts << "<Tokens version=\"1.0\">" << endl;␊ |
161 | }␊ |
162 | ␊ |
163 | void DocSets::finalize()␊ |
164 | {␊ |
165 | m_nts << indent() << " </Node>" << endl;␊ |
166 | m_dc--;␊ |
167 | m_nts << " </Subnodes>" << endl;␊ |
168 | m_nts << " </Node>" << endl;␊ |
169 | m_nts << " </TOC>" << endl;␊ |
170 | m_nts << "</DocSetNodes>" << endl;␊ |
171 | m_nf->close();␊ |
172 | delete m_nf;␊ |
173 | m_nf=0;␊ |
174 | ␊ |
175 | m_tts << "</Tokens>" << endl;␊ |
176 | m_tf->close();␊ |
177 | delete m_tf;␊ |
178 | m_tf=0;␊ |
179 | }␊ |
180 | ␊ |
181 | QCString DocSets::indent()␊ |
182 | {␊ |
183 | QCString result;␊ |
184 | result.fill(' ',(m_dc+2)*2);␊ |
185 | return result;␊ |
186 | }␊ |
187 | ␊ |
188 | void DocSets::incContentsDepth()␊ |
189 | {␊ |
190 | ++m_dc;␊ |
191 | m_nts << indent() << "<Subnodes>" << endl;␊ |
192 | m_firstNode.resize(m_dc);␊ |
193 | if (m_dc>0)␊ |
194 | {␊ |
195 | m_firstNode.at(m_dc-1)=TRUE;␊ |
196 | }␊ |
197 | }␊ |
198 | ␊ |
199 | void DocSets::decContentsDepth()␊ |
200 | {␊ |
201 | if (!m_firstNode.at(m_dc-1))␊ |
202 | {␊ |
203 | m_nts << indent() << " </Node>" << endl;␊ |
204 | }␊ |
205 | m_nts << indent() << "</Subnodes>" << endl;␊ |
206 | --m_dc;␊ |
207 | }␊ |
208 | ␊ |
209 | void DocSets::addContentsItem(bool isDir,␊ |
210 | const char *name, ␊ |
211 | const char *ref, ␊ |
212 | const char *file,␊ |
213 | const char *anchor)␊ |
214 | {␊ |
215 | (void)isDir;␊ |
216 | if (file && ref==0)␊ |
217 | {␊ |
218 | if (!m_firstNode.at(m_dc-1))␊ |
219 | {␊ |
220 | m_nts << indent() << " </Node>" << endl;␊ |
221 | }␊ |
222 | m_firstNode.at(m_dc-1)=FALSE;␊ |
223 | m_nts << indent() << " <Node>" << endl;␊ |
224 | m_nts << indent() << " <Name>" << convertToXML(name) << "</Name>" << endl;␊ |
225 | m_nts << indent() << " <Path>" << file << Doxygen::htmlFileExtension << "</Path>" << endl;␊ |
226 | if (anchor)␊ |
227 | {␊ |
228 | m_nts << indent() << " <Anchor>" << anchor << "</Anchor>" << endl;␊ |
229 | }␊ |
230 | }␊ |
231 | }␊ |
232 | ␊ |
233 | void DocSets::addIndexItem(Definition *context,MemberDef *md,const char *)␊ |
234 | {␊ |
235 | if (md==0 && context==0) return;␊ |
236 | ␊ |
237 | FileDef *fd = 0;␊ |
238 | ClassDef *cd = 0;␊ |
239 | NamespaceDef *nd = 0;␊ |
240 | ␊ |
241 | if (md)␊ |
242 | {␊ |
243 | fd = md->getFileDef();␊ |
244 | cd = md->getClassDef();␊ |
245 | nd = md->getNamespaceDef();␊ |
246 | if (!md->isLinkable()) return; // internal symbol␊ |
247 | }␊ |
248 | ␊ |
249 | QCString scope;␊ |
250 | QCString type;␊ |
251 | QCString decl;␊ |
252 | ␊ |
253 | // determine language␊ |
254 | QCString lang;␊ |
255 | SrcLangExt langExt = SrcLangExt_Cpp;␊ |
256 | if (fd) langExt = getLanguageFromFileName(fd->name());␊ |
257 | switch (langExt)␊ |
258 | {␊ |
259 | case SrcLangExt_Cpp:␊ |
260 | case SrcLangExt_ObjC:␊ |
261 | {␊ |
262 | if (md && (md->isObjCMethod() || md->isObjCProperty()))␊ |
263 | lang="occ"; // Objective C/C++␊ |
264 | else if (fd && fd->name().right(2).lower()==".c") ␊ |
265 | lang="c"; // Plain C␊ |
266 | else if (cd==0 && nd==0)␊ |
267 | lang="c"; // Plain C symbol outside any class or namespace␊ |
268 | else␊ |
269 | lang="cpp"; // C++␊ |
270 | }␊ |
271 | break;␊ |
272 | case SrcLangExt_IDL: lang="idl"; break; // IDL␊ |
273 | case SrcLangExt_CSharp: lang="csharp"; break; // C#␊ |
274 | case SrcLangExt_PHP: lang="php"; break; // PHP4/5␊ |
275 | case SrcLangExt_D: lang="d"; break; // D␊ |
276 | case SrcLangExt_Java: lang="java"; break; // Java␊ |
277 | case SrcLangExt_JS: lang="javascript"; break; // Javascript␊ |
278 | case SrcLangExt_Python: lang="python"; break; // Python␊ |
279 | case SrcLangExt_F90: lang="fortran"; break; // Fortran␊ |
280 | case SrcLangExt_VHDL: lang="vhdl"; break; // VHDL␊ |
281 | case SrcLangExt_XML: lang="xml"; break; // DBUS XML␊ |
282 | case SrcLangExt_Unknown: lang="unknown"; break; // should not happen!␊ |
283 | }␊ |
284 | ␊ |
285 | if (md)␊ |
286 | {␊ |
287 | if (context==0)␊ |
288 | {␊ |
289 | if (md->getGroupDef())␊ |
290 | context = md->getGroupDef();␊ |
291 | else if (md->getFileDef())␊ |
292 | context = md->getFileDef();␊ |
293 | }␊ |
294 | if (context==0) return; // should not happen␊ |
295 | ␊ |
296 | switch (md->memberType())␊ |
297 | {␊ |
298 | case MemberDef::Define:␊ |
299 | type="macro"; break;␊ |
300 | case MemberDef::Function:␊ |
301 | if (cd && (cd->compoundType()==ClassDef::Interface ||␊ |
302 | cd->compoundType()==ClassDef::Class))␊ |
303 | {␊ |
304 | if (md->isStatic())␊ |
305 | type="clm"; // class member␊ |
306 | else␊ |
307 | type="instm"; // instance member␊ |
308 | }␊ |
309 | else if (cd && cd->compoundType()==ClassDef::Protocol)␊ |
310 | {␊ |
311 | if (md->isStatic())␊ |
312 | type="intfcm"; // interface class member␊ |
313 | else␊ |
314 | type="intfm"; // interface member␊ |
315 | }␊ |
316 | else␊ |
317 | type="func";␊ |
318 | break;␊ |
319 | case MemberDef::Variable:␊ |
320 | type="data"; break;␊ |
321 | case MemberDef::Typedef:␊ |
322 | type="tdef"; break;␊ |
323 | case MemberDef::Enumeration:␊ |
324 | type="enum"; break;␊ |
325 | case MemberDef::EnumValue:␊ |
326 | type="econst"; break;␊ |
327 | //case MemberDef::Prototype:␊ |
328 | // type="prototype"; break;␊ |
329 | case MemberDef::Signal:␊ |
330 | type="signal"; break;␊ |
331 | case MemberDef::Slot:␊ |
332 | type="slot"; break;␊ |
333 | case MemberDef::Friend:␊ |
334 | type="ffunc"; break;␊ |
335 | case MemberDef::DCOP:␊ |
336 | type="dcop"; break;␊ |
337 | case MemberDef::Property:␊ |
338 | if (cd && cd->compoundType()==ClassDef::Protocol) ␊ |
339 | type="intfp"; // interface property␊ |
340 | else ␊ |
341 | type="instp"; // instance property␊ |
342 | break;␊ |
343 | case MemberDef::Event:␊ |
344 | type="event"; break;␊ |
345 | }␊ |
346 | cd = md->getClassDef();␊ |
347 | nd = md->getNamespaceDef();␊ |
348 | if (cd) ␊ |
349 | {␊ |
350 | scope = cd->qualifiedName();␊ |
351 | }␊ |
352 | else if (nd)␊ |
353 | {␊ |
354 | scope = nd->name();␊ |
355 | }␊ |
356 | writeToken(m_tts,md,type,lang,scope,md->anchor());␊ |
357 | }␊ |
358 | else if (context && context->isLinkable())␊ |
359 | {␊ |
360 | if (fd==0 && context->definitionType()==Definition::TypeFile)␊ |
361 | {␊ |
362 | fd = (FileDef*)context;␊ |
363 | }␊ |
364 | if (cd==0 && context->definitionType()==Definition::TypeClass)␊ |
365 | {␊ |
366 | cd = (ClassDef*)context;␊ |
367 | }␊ |
368 | if (nd==0 && context->definitionType()==Definition::TypeNamespace)␊ |
369 | {␊ |
370 | nd = (NamespaceDef*)context;␊ |
371 | }␊ |
372 | if (fd)␊ |
373 | {␊ |
374 | type="file";␊ |
375 | }␊ |
376 | else if (cd) ␊ |
377 | {␊ |
378 | scope = cd->qualifiedName();␊ |
379 | if (cd->isTemplate())␊ |
380 | {␊ |
381 | type="tmplt";␊ |
382 | }␊ |
383 | else if (cd->compoundType()==ClassDef::Protocol) ␊ |
384 | {␊ |
385 | type="intf";␊ |
386 | if (scope.right(2)=="-p") scope=scope.left(scope.length()-2);␊ |
387 | }␊ |
388 | else if (cd->compoundType()==ClassDef::Interface)␊ |
389 | {␊ |
390 | type="cl";␊ |
391 | }␊ |
392 | else if (cd->compoundType()==ClassDef::Category)␊ |
393 | {␊ |
394 | type="cat";␊ |
395 | }␊ |
396 | else ␊ |
397 | {␊ |
398 | type = "cl";␊ |
399 | }␊ |
400 | IncludeInfo *ii = cd->includeInfo();␊ |
401 | if (ii)␊ |
402 | {␊ |
403 | decl=ii->includeName;␊ |
404 | if (decl.isEmpty())␊ |
405 | {␊ |
406 | decl=ii->local;␊ |
407 | }␊ |
408 | }␊ |
409 | }␊ |
410 | else if (nd)␊ |
411 | {␊ |
412 | scope = nd->name();␊ |
413 | type = "ns";␊ |
414 | }␊ |
415 | if (m_scopes.find(context->getOutputFileBase())==0)␊ |
416 | {␊ |
417 | writeToken(m_tts,context,type,lang,scope,0,decl);␊ |
418 | m_scopes.append(context->getOutputFileBase(),(void*)0x8);␊ |
419 | }␊ |
420 | }␊ |
421 | }␊ |
422 | ␊ |
423 | void DocSets::writeToken(FTextStream &t,␊ |
424 | const Definition *d,␊ |
425 | const QCString &type,␊ |
426 | const QCString &lang,␊ |
427 | const char *scope,␊ |
428 | const char *anchor,␊ |
429 | const char *decl)␊ |
430 | {␊ |
431 | t << " <Token>" << endl;␊ |
432 | t << " <TokenIdentifier>" << endl;␊ |
433 | QString name = d->name();␊ |
434 | if (name.right(2)=="-p") name=name.left(name.length()-2);␊ |
435 | t << " <Name>" << convertToXML(name) << "</Name>" << endl;␊ |
436 | if (!lang.isEmpty())␊ |
437 | {␊ |
438 | t << " <APILanguage>" << lang << "</APILanguage>" << endl;␊ |
439 | }␊ |
440 | if (!type.isEmpty())␊ |
441 | {␊ |
442 | t << " <Type>" << type << "</Type>" << endl;␊ |
443 | }␊ |
444 | if (scope)␊ |
445 | {␊ |
446 | t << " <Scope>" << convertToXML(scope) << "</Scope>" << endl;␊ |
447 | }␊ |
448 | t << " </TokenIdentifier>" << endl;␊ |
449 | t << " <Path>" << d->getOutputFileBase() ␊ |
450 | << Doxygen::htmlFileExtension << "</Path>" << endl;␊ |
451 | if (anchor)␊ |
452 | {␊ |
453 | t << " <Anchor>" << anchor << "</Anchor>" << endl;␊ |
454 | }␊ |
455 | QCString tooltip = d->briefDescriptionAsTooltip();␊ |
456 | if (!tooltip.isEmpty())␊ |
457 | {␊ |
458 | t << " <Abstract>" << convertToXML(tooltip) << "</Abstract>" << endl;␊ |
459 | }␊ |
460 | if (decl)␊ |
461 | {␊ |
462 | t << " <DeclaredIn>" << convertToXML(decl) << "</DeclaredIn>" << endl;␊ |
463 | }␊ |
464 | t << " </Token>" << endl;␊ |
465 | }␊ |
466 | ␊ |
467 | void DocSets::addIndexFile(const char *name)␊ |
468 | {␊ |
469 | (void)name;␊ |
470 | }␊ |
471 | ␊ |
472 |