1## @file
2#
3# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
4#
5# SPDX-License-Identifier: BSD-2-Clause-Patent
6#
7
8from __future__ import print_function
9from __future__ import absolute_import
10import os
11
12from .message import *
13
14class BaseDoxygeItem:
15    def __init__(self, name, tag=''):
16        self.mName = name
17        self.mTag  = tag
18        self.mDescription = ''
19        self.mText = []
20
21    def AddDescription(self, desc):
22        self.mDescription = '%s%s' % (self.mDescription, desc)
23
24    def __str__(self):
25        return '\n'.join(self.mText)
26
27    def Generate(self):
28        """This interface need to be override"""
29
30class Section(BaseDoxygeItem):
31    def Generate(self):
32        """This interface need to be override"""
33        if len(self.mTag) != 0:
34            self.mText.append(' \section %s %s' % (self.mName, self.mTag))
35        else:
36            self.mText.append(' \section %s' % self.mName)
37
38        self.mText.append(self.mDescription)
39        return self.mText
40
41class Page(BaseDoxygeItem):
42    def __init__(self, name, tag=None, isSort=True):
43        BaseDoxygeItem.__init__(self, name, tag)
44        self.mSubPages     = []
45        self.mIsMainPage   = False
46        self.mSections     = []
47        self.mIsSort       = isSort
48
49    def GetSubpageCount(self):
50        return len(self.mSubPages)
51
52    def AddPage(self, subpage):
53        self.mSubPages.append(subpage)
54        return subpage
55
56    def AddPages(self, pageArray):
57        if pageArray is None:
58            return
59        for page in pageArray:
60            self.AddPage(page)
61
62    def AddSection(self, section):
63        self.mSections.append(section)
64        self.mSections.sort(key=lambda x: x.mName.lower())
65
66    def Generate(self):
67        if self.mIsMainPage:
68            self.mText.append('/** \mainpage %s' % self.mName)
69            self.mIsSort = False
70        else:
71            self.mText.append('/** \page %s %s' % (self.mTag, self.mName))
72
73        if len(self.mDescription) != 0:
74            self.mText.append(self.mDescription)
75        endIndex = len(self.mText)
76
77        self.mSections.sort(key=lambda x: x.mName.lower())
78        for sect in self.mSections:
79            self.mText += sect.Generate()
80
81        endIndex = len(self.mText)
82
83        if len(self.mSubPages) != 0:
84            self.mText.insert(endIndex, "<p> \section content_index INDEX")
85            endIndex = len(self.mText)
86            self.mText.insert(endIndex, '<ul>')
87            endIndex += 1
88            if self.mIsSort:
89                self.mSubPages.sort(key=lambda x: x.mName.lower())
90            for page in self.mSubPages:
91                self.mText.insert(endIndex, '<li>\subpage %s \"%s\" </li>' % (page.mTag, page.mName))
92                endIndex += 1
93                self.mText += page.Generate()
94            self.mText.insert(endIndex, '</ul>')
95            endIndex += 1
96        self.mText.insert(endIndex, ' **/')
97        return self.mText
98
99class DoxygenFile(Page):
100    def __init__(self, name, file):
101        Page.__init__(self, name)
102        self.mFilename  = file
103        self.mIsMainPage = True
104
105    def GetFilename(self):
106        return self.mFilename.replace('/', '\\')
107
108    def Save(self):
109        str = self.Generate()
110        try:
111            f = open(self.mFilename, 'w')
112            f.write('\n'.join(str))
113            f.close()
114        except IOError as e:
115            ErrorMsg ('Fail to write file %s' % self.mFilename)
116            return False
117
118        return True
119
120doxygenConfigTemplate = """
121DOXYFILE_ENCODING      = UTF-8
122PROJECT_NAME           = %(ProjectName)s
123PROJECT_NUMBER         = %(ProjectVersion)s
124OUTPUT_DIRECTORY       = %(OutputDir)s
125CREATE_SUBDIRS         = YES
126OUTPUT_LANGUAGE        = English
127BRIEF_MEMBER_DESC      = YES
128REPEAT_BRIEF           = YES
129ABBREVIATE_BRIEF       = "The $name class           " \\
130                         "The $name widget           " \\
131                         "The $name file           " \\
132                         is \\
133                         provides \\
134                         specifies \\
135                         contains \\
136                         represents \\
137                         a \\
138                         an \\
139                         the
140ALWAYS_DETAILED_SEC    = NO
141INLINE_INHERITED_MEMB  = NO
142FULL_PATH_NAMES        = YES
143STRIP_FROM_PATH        = %(StripPath)s
144STRIP_FROM_INC_PATH    =
145SHORT_NAMES            = YES
146JAVADOC_AUTOBRIEF      = NO
147QT_AUTOBRIEF           = NO
148MULTILINE_CPP_IS_BRIEF = NO
149DETAILS_AT_TOP         = YES
150INHERIT_DOCS           = YES
151SEPARATE_MEMBER_PAGES  = NO
152TAB_SIZE               = 1
153ALIASES                =
154OPTIMIZE_OUTPUT_FOR_C  = YES
155OPTIMIZE_OUTPUT_JAVA   = NO
156BUILTIN_STL_SUPPORT    = NO
157CPP_CLI_SUPPORT        = NO
158SIP_SUPPORT            = NO
159DISTRIBUTE_GROUP_DOC   = YES
160SUBGROUPING            = YES
161TYPEDEF_HIDES_STRUCT   = NO
162
163EXTRACT_ALL            = YES
164EXTRACT_PRIVATE        = NO
165EXTRACT_STATIC         = NO
166EXTRACT_LOCAL_CLASSES  = NO
167EXTRACT_LOCAL_METHODS  = NO
168EXTRACT_ANON_NSPACES   = NO
169HIDE_UNDOC_MEMBERS     = NO
170HIDE_UNDOC_CLASSES     = NO
171HIDE_FRIEND_COMPOUNDS  = NO
172HIDE_IN_BODY_DOCS      = NO
173INTERNAL_DOCS          = NO
174CASE_SENSE_NAMES       = NO
175HIDE_SCOPE_NAMES       = NO
176SHOW_INCLUDE_FILES     = NO
177INLINE_INFO            = YES
178SORT_MEMBER_DOCS       = YES
179SORT_BRIEF_DOCS        = NO
180SORT_BY_SCOPE_NAME     = YES
181GENERATE_TODOLIST      = YES
182GENERATE_TESTLIST      = YES
183GENERATE_BUGLIST       = YES
184GENERATE_DEPRECATEDLIST= YES
185ENABLED_SECTIONS       =
186MAX_INITIALIZER_LINES  = 30
187SHOW_USED_FILES        = NO
188SHOW_DIRECTORIES       = NO
189FILE_VERSION_FILTER    =
190
191QUIET                  = NO
192WARNINGS               = YES
193WARN_IF_UNDOCUMENTED   = YES
194WARN_IF_DOC_ERROR      = YES
195WARN_NO_PARAMDOC       = YES
196WARN_FORMAT            = "$file:$line: $text           "
197WARN_LOGFILE           = %(WarningFile)s
198
199INPUT                  = %(FileList)s
200INPUT_ENCODING         = UTF-8
201FILE_PATTERNS          = %(Pattern)s
202RECURSIVE              = NO
203EXCLUDE                = *.svn
204EXCLUDE_SYMLINKS       = NO
205EXCLUDE_PATTERNS       = .svn
206EXCLUDE_SYMBOLS        =
207EXAMPLE_PATH           = %(ExamplePath)s
208EXAMPLE_PATTERNS       = *
209EXAMPLE_RECURSIVE      = NO
210IMAGE_PATH             =
211INPUT_FILTER           =
212FILTER_PATTERNS        =
213FILTER_SOURCE_FILES    = NO
214
215SOURCE_BROWSER         = NO
216INLINE_SOURCES         = NO
217STRIP_CODE_COMMENTS    = YES
218REFERENCED_BY_RELATION = YES
219REFERENCES_RELATION    = YES
220REFERENCES_LINK_SOURCE = NO
221USE_HTAGS              = NO
222VERBATIM_HEADERS       = NO
223
224ALPHABETICAL_INDEX     = NO
225COLS_IN_ALPHA_INDEX    = 5
226IGNORE_PREFIX          =
227
228GENERATE_HTML          = YES
229HTML_OUTPUT            = html
230HTML_FILE_EXTENSION    = .html
231HTML_HEADER            =
232HTML_FOOTER            =
233HTML_STYLESHEET        =
234HTML_ALIGN_MEMBERS     = YES
235GENERATE_HTMLHELP      = %(WhetherGenerateHtmlHelp)s
236HTML_DYNAMIC_SECTIONS  = NO
237CHM_FILE               = index.chm
238HHC_LOCATION           =
239GENERATE_CHI           = NO
240BINARY_TOC             = NO
241TOC_EXPAND             = NO
242DISABLE_INDEX          = NO
243ENUM_VALUES_PER_LINE   = 4
244GENERATE_TREEVIEW      = %(WhetherGenerateTreeView)s
245TREEVIEW_WIDTH         = 250
246
247GENERATE_LATEX         = NO
248LATEX_OUTPUT           = latex
249LATEX_CMD_NAME         = latex
250MAKEINDEX_CMD_NAME     = makeindex
251COMPACT_LATEX          = NO
252PAPER_TYPE             = a4wide
253EXTRA_PACKAGES         =
254LATEX_HEADER           =
255PDF_HYPERLINKS         = YES
256USE_PDFLATEX           = YES
257LATEX_BATCHMODE        = NO
258LATEX_HIDE_INDICES     = NO
259
260GENERATE_RTF           = NO
261RTF_OUTPUT             = rtf
262COMPACT_RTF            = NO
263RTF_HYPERLINKS         = NO
264RTF_STYLESHEET_FILE    =
265RTF_EXTENSIONS_FILE    =
266
267GENERATE_MAN           = NO
268MAN_OUTPUT             = man
269MAN_EXTENSION          = .3
270MAN_LINKS              = NO
271
272GENERATE_XML           = NO
273XML_OUTPUT             = xml
274XML_SCHEMA             =
275XML_DTD                =
276XML_PROGRAMLISTING     = YES
277
278GENERATE_AUTOGEN_DEF   = NO
279
280GENERATE_PERLMOD       = NO
281PERLMOD_LATEX          = NO
282PERLMOD_PRETTY         = YES
283PERLMOD_MAKEVAR_PREFIX =
284
285ENABLE_PREPROCESSING   = YES
286MACRO_EXPANSION        = YES
287EXPAND_ONLY_PREDEF     = YES
288SEARCH_INCLUDES        = YES
289INCLUDE_PATH           = %(IncludePath)s
290INCLUDE_FILE_PATTERNS  = *.h
291PREDEFINED             = %(PreDefined)s
292EXPAND_AS_DEFINED      =
293SKIP_FUNCTION_MACROS   = NO
294
295TAGFILES               =
296GENERATE_TAGFILE       =
297ALLEXTERNALS           = NO
298EXTERNAL_GROUPS        = YES
299PERL_PATH              = /usr/bin/perl
300
301CLASS_DIAGRAMS         = NO
302MSCGEN_PATH            =
303HIDE_UNDOC_RELATIONS   = YES
304HAVE_DOT               = NO
305CLASS_GRAPH            = YES
306COLLABORATION_GRAPH    = YES
307GROUP_GRAPHS           = YES
308UML_LOOK               = NO
309TEMPLATE_RELATIONS     = NO
310INCLUDE_GRAPH          = YES
311INCLUDED_BY_GRAPH      = YES
312CALL_GRAPH             = NO
313CALLER_GRAPH           = NO
314GRAPHICAL_HIERARCHY    = YES
315DIRECTORY_GRAPH        = YES
316DOT_IMAGE_FORMAT       = png
317DOT_PATH               =
318DOTFILE_DIRS           =
319DOT_GRAPH_MAX_NODES    = 50
320MAX_DOT_GRAPH_DEPTH    = 1000
321DOT_TRANSPARENT        = YES
322DOT_MULTI_TARGETS      = NO
323GENERATE_LEGEND        = YES
324DOT_CLEANUP            = YES
325
326SEARCHENGINE           = NO
327
328"""
329class DoxygenConfigFile:
330    def __init__(self):
331        self.mProjectName  = ''
332        self.mOutputDir    = ''
333        self.mFileList     = []
334        self.mIncludeList  = []
335        self.mStripPath    = ''
336        self.mExamplePath  = ''
337        self.mPattern      = ['*.c', '*.h',
338                              '*.asm', '*.s', '.nasm', '*.html', '*.dox']
339        self.mMode         = 'HTML'
340        self.mWarningFile  = ''
341        self.mPreDefined   = []
342        self.mProjectVersion = 0.1
343
344    def SetChmMode(self):
345        self.mMode = 'CHM'
346
347    def SetHtmlMode(self):
348        self.mMode = 'HTML'
349
350    def SetProjectName(self, str):
351        self.mProjectName = str
352
353    def SetProjectVersion(self, str):
354        self.mProjectVersion = str
355
356    def SetOutputDir(self, str):
357        self.mOutputDir = str
358
359    def SetStripPath(self, str):
360        self.mStripPath = str
361
362    def SetExamplePath(self, str):
363        self.mExamplePath = str
364
365    def SetWarningFilePath(self, str):
366        self.mWarningFile = str.replace('\\', '/')
367
368    def FileExists(self, path):
369        if path is None:
370            return False
371        if len(path) == 0:
372            return False
373
374        for p in self.mFileList:
375            if path.lower() == p.lower():
376                return True
377
378        return False
379
380    def AddFile(self, path):
381        if path is None:
382            return
383
384        if len(path) == 0:
385            return
386        path = path.replace('\\', '/')
387        if not self.FileExists(path):
388            self.mFileList.append(path)
389
390    def AddIncludePath(self, path):
391        path = path.replace('\\', '/')
392        if path not in self.mIncludeList:
393            self.mIncludeList.append(path)
394
395    def AddPattern(self, pattern):
396        self.mPattern.append(pattern)
397
398    def AddPreDefined(self, macro):
399        self.mPreDefined.append(macro)
400
401    def Generate(self, path):
402        files    = ' \\\n'.join(self.mFileList)
403        includes = ' \\\n'.join(self.mIncludeList)
404        patterns = ' \\\n'.join(self.mPattern)
405        if self.mMode.lower() == 'html':
406            sHtmlHelp = 'NO'
407            sTreeView = 'YES'
408        else:
409            sHtmlHelp = 'YES'
410            sTreeView = 'NO'
411
412        text = doxygenConfigTemplate % {'ProjectName':self.mProjectName,
413                                        'OutputDir':self.mOutputDir,
414                                        'StripPath':self.mStripPath,
415                                        'ExamplePath':self.mExamplePath,
416                                        'FileList':files,
417                                        'Pattern':patterns,
418                                        'WhetherGenerateHtmlHelp':sHtmlHelp,
419                                        'WhetherGenerateTreeView':sTreeView,
420                                        'IncludePath':includes,
421                                        'WarningFile':self.mWarningFile,
422                                        'PreDefined':' '.join(self.mPreDefined),
423                                        'ProjectVersion':self.mProjectVersion}
424        try:
425            f = open(path, 'w')
426            f.write(text)
427            f.close()
428        except IOError as e:
429            ErrorMsg ('Fail to generate doxygen config file %s' % path)
430            return False
431
432        return True
433
434########################################################################
435#                  TEST                   CODE
436########################################################################
437if __name__== '__main__':
438    df = DoxygenFile('Platform Document', 'm:\tree')
439    df.AddPage(Page('Module', 'module'))
440    p = df.AddPage(Page('Library', 'library'))
441    p.AddDescription(desc)
442    p.AddPage(Page('PCD', 'pcds'))
443
444    df.Generate()
445    print(df)
446