102f4aeb0Sopenharmony_ci#!/usr/bin/python3
202f4aeb0Sopenharmony_ci#
302f4aeb0Sopenharmony_ci# Copyright (c) 2013-2014 The Khronos Group Inc.
402f4aeb0Sopenharmony_ci#
502f4aeb0Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a
602f4aeb0Sopenharmony_ci# copy of this software and/or associated documentation files (the
702f4aeb0Sopenharmony_ci# "Materials"), to deal in the Materials without restriction, including
802f4aeb0Sopenharmony_ci# without limitation the rights to use, copy, modify, merge, publish,
902f4aeb0Sopenharmony_ci# distribute, sublicense, and/or sell copies of the Materials, and to
1002f4aeb0Sopenharmony_ci# permit persons to whom the Materials are furnished to do so, subject to
1102f4aeb0Sopenharmony_ci# the following conditions:
1202f4aeb0Sopenharmony_ci#
1302f4aeb0Sopenharmony_ci# The above copyright notice and this permission notice shall be included
1402f4aeb0Sopenharmony_ci# in all copies or substantial portions of the Materials.
1502f4aeb0Sopenharmony_ci#
1602f4aeb0Sopenharmony_ci# THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1702f4aeb0Sopenharmony_ci# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1802f4aeb0Sopenharmony_ci# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1902f4aeb0Sopenharmony_ci# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
2002f4aeb0Sopenharmony_ci# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2102f4aeb0Sopenharmony_ci# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2202f4aeb0Sopenharmony_ci# MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
2302f4aeb0Sopenharmony_ci
2402f4aeb0Sopenharmony_ciimport io, os, re, string, sys;
2502f4aeb0Sopenharmony_ci
2602f4aeb0Sopenharmony_ciif __name__ == '__main__':
2702f4aeb0Sopenharmony_ci    if (len(sys.argv) != 5):
2802f4aeb0Sopenharmony_ci        print('Usage:', sys.argv[0], ' gendir srcdir accordfilename flatfilename', file=sys.stderr)
2902f4aeb0Sopenharmony_ci        exit(1)
3002f4aeb0Sopenharmony_ci    else:
3102f4aeb0Sopenharmony_ci        gendir = sys.argv[1]
3202f4aeb0Sopenharmony_ci        srcdir = sys.argv[2]
3302f4aeb0Sopenharmony_ci        accordfilename = sys.argv[3]
3402f4aeb0Sopenharmony_ci        flatfilename = sys.argv[4]
3502f4aeb0Sopenharmony_ci        # print(' gendir = ', gendir, ' srcdir = ', srcdir, 'accordfilename = ', accordfilename, 'flatfilename = ', flatfilename)
3602f4aeb0Sopenharmony_cielse:
3702f4aeb0Sopenharmony_ci    print('Unknown invocation mode', file=sys.stderr)
3802f4aeb0Sopenharmony_ci    exit(1)
3902f4aeb0Sopenharmony_ci
4002f4aeb0Sopenharmony_ci# Various levels of indentation in generated HTML
4102f4aeb0Sopenharmony_ciind1 = '    '
4202f4aeb0Sopenharmony_ciind2 = ind1 + ind1
4302f4aeb0Sopenharmony_ciind3 = ind2 + ind1
4402f4aeb0Sopenharmony_ciind4 = ind2 + ind2
4502f4aeb0Sopenharmony_ci
4602f4aeb0Sopenharmony_ci# Symbolic names
4702f4aeb0Sopenharmony_cinotAlias = False
4802f4aeb0Sopenharmony_ciisAlias = True
4902f4aeb0Sopenharmony_ci
5002f4aeb0Sopenharmony_ci# Page title
5102f4aeb0Sopenharmony_cipageTitle = 'EGL Reference Pages'
5202f4aeb0Sopenharmony_ci
5302f4aeb0Sopenharmony_ci# Docbook source and generated HTML 5 file extensions
5402f4aeb0Sopenharmony_cisrcext = '.xml'
5502f4aeb0Sopenharmony_cigenext = '.xhtml'
5602f4aeb0Sopenharmony_ci
5702f4aeb0Sopenharmony_ci# List of generated files
5802f4aeb0Sopenharmony_cifiles = os.listdir(gendir)
5902f4aeb0Sopenharmony_ci
6002f4aeb0Sopenharmony_ci# Feature - class representing a command or function to be indexed, used
6102f4aeb0Sopenharmony_ci# as dictionary values keyed by the feature name to be indexed.
6202f4aeb0Sopenharmony_ci#
6302f4aeb0Sopenharmony_ci# Members
6402f4aeb0Sopenharmony_ci#   file - name of file containing the feature
6502f4aeb0Sopenharmony_ci#   feature - feature name for the index (basis for the dictionary key).
6602f4aeb0Sopenharmony_ci#   alias - True if this is an alias of another feature in the file.
6702f4aeb0Sopenharmony_ci#       Usually if alias is False, feature is the basename of file.
6802f4aeb0Sopenharmony_ci#   apiCommand - True if this is an API command, or should be grouped
6902f4aeb0Sopenharmony_ci#       like one
7002f4aeb0Sopenharmony_ciclass Feature:
7102f4aeb0Sopenharmony_ci    def __init__(self,
7202f4aeb0Sopenharmony_ci                 file = None,
7302f4aeb0Sopenharmony_ci                 feature = None,
7402f4aeb0Sopenharmony_ci                 alias = False,
7502f4aeb0Sopenharmony_ci                 apiCommand = None):
7602f4aeb0Sopenharmony_ci        self.file = file
7702f4aeb0Sopenharmony_ci        self.feature = feature
7802f4aeb0Sopenharmony_ci        self.alias = alias
7902f4aeb0Sopenharmony_ci        self.apiCommand = apiCommand
8002f4aeb0Sopenharmony_ci        # This is the API-dependent command prefix
8102f4aeb0Sopenharmony_ci        self.prefix = 'egl'
8202f4aeb0Sopenharmony_ci        self.prefixLen = len(self.prefix)
8302f4aeb0Sopenharmony_ci    def makeKey(self):
8402f4aeb0Sopenharmony_ci        # Return dictionary / sort key based on the feature name
8502f4aeb0Sopenharmony_ci        if (self.apiCommand and self.feature[0:self.prefixLen]
8602f4aeb0Sopenharmony_ci              == self.prefix):
8702f4aeb0Sopenharmony_ci            return self.feature[self.prefixLen:]
8802f4aeb0Sopenharmony_ci        else:
8902f4aeb0Sopenharmony_ci            return self.feature
9002f4aeb0Sopenharmony_ci
9102f4aeb0Sopenharmony_ci# Add dictionary entry for specified Feature.
9202f4aeb0Sopenharmony_ci# The key used is the feature name, with the leading 'gl' stripped
9302f4aeb0Sopenharmony_ci#  off if this is an API command
9402f4aeb0Sopenharmony_cidef addkey(dict, feature):
9502f4aeb0Sopenharmony_ci    key = feature.makeKey()
9602f4aeb0Sopenharmony_ci    if (key in dict.keys()):
9702f4aeb0Sopenharmony_ci        print('Key', key, ' already exists in dictionary!')
9802f4aeb0Sopenharmony_ci    else:
9902f4aeb0Sopenharmony_ci        dict[key] = feature
10002f4aeb0Sopenharmony_ci
10102f4aeb0Sopenharmony_ci# Create list of entry point names to be indexed.
10202f4aeb0Sopenharmony_ci# Unlike the old Perl script, this proceeds as follows:
10302f4aeb0Sopenharmony_ci# - Each .xhtml page with a parent .xml page gets an
10402f4aeb0Sopenharmony_ci#   index entry for its base name.
10502f4aeb0Sopenharmony_ci# - Additionally, each <function> tag inside a <funcdef>
10602f4aeb0Sopenharmony_ci#   in the parent page gets an aliased index entry.
10702f4aeb0Sopenharmony_ci# - Each .xhtml page *without* a parent is reported but
10802f4aeb0Sopenharmony_ci#   not indexed.
10902f4aeb0Sopenharmony_ci# - Each collision in index terms is reported.
11002f4aeb0Sopenharmony_ci# - Index terms are keys in a dictionary whose entries
11102f4aeb0Sopenharmony_ci#   are [ pagename, alias, glPrefix ] where pagename is
11202f4aeb0Sopenharmony_ci#   the base name of the indexed page and alias is True
11302f4aeb0Sopenharmony_ci#   if this index isn't the same as pagename.
11402f4aeb0Sopenharmony_ci# - API keys have their glPrefix value set to True,
11502f4aeb0Sopenharmony_ci#   GLSL keys to False. There is a simplistic way of
11602f4aeb0Sopenharmony_ci#   telling the files apart based on the file name:
11702f4aeb0Sopenharmony_ci#
11802f4aeb0Sopenharmony_ci#   * Everything starting with 'egl[A-Z]' is API
11902f4aeb0Sopenharmony_ci#   * 'removedTypes.*' is API (more may be added)
12002f4aeb0Sopenharmony_ci#   * Everything else is GLSL
12102f4aeb0Sopenharmony_ci
12202f4aeb0Sopenharmony_cidef isAPIfile(entrypoint):
12302f4aeb0Sopenharmony_ci    if (re.match('^egl[A-Z]', entrypoint) or entrypoint == 'removedTypes'):
12402f4aeb0Sopenharmony_ci        return True
12502f4aeb0Sopenharmony_ci    else:
12602f4aeb0Sopenharmony_ci        return False
12702f4aeb0Sopenharmony_ci
12802f4aeb0Sopenharmony_ci# Dictionary of all keys mapped to Feature values
12902f4aeb0Sopenharmony_cirefIndex = {}
13002f4aeb0Sopenharmony_ci
13102f4aeb0Sopenharmony_cifor file in files:
13202f4aeb0Sopenharmony_ci    # print('Processing file', file)
13302f4aeb0Sopenharmony_ci    (entrypoint,ext) = os.path.splitext(file)
13402f4aeb0Sopenharmony_ci    if (ext == genext):
13502f4aeb0Sopenharmony_ci        parent = srcdir + '/' + entrypoint + srcext
13602f4aeb0Sopenharmony_ci        # Determine if this is an API or GLSL page
13702f4aeb0Sopenharmony_ci        apiCommand = isAPIfile(entrypoint)
13802f4aeb0Sopenharmony_ci        if (os.path.exists(parent)):
13902f4aeb0Sopenharmony_ci            addkey(refIndex, Feature(file, entrypoint, False, apiCommand))
14002f4aeb0Sopenharmony_ci            # Search parent file for <function> tags inside <funcdef> tags
14102f4aeb0Sopenharmony_ci            # This doesn't search for <varname> inside <fieldsynopsis>, because
14202f4aeb0Sopenharmony_ci            #   those aren't on the same line and it's hard.
14302f4aeb0Sopenharmony_ci            fp = open(parent)
14402f4aeb0Sopenharmony_ci            for line in fp.readlines():
14502f4aeb0Sopenharmony_ci                # Look for <function> tag contents and add as aliases
14602f4aeb0Sopenharmony_ci                # Don't add the same key twice
14702f4aeb0Sopenharmony_ci                for m in re.finditer(r"<funcdef>.*<function>(.*)</function>.*</funcdef>", line):
14802f4aeb0Sopenharmony_ci                    funcname = m.group(1)
14902f4aeb0Sopenharmony_ci                    if (funcname != entrypoint):
15002f4aeb0Sopenharmony_ci                        addkey(refIndex, Feature(file, funcname, True, apiCommand))
15102f4aeb0Sopenharmony_ci            fp.close()
15202f4aeb0Sopenharmony_ci        else:
15302f4aeb0Sopenharmony_ci            print('No parent page for', file, ', will not be indexed')
15402f4aeb0Sopenharmony_ci
15502f4aeb0Sopenharmony_ci# Some utility functions for generating the navigation table
15602f4aeb0Sopenharmony_ci# Opencl_tofc.html uses style.css instead of style-index.css
15702f4aeb0Sopenharmony_ci# flatMenu - if True, don't include accordion JavaScript,
15802f4aeb0Sopenharmony_ci#   generating a flat (expanded) menu.
15902f4aeb0Sopenharmony_ci# letters - if not None, include per-letter links to within
16002f4aeb0Sopenharmony_ci#   the indices for each letter in the list.
16102f4aeb0Sopenharmony_ci# altMenu - if not None, the name of the alternate index to
16202f4aeb0Sopenharmony_ci#   link to.
16302f4aeb0Sopenharmony_cidef printHeader(fp, flatMenu = False, letters = None, altMenu = None):
16402f4aeb0Sopenharmony_ci    if (flatMenu):
16502f4aeb0Sopenharmony_ci        scriptInclude = '    <!-- Don\'t include accord.js -->'
16602f4aeb0Sopenharmony_ci    else:
16702f4aeb0Sopenharmony_ci        scriptInclude = '    <?php include \'accord.js\'; ?>'
16802f4aeb0Sopenharmony_ci
16902f4aeb0Sopenharmony_ci    print('<html>',
17002f4aeb0Sopenharmony_ci          '<head>',
17102f4aeb0Sopenharmony_ci          '    <link rel="stylesheet" type="text/css" href="style-index.css" />',
17202f4aeb0Sopenharmony_ci          '    <title>' + pageTitle + '</title>',
17302f4aeb0Sopenharmony_ci               scriptInclude,
17402f4aeb0Sopenharmony_ci          '</head>',
17502f4aeb0Sopenharmony_ci          '<body>',
17602f4aeb0Sopenharmony_ci          sep='\n', file=fp)
17702f4aeb0Sopenharmony_ci
17802f4aeb0Sopenharmony_ci    if (altMenu):
17902f4aeb0Sopenharmony_ci        if (flatMenu):
18002f4aeb0Sopenharmony_ci            altLabel = '(accordion-style)'
18102f4aeb0Sopenharmony_ci        else:
18202f4aeb0Sopenharmony_ci            altLabel = '(flat)'
18302f4aeb0Sopenharmony_ci        print('    <a href="' + altMenu + '">' +
18402f4aeb0Sopenharmony_ci              'Use alternate ' + altLabel + ' index' +
18502f4aeb0Sopenharmony_ci              '</a>', file=fp)
18602f4aeb0Sopenharmony_ci
18702f4aeb0Sopenharmony_ci    if (letters):
18802f4aeb0Sopenharmony_ci        print('    <center>\n<div id="container">', file=fp)
18902f4aeb0Sopenharmony_ci        for letter in letters:
19002f4aeb0Sopenharmony_ci            print('        <b><a href="#' +
19102f4aeb0Sopenharmony_ci                  letter +
19202f4aeb0Sopenharmony_ci                  '" style="text-decoration:none">' +
19302f4aeb0Sopenharmony_ci                  letter +
19402f4aeb0Sopenharmony_ci                  '</a></b> &nbsp;', file=fp)
19502f4aeb0Sopenharmony_ci        print('    </div>\n</center>', file=fp)
19602f4aeb0Sopenharmony_ci
19702f4aeb0Sopenharmony_ci    print('    <div id="navwrap">',
19802f4aeb0Sopenharmony_ci          '    <ul id="containerul"> <!-- Must wrap entire list for expand/contract -->',
19902f4aeb0Sopenharmony_ci          '    <li class="Level1">',
20002f4aeb0Sopenharmony_ci          '        <a href="start.html" target="pagedisplay">Introduction</a>',
20102f4aeb0Sopenharmony_ci          '    </li>',
20202f4aeb0Sopenharmony_ci          sep='\n', file=fp)
20302f4aeb0Sopenharmony_ci
20402f4aeb0Sopenharmony_cidef printFooter(fp, flatMenu = False):
20502f4aeb0Sopenharmony_ci    print('    </div> <!-- End containerurl -->', file=fp)
20602f4aeb0Sopenharmony_ci    if (not flatMenu):
20702f4aeb0Sopenharmony_ci        print('    <script type="text/javascript">initiate();</script>', file=fp)
20802f4aeb0Sopenharmony_ci    print('</body>',
20902f4aeb0Sopenharmony_ci          '</html>',
21002f4aeb0Sopenharmony_ci          sep='\n', file=fp)
21102f4aeb0Sopenharmony_ci
21202f4aeb0Sopenharmony_ci# Add a nav table entry. key = link name, feature = Feature info for key
21302f4aeb0Sopenharmony_cidef addMenuLink(key, feature, fp):
21402f4aeb0Sopenharmony_ci    file = feature.file
21502f4aeb0Sopenharmony_ci    linkname = feature.feature
21602f4aeb0Sopenharmony_ci
21702f4aeb0Sopenharmony_ci    print(ind4 + '<li><a href="' + file + '" target="pagedisplay">'
21802f4aeb0Sopenharmony_ci               + linkname + '</a></li>',
21902f4aeb0Sopenharmony_ci          sep='\n', file=fp)
22002f4aeb0Sopenharmony_ci
22102f4aeb0Sopenharmony_ci# Begin index section for a letter, include an anchor to link to
22202f4aeb0Sopenharmony_cidef beginLetterSection(letter, fp):
22302f4aeb0Sopenharmony_ci    print(ind2 + '<a name="' + letter + '"></a>',
22402f4aeb0Sopenharmony_ci          ind2 + '<li>' + letter,
22502f4aeb0Sopenharmony_ci          ind3 + '<ul class="Level3">',
22602f4aeb0Sopenharmony_ci          sep='\n', file=fp)
22702f4aeb0Sopenharmony_ci
22802f4aeb0Sopenharmony_ci# End index section for a letter
22902f4aeb0Sopenharmony_cidef endLetterSection(opentable, fp):
23002f4aeb0Sopenharmony_ci    if (opentable == 0):
23102f4aeb0Sopenharmony_ci        return
23202f4aeb0Sopenharmony_ci    print(ind3 + '</ul> <!-- End Level3 -->',
23302f4aeb0Sopenharmony_ci          ind2 + '</li>',
23402f4aeb0Sopenharmony_ci          sep='\n', file=fp)
23502f4aeb0Sopenharmony_ci
23602f4aeb0Sopenharmony_ci# Return the keys in a dictionary sorted by name.
23702f4aeb0Sopenharmony_ci# Select only keys matching whichKeys (see genDict below)
23802f4aeb0Sopenharmony_cidef sortedKeys(dict, whichKeys):
23902f4aeb0Sopenharmony_ci    list = []
24002f4aeb0Sopenharmony_ci    for key in dict.keys():
24102f4aeb0Sopenharmony_ci        if (whichKeys == 'all' or
24202f4aeb0Sopenharmony_ci            (whichKeys == 'api' and dict[key].apiCommand) or
24302f4aeb0Sopenharmony_ci            (whichKeys == 'glsl' and not dict[key].apiCommand)):
24402f4aeb0Sopenharmony_ci            list.append(key)
24502f4aeb0Sopenharmony_ci    list.sort(key=str.lower)
24602f4aeb0Sopenharmony_ci    return list
24702f4aeb0Sopenharmony_ci
24802f4aeb0Sopenharmony_ci# Generate accordion menu for this dictionary, titled as specified.
24902f4aeb0Sopenharmony_ci#
25002f4aeb0Sopenharmony_ci# If whichKeys is 'all', generate index for all features
25102f4aeb0Sopenharmony_ci# If whichKeys is 'api', generate index only for API features
25202f4aeb0Sopenharmony_ci# If whichKeys is 'glsl', generate index only for GLSL features
25302f4aeb0Sopenharmony_ci#
25402f4aeb0Sopenharmony_ci# fp is the file to write to
25502f4aeb0Sopenharmony_cidef genDict(dict, title, whichKeys, fp):
25602f4aeb0Sopenharmony_ci    print(ind1 + '<li class="Level1">' + title,
25702f4aeb0Sopenharmony_ci          ind2 + '<ul class="Level2">',
25802f4aeb0Sopenharmony_ci          sep='\n', file=fp)
25902f4aeb0Sopenharmony_ci
26002f4aeb0Sopenharmony_ci    # Print links for sorted keys in each letter section
26102f4aeb0Sopenharmony_ci    curletter = ''
26202f4aeb0Sopenharmony_ci    opentable = 0
26302f4aeb0Sopenharmony_ci
26402f4aeb0Sopenharmony_ci    # Determine which letters are in the table of contents for this
26502f4aeb0Sopenharmony_ci    # dictionary. If apiPrefix is set, strip the API prefix from each
26602f4aeb0Sopenharmony_ci    # key containing it first.
26702f4aeb0Sopenharmony_ci
26802f4aeb0Sopenharmony_ci    # Generatesorted list of page indexes. Select keys matching whichKeys.
26902f4aeb0Sopenharmony_ci    keys = sortedKeys(dict, whichKeys)
27002f4aeb0Sopenharmony_ci
27102f4aeb0Sopenharmony_ci    # print('@ Sorted list of page indexes:\n', keys)
27202f4aeb0Sopenharmony_ci
27302f4aeb0Sopenharmony_ci    for key in keys:
27402f4aeb0Sopenharmony_ci        # Character starting this key
27502f4aeb0Sopenharmony_ci        c = str.lower(key[0])
27602f4aeb0Sopenharmony_ci
27702f4aeb0Sopenharmony_ci        if (c != curletter):
27802f4aeb0Sopenharmony_ci            endLetterSection(opentable, fp)
27902f4aeb0Sopenharmony_ci            # Start a new subtable for this letter
28002f4aeb0Sopenharmony_ci            beginLetterSection(c, fp)
28102f4aeb0Sopenharmony_ci            opentable = 1
28202f4aeb0Sopenharmony_ci            curletter = c
28302f4aeb0Sopenharmony_ci        addMenuLink(key, dict[key], fp)
28402f4aeb0Sopenharmony_ci    endLetterSection(opentable, fp)
28502f4aeb0Sopenharmony_ci
28602f4aeb0Sopenharmony_ci    print(ind2 + '</ul> <!-- End Level2 -->',
28702f4aeb0Sopenharmony_ci          ind1 + '</li> <!-- End Level1 -->',
28802f4aeb0Sopenharmony_ci          sep='\n', file=fp)
28902f4aeb0Sopenharmony_ci
29002f4aeb0Sopenharmony_ci######################################################################
29102f4aeb0Sopenharmony_ci
29202f4aeb0Sopenharmony_ci# Generate the accordion menu
29302f4aeb0Sopenharmony_cifp = open(accordfilename, 'w')
29402f4aeb0Sopenharmony_ciprintHeader(fp, flatMenu = False, altMenu = flatfilename)
29502f4aeb0Sopenharmony_ci
29602f4aeb0Sopenharmony_cigenDict(refIndex, 'EGL Entry Points', 'all', fp)
29702f4aeb0Sopenharmony_ci
29802f4aeb0Sopenharmony_ciprintFooter(fp, flatMenu = False)
29902f4aeb0Sopenharmony_cifp.close()
30002f4aeb0Sopenharmony_ci
30102f4aeb0Sopenharmony_ci######################################################################
30202f4aeb0Sopenharmony_ci
30302f4aeb0Sopenharmony_ci# Generate the non-accordion menu, with combined API and GLSL sections
30402f4aeb0Sopenharmony_cifp = open(flatfilename, 'w')
30502f4aeb0Sopenharmony_ci
30602f4aeb0Sopenharmony_ci# Set containing all index letters
30702f4aeb0Sopenharmony_ciindices = { key[0].lower() for key in refIndex.keys() }
30802f4aeb0Sopenharmony_ciletters = [c for c in indices]
30902f4aeb0Sopenharmony_ciletters.sort()
31002f4aeb0Sopenharmony_ci
31102f4aeb0Sopenharmony_ciprintHeader(fp, flatMenu = True, letters = letters, altMenu = accordfilename)
31202f4aeb0Sopenharmony_ci
31302f4aeb0Sopenharmony_cigenDict(refIndex, 'EGL Entry Points', 'all', fp)
31402f4aeb0Sopenharmony_ci
31502f4aeb0Sopenharmony_ciprintFooter(fp, flatMenu = True)
31602f4aeb0Sopenharmony_cifp.close()
317