#!/usr/bin/python3 # # Copyright (c) 2013-2014 The Khronos Group Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and/or associated documentation files (the # "Materials"), to deal in the Materials without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Materials, and to # permit persons to whom the Materials are furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Materials. # # THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. import io, os, re, string, sys; if __name__ == '__main__': if (len(sys.argv) != 5): print('Usage:', sys.argv[0], ' gendir srcdir accordfilename flatfilename', file=sys.stderr) exit(1) else: gendir = sys.argv[1] srcdir = sys.argv[2] accordfilename = sys.argv[3] flatfilename = sys.argv[4] # print(' gendir = ', gendir, ' srcdir = ', srcdir, 'accordfilename = ', accordfilename, 'flatfilename = ', flatfilename) else: print('Unknown invocation mode', file=sys.stderr) exit(1) # Various levels of indentation in generated HTML ind1 = ' ' ind2 = ind1 + ind1 ind3 = ind2 + ind1 ind4 = ind2 + ind2 # Symbolic names notAlias = False isAlias = True # Page title pageTitle = 'EGL Reference Pages' # Docbook source and generated HTML 5 file extensions srcext = '.xml' genext = '.xhtml' # List of generated files files = os.listdir(gendir) # Feature - class representing a command or function to be indexed, used # as dictionary values keyed by the feature name to be indexed. # # Members # file - name of file containing the feature # feature - feature name for the index (basis for the dictionary key). # alias - True if this is an alias of another feature in the file. # Usually if alias is False, feature is the basename of file. # apiCommand - True if this is an API command, or should be grouped # like one class Feature: def __init__(self, file = None, feature = None, alias = False, apiCommand = None): self.file = file self.feature = feature self.alias = alias self.apiCommand = apiCommand # This is the API-dependent command prefix self.prefix = 'egl' self.prefixLen = len(self.prefix) def makeKey(self): # Return dictionary / sort key based on the feature name if (self.apiCommand and self.feature[0:self.prefixLen] == self.prefix): return self.feature[self.prefixLen:] else: return self.feature # Add dictionary entry for specified Feature. # The key used is the feature name, with the leading 'gl' stripped # off if this is an API command def addkey(dict, feature): key = feature.makeKey() if (key in dict.keys()): print('Key', key, ' already exists in dictionary!') else: dict[key] = feature # Create list of entry point names to be indexed. # Unlike the old Perl script, this proceeds as follows: # - Each .xhtml page with a parent .xml page gets an # index entry for its base name. # - Additionally, each tag inside a # in the parent page gets an aliased index entry. # - Each .xhtml page *without* a parent is reported but # not indexed. # - Each collision in index terms is reported. # - Index terms are keys in a dictionary whose entries # are [ pagename, alias, glPrefix ] where pagename is # the base name of the indexed page and alias is True # if this index isn't the same as pagename. # - API keys have their glPrefix value set to True, # GLSL keys to False. There is a simplistic way of # telling the files apart based on the file name: # # * Everything starting with 'egl[A-Z]' is API # * 'removedTypes.*' is API (more may be added) # * Everything else is GLSL def isAPIfile(entrypoint): if (re.match('^egl[A-Z]', entrypoint) or entrypoint == 'removedTypes'): return True else: return False # Dictionary of all keys mapped to Feature values refIndex = {} for file in files: # print('Processing file', file) (entrypoint,ext) = os.path.splitext(file) if (ext == genext): parent = srcdir + '/' + entrypoint + srcext # Determine if this is an API or GLSL page apiCommand = isAPIfile(entrypoint) if (os.path.exists(parent)): addkey(refIndex, Feature(file, entrypoint, False, apiCommand)) # Search parent file for tags inside tags # This doesn't search for inside , because # those aren't on the same line and it's hard. fp = open(parent) for line in fp.readlines(): # Look for tag contents and add as aliases # Don't add the same key twice for m in re.finditer(r".*(.*).*", line): funcname = m.group(1) if (funcname != entrypoint): addkey(refIndex, Feature(file, funcname, True, apiCommand)) fp.close() else: print('No parent page for', file, ', will not be indexed') # Some utility functions for generating the navigation table # Opencl_tofc.html uses style.css instead of style-index.css # flatMenu - if True, don't include accordion JavaScript, # generating a flat (expanded) menu. # letters - if not None, include per-letter links to within # the indices for each letter in the list. # altMenu - if not None, the name of the alternate index to # link to. def printHeader(fp, flatMenu = False, letters = None, altMenu = None): if (flatMenu): scriptInclude = ' ' else: scriptInclude = ' ' print('', '', ' ', ' ' + pageTitle + '', scriptInclude, '', '', sep='\n', file=fp) if (altMenu): if (flatMenu): altLabel = '(accordion-style)' else: altLabel = '(flat)' print(' ' + 'Use alternate ' + altLabel + ' index' + '', file=fp) if (letters): print('
\n
', file=fp) for letter in letters: print(' ' + letter + '  ', file=fp) print('
\n
', file=fp) print(' ', file=fp) if (not flatMenu): print(' ', file=fp) print('', '', sep='\n', file=fp) # Add a nav table entry. key = link name, feature = Feature info for key def addMenuLink(key, feature, fp): file = feature.file linkname = feature.feature print(ind4 + '
  • ' + linkname + '
  • ', sep='\n', file=fp) # Begin index section for a letter, include an anchor to link to def beginLetterSection(letter, fp): print(ind2 + '', ind2 + '
  • ' + letter, ind3 + '
      ', sep='\n', file=fp) # End index section for a letter def endLetterSection(opentable, fp): if (opentable == 0): return print(ind3 + '
    ', ind2 + '
  • ', sep='\n', file=fp) # Return the keys in a dictionary sorted by name. # Select only keys matching whichKeys (see genDict below) def sortedKeys(dict, whichKeys): list = [] for key in dict.keys(): if (whichKeys == 'all' or (whichKeys == 'api' and dict[key].apiCommand) or (whichKeys == 'glsl' and not dict[key].apiCommand)): list.append(key) list.sort(key=str.lower) return list # Generate accordion menu for this dictionary, titled as specified. # # If whichKeys is 'all', generate index for all features # If whichKeys is 'api', generate index only for API features # If whichKeys is 'glsl', generate index only for GLSL features # # fp is the file to write to def genDict(dict, title, whichKeys, fp): print(ind1 + '
  • ' + title, ind2 + '
      ', sep='\n', file=fp) # Print links for sorted keys in each letter section curletter = '' opentable = 0 # Determine which letters are in the table of contents for this # dictionary. If apiPrefix is set, strip the API prefix from each # key containing it first. # Generatesorted list of page indexes. Select keys matching whichKeys. keys = sortedKeys(dict, whichKeys) # print('@ Sorted list of page indexes:\n', keys) for key in keys: # Character starting this key c = str.lower(key[0]) if (c != curletter): endLetterSection(opentable, fp) # Start a new subtable for this letter beginLetterSection(c, fp) opentable = 1 curletter = c addMenuLink(key, dict[key], fp) endLetterSection(opentable, fp) print(ind2 + '
    ', ind1 + '
  • ', sep='\n', file=fp) ###################################################################### # Generate the accordion menu fp = open(accordfilename, 'w') printHeader(fp, flatMenu = False, altMenu = flatfilename) genDict(refIndex, 'EGL Entry Points', 'all', fp) printFooter(fp, flatMenu = False) fp.close() ###################################################################### # Generate the non-accordion menu, with combined API and GLSL sections fp = open(flatfilename, 'w') # Set containing all index letters indices = { key[0].lower() for key in refIndex.keys() } letters = [c for c in indices] letters.sort() printHeader(fp, flatMenu = True, letters = letters, altMenu = accordfilename) genDict(refIndex, 'EGL Entry Points', 'all', fp) printFooter(fp, flatMenu = True) fp.close()