mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
makepanda: Remove old and obsolete gendocs scripts
This commit is contained in:
parent
be9dde1eee
commit
ae7eae10c5
@ -1,986 +0,0 @@
|
|||||||
########################################################################
|
|
||||||
#
|
|
||||||
# Documentation generator for panda.
|
|
||||||
#
|
|
||||||
# How to use this module:
|
|
||||||
#
|
|
||||||
# from direct.directscripts import gendocs
|
|
||||||
# gendocs.generate(version, indirlist, directdirlist, docdir, header, footer, urlprefix, urlsuffix)
|
|
||||||
#
|
|
||||||
# - version is the panda version number
|
|
||||||
#
|
|
||||||
# - indirlist is the name of a directory, or a list of directories,
|
|
||||||
# containing the "xxx.in" files that interrogate generates. No
|
|
||||||
# slash at end.
|
|
||||||
#
|
|
||||||
# - directdirlist is the name of a directory, or a list of
|
|
||||||
# directories, containing the source code for "direct," as well as
|
|
||||||
# for other Python-based trees that should be included in the
|
|
||||||
# documentation pages. No slash at end.
|
|
||||||
#
|
|
||||||
# - docdir is the name of a directory into which HTML files
|
|
||||||
# will be emitted. No slash at end.
|
|
||||||
#
|
|
||||||
# - header is a string that will be placed at the front of
|
|
||||||
# every HTML page.
|
|
||||||
#
|
|
||||||
# - footer is a string that will be placed at the end of
|
|
||||||
# every HTML page.
|
|
||||||
#
|
|
||||||
# - urlprefix is a string that will be appended to the front of
|
|
||||||
# every URL.
|
|
||||||
#
|
|
||||||
# - urlsuffix is a string that will be appended to the end of
|
|
||||||
# every URL.
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
#
|
|
||||||
# The major subsystems are:
|
|
||||||
#
|
|
||||||
# * The module that loads interrogate databases.
|
|
||||||
#
|
|
||||||
# * The module that loads python parse-trees.
|
|
||||||
#
|
|
||||||
# * The "code database", which provides a single access point
|
|
||||||
# for both interrogate databases and python parse trees.
|
|
||||||
#
|
|
||||||
# * The HTML generator.
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
import os, sys, parser, symbol, token, re
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
#
|
|
||||||
# assorted utility functions
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
SECHEADER = re.compile("^[A-Z][a-z]+\\s*:")
|
|
||||||
JUNKHEADER = re.compile("^((Function)|(Access))\\s*:")
|
|
||||||
IMPORTSTAR = re.compile("^from\\s+([a-zA-Z0-9_.]+)\\s+import\\s+[*]\\s*$")
|
|
||||||
IDENTIFIER = re.compile("[a-zA-Z0-9_]+")
|
|
||||||
FILEHEADER = re.compile(
|
|
||||||
r"""^// Filename: [a-zA-Z.]+
|
|
||||||
// Created by: [a-zA-Z. ()0-9]+(
|
|
||||||
//)?
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
//
|
|
||||||
// PANDA 3D SOFTWARE
|
|
||||||
// Copyright \(c\) Carnegie Mellon University. All rights reserved.
|
|
||||||
//
|
|
||||||
// All use of this software is subject to the terms of the revised BSD
|
|
||||||
// license. You should have received a copy of this license along
|
|
||||||
// with this source code in a file named "LICENSE."
|
|
||||||
//
|
|
||||||
////////////////////////////////////////////////////////////////////""")
|
|
||||||
|
|
||||||
def readFile(fn):
|
|
||||||
try:
|
|
||||||
srchandle = open(fn, "r")
|
|
||||||
data = srchandle.read()
|
|
||||||
srchandle.close()
|
|
||||||
return data
|
|
||||||
except:
|
|
||||||
sys.exit("Cannot read "+fn)
|
|
||||||
|
|
||||||
def writeFile(wfile, data):
|
|
||||||
try:
|
|
||||||
dsthandle = open(wfile, "wb")
|
|
||||||
dsthandle.write(data)
|
|
||||||
dsthandle.close()
|
|
||||||
except:
|
|
||||||
sys.exit("Cannot write "+wfile)
|
|
||||||
|
|
||||||
def writeFileLines(wfile, lines):
|
|
||||||
try:
|
|
||||||
dsthandle = open(wfile, "wb")
|
|
||||||
for x in lines:
|
|
||||||
dsthandle.write(x)
|
|
||||||
dsthandle.write("\n")
|
|
||||||
dsthandle.close()
|
|
||||||
except:
|
|
||||||
sys.exit("Cannot write "+wfile)
|
|
||||||
|
|
||||||
def findFiles(dirlist, ext, ign, list):
|
|
||||||
if isinstance(dirlist, str):
|
|
||||||
dirlist = [dirlist]
|
|
||||||
for dir in dirlist:
|
|
||||||
for file in os.listdir(dir):
|
|
||||||
full = dir + "/" + file
|
|
||||||
if full not in ign and file not in ign:
|
|
||||||
if (os.path.isfile(full)):
|
|
||||||
if (file.endswith(ext)):
|
|
||||||
list.append(full)
|
|
||||||
elif (os.path.isdir(full)):
|
|
||||||
findFiles(full, ext, ign, list)
|
|
||||||
|
|
||||||
def pathToModule(result):
|
|
||||||
if (result[-3:]==".py"): result=result[:-3]
|
|
||||||
result = result.replace("/src/","/")
|
|
||||||
result = result.replace("/",".")
|
|
||||||
return result
|
|
||||||
|
|
||||||
def textToHTML(comment, sep, delsection=None):
|
|
||||||
sections = [""]
|
|
||||||
included = {}
|
|
||||||
for line in comment.split("\n"):
|
|
||||||
line = line.lstrip(" ").lstrip(sep).lstrip(" ").rstrip("\r").rstrip(" ")
|
|
||||||
if (line == ""):
|
|
||||||
sections.append("")
|
|
||||||
elif (line[0]=="*") or (line[0]=="-"):
|
|
||||||
sections.append(line)
|
|
||||||
sections.append("")
|
|
||||||
elif (SECHEADER.match(line)):
|
|
||||||
sections.append(line)
|
|
||||||
else:
|
|
||||||
sections[-1] = sections[-1] + " " + line
|
|
||||||
total = ""
|
|
||||||
for sec in sections:
|
|
||||||
if (sec != ""):
|
|
||||||
sec = sec.replace("&","&")
|
|
||||||
sec = sec.replace("<","<")
|
|
||||||
sec = sec.replace(">",">")
|
|
||||||
sec = sec.replace(" "," ")
|
|
||||||
sec = sec.replace(" "," ")
|
|
||||||
if (delsection != None) and (delsection.match(sec)):
|
|
||||||
included[sec] = 1
|
|
||||||
if sec not in included:
|
|
||||||
included[sec] = 1
|
|
||||||
total = total + sec + "<br>\n"
|
|
||||||
return total
|
|
||||||
|
|
||||||
def linkTo(link, text):
|
|
||||||
return '<a href="' + link + '">' + text + '</a>'
|
|
||||||
|
|
||||||
def convertToPythonFn(fn):
|
|
||||||
result = ""
|
|
||||||
lastc = 0
|
|
||||||
for c in fn:
|
|
||||||
if (c!="_"):
|
|
||||||
if (lastc=="_"):
|
|
||||||
result = result + c.upper()
|
|
||||||
else:
|
|
||||||
result = result + c
|
|
||||||
lastc = c
|
|
||||||
return result
|
|
||||||
|
|
||||||
def removeFileLicense(content):
|
|
||||||
# Removes the license part at the top of a file.
|
|
||||||
return re.sub(FILEHEADER, "", content).strip()
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
#
|
|
||||||
# Interrogate Database Tokenizer
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
class InterrogateTokenizer:
|
|
||||||
"""
|
|
||||||
A big string, with a "parse pointer", and routines to
|
|
||||||
extract integers and strings. The token syntax is that
|
|
||||||
used by interrogate databases.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, fn):
|
|
||||||
self.fn = fn
|
|
||||||
self.pos = 0
|
|
||||||
self.data = readFile(fn)
|
|
||||||
|
|
||||||
def readint(self):
|
|
||||||
neg = 0
|
|
||||||
while (self.data[self.pos].isspace()):
|
|
||||||
self.pos += 1
|
|
||||||
if (self.data[self.pos] == "-"):
|
|
||||||
neg = 1
|
|
||||||
self.pos += 1
|
|
||||||
if (self.data[self.pos].isdigit()==0):
|
|
||||||
print("File position " + str(self.pos))
|
|
||||||
print("Text: " + self.data[self.pos:self.pos+50])
|
|
||||||
sys.exit("Syntax error in interrogate file format 0")
|
|
||||||
value = 0
|
|
||||||
while (self.data[self.pos].isdigit()):
|
|
||||||
value = value*10 + int(self.data[self.pos])
|
|
||||||
self.pos += 1
|
|
||||||
if (neg): value = -value
|
|
||||||
return value
|
|
||||||
|
|
||||||
def readstring(self):
|
|
||||||
length = self.readint()
|
|
||||||
if (self.data[self.pos].isspace()==0):
|
|
||||||
sys.exit("Syntax error in interrogate file format 1")
|
|
||||||
self.pos += 1
|
|
||||||
body = self.data[self.pos:self.pos+length]
|
|
||||||
if (len(body) != length):
|
|
||||||
sys.exit("Syntax error in interrogate file format 2")
|
|
||||||
self.pos += length
|
|
||||||
return body
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
#
|
|
||||||
# Interrogate Database Storage/Parsing
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
def parseInterrogateIntVec(tokzr):
|
|
||||||
length = tokzr.readint()
|
|
||||||
result = []
|
|
||||||
for i in range(length):
|
|
||||||
result.append(tokzr.readint())
|
|
||||||
return result
|
|
||||||
|
|
||||||
class InterrogateFunction:
|
|
||||||
def __init__(self, tokzr, db):
|
|
||||||
self.db = db
|
|
||||||
self.index = tokzr.readint()
|
|
||||||
self.componentname = tokzr.readstring()
|
|
||||||
self.flags = tokzr.readint()
|
|
||||||
self.classindex = tokzr.readint()
|
|
||||||
self.scopedname = tokzr.readstring()
|
|
||||||
self.cwrappers = parseInterrogateIntVec(tokzr)
|
|
||||||
self.pythonwrappers = parseInterrogateIntVec(tokzr)
|
|
||||||
self.comment = tokzr.readstring()
|
|
||||||
self.prototype = tokzr.readstring()
|
|
||||||
|
|
||||||
class InterrogateEnumValue:
|
|
||||||
def __init__(self, tokzr):
|
|
||||||
self.name = tokzr.readstring()
|
|
||||||
self.scopedname = tokzr.readstring()
|
|
||||||
self.value = tokzr.readint()
|
|
||||||
|
|
||||||
class InterrogateDerivation:
|
|
||||||
def __init__(self, tokzr):
|
|
||||||
self.flags = tokzr.readint()
|
|
||||||
self.base = tokzr.readint()
|
|
||||||
self.upcast = tokzr.readint()
|
|
||||||
self.downcast = tokzr.readint()
|
|
||||||
|
|
||||||
class InterrogateType:
|
|
||||||
def __init__(self, tokzr, db):
|
|
||||||
self.db = db
|
|
||||||
self.index = tokzr.readint()
|
|
||||||
self.componentname = tokzr.readstring()
|
|
||||||
self.flags = tokzr.readint()
|
|
||||||
self.scopedname = tokzr.readstring()
|
|
||||||
self.truename = tokzr.readstring()
|
|
||||||
self.outerclass = tokzr.readint()
|
|
||||||
self.atomictype = tokzr.readint()
|
|
||||||
self.wrappedtype = tokzr.readint()
|
|
||||||
self.constructors = parseInterrogateIntVec(tokzr)
|
|
||||||
self.destructor = tokzr.readint()
|
|
||||||
self.elements = parseInterrogateIntVec(tokzr)
|
|
||||||
self.methods = parseInterrogateIntVec(tokzr)
|
|
||||||
self.casts = parseInterrogateIntVec(tokzr)
|
|
||||||
self.derivations = []
|
|
||||||
nderivations = tokzr.readint()
|
|
||||||
for i in range(nderivations):
|
|
||||||
self.derivations.append(InterrogateDerivation(tokzr))
|
|
||||||
self.enumvalues = []
|
|
||||||
nenumvalues = tokzr.readint()
|
|
||||||
for i in range(nenumvalues):
|
|
||||||
self.enumvalues.append(InterrogateEnumValue(tokzr))
|
|
||||||
self.nested = parseInterrogateIntVec(tokzr)
|
|
||||||
self.comment = tokzr.readstring()
|
|
||||||
|
|
||||||
class InterrogateParameter:
|
|
||||||
def __init__(self, tokzr):
|
|
||||||
self.name = tokzr.readstring()
|
|
||||||
self.parameterflags = tokzr.readint()
|
|
||||||
self.type = tokzr.readint()
|
|
||||||
|
|
||||||
class InterrogateWrapper:
|
|
||||||
def __init__(self, tokzr, db):
|
|
||||||
self.db = db
|
|
||||||
self.index = tokzr.readint()
|
|
||||||
self.componentname = tokzr.readstring()
|
|
||||||
self.flags = tokzr.readint()
|
|
||||||
self.function = tokzr.readint()
|
|
||||||
self.returntype = tokzr.readint()
|
|
||||||
self.returnvaluedestructor = tokzr.readint()
|
|
||||||
self.uniquename = tokzr.readstring()
|
|
||||||
self.parameters = []
|
|
||||||
nparameters = tokzr.readint()
|
|
||||||
for i in range(nparameters):
|
|
||||||
self.parameters.append(InterrogateParameter(tokzr))
|
|
||||||
|
|
||||||
class InterrogateDatabase:
|
|
||||||
def __init__(self, tokzr):
|
|
||||||
self.fn = tokzr.fn
|
|
||||||
self.magic = tokzr.readint()
|
|
||||||
version1 = tokzr.readint()
|
|
||||||
version2 = tokzr.readint()
|
|
||||||
if (version1 != 2) or (version2 != 2):
|
|
||||||
sys.exit("This program only understands interrogate file format 2.2")
|
|
||||||
self.library = tokzr.readstring()
|
|
||||||
self.libhash = tokzr.readstring()
|
|
||||||
self.module = tokzr.readstring()
|
|
||||||
self.functions = {}
|
|
||||||
self.wrappers = {}
|
|
||||||
self.types = {}
|
|
||||||
self.namedtypes = {}
|
|
||||||
count_functions = tokzr.readint()
|
|
||||||
for i in range(count_functions):
|
|
||||||
fn = InterrogateFunction(tokzr, self)
|
|
||||||
self.functions[fn.index] = fn
|
|
||||||
count_wrappers = tokzr.readint()
|
|
||||||
for i in range(count_wrappers):
|
|
||||||
wr = InterrogateWrapper(tokzr, self)
|
|
||||||
self.wrappers[wr.index] = wr
|
|
||||||
count_types = tokzr.readint()
|
|
||||||
for i in range(count_types):
|
|
||||||
tp = InterrogateType(tokzr, self)
|
|
||||||
self.types[tp.index] = tp
|
|
||||||
self.namedtypes[tp.scopedname] = tp
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
#
|
|
||||||
# Pattern Matching for Python Parse Trees
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
def printTree(tree, indent):
|
|
||||||
spacing = " "[:indent]
|
|
||||||
if isinstance(tree, tuple) and isinstance(tree[0], int):
|
|
||||||
if tree[0] in symbol.sym_name:
|
|
||||||
for i in range(len(tree)):
|
|
||||||
if (i==0):
|
|
||||||
print(spacing + "(symbol." + symbol.sym_name[tree[0]] + ",")
|
|
||||||
else:
|
|
||||||
printTree(tree[i], indent+1)
|
|
||||||
print(spacing + "),")
|
|
||||||
elif tree[0] in token.tok_name:
|
|
||||||
print(spacing + "(token." + token.tok_name[tree[0]] + ", '" + tree[1] + "'),")
|
|
||||||
else:
|
|
||||||
print(spacing + str(tree))
|
|
||||||
else:
|
|
||||||
print(spacing + str(tree))
|
|
||||||
|
|
||||||
|
|
||||||
COMPOUND_STMT_PATTERN = (
|
|
||||||
symbol.stmt,
|
|
||||||
(symbol.compound_stmt, ['compound'])
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
DOCSTRING_STMT_PATTERN = (
|
|
||||||
symbol.stmt,
|
|
||||||
(symbol.simple_stmt,
|
|
||||||
(symbol.small_stmt,
|
|
||||||
(symbol.expr_stmt,
|
|
||||||
(symbol.testlist,
|
|
||||||
(symbol.test,
|
|
||||||
(symbol.or_test,
|
|
||||||
(symbol.and_test,
|
|
||||||
(symbol.not_test,
|
|
||||||
(symbol.comparison,
|
|
||||||
(symbol.expr,
|
|
||||||
(symbol.xor_expr,
|
|
||||||
(symbol.and_expr,
|
|
||||||
(symbol.shift_expr,
|
|
||||||
(symbol.arith_expr,
|
|
||||||
(symbol.term,
|
|
||||||
(symbol.factor,
|
|
||||||
(symbol.power,
|
|
||||||
(symbol.atom,
|
|
||||||
(token.STRING, ['docstring'])
|
|
||||||
))))))))))))))))),
|
|
||||||
(token.NEWLINE, '')
|
|
||||||
))
|
|
||||||
|
|
||||||
DERIVATION_PATTERN = (
|
|
||||||
symbol.test,
|
|
||||||
(symbol.or_test,
|
|
||||||
(symbol.and_test,
|
|
||||||
(symbol.not_test,
|
|
||||||
(symbol.comparison,
|
|
||||||
(symbol.expr,
|
|
||||||
(symbol.xor_expr,
|
|
||||||
(symbol.and_expr,
|
|
||||||
(symbol.shift_expr,
|
|
||||||
(symbol.arith_expr,
|
|
||||||
(symbol.term,
|
|
||||||
(symbol.factor,
|
|
||||||
(symbol.power,
|
|
||||||
(symbol.atom,
|
|
||||||
(token.NAME, ['classname'])
|
|
||||||
))))))))))))))
|
|
||||||
|
|
||||||
ASSIGNMENT_STMT_PATTERN = (
|
|
||||||
symbol.stmt,
|
|
||||||
(symbol.simple_stmt,
|
|
||||||
(symbol.small_stmt,
|
|
||||||
(symbol.expr_stmt,
|
|
||||||
(symbol.testlist,
|
|
||||||
(symbol.test,
|
|
||||||
(symbol.or_test,
|
|
||||||
(symbol.and_test,
|
|
||||||
(symbol.not_test,
|
|
||||||
(symbol.comparison,
|
|
||||||
(symbol.expr,
|
|
||||||
(symbol.xor_expr,
|
|
||||||
(symbol.and_expr,
|
|
||||||
(symbol.shift_expr,
|
|
||||||
(symbol.arith_expr,
|
|
||||||
(symbol.term,
|
|
||||||
(symbol.factor,
|
|
||||||
(symbol.power,
|
|
||||||
(symbol.atom,
|
|
||||||
(token.NAME, ['varname']),
|
|
||||||
))))))))))))))),
|
|
||||||
(token.EQUAL, '='),
|
|
||||||
(symbol.testlist, ['rhs']))),
|
|
||||||
(token.NEWLINE, ''),
|
|
||||||
))
|
|
||||||
|
|
||||||
class ParseTreeInfo:
|
|
||||||
docstring = ''
|
|
||||||
name = ''
|
|
||||||
|
|
||||||
def __init__(self, tree, name, file):
|
|
||||||
"""
|
|
||||||
The code can be a string (in which case it is parsed), or it
|
|
||||||
can be in parse tree form already.
|
|
||||||
"""
|
|
||||||
self.name = name
|
|
||||||
self.file = file
|
|
||||||
self.class_info = {}
|
|
||||||
self.function_info = {}
|
|
||||||
self.assign_info = {}
|
|
||||||
self.derivs = {}
|
|
||||||
if isinstance(tree, str):
|
|
||||||
try:
|
|
||||||
tree = parser.suite(tree+"\n").totuple()
|
|
||||||
if (tree):
|
|
||||||
found, vars = self.match(DOCSTRING_STMT_PATTERN, tree[1])
|
|
||||||
if found:
|
|
||||||
self.docstring = vars["docstring"]
|
|
||||||
except:
|
|
||||||
print("CAUTION --- Parse failed: " + name)
|
|
||||||
if isinstance(tree, tuple):
|
|
||||||
self.extract_info(tree)
|
|
||||||
|
|
||||||
def match(self, pattern, data, vars=None):
|
|
||||||
"""
|
|
||||||
pattern
|
|
||||||
Pattern to match against, possibly containing variables.
|
|
||||||
data
|
|
||||||
Data to be checked and against which variables are extracted.
|
|
||||||
vars
|
|
||||||
Dictionary of variables which have already been found. If not
|
|
||||||
provided, an empty dictionary is created.
|
|
||||||
|
|
||||||
The `pattern' value may contain variables of the form ['varname']
|
|
||||||
which are allowed to parseTreeMatch anything. The value that is
|
|
||||||
parseTreeMatched is returned as part of a dictionary which maps
|
|
||||||
'varname' to the parseTreeMatched value. 'varname' is not required
|
|
||||||
to be a string object, but using strings makes patterns and the code
|
|
||||||
which uses them more readable. This function returns two values: a
|
|
||||||
boolean indicating whether a parseTreeMatch was found and a
|
|
||||||
dictionary mapping variable names to their associated values.
|
|
||||||
"""
|
|
||||||
if vars is None:
|
|
||||||
vars = {}
|
|
||||||
if type(pattern) is list: # 'variables' are ['varname']
|
|
||||||
vars[pattern[0]] = data
|
|
||||||
return 1, vars
|
|
||||||
if type(pattern) is not tuple:
|
|
||||||
return (pattern == data), vars
|
|
||||||
if len(data) != len(pattern):
|
|
||||||
return 0, vars
|
|
||||||
for pattern, data in map(None, pattern, data):
|
|
||||||
same, vars = self.match(pattern, data, vars)
|
|
||||||
if not same:
|
|
||||||
break
|
|
||||||
return same, vars
|
|
||||||
|
|
||||||
def extract_info(self, tree):
|
|
||||||
# extract docstring
|
|
||||||
found = 0
|
|
||||||
if len(tree) == 2:
|
|
||||||
found, vars = self.match(DOCSTRING_STMT_PATTERN[1], tree[1])
|
|
||||||
elif len(tree) >= 4:
|
|
||||||
found, vars = self.match(DOCSTRING_STMT_PATTERN, tree[3])
|
|
||||||
if found:
|
|
||||||
self.docstring = eval(vars['docstring'])
|
|
||||||
# discover inner definitions
|
|
||||||
for node in tree[1:]:
|
|
||||||
found, vars = self.match(ASSIGNMENT_STMT_PATTERN, node)
|
|
||||||
if found:
|
|
||||||
self.assign_info[vars['varname']] = 1
|
|
||||||
found, vars = self.match(COMPOUND_STMT_PATTERN, node)
|
|
||||||
if found:
|
|
||||||
cstmt = vars['compound']
|
|
||||||
if cstmt[0] == symbol.funcdef:
|
|
||||||
name = cstmt[2][1]
|
|
||||||
# Workaround for a weird issue with static and classmethods
|
|
||||||
if name == "def":
|
|
||||||
name = cstmt[3][1]
|
|
||||||
self.function_info[name] = ParseTreeInfo(cstmt and cstmt[-1] or None, name, self.file)
|
|
||||||
self.function_info[name].prototype = self.extract_tokens("", cstmt[4])
|
|
||||||
else:
|
|
||||||
self.function_info[name] = ParseTreeInfo(cstmt and cstmt[-1] or None, name, self.file)
|
|
||||||
self.function_info[name].prototype = self.extract_tokens("", cstmt[3])
|
|
||||||
elif cstmt[0] == symbol.classdef:
|
|
||||||
name = cstmt[2][1]
|
|
||||||
self.class_info[name] = ParseTreeInfo(cstmt and cstmt[-1] or None, name, self.file)
|
|
||||||
self.extract_derivs(self.class_info[name], cstmt)
|
|
||||||
|
|
||||||
def extract_derivs(self, classinfo, tree):
|
|
||||||
if (len(tree)==8):
|
|
||||||
derivs = tree[4]
|
|
||||||
for deriv in derivs[1:]:
|
|
||||||
found, vars = self.match(DERIVATION_PATTERN, deriv)
|
|
||||||
if (found):
|
|
||||||
classinfo.derivs[vars["classname"]] = 1
|
|
||||||
|
|
||||||
def extract_tokens(self, str, tree):
|
|
||||||
if (isinstance(tree, tuple)):
|
|
||||||
if tree[0] in token.tok_name:
|
|
||||||
str = str + tree[1]
|
|
||||||
if (tree[1]==","): str=str+" "
|
|
||||||
elif tree[0] in symbol.sym_name:
|
|
||||||
for sub in tree[1:]:
|
|
||||||
str = self.extract_tokens(str, sub)
|
|
||||||
return str
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
#
|
|
||||||
# The code database contains:
|
|
||||||
#
|
|
||||||
# - a list of InterrogateDatabase objects representing C++ modules.
|
|
||||||
# - a list of ParseTreeInfo objects representing python modules.
|
|
||||||
#
|
|
||||||
# Collectively, these make up all the data about all the code.
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
class CodeDatabase:
|
|
||||||
def __init__(self, cxxlist, pylist):
|
|
||||||
self.types = {}
|
|
||||||
self.funcs = {}
|
|
||||||
self.goodtypes = {}
|
|
||||||
self.funcExports = {}
|
|
||||||
self.typeExports = {}
|
|
||||||
self.varExports = {}
|
|
||||||
self.globalfn = []
|
|
||||||
self.formattedprotos = {}
|
|
||||||
print("Reading C++ source files")
|
|
||||||
for cxx in cxxlist:
|
|
||||||
tokzr = InterrogateTokenizer(cxx)
|
|
||||||
idb = InterrogateDatabase(tokzr)
|
|
||||||
for type in idb.types.values():
|
|
||||||
if (type.flags & 8192) or type.scopedname not in self.types:
|
|
||||||
self.types[type.scopedname] = type
|
|
||||||
if (type.flags & 8192) and (type.atomictype == 0) and (type.scopedname.count(" ")==0) and (type.scopedname.count(":")==0):
|
|
||||||
self.goodtypes[type.scopedname] = type
|
|
||||||
self.typeExports.setdefault("pandac.PandaModules", []).append(type.scopedname)
|
|
||||||
for func in idb.functions.values():
|
|
||||||
type = idb.types.get(func.classindex)
|
|
||||||
func.pyname = convertToPythonFn(func.componentname)
|
|
||||||
if (type == None):
|
|
||||||
self.funcs["GLOBAL."+func.pyname] = func
|
|
||||||
self.globalfn.append("GLOBAL."+func.pyname)
|
|
||||||
self.funcExports.setdefault("pandac.PandaModules", []).append(func.pyname)
|
|
||||||
else:
|
|
||||||
self.funcs[type.scopedname+"."+func.pyname] = func
|
|
||||||
print("Reading Python sources files")
|
|
||||||
for py in pylist:
|
|
||||||
pyinf = ParseTreeInfo(readFile(py), py, py)
|
|
||||||
mod = pathToModule(py)
|
|
||||||
for type in pyinf.class_info.keys():
|
|
||||||
typinf = pyinf.class_info[type]
|
|
||||||
self.types[type] = typinf
|
|
||||||
self.goodtypes[type] = typinf
|
|
||||||
self.typeExports.setdefault(mod, []).append(type)
|
|
||||||
for func in typinf.function_info.keys():
|
|
||||||
self.funcs[type+"."+func] = typinf.function_info[func]
|
|
||||||
for func in pyinf.function_info.keys():
|
|
||||||
self.funcs["GLOBAL."+func] = pyinf.function_info[func]
|
|
||||||
self.globalfn.append("GLOBAL."+func)
|
|
||||||
self.funcExports.setdefault(mod, []).append(func)
|
|
||||||
for var in pyinf.assign_info.keys():
|
|
||||||
self.varExports.setdefault(mod, []).append(var)
|
|
||||||
|
|
||||||
def getClassList(self):
|
|
||||||
return list(self.goodtypes.keys())
|
|
||||||
|
|
||||||
def getGlobalFunctionList(self):
|
|
||||||
return self.globalfn
|
|
||||||
|
|
||||||
def getClassComment(self, cn):
|
|
||||||
type = self.types.get(cn)
|
|
||||||
if (isinstance(type, InterrogateType)):
|
|
||||||
return textToHTML(type.comment,"/")
|
|
||||||
elif (isinstance(type, ParseTreeInfo)):
|
|
||||||
return textToHTML(type.docstring,"#")
|
|
||||||
else:
|
|
||||||
return ""
|
|
||||||
|
|
||||||
def getClassParents(self, cn):
|
|
||||||
type = self.types.get(cn)
|
|
||||||
if (isinstance(type, InterrogateType)):
|
|
||||||
parents = []
|
|
||||||
for deriv in type.derivations:
|
|
||||||
basetype = type.db.types[deriv.base]
|
|
||||||
parents.append(basetype.scopedname)
|
|
||||||
return parents
|
|
||||||
elif (isinstance(type, ParseTreeInfo)):
|
|
||||||
return list(type.derivs.keys())
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def getClassConstants(self, cn):
|
|
||||||
type = self.types.get(cn)
|
|
||||||
if (isinstance(type, InterrogateType)):
|
|
||||||
result = []
|
|
||||||
for subtype in type.nested:
|
|
||||||
enumtype = type.db.types[subtype]
|
|
||||||
if (len(enumtype.enumvalues)):
|
|
||||||
for enumvalue in enumtype.enumvalues:
|
|
||||||
name = convertToPythonFn(enumvalue.name)
|
|
||||||
result.append((name, "("+enumtype.componentname+")"))
|
|
||||||
result.append(("",""))
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
return []
|
|
||||||
|
|
||||||
def buildInheritance(self, inheritance, cn):
|
|
||||||
if (inheritance.count(cn) == 0):
|
|
||||||
inheritance.append(cn)
|
|
||||||
for parent in self.getClassParents(cn):
|
|
||||||
self.buildInheritance(inheritance, parent)
|
|
||||||
|
|
||||||
def getInheritance(self, cn):
|
|
||||||
inheritance = []
|
|
||||||
self.buildInheritance(inheritance, cn)
|
|
||||||
return inheritance
|
|
||||||
|
|
||||||
def getClassImport(self, cn):
|
|
||||||
type = self.types.get(cn)
|
|
||||||
if (isinstance(type, InterrogateType)):
|
|
||||||
return "pandac.PandaModules"
|
|
||||||
else:
|
|
||||||
return pathToModule(type.file)
|
|
||||||
|
|
||||||
def getClassConstructors(self, cn):
|
|
||||||
# Only detects C++ constructors, not Python constructors, since
|
|
||||||
# those are treated as ordinary methods.
|
|
||||||
type = self.types.get(cn)
|
|
||||||
result = []
|
|
||||||
if (isinstance(type, InterrogateType)):
|
|
||||||
for constructor in type.constructors:
|
|
||||||
func = type.db.functions[constructor]
|
|
||||||
if (func.classindex == type.index):
|
|
||||||
result.append(type.scopedname+"."+func.pyname)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def getClassMethods(self, cn):
|
|
||||||
type = self.types.get(cn)
|
|
||||||
result = []
|
|
||||||
if (isinstance(type, InterrogateType)):
|
|
||||||
for method in type.methods:
|
|
||||||
func = type.db.functions[method]
|
|
||||||
if (func.classindex == type.index):
|
|
||||||
result.append(type.scopedname+"."+func.pyname)
|
|
||||||
elif (isinstance(type, ParseTreeInfo)):
|
|
||||||
for method in type.function_info.keys():
|
|
||||||
result.append(type.name + "." + method)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def getFunctionName(self, fn):
|
|
||||||
func = self.funcs.get(fn)
|
|
||||||
if (isinstance(func, InterrogateFunction)):
|
|
||||||
return func.pyname
|
|
||||||
elif (isinstance(func, ParseTreeInfo)):
|
|
||||||
return func.name
|
|
||||||
else:
|
|
||||||
return fn
|
|
||||||
|
|
||||||
def getFunctionImport(self, fn):
|
|
||||||
func = self.funcs.get(fn)
|
|
||||||
if (isinstance(func, InterrogateFunction)):
|
|
||||||
return "pandac.PandaModules"
|
|
||||||
else:
|
|
||||||
return pathToModule(func.file)
|
|
||||||
|
|
||||||
def getFunctionPrototype(self, fn, urlprefix, urlsuffix):
|
|
||||||
func = self.funcs.get(fn)
|
|
||||||
if (isinstance(func, InterrogateFunction)):
|
|
||||||
if fn in self.formattedprotos:
|
|
||||||
proto = self.formattedprotos[fn]
|
|
||||||
else:
|
|
||||||
proto = func.prototype
|
|
||||||
proto = proto.replace(" inline "," ")
|
|
||||||
if (proto.startswith("inline ")): proto = proto[7:]
|
|
||||||
proto = proto.replace("basic_string< char >", "string")
|
|
||||||
proto = textToHTML(proto,"")
|
|
||||||
if "." in fn:
|
|
||||||
for c in self.goodtypes.keys():
|
|
||||||
if c != fn.split(".")[0] and (c in proto):
|
|
||||||
proto = re.sub("\\b%s\\b" % c, linkTo(urlprefix+c+urlsuffix, c), proto)
|
|
||||||
self.formattedprotos[fn] = proto
|
|
||||||
return proto
|
|
||||||
elif (isinstance(func, ParseTreeInfo)):
|
|
||||||
return textToHTML("def "+func.name+func.prototype,"")
|
|
||||||
return fn
|
|
||||||
|
|
||||||
def getFunctionComment(self, fn):
|
|
||||||
func = self.funcs.get(fn)
|
|
||||||
if (isinstance(func, InterrogateFunction)):
|
|
||||||
return textToHTML(removeFileLicense(func.comment), "/", JUNKHEADER)
|
|
||||||
elif (isinstance(func, ParseTreeInfo)):
|
|
||||||
return textToHTML(func.docstring, "#")
|
|
||||||
return fn
|
|
||||||
|
|
||||||
def isFunctionPython(self, fn):
|
|
||||||
func = self.funcs.get(fn)
|
|
||||||
if (isinstance(func, InterrogateFunction)):
|
|
||||||
return False
|
|
||||||
elif (isinstance(func, ParseTreeInfo)):
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def getFuncExports(self, mod):
|
|
||||||
return self.funcExports.get(mod, [])
|
|
||||||
|
|
||||||
def getTypeExports(self, mod):
|
|
||||||
return self.typeExports.get(mod, [])
|
|
||||||
|
|
||||||
def getVarExports(self, mod):
|
|
||||||
return self.varExports.get(mod, [])
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
#
|
|
||||||
# The "Class Rename Dictionary" - Yech.
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
CLASS_RENAME_DICT = {
|
|
||||||
# No longer used, now empty.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
#
|
|
||||||
# HTML generation
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
def makeCodeDatabase(indirlist, directdirlist):
|
|
||||||
if isinstance(directdirlist, str):
|
|
||||||
directdirlist = [directdirlist]
|
|
||||||
ignore = {}
|
|
||||||
ignore["__init__.py"] = 1
|
|
||||||
for directdir in directdirlist:
|
|
||||||
ignore[directdir + "/src/directscripts"] = 1
|
|
||||||
ignore[directdir + "/src/extensions"] = 1
|
|
||||||
ignore[directdir + "/src/extensions_native"] = 1
|
|
||||||
ignore[directdir + "/src/ffi"] = 1
|
|
||||||
ignore[directdir + "/built"] = 1
|
|
||||||
cxxfiles = []
|
|
||||||
pyfiles = []
|
|
||||||
findFiles(indirlist, ".in", ignore, cxxfiles)
|
|
||||||
findFiles(directdirlist, ".py", ignore, pyfiles)
|
|
||||||
return CodeDatabase(cxxfiles, pyfiles)
|
|
||||||
|
|
||||||
def generateFunctionDocs(code, method, urlprefix, urlsuffix):
|
|
||||||
name = code.getFunctionName(method)
|
|
||||||
proto = code.getFunctionPrototype(method, urlprefix, urlsuffix)
|
|
||||||
comment = code.getFunctionComment(method)
|
|
||||||
if (comment == ""): comment = "Undocumented function.<br>\n"
|
|
||||||
chunk = '<table bgcolor="e8e8e8" border=0 cellspacing=0 cellpadding=5 width="100%"><tr><td>' + "\n"
|
|
||||||
chunk = chunk + '<a name="' + name + '"><b>' + name + "</b></a><br>\n"
|
|
||||||
chunk = chunk + proto + "<br>\n"
|
|
||||||
chunk = chunk + comment
|
|
||||||
chunk = chunk + "</td></tr></table><br>\n"
|
|
||||||
return chunk
|
|
||||||
|
|
||||||
def generateLinkTable(link, text, cols, urlprefix, urlsuffix):
|
|
||||||
column = (len(link)+cols-1)/cols
|
|
||||||
percent = 100 / cols
|
|
||||||
result = '<table width="100%">\n'
|
|
||||||
for i in range(column):
|
|
||||||
line = ""
|
|
||||||
for j in range(cols):
|
|
||||||
slot = i + column*j
|
|
||||||
linkval = ""
|
|
||||||
textval = ""
|
|
||||||
if (slot < len(link)): linkval = link[slot]
|
|
||||||
if (slot < len(text)): textval = text[slot]
|
|
||||||
if (i==0):
|
|
||||||
line = line + '<td width="' + str(percent) + '%">' + linkTo(urlprefix+linkval+urlsuffix, textval) + "</td>"
|
|
||||||
else:
|
|
||||||
line = line + '<td>' + linkTo(urlprefix+linkval+urlsuffix, textval) + "</td>"
|
|
||||||
result = result + "<tr>" + line + "</tr>\n"
|
|
||||||
result = result + "</table>\n"
|
|
||||||
return result
|
|
||||||
|
|
||||||
def generate(pversion, indirlist, directdirlist, docdir, header, footer, urlprefix, urlsuffix):
|
|
||||||
code = makeCodeDatabase(indirlist, directdirlist)
|
|
||||||
classes = code.getClassList()[:]
|
|
||||||
classes.sort(None, str.lower)
|
|
||||||
xclasses = classes[:]
|
|
||||||
print("Generating HTML pages")
|
|
||||||
for type in classes:
|
|
||||||
body = "<h1>" + type + "</h1>\n"
|
|
||||||
comment = code.getClassComment(type)
|
|
||||||
body = body + "<ul>\nfrom " + code.getClassImport(type) + " import " + type + "</ul>\n\n"
|
|
||||||
body = body + "<ul>\n" + comment + "</ul>\n\n"
|
|
||||||
inheritance = code.getInheritance(type)
|
|
||||||
body = body + "<h2>Inheritance:</h2>\n<ul>\n"
|
|
||||||
for inh in inheritance:
|
|
||||||
line = " " + linkTo(urlprefix+inh+urlsuffix, inh) + ": "
|
|
||||||
for parent in code.getClassParents(inh):
|
|
||||||
line = line + linkTo(urlprefix+parent+urlsuffix, parent) + " "
|
|
||||||
body = body + line + "<br>\n"
|
|
||||||
body = body + "</ul>\n"
|
|
||||||
for sclass in inheritance:
|
|
||||||
methods = code.getClassMethods(sclass)[:]
|
|
||||||
methods.sort(None, str.lower)
|
|
||||||
constructors = code.getClassConstructors(sclass)
|
|
||||||
if (len(methods) > 0 or len(constructors) > 0):
|
|
||||||
body = body + "<h2>Methods of "+sclass+":</h2>\n<ul>\n"
|
|
||||||
if len(constructors) > 0:
|
|
||||||
fn = code.getFunctionName(constructors[0])
|
|
||||||
body = body + '<a href="#' + fn + '">' + fn + " (Constructor)</a><br>\n"
|
|
||||||
for method in methods:
|
|
||||||
fn = code.getFunctionName(method)
|
|
||||||
body = body + '<a href="#' + fn + '">' + fn + "</a><br>\n"
|
|
||||||
body = body + "</ul>\n"
|
|
||||||
for sclass in inheritance:
|
|
||||||
enums = code.getClassConstants(sclass)[:]
|
|
||||||
if (len(enums) > 0):
|
|
||||||
body = body + "<h2>Constants in "+sclass+":</h2>\n<ul><table>\n"
|
|
||||||
for (value, comment) in enums:
|
|
||||||
body = body + "<tr><td>" + value + "</td><td>" + comment + "</td></tr>\n"
|
|
||||||
body = body + "</table></ul>"
|
|
||||||
for sclass in inheritance:
|
|
||||||
constructors = code.getClassConstructors(sclass)
|
|
||||||
for constructor in constructors:
|
|
||||||
body = body + generateFunctionDocs(code, constructor, urlprefix, urlsuffix)
|
|
||||||
methods = code.getClassMethods(sclass)[:]
|
|
||||||
methods.sort(None, str.lower)
|
|
||||||
for method in methods:
|
|
||||||
body = body + generateFunctionDocs(code, method, urlprefix, urlsuffix)
|
|
||||||
body = header + body + footer
|
|
||||||
writeFile(docdir + "/" + type + ".html", body)
|
|
||||||
if type in CLASS_RENAME_DICT:
|
|
||||||
modtype = CLASS_RENAME_DICT[type]
|
|
||||||
writeFile(docdir + "/" + modtype + ".html", body)
|
|
||||||
xclasses.append(modtype)
|
|
||||||
xclasses.sort(None, str.lower)
|
|
||||||
|
|
||||||
index = "<h1>List of Classes - Panda " + pversion + "</h1>\n"
|
|
||||||
index = index + generateLinkTable(xclasses, xclasses, 3, urlprefix, urlsuffix)
|
|
||||||
fnlist = code.getGlobalFunctionList()[:]
|
|
||||||
fnlist.sort(None, str.lower)
|
|
||||||
fnnames = []
|
|
||||||
for i in range(len(fnlist)):
|
|
||||||
fnnames.append(code.getFunctionName(fnlist[i]))
|
|
||||||
index = header + index + footer
|
|
||||||
writeFile(docdir + "/classes.html", index)
|
|
||||||
|
|
||||||
index = "<h1>List of Global Functions - Panda " + pversion + "</h1>\n"
|
|
||||||
index = index + generateLinkTable(fnnames, fnnames, 3,"#","")
|
|
||||||
for func in fnlist:
|
|
||||||
index = index + generateFunctionDocs(code, func, urlprefix, urlsuffix)
|
|
||||||
index = header + index + footer
|
|
||||||
writeFile(docdir + "/functions.html", index)
|
|
||||||
|
|
||||||
table = {}
|
|
||||||
for type in classes:
|
|
||||||
for method in code.getClassMethods(type)[:]:
|
|
||||||
name = code.getFunctionName(method)
|
|
||||||
prefix = name[0].upper()
|
|
||||||
if prefix not in table:
|
|
||||||
table[prefix] = {}
|
|
||||||
if name not in table[prefix]:
|
|
||||||
table[prefix][name] = []
|
|
||||||
table[prefix][name].append(type)
|
|
||||||
|
|
||||||
index = "<h1>List of Methods - Panda " + pversion + "</h1>\n"
|
|
||||||
|
|
||||||
prefixes = list(table.keys())
|
|
||||||
prefixes.sort(None, str.lower)
|
|
||||||
for prefix in prefixes:
|
|
||||||
index = index + linkTo("#"+prefix, prefix) + " "
|
|
||||||
index = index + "<br><br>"
|
|
||||||
for prefix in prefixes:
|
|
||||||
index = index + '<a name="' + prefix + '">' + "\n"
|
|
||||||
names = list(table[prefix].keys())
|
|
||||||
names.sort(None, str.lower)
|
|
||||||
for name in names:
|
|
||||||
line = '<b>' + name + ":</b><ul>\n"
|
|
||||||
ctypes = table[prefix][name]
|
|
||||||
ctypes.sort(None, str.lower)
|
|
||||||
for type in ctypes:
|
|
||||||
line = line + "<li>" + linkTo(urlprefix+type+urlsuffix+"#"+name, type) + "\n"
|
|
||||||
line = line + "</ul>\n"
|
|
||||||
index = index + line + "\n"
|
|
||||||
index = header + index + footer
|
|
||||||
writeFile(docdir + "/methods.html", index)
|
|
||||||
|
|
||||||
index = "<h1>Panda " + pversion + "</h1>\n"
|
|
||||||
index = index + "<ul>\n"
|
|
||||||
index = index + "<li>" + linkTo(urlprefix+"classes"+urlsuffix, "List of all Classes") + "\n"
|
|
||||||
index = index + "</ul>\n"
|
|
||||||
index = index + "<ul>\n"
|
|
||||||
index = index + "<li>" + linkTo(urlprefix+"functions"+urlsuffix, "List of all Global Functions") + "\n"
|
|
||||||
index = index + "</ul>\n"
|
|
||||||
index = index + "<ul>\n"
|
|
||||||
index = index + "<li>" + linkTo(urlprefix+"methods"+urlsuffix, "List of all Methods (very long)") + "\n"
|
|
||||||
index = index + "</ul>\n"
|
|
||||||
writeFile(docdir + "/index.html", index)
|
|
||||||
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
#
|
|
||||||
# IMPORT repair
|
|
||||||
#
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
def expandImports(indirlist, directdirlist, fixdirlist):
|
|
||||||
code = makeCodeDatabase(indirlist, directdirlist)
|
|
||||||
fixfiles = []
|
|
||||||
findFiles(fixdirlist, ".py", {}, fixfiles)
|
|
||||||
for fixfile in fixfiles:
|
|
||||||
if (os.path.isfile(fixfile+".orig")):
|
|
||||||
text = readFile(fixfile+".orig")
|
|
||||||
else:
|
|
||||||
text = readFile(fixfile)
|
|
||||||
writeFile(fixfile+".orig", text)
|
|
||||||
text = text.replace("\r","")
|
|
||||||
lines = text.split("\n")
|
|
||||||
used = {}
|
|
||||||
for id in IDENTIFIER.findall(text):
|
|
||||||
used[id] = 1
|
|
||||||
result = []
|
|
||||||
for line in lines:
|
|
||||||
mat = IMPORTSTAR.match(line)
|
|
||||||
if (mat):
|
|
||||||
module = mat.group(1)
|
|
||||||
if (fixfile.count("/")!=0) and (module.count(".")==0):
|
|
||||||
modfile = os.path.dirname(fixfile)+"/"+module+".py"
|
|
||||||
if (os.path.isfile(modfile)):
|
|
||||||
module = pathToModule(modfile)
|
|
||||||
typeExports = code.getTypeExports(module)
|
|
||||||
funcExports = code.getFuncExports(module)
|
|
||||||
varExports = code.getVarExports(module)
|
|
||||||
if (len(typeExports)+len(funcExports)+len(varExports)==0):
|
|
||||||
result.append(line)
|
|
||||||
print(fixfile + " : " + module + " : no exports")
|
|
||||||
else:
|
|
||||||
print(fixfile + " : " + module + " : repairing")
|
|
||||||
for x in funcExports:
|
|
||||||
fn = code.getFunctionName(x)
|
|
||||||
if fn in used:
|
|
||||||
result.append("from "+module+" import "+fn)
|
|
||||||
for x in typeExports:
|
|
||||||
if x in used:
|
|
||||||
result.append("from "+module+" import "+x)
|
|
||||||
for x in varExports:
|
|
||||||
if x in used:
|
|
||||||
result.append("from "+module+" import "+x)
|
|
||||||
else:
|
|
||||||
result.append(line)
|
|
||||||
writeFileLines(fixfile, result)
|
|
@ -1,29 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
REM
|
|
||||||
REM Verify that we can find the 'expandimports' python script
|
|
||||||
REM and the python interpreter. If we can find both, then
|
|
||||||
REM run 'expandimports'.
|
|
||||||
REM
|
|
||||||
|
|
||||||
set thirdparty=thirdparty
|
|
||||||
if defined MAKEPANDA_THIRDPARTY set thirdparty=%MAKEPANDA_THIRDPARTY%
|
|
||||||
|
|
||||||
if not exist makepanda\expandimports.py goto :missing1
|
|
||||||
if not exist %thirdparty%\win-python\python.exe goto :missing2
|
|
||||||
%thirdparty%\win-python\python.exe makepanda\expandimports.py %*
|
|
||||||
goto done
|
|
||||||
|
|
||||||
:missing1
|
|
||||||
echo You need to change directory to the root of the panda source tree
|
|
||||||
echo before invoking expandimports.
|
|
||||||
goto done
|
|
||||||
|
|
||||||
:missing2
|
|
||||||
echo You seem to be missing the 'thirdparty' directory. You probably checked
|
|
||||||
echo the source code out from GitHub. The GitHub repository is
|
|
||||||
echo missing the 'thirdparty' directory. You will need to supplement the
|
|
||||||
echo code by downloading the 'thirdparty' directory from www.panda3d.org
|
|
||||||
goto done
|
|
||||||
|
|
||||||
:done
|
|
@ -1,21 +0,0 @@
|
|||||||
########################################################################
|
|
||||||
##
|
|
||||||
## Win32 Usage: makepanda\expandimports.bat
|
|
||||||
## Linux Usage: makepanda/expandimports.py
|
|
||||||
##
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
import sys,os,re
|
|
||||||
sys.path = ["direct/src/directscripts"] + sys.path
|
|
||||||
import gendocs
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
##
|
|
||||||
## Make sure panda has been built.
|
|
||||||
##
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
if (os.path.isfile("built/pandac/input/libpgraph.in")==0) or (os.path.isfile("built/pandac/input/libputil.in")==0):
|
|
||||||
sys.exit("Cannot read the interrogate-output files in built/pandac/input")
|
|
||||||
|
|
||||||
gendocs.expandImports("built/pandac/input", "direct", "samples")
|
|
@ -1,29 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
REM
|
|
||||||
REM Verify that we can find the 'makechm' python script
|
|
||||||
REM and the python interpreter. If we can find both, then
|
|
||||||
REM run 'makechm'.
|
|
||||||
REM
|
|
||||||
|
|
||||||
set thirdparty=thirdparty
|
|
||||||
if defined MAKEPANDA_THIRDPARTY set thirdparty=%MAKEPANDA_THIRDPARTY%
|
|
||||||
|
|
||||||
if not exist makepanda\makechm.py goto :missing1
|
|
||||||
if not exist %thirdparty%\win-python\python.exe goto :missing2
|
|
||||||
%thirdparty%\win-python\python.exe makepanda\makechm.py %*
|
|
||||||
goto done
|
|
||||||
|
|
||||||
:missing1
|
|
||||||
echo You need to change directory to the root of the panda source tree
|
|
||||||
echo before invoking makechm.
|
|
||||||
goto done
|
|
||||||
|
|
||||||
:missing2
|
|
||||||
echo You seem to be missing the 'thirdparty' directory. You probably checked
|
|
||||||
echo the source code out from GitHub. The GitHub repository is
|
|
||||||
echo missing the 'thirdparty' directory. You will need to supplement the
|
|
||||||
echo code by downloading the 'thirdparty' directory from www.panda3d.org
|
|
||||||
goto done
|
|
||||||
|
|
||||||
:done
|
|
@ -1,281 +0,0 @@
|
|||||||
########################################################################
|
|
||||||
##
|
|
||||||
## Win32 Usage: makepanda\makechm.bat
|
|
||||||
## Linux Usage: makepanda/makechm.py
|
|
||||||
##
|
|
||||||
## To use this script, you will need to have hhc.exe on your system.
|
|
||||||
## For verbose output, run with -v or --verbose option.
|
|
||||||
## To keep the temporary .hhc, .hhk, .hhp, .chw files use -k or --keep.
|
|
||||||
##
|
|
||||||
## You can also import this file as a python module. You will then have
|
|
||||||
## access to three functions: makeCHM, makeManualCHM, makeReferenceCHM.
|
|
||||||
## This is how you call them:
|
|
||||||
## makeCHM(outputfile, dirname, title)
|
|
||||||
## where outputfile is the filename where the .chm file will be written,
|
|
||||||
## and dirname is the directory containing the html files to include.
|
|
||||||
## Title will be the title of the CHM file.
|
|
||||||
## The functions makeManualCHM and makeReferenceCHM work exactly the
|
|
||||||
## same, except that they work with a structure resembling that of the
|
|
||||||
## Panda3D manual and reference, respectively.
|
|
||||||
## Note: outputfile should not contain spaces.
|
|
||||||
##
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
__all__ = ["makeCHM", "makeManualCHM", "makeReferenceCHM"]
|
|
||||||
import os, re
|
|
||||||
from sys import exit
|
|
||||||
import xml.dom.minidom
|
|
||||||
from xml.dom.minidom import Node
|
|
||||||
|
|
||||||
VERBOSE = False
|
|
||||||
KEEPTEMP = False
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
from sys import argv
|
|
||||||
VERBOSE = ("-v" in argv) or ("-vk" in argv) or ("-kv" in argv) or ("--verbose" in argv)
|
|
||||||
KEEPTEMP = ("-k" in argv) or ("-kv" in argv) or ("-vk" in argv) or ("--keep" in argv)
|
|
||||||
|
|
||||||
OPTIONBLOCK = """
|
|
||||||
Binary TOC=Yes
|
|
||||||
Compatibility=1.1 or later
|
|
||||||
Compiled file=%s
|
|
||||||
Contents file=%s.hhc
|
|
||||||
Default Font=Arial,10,0
|
|
||||||
Default topic=%s
|
|
||||||
Display compile progress=VERBOSE
|
|
||||||
Full-text search=Yes
|
|
||||||
Index file=%s.hhk
|
|
||||||
Language=0x409 English (United States)
|
|
||||||
Title=%s""".replace("VERBOSE", VERBOSE and "Yes" or "No")
|
|
||||||
|
|
||||||
HTMLBLOCK = """<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta name="generator" content="Panda3D - makechm.py">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<object type="text/site properties">
|
|
||||||
<param name="Window Styles" value="0x800025">
|
|
||||||
<param name="ImageType" value="Folder">
|
|
||||||
<param name="Font" value="Arial,8,0">
|
|
||||||
</object>
|
|
||||||
<ul>\n"""
|
|
||||||
|
|
||||||
REFERENCEITEMS = [
|
|
||||||
("index.html", "Main Page"),
|
|
||||||
("methods.html", "Methods"),
|
|
||||||
("functions.html", "Global Functions"),
|
|
||||||
("classes.html", "Classes"),
|
|
||||||
]
|
|
||||||
|
|
||||||
def urldecode(url):
|
|
||||||
regex = re.compile("%([0-9a-hA-H][0-9a-hA-H])", re.M)
|
|
||||||
return regex.sub(lambda x: chr(int(x.group(1), 16)), url)
|
|
||||||
|
|
||||||
def ireplace(string, target, replacement):
|
|
||||||
"""Case-insensitive replace."""
|
|
||||||
index = string.lower().find(target.lower())
|
|
||||||
if index >= 0:
|
|
||||||
result = string[:index] + replacement + string[index + len(target):]
|
|
||||||
return result
|
|
||||||
else:
|
|
||||||
return string
|
|
||||||
|
|
||||||
def parseAnchor(node):
|
|
||||||
"""Parses an XML minidom node representing an anchor and returns a tuple
|
|
||||||
containing the href and the content of the link."""
|
|
||||||
assert node.nodeType == Node.ELEMENT_NODE
|
|
||||||
assert node.localName == "a"
|
|
||||||
href = ""
|
|
||||||
title = ""
|
|
||||||
for localName, a in node.attributes.items():
|
|
||||||
if localName.lower() == "href":
|
|
||||||
href = a
|
|
||||||
for e in node.childNodes:
|
|
||||||
if e.nodeType == Node.TEXT_NODE:
|
|
||||||
title += e.data
|
|
||||||
return href, title
|
|
||||||
|
|
||||||
def parseManualTree(node):
|
|
||||||
"""Parses a tree of the manual Main_Page and returns it through a list containing tuples:
|
|
||||||
[(title, href, [(title, href, [...]), ...]), ...]"""
|
|
||||||
if node.nodeType != Node.ELEMENT_NODE: return []
|
|
||||||
result = []
|
|
||||||
lastadded = None
|
|
||||||
for e in node.childNodes:
|
|
||||||
if e.nodeType == Node.ELEMENT_NODE:
|
|
||||||
if e.localName == "ol":
|
|
||||||
assert lastadded != None
|
|
||||||
for i in xrange(len(result)):
|
|
||||||
if result[i][:2] == lastadded:
|
|
||||||
result[i] = lastadded + (parseManualTree(e),)
|
|
||||||
elif e.localName == "a":
|
|
||||||
href, title = parseAnchor(e)
|
|
||||||
lastadded = title, href
|
|
||||||
result.append((title, href, None))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def parseManualTOC(filename):
|
|
||||||
"""Reads the manual's Main_Page file and returns a list of all the trees found."""
|
|
||||||
filename = open(filename)
|
|
||||||
text = filename.read()
|
|
||||||
filename.close()
|
|
||||||
text = text.split("<h2>Table of Contents</h2>")[1].split("</div>")[0]
|
|
||||||
text = "<root>" + text.replace("<li>", "") + "</root>"
|
|
||||||
text = re.sub(re.compile("<!--([^>]+)>"), "", text)
|
|
||||||
result = []
|
|
||||||
for e in xml.dom.minidom.parseString(text).childNodes[0].childNodes:
|
|
||||||
if e.nodeType == Node.ELEMENT_NODE:
|
|
||||||
result.append(parseManualTree(e))
|
|
||||||
return result
|
|
||||||
|
|
||||||
def treeToHTML(tree, dirname, indent = ""):
|
|
||||||
"""Converts a tree into HTML code suitable for .hhc or .hhk files. The tree should be like:
|
|
||||||
[(title, href, [(title, href, [...]), ...]), ...]"""
|
|
||||||
html = ""
|
|
||||||
for title, href, sub in tree:
|
|
||||||
html += indent + "<li><object type=\"text/sitemap\">\n"
|
|
||||||
html += indent + " <param name=\"Name\" value=\"%s\">\n" % title.replace("CXX", "C++").replace("\"", """)
|
|
||||||
html += indent + " <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, href))
|
|
||||||
html += indent + "</object>\n"
|
|
||||||
if sub != None:
|
|
||||||
html += indent + "<ul>\n"
|
|
||||||
html += treeToHTML(sub, dirname, indent + " ")
|
|
||||||
html += indent + "</ul>\n"
|
|
||||||
return html
|
|
||||||
|
|
||||||
def makeCHM(outputfile, dirname, title, special = None):
|
|
||||||
"""Creates a CHM file based on a directory of HTML files. See the top of this file for more info."""
|
|
||||||
assert special == None or special in ["manual", "reference"]
|
|
||||||
reference = (special == "reference")
|
|
||||||
manual = (special == "manual")
|
|
||||||
base = ireplace(outputfile, ".chm", "")
|
|
||||||
if os.path.isfile(base + ".chm"): os.remove(base + ".chm")
|
|
||||||
# Create the hhp file
|
|
||||||
hhp = open(base + ".hhp", "w")
|
|
||||||
hhp.write("[OPTIONS]\n")
|
|
||||||
hhp.write(OPTIONBLOCK % (base + ".chm", base, urldecode(os.path.join(dirname, "index.html")), base, title))
|
|
||||||
hhp.write("\n[FILES]\n")
|
|
||||||
# Create the TOC file and Index file
|
|
||||||
hhk = open(base + ".hhk", "w")
|
|
||||||
hhc = open(base + ".hhc", "w")
|
|
||||||
hhk.write(HTMLBLOCK)
|
|
||||||
hhc.write(HTMLBLOCK)
|
|
||||||
# The manual should be treated as a special case.
|
|
||||||
if manual:
|
|
||||||
hhc.write(" <li><object type=\"text/sitemap\">\n")
|
|
||||||
hhc.write(" <param name=\"Name\" value=\"Main Page\">\n")
|
|
||||||
hhc.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, "index.html")))
|
|
||||||
hhc.write(" </object>\n")
|
|
||||||
for item in parseManualTOC(dirname + "/index.html"):
|
|
||||||
hhc.write(treeToHTML(item, dirname, " "))
|
|
||||||
for i in os.listdir(dirname):
|
|
||||||
hhp.write(os.path.join(dirname, i) + "\n")
|
|
||||||
if i != "index.html":
|
|
||||||
hhk.write(" <li><object type=\"text/sitemap\">\n")
|
|
||||||
hhk.write(" <param name=\"Name\" value=\"%s\">\n" % ireplace(urldecode(i).replace(".1", "").replace("_", " ").replace("CXX", "C++"), ".html", "").replace("\"", """))
|
|
||||||
hhk.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
|
||||||
hhk.write(" </object>\n")
|
|
||||||
else:
|
|
||||||
idt = " "
|
|
||||||
# If we are writing out the reference, write some extra stuff.
|
|
||||||
if reference:
|
|
||||||
idt = " "
|
|
||||||
for i, desc in REFERENCEITEMS:
|
|
||||||
hhk.write(" <li><object type=\"text/sitemap\">\n")
|
|
||||||
hhk.write(" <param name=\"Name\" value=\"%s\">\n" % desc.replace("\"", """))
|
|
||||||
hhk.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
|
||||||
hhk.write(" </object>\n")
|
|
||||||
hhc.write(" <li><object type=\"text/sitemap\">\n")
|
|
||||||
hhc.write(" <param name=\"Name\" value=\"%s\">\n" % desc.replace("\"", """))
|
|
||||||
hhc.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
|
||||||
hhc.write(" </object>\n")
|
|
||||||
hhc.write(" <ul>\n")
|
|
||||||
# Loop through the directories and write out relevant data.
|
|
||||||
for i in os.listdir(dirname):
|
|
||||||
hhp.write(os.path.join(dirname, i) + "\n")
|
|
||||||
if i != "index.html" and ((not reference) or (not i in ["classes.html", "methods.html", "functions.html"])):
|
|
||||||
hhk.write(" <li><object type=\"text/sitemap\">\n")
|
|
||||||
hhk.write(" <param name=\"Name\" value=\"%s\">\n" % ireplace(urldecode(i).replace(".1", ""), ".html", "").replace("\"", """))
|
|
||||||
hhk.write(" <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
|
||||||
hhk.write(" </object>\n")
|
|
||||||
hhc.write(idt + "<li><object type=\"text/sitemap\">\n")
|
|
||||||
hhc.write(idt + " <param name=\"Name\" value=\"%s\">\n" % ireplace(urldecode(i).replace(".1", ""), ".html", "").replace("\"", """))
|
|
||||||
hhc.write(idt + " <param name=\"Local\" value=\"%s\">\n" % urldecode(os.path.join(dirname, i)))
|
|
||||||
hhc.write(idt + "</object>\n")
|
|
||||||
# Close the files.
|
|
||||||
if reference: hhc.write(" </ul>\n")
|
|
||||||
hhk.write(" </ul>\n </body>\n</html>")
|
|
||||||
hhc.write(" </ul>\n </body>\n</html>")
|
|
||||||
hhk.close()
|
|
||||||
hhc.close()
|
|
||||||
hhp.close()
|
|
||||||
# Now, execute the command to compile the files.
|
|
||||||
if "PROGRAMFILES" in os.environ and os.path.isdir("%s\\HTML Help Workshop" % os.environ["PROGRAMFILES"]):
|
|
||||||
cmd = "\"%s\\HTML Help Workshop\\hhc.exe\" %s.hhp" % (os.environ["PROGRAMFILES"], base)
|
|
||||||
elif os.path.isdir("C:\\Program Files\\HTML Help Workshop"):
|
|
||||||
cmd = "\"C:\\Program Files\\HTML Help Workshop\\hhc.exe\" %s.hhp" % base
|
|
||||||
else:
|
|
||||||
cmd = "hhc \"%s.hhp\"" % base
|
|
||||||
print(cmd)
|
|
||||||
os.system(cmd)
|
|
||||||
if not KEEPTEMP:
|
|
||||||
if os.path.isfile("%s.hhp" % base): os.remove("%s.hhp" % base)
|
|
||||||
if os.path.isfile("%s.hhc" % base): os.remove("%s.hhc" % base)
|
|
||||||
if os.path.isfile("%s.hhk" % base): os.remove("%s.hhk" % base)
|
|
||||||
if os.path.isfile("%s.chw" % base): os.remove("%s.chw" % base)
|
|
||||||
if not os.path.isfile(base + ".chm"):
|
|
||||||
print("An error has occurred!")
|
|
||||||
if __name__ == "__main__":
|
|
||||||
exit(1)
|
|
||||||
else:
|
|
||||||
return False
|
|
||||||
if __name__ != "__main__":
|
|
||||||
return True
|
|
||||||
|
|
||||||
def makeManualCHM(outputfile, dirname, title):
|
|
||||||
"""Same as makeCHM, but suitable for converting the Panda3D manual."""
|
|
||||||
return makeCHM(outputfile, dirname, title, special = "manual")
|
|
||||||
|
|
||||||
def makeReferenceCHM(outputfile, dirname, title):
|
|
||||||
"""Same as makeCHM, but converts a structure resembling that of the Panda3D reference."""
|
|
||||||
return makeCHM(outputfile, dirname, title, special = "reference")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# Extract a version number, if we have one.
|
|
||||||
VERSION = None
|
|
||||||
try:
|
|
||||||
f = file("built/include/pandaVersion.h","r")
|
|
||||||
pattern = re.compile('^\\s*[#]\\s*define\\s+PANDA_VERSION_STR\\s+["]([0-9.]+)["]')
|
|
||||||
for line in f:
|
|
||||||
match = pattern.match(line,0)
|
|
||||||
if (match):
|
|
||||||
VERSION = match.group(1)
|
|
||||||
break
|
|
||||||
f.close()
|
|
||||||
except:
|
|
||||||
# If not, we don't care at all.
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Now, make CHM's for both the manual and reference, if we have them.
|
|
||||||
for lang in ["python", "cxx"]:
|
|
||||||
if not os.path.isdir("manual-" + lang):
|
|
||||||
print("No directory named 'manual-%s' found" % lang)
|
|
||||||
else:
|
|
||||||
print("Making CHM file for manual-%s..." % lang)
|
|
||||||
if VERSION == None:
|
|
||||||
makeManualCHM("manual-%s.chm" % lang, "manual-" + lang, "Panda3D Manual")
|
|
||||||
else:
|
|
||||||
makeManualCHM("manual-%s-%s.chm" % (VERSION, lang), "manual-" + lang, "Panda3D %s Manual" % VERSION)
|
|
||||||
|
|
||||||
if not os.path.isdir("reference-" + lang):
|
|
||||||
print("No directory named 'reference-%s' found" % lang)
|
|
||||||
else:
|
|
||||||
print("Making CHM file for reference-%s..." % lang)
|
|
||||||
if VERSION == None:
|
|
||||||
makeReferenceCHM("reference-%s.chm" % lang, "reference-" + lang, "Panda3D Reference")
|
|
||||||
else:
|
|
||||||
makeReferenceCHM("reference-%s-%s.chm" % (VERSION, lang), "reference-" + lang, "Panda3D %s Reference" % VERSION)
|
|
||||||
|
|
||||||
print("Done!")
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
|||||||
@echo off
|
|
||||||
|
|
||||||
REM
|
|
||||||
REM Verify that we can find the 'makedocs' python script
|
|
||||||
REM and the python interpreter. If we can find both, then
|
|
||||||
REM run 'makedocs'.
|
|
||||||
REM
|
|
||||||
|
|
||||||
set thirdparty=thirdparty
|
|
||||||
if defined MAKEPANDA_THIRDPARTY set thirdparty=%MAKEPANDA_THIRDPARTY%
|
|
||||||
|
|
||||||
if not exist makepanda\makedocs.py goto :missing1
|
|
||||||
if not exist %thirdparty%\win-python\python.exe goto :missing2
|
|
||||||
%thirdparty%\win-python\python.exe makepanda\makedocs.py %*
|
|
||||||
goto done
|
|
||||||
|
|
||||||
:missing1
|
|
||||||
echo You need to change directory to the root of the panda source tree
|
|
||||||
echo before invoking makedocs.
|
|
||||||
goto done
|
|
||||||
|
|
||||||
:missing2
|
|
||||||
echo You seem to be missing the 'thirdparty' directory. You probably checked
|
|
||||||
echo the source code out from GitHub. The GitHub repository is
|
|
||||||
echo missing the 'thirdparty' directory. You will need to supplement the
|
|
||||||
echo code by downloading the 'thirdparty' directory from www.panda3d.org
|
|
||||||
goto done
|
|
||||||
|
|
||||||
:done
|
|
@ -1,77 +0,0 @@
|
|||||||
########################################################################
|
|
||||||
##
|
|
||||||
## Win32 Usage: makepanda\makedocs.bat
|
|
||||||
## Linux Usage: makepanda/makedocs.py
|
|
||||||
##
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
import sys,os,re
|
|
||||||
sys.path = ["direct/src/directscripts"] + sys.path
|
|
||||||
import gendocs
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
##
|
|
||||||
## Some handy utility functions.
|
|
||||||
##
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
def MakeDirectory(path):
|
|
||||||
if os.path.isdir(path): return 0
|
|
||||||
os.mkdir(path)
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
##
|
|
||||||
## Read the version number from built/include/pandaVersion.h
|
|
||||||
##
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
VERSION="0.0.0"
|
|
||||||
try:
|
|
||||||
f = file("built/include/pandaVersion.h","r")
|
|
||||||
pattern = re.compile('^\s*[#]\s*define\s+PANDA_VERSION_STR\s+["]([0-9.]+)["]')
|
|
||||||
for line in f:
|
|
||||||
match = pattern.match(line,0)
|
|
||||||
if (match):
|
|
||||||
VERSION = match.group(1)
|
|
||||||
break
|
|
||||||
f.close()
|
|
||||||
except: sys.exit("Cannot read version number from built/include/pandaVersion.h")
|
|
||||||
|
|
||||||
print "Generating docs for "+VERSION
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
##
|
|
||||||
## Make sure panda has been built.
|
|
||||||
##
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
if (os.path.isfile("built/pandac/input/libpgraph.in")==0) or (os.path.isfile("built/pandac/input/libputil.in")==0):
|
|
||||||
sys.exit("Cannot read the interrogate-output files in built/pandac/input")
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
##
|
|
||||||
## Generate the PHP version.
|
|
||||||
##
|
|
||||||
## The manual is in the form of a bunch of HTML files that can be
|
|
||||||
## included by a PHP script called "/apiref.php".
|
|
||||||
##
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
MakeDirectory("referphp")
|
|
||||||
gendocs.generate(VERSION, "built/pandac/input", "direct", "referphp", "", "", "/apiref.php?page=", "")
|
|
||||||
|
|
||||||
########################################################################
|
|
||||||
##
|
|
||||||
## Generate the HTML version.
|
|
||||||
##
|
|
||||||
## The manual is in the form of a bunch of standalone HTML files
|
|
||||||
## that contain links to each other.
|
|
||||||
##
|
|
||||||
########################################################################
|
|
||||||
|
|
||||||
HEADER = "<html><head></head><body>\n"
|
|
||||||
FOOTER = "</body></html>\n"
|
|
||||||
|
|
||||||
MakeDirectory("reference")
|
|
||||||
gendocs.generate(VERSION, "built/pandac/input", "direct", "reference", HEADER, FOOTER, "", ".html")
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user