#! /usr/bin/python
# see main function at bottom of file
"""
Version 1.0 written by Randy Phillips September 2001
Copyright 2001 El Paso Energy, Inc. All Rights Reserved
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Author contact information: randy-san@users.sourceforge.net
"""
import os, sys, string, time
class ViewInfo:
def __init__(self):
self.viewName = ""
self.lineNumber = -1
self.whereUsed = {} # file name key, fileInfo and line number list
self.uniqueNumber = 0 # used to create unique file name for where used list
self.parent = None
class FunctionInfo:
def __init__(self):
self.functionName = ""
self.lineNumber = -1
self.whereUsed = {} # file name key, fileInfo and line number list
self.uniqueNumber = 0 # used to create unique file name for where used list
self.parent = None
class ProcedureInfo:
def __init__(self):
self.procedureName = ""
self.lineNumber = -1
self.whereUsed = {} # file name key, fileInfo and line number list
self.uniqueNumber = 0 # used to create unique file name for where used list
self.parent = None
class PackageInfo:
def __init__(self):
self.packageName = ""
self.lineNumber = -1
self.functionInfoList = []
self.procedureInfoList = []
self.whereUsed = {} # file name key, fileInfo and line number list
self.uniqueNumber = 0 # used to create unique file name for where used list
self.parent = None
class FileInfo:
def __init__(self):
self.fileName = ""
self.fileType = "" # cpp files are only scanned for sql "where used" information
self.viewInfoList = []
self.packageInfoList = []
self.uniqueNumber = 0 # used to create unique file name for where used list
class MetaInfo:
def __init__(self):
self.fileInfoList = []
self.fileWithPathnamesIndex_FileName = ""
self.fileNoPathnamesIndex_FileName = ""
self.viewIndex_FileName = ""
self.packageIndex_FileName = ""
self.functionIndex_FileName = ""
self.procedureIndex_FileName = ""
self.packageFuncProdIndex_FileName = ""
self.scriptName = ""
self.htmlDir = ""
self.versionString = ""
self.toDoList = ""
self.indexForWhereUsedFiles = 0
def NextIndex(self):
"""Used to generate unique file names for where used indices"""
self.indexForWhereUsedFiles += 1
return self.indexForWhereUsedFiles
def TupleCompareFirstElements(a, b):
""" used for sorting list of tuples by values of first elements in the tuples"""
if a[0] < b[0]:
return -1
if a[0] > b[0]:
return 1
return 0
def CaseInsensitiveComparison(a, b):
""" used for case insensitive string sorts"""
if a.upper() < b.upper():
return -1
if a.upper() > b.upper():
return 1
return 0
def FindFilesAndBuildFileList(dir, fileInfoList, meta_info):
# get a list of this directory's contents
# these items are relative and not absolute
names=os.listdir(dir)
# iterate through this list
for i in names:
if i == "RCS": # do not look in RCS
continue
if i == "old_directories": # do not look in old directories
continue
# convert from relative to absolute addressing
# to allow recursive calls
f1=os.path.join(dir, i)
# if this item is also a directory, recurse it too
if os.path.isdir(f1):
FindFilesAndBuildFileList(f1, fileInfoList, meta_info)
# file found, only add specific file extensions to the list
else:
if f1[len(f1)-4:] == ".sql" or f1[len(f1)-4:] == ".bdy" or f1[len(f1)-3:] == ".qf":
temp = FileInfo()
temp.fileName = f1
temp.fileType = "sql"
if temp.uniqueNumber == 0:
temp.uniqueNumber = meta_info.NextIndex()
fileInfoList.append(temp)
if f1[len(f1)-2:] == ".C" or f1[len(f1)-2:] == ".c" or f1[len(f1)-2:] == ".cpp":
temp = FileInfo()
temp.fileName = f1
temp.fileType = "cpp"
if temp.uniqueNumber == 0:
temp.uniqueNumber = meta_info.NextIndex()
fileInfoList.append(temp)
def ScanFilesForViewsAndPackages(meta_info):
fileInfoList = meta_info.fileInfoList
# first, find views in files
dot_count = 1
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
# print a . every file
sys.stdout.write(".")
sys.stdout.flush()
if (dot_count % 60) == 0: # carriage return every 60 dots
print
sys.stdout.flush()
dot_count += 1
infile = open(file_info.fileName, "r")
fileLines = infile.readlines()
infile.close()
# if we find a package definition, this flag tells us to also look for
# functions and procedures. If we don't find a package definition, there
# is no reason to look for them
package_count = -1
for lineNumber in range(len(fileLines)):
token_list = fileLines[lineNumber].split()
# ignore very short lines
if len(token_list) < 2:
continue
# ignore lines that begin with comments
if token_list[0][:2] == "--" or token_list[0][:2] == "//" or token_list[0][:2] == "##":
continue
# find views. Loop through looking for the different styles of view definition
for token_index in range(len(token_list)):
# look for CREATE VIEW, REPLACE VIEW, FORCE VIEW, making sure enough tokens exist
if len(token_list) > token_index+1 \
and token_list[token_index+1].upper() == "VIEW" \
and (token_list[token_index].upper() == "CREATE" \
or token_list[token_index].upper() == "REPLACE" \
or token_list[token_index].upper() == "FORCE"):
view_info = ViewInfo()
view_info.parent = file_info
view_info.viewName = token_list[token_index+2]
view_info.lineNumber = lineNumber
file_info.viewInfoList.append(view_info)
# find package definitions - set flag if found
# look for PACKAGE BODY x, making sure enough tokens exist
for token_index in range(len(token_list)):
if len(token_list) > token_index+2 \
and token_list[token_index].upper() == "PACKAGE" \
and token_list[token_index+1].upper() == "BODY":
package_info = PackageInfo()
package_info.parent = file_info
package_info.packageName = token_list[token_index+2]
package_info.lineNumber = lineNumber
file_info.packageInfoList.append(package_info) # permanent storage
package_count += 1 # use this flag below
# if a package definition was found, look for functions and procedures
if package_count != -1:
# first find functions
if len(token_list) > 1 and token_list[0].upper() == "FUNCTION":
function_name = token_list[1].split('(')[0] # some are "name(" and some are "name ("
function_info = FunctionInfo()
function_info.parent = file_info.packageInfoList[package_count]
function_info.functionName = function_name
function_info.lineNumber = lineNumber
file_info.packageInfoList[package_count].functionInfoList.append(function_info)
# now find procedures
if len(token_list) > 1 and token_list[0] == "PROCEDURE":
procedure_name = token_list[1].split('(')[0] # some are "name(" and some are "name ("
procedure_info = ProcedureInfo()
procedure_info.parent = file_info.packageInfoList[package_count]
procedure_info.procedureName = procedure_name
procedure_info.lineNumber = lineNumber
file_info.packageInfoList[package_count].procedureInfoList.append(procedure_info)
# print carriage return after last dot
print
def ScanFilesForWhereViewsAndPackagesAreUsed(meta_info):
fileInfoList = meta_info.fileInfoList
outerfileInfoList = []
for file_info in fileInfoList:
outerfileInfoList.append(file_info)
dot_count = 1
for outer_file_info in outerfileInfoList:
# print a . every file
sys.stdout.write(".")
sys.stdout.flush()
if (dot_count % 60) == 0: # carriage return every 60 dots
print
sys.stdout.flush()
dot_count += 1
infile = open(outer_file_info.fileName, "r")
fileLines = infile.readlines()
infile.close()
# if we find a package definition, this flag tells us to also look for
# functions and procedures. If we don't find a package definition, there
# is no reason to look for them
package_count = -1
for lineNumber in range(len(fileLines)):
token_list = fileLines[lineNumber].split()
# ignore very short lines
if len(token_list) < 2:
continue
# ignore lines that begin with comments
if token_list[0][:2] == "--" or token_list[0][:2] == "//" or token_list[0][:2] == "##":
continue
# usage only, no creates, replace, force views packages functions or procedures
usage_flag = 1
for token_index in range(len(token_list)):
# look for CREATE VIEW, REPLACE VIEW, FORCE VIEW, making sure enough tokens exist
if len(token_list) > token_index+1 \
and token_list[token_index+1].upper() == "VIEW" \
and (token_list[token_index].upper() == "CREATE" \
or token_list[token_index].upper() == "REPLACE" \
or token_list[token_index].upper() == "FORCE"):
# we are creating, forcing, or replacing - not using. Set flag to 0
usage_flag = 0
# look for PACKAGE BODY x IS, making sure enough tokens exist
if token_list[token_index].upper() == "PACKAGE" \
and len(token_list) > token_index+2 \
and token_list[token_index+1].upper() == "BODY":
package_count += 1 # set flag
usage_flag = 0
# if a package definition was found, look for functions and procedures
if package_count != -1:
# first find functions
if token_list[0] == "FUNCTION" and len(token_list) > 1:
usage_flag = 0
# now find procedures
if token_list[0] == "PROCEDURE" and len(token_list) > 1:
usage_flag = 0
if usage_flag == 0:
continue
# Loop through all previously found views and packages to see if they are used in this line of text
for inner_file_info in fileInfoList:
# if this FileInfo instance has views
if len(inner_file_info.viewInfoList) != 0:
for view_info in inner_file_info.viewInfoList:
# perform case insensitive find
if fileLines[lineNumber].upper().find(view_info.viewName.upper()) != -1:
if outer_file_info.fileName not in view_info.whereUsed.keys():
view_info.whereUsed[outer_file_info.fileName] = []
view_info.whereUsed[outer_file_info.fileName].append((outer_file_info, lineNumber))
else:
view_info.whereUsed[outer_file_info.fileName].append((outer_file_info, lineNumber))
# generate a unique number for use in making where used file if needed
if view_info.uniqueNumber == 0:
view_info.uniqueNumber = meta_info.NextIndex()
# if this FileInfo instance has packages
if len(inner_file_info.packageInfoList) != 0:
for package_info in inner_file_info.packageInfoList:
# perform case insensitive find, this is "package name"."function or procedure name"
if fileLines[lineNumber].upper().find(package_info.packageName.upper() + ".") != -1:
if outer_file_info.fileName not in package_info.whereUsed.keys():
package_info.whereUsed[outer_file_info.fileName] = []
package_info.whereUsed[outer_file_info.fileName].append((outer_file_info, lineNumber))
else:
package_info.whereUsed[outer_file_info.fileName].append((outer_file_info, lineNumber))
# generate a unique number for use in making where used file if needed
if package_info.uniqueNumber == 0:
package_info.uniqueNumber = meta_info.NextIndex()
#look for any of this packages' functions
for function_info in package_info.functionInfoList:
# perform case insensitive find
if fileLines[lineNumber].upper().find(package_info.packageName.upper() + "." \
+ function_info.functionName.upper()) != -1:
if outer_file_info.fileName not in function_info.whereUsed.keys():
function_info.whereUsed[outer_file_info.fileName] = []
function_info.whereUsed[outer_file_info.fileName].append((outer_file_info, lineNumber))
else:
function_info.whereUsed[outer_file_info.fileName].append((outer_file_info, lineNumber))
# generate a unique number for use in making where used file if needed
if function_info.uniqueNumber == 0:
function_info.uniqueNumber = meta_info.NextIndex()
#look for any of this packages procedures
for procedure_info in package_info.procedureInfoList:
# perform case insensitive find
if fileLines[lineNumber].upper().find(package_info.packageName.upper() + "." \
+ procedure_info.procedureName.upper()) != -1:
if outer_file_info.fileName not in procedure_info.whereUsed.keys():
procedure_info.whereUsed[outer_file_info.fileName] = []
procedure_info.whereUsed[outer_file_info.fileName].append((outer_file_info, lineNumber))
else:
procedure_info.whereUsed[outer_file_info.fileName].append((outer_file_info, lineNumber))
# generate a unique number for use in making where used file if needed
if procedure_info.uniqueNumber == 0:
procedure_info.uniqueNumber = meta_info.NextIndex()
# print carriage return after last dot
print
def MakeHTMLHeader(meta_info):
"""Allows for common header with menu for all pages"""
s = '
\n' # white background on all pages
s += "\n"
s += 'Package Index \n'
s += 'Function Index \n'
s += 'Procedure Index \n'
s += 'Full Package Listing \n'
s += "
\n"
s += 'View Index \n'
s += 'File Name Index \n'
s += 'File Names by Path Index \n'
s += 'HyperSQL Home Page \n'
s += "\n"
s += "
\n"
return s
def MakeHTMLFooter():
"""Allows for common footer on all pages"""
s = "
\n"
s += "\n"
s += 'Home\n'
s += "\n"
s += ""
return s
def CreateHTMLDirectory(metaInfo):
# create the html directory if needed
splitted = metaInfo.htmlDir.split(os.sep)
temp = ""
for path_element in splitted: # loop through path components, making directories as needed
temp += path_element + os.sep
if os.access(temp, os.F_OK) == 1:
continue
else:
os.mkdir(temp)
def MakeFileIndexWithPathNames(meta_info):
fileInfoList = meta_info.fileInfoList
html_dir = meta_info.htmlDir
outfilename = meta_info.fileWithPathnamesIndex_FileName
filenametuplelist = []
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
filenametuplelist.append((file_info.fileName.upper(), file_info))
filenametuplelist.sort(TupleCompareFirstElements)
outfile = open(html_dir + outfilename, "w")
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("Index Of All Files By Path Name
\n")
for filenametuple in filenametuplelist:
file_name = filenametuple[1].fileName
temp = os.path.split(file_name)[1].replace(".", "_")
temp += "_" + `filenametuple[1].uniqueNumber` + ".html"
outfile.write("" + file_name[len(meta_info.topLevelDirectory)+1:])
outfile.write("
\n")
outfile.write(MakeHTMLFooter())
outfile.close()
def MakeFileIndexNoPathNames(meta_info):
fileInfoList = meta_info.fileInfoList
html_dir = meta_info.htmlDir
outfilename = meta_info.fileNoPathnamesIndex_FileName
filenametuplelist = []
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
filenametuplelist.append((os.path.split(file_info.fileName)[1].upper(), file_info))
filenametuplelist.sort(TupleCompareFirstElements)
outfile = open(html_dir + outfilename, "w")
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("Index Of All Files By File Name
\n")
for filenametuple in filenametuplelist:
file_name = filenametuple[1].fileName
temp = os.path.split(file_name)[1].replace(".", "_")
temp += "_" + `filenametuple[1].uniqueNumber` + ".html"
outfile.write("" + os.path.split(file_name)[1])
outfile.write("
\n")
outfile.write(MakeHTMLFooter())
outfile.close()
def MakeViewIndex(meta_info):
fileInfoList = meta_info.fileInfoList
html_dir = meta_info.htmlDir
outfilename = meta_info.viewIndex_FileName
top_level_directory = meta_info.topLevelDirectory
viewtuplelist = []
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
for view_info in file_info.viewInfoList:
viewtuplelist.append((view_info.viewName.upper(), view_info, file_info)) # append as tuple for case insensitive sort
viewtuplelist.sort(TupleCompareFirstElements)
outfile = open(html_dir + outfilename, "w")
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("Index Of All Views
\n")
for view_tuple in viewtuplelist: # list of tuples describing every view
# file name and line number as an HTML reference
HTMLref = os.path.split(view_tuple[2].fileName)[1].replace(".", "_")
HTMLref += "_" + `view_tuple[2].uniqueNumber` + ".html"
HTMLref += "#" + `view_tuple[1].lineNumber`
outfile.write("" + view_tuple[1].viewName.lower() + "\n")
if len(view_tuple[1].whereUsed.keys()) > 0:
HTMLwhereusedref = "where_used_" + `view_tuple[1].uniqueNumber` + ".html"
outfile.write(" - where used list\n")
else:
outfile.write(" - no use found by HyperSQL\n")
outfile.write("
\n")
outfile.write(MakeHTMLFooter())
outfile.close()
def MakePackageIndex(meta_info):
fileInfoList = meta_info.fileInfoList
html_dir = meta_info.htmlDir
outfilename = meta_info.packageIndex_FileName
top_level_directory = meta_info.topLevelDirectory
packagetuplelist = []
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
for package_info in file_info.packageInfoList:
packagetuplelist.append((package_info.packageName.upper(), package_info, file_info)) # append as tuple for case insensitive sort
packagetuplelist.sort(TupleCompareFirstElements)
outfile = open(html_dir + outfilename, "w")
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("Index Of All Packages
\n")
for package_tuple in packagetuplelist: # list of tuples describing every package
# file name and line number as an HTML reference
HTMLref = os.path.split(package_tuple[2].fileName)[1].replace(".", "_")
HTMLref += "_" + `package_tuple[2].uniqueNumber` + ".html"
HTMLref += "#" + `package_tuple[1].lineNumber`
outfile.write("" + package_tuple[1].packageName.lower() + "\n")
if len(package_tuple[1].whereUsed.keys()) > 0:
HTMLwhereusedref = "where_used_" + `package_tuple[1].uniqueNumber` + ".html"
outfile.write(" - where used list\n")
else:
outfile.write(" - no use found by HyperSQL\n")
outfile.write("
\n")
outfile.write(MakeHTMLFooter())
outfile.close()
def MakeFunctionIndex(meta_info):
fileInfoList = meta_info.fileInfoList
html_dir = meta_info.htmlDir
outfilename = meta_info.functionIndex_FileName
top_level_directory = meta_info.topLevelDirectory
functiontuplelist = []
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
for package_info in file_info.packageInfoList:
for function_info in package_info.functionInfoList:
functiontuplelist.append((function_info.functionName.upper(), function_info, file_info, package_info)) # append as tuple for case insensitive sort
functiontuplelist.sort(TupleCompareFirstElements)
outfile = open(html_dir + outfilename, "w")
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("Index Of All Functions
\n")
for function_tuple in functiontuplelist: # list of tuples describing every function
# file name and line number as an HTML reference
HTMLref = os.path.split(function_tuple[2].fileName)[1].replace(".", "_")
HTMLref += "_" + `function_tuple[2].uniqueNumber` + ".html"
HTMLref += "#" + `function_tuple[1].lineNumber`
outfile.write("" + function_tuple[1].functionName.lower())
outfile.write(" - from package " + function_tuple[3].packageName.lower() + "\n")
if len(function_tuple[1].whereUsed.keys()) > 0:
HTMLwhereusedref = "where_used_" + `function_tuple[1].uniqueNumber` + ".html"
outfile.write(" - where used list\n")
else:
outfile.write(" - no use found by HyperSQL\n")
outfile.write("
\n")
outfile.write(MakeHTMLFooter())
outfile.close()
def MakeProcedureIndex(meta_info):
fileInfoList = meta_info.fileInfoList
html_dir = meta_info.htmlDir
outfilename = meta_info.procedureIndex_FileName
top_level_directory = meta_info.topLevelDirectory
proceduretuplelist = []
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
for package_info in file_info.packageInfoList:
for procedure_info in package_info.procedureInfoList:
proceduretuplelist.append((procedure_info.procedureName.upper(), procedure_info, file_info, package_info)) # append as tuple for case insensitive sort
proceduretuplelist.sort(TupleCompareFirstElements)
outfile = open(html_dir + outfilename, "w")
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("Index Of All Procedures
\n")
for procedure_tuple in proceduretuplelist: # list of tuples describing every function
# file name and line number as an HTML reference
HTMLref = os.path.split(procedure_tuple[2].fileName)[1].replace(".", "_")
HTMLref += "_" + `procedure_tuple[2].uniqueNumber` + ".html"
HTMLref += "#" + `procedure_tuple[1].lineNumber`
outfile.write("" + procedure_tuple[1].procedureName.lower())
outfile.write(" - from package " + procedure_tuple[3].packageName.lower() + "\n")
if len(procedure_tuple[1].whereUsed.keys()) > 0:
HTMLwhereusedref = "where_used_" + `procedure_tuple[1].uniqueNumber` + ".html"
outfile.write(" - where used list\n")
else:
outfile.write(" - no use found by HyperSQL\n")
outfile.write("
\n")
outfile.write(MakeHTMLFooter())
outfile.close()
def MakePackagesWithFuncsAndProcsIndex(meta_info):
fileInfoList = meta_info.fileInfoList
html_dir = meta_info.htmlDir
outfilename = meta_info.packageFuncProdIndex_FileName
top_level_directory = meta_info.topLevelDirectory
packagetuplelist = []
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
for package_info in file_info.packageInfoList:
packagetuplelist.append((package_info.packageName.upper(), package_info, file_info)) # append as tuple for case insensitive sort
packagetuplelist.sort(TupleCompareFirstElements)
outfile = open(html_dir + outfilename, "w")
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("Index Of All Packages, Their Functions And Procedures
\n")
for package_tuple in packagetuplelist:
# file name and line number as an HTML reference
HTMLref = os.path.split(package_tuple[2].fileName)[1].replace(".", "_")
HTMLref += "_" + `package_tuple[2].uniqueNumber` + ".html"
HTMLref += "#" + `package_tuple[1].lineNumber`
outfile.write("
" + package_tuple[1].packageName.lower() + "\n")
if len(package_tuple[1].whereUsed.keys()) > 0:
HTMLwhereusedref = "where_used_" + `package_tuple[1].uniqueNumber` + ".html"
outfile.write(" - where used list\n")
else:
outfile.write(" - no use found by HyperSQL\n")
outfile.write("
\n")
# functions in this package
functiontuplelist = []
for function_info in package_tuple[1].functionInfoList:
functiontuplelist.append((function_info.functionName.upper(), function_info, package_tuple[2])) # append as tuple for case insensitive sort
functiontuplelist.sort(TupleCompareFirstElements)
if len(functiontuplelist) != 0:
outfile.write(" Functions:
\n")
for function_tuple in functiontuplelist:
HTMLref = os.path.split(function_tuple[2].fileName)[1].replace(".", "_")
HTMLref += "_" + `function_tuple[2].uniqueNumber` + ".html"
HTMLref += "#" + `function_tuple[1].lineNumber`
outfile.write(" ")
outfile.write("" + function_tuple[1].functionName.lower() + "\n")
if len(function_tuple[1].whereUsed.keys()) > 0:
HTMLwhereusedref = "where_used_" + `function_tuple[1].uniqueNumber` + ".html"
outfile.write(" - where used list\n")
else:
outfile.write(" - no use found by HyperSQL\n")
outfile.write("
\n")
# procedures in this package
proceduretuplelist = []
for procedure_info in package_tuple[1].procedureInfoList:
proceduretuplelist.append((procedure_info.procedureName.upper(), procedure_info, package_tuple[2])) # append as tuple for case insensitive sort
proceduretuplelist.sort(TupleCompareFirstElements)
if len(proceduretuplelist) != 0:
outfile.write(" Procedures:
\n")
for procedure_tuple in proceduretuplelist:
HTMLref = os.path.split(procedure_tuple[2].fileName)[1].replace(".", "_")
HTMLref += "_" + `procedure_tuple[2].uniqueNumber` + ".html"
HTMLref += "#" + `procedure_tuple[1].lineNumber`
outfile.write(" ")
outfile.write("" + procedure_tuple[1].procedureName.lower() + "\n")
if len(procedure_tuple[1].whereUsed.keys()) > 0:
HTMLwhereusedref = "where_used_" + `procedure_tuple[1].uniqueNumber` + ".html"
outfile.write(" - where used list\n")
else:
outfile.write(" - no use found by HyperSQL\n")
outfile.write("
\n")
outfile.write(MakeHTMLFooter())
outfile.close()
def CreateHyperlinkedSourceFilePages(meta_info):
fileInfoList = meta_info.fileInfoList
html_dir = meta_info.htmlDir
top_level_directory = meta_info.topLevelDirectory
dot_count = 1
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
# print a . every file
sys.stdout.write(".")
sys.stdout.flush()
if (dot_count % 60) == 0: # carriage return every 60 dots
print
sys.stdout.flush()
dot_count += 1
# read up the source file
infile = open(file_info.fileName, "r")
infile_line_list = infile.readlines()
infile.close()
# generate a file name for us to write to (+1 for delimiter)
outfilename = os.path.split(file_info.fileName)[1].replace(".", "_")
outfilename += "_" + `file_info.uniqueNumber` + ".html"
# we need leading zeroes for the line numbers
line_number_width = len(`len(infile_line_list)`) # number of chars in "number of lines of text"
outfile = open(html_dir + outfilename, "w")
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("" + file_info.fileName[len(top_level_directory)+1:] + "
\n")
# use non-linw-wrapping monospaced font, text is preformatted in terms of whitespace
outfile.write('
')
for line_number in range(len(infile_line_list)):
zeroes = (1 + line_number_width - len(`line_number`)) * "0" # leading zeroes for line numbers
outfile.write("") # hyperlink target
outfile.write(zeroes + `line_number` + ": " + infile_line_list[line_number]) #text
outfile.write("
")
outfile.write(MakeHTMLFooter())
outfile.close()
# print carriage return after last dot
print
def CreateIndexPage(meta_info):
html_dir = meta_info.htmlDir
script_name = meta_info.scriptName
outfile = open(html_dir + 'index.html', "w")
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("Premier HyperSQL Home Page
\n")
# Copy this script over to the HTML directory and link to it
script_name_no_path = os.path.split(script_name)[1] # os.sep is path delimiter
scriptinfile = open(script_name, "r")
scriptoutfile = open(html_dir + script_name_no_path, "w")
scriptoutfile.write(scriptinfile.read())
scriptoutfile.close()
scriptinfile.close()
outfile.write('Here is the current (version ' + meta_info.versionString + ') ')
outfile.write('HypersSQL Source Code, written in Python\n')
outfile.write("
\n")
outfile.write("" + metaInfo.toDoList + "
\n")
outfile.write("
\n")
outfile.write("This instance of Premier HyperSQL was generated " + time.asctime(time.localtime(time.time())) + '\n')
outfile.write(MakeHTMLFooter())
outfile.close()
def CreateWhereUsedPages(meta_info):
html_dir = meta_info.htmlDir
fileInfoList = meta_info.fileInfoList
# loop through files
dot_count = 1
for file_info in fileInfoList:
# skip all non-sql files
if file_info.fileType != "sql":
continue
# print a . every file
sys.stdout.write(".")
sys.stdout.flush()
if (dot_count % 60) == 0: # carriage return every 60 dots
print
sys.stdout.flush()
dot_count += 1
# loop through views
for view_info in file_info.viewInfoList:
if len(view_info.whereUsed.keys()) == 0:
continue
#open a "where used" file
whereusedfilename = "where_used_" + `view_info.uniqueNumber` + ".html"
outfile = open(html_dir + whereusedfilename, "w")
# write our header
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("" + view_info.viewName + " Where Used List
\n")
# each where used
where_used_keys = view_info.whereUsed.keys()
where_used_keys.sort(CaseInsensitiveComparison)
for key in where_used_keys:
for whereusedtuple in view_info.whereUsed[key]:
line_number = whereusedtuple[1]
unique_number = whereusedtuple[0].uniqueNumber
# only make hypertext references for SQL files for now
if whereusedtuple[0].fileType == "sql":
outfile.write("\n")
outfile.write(key[len(top_level_directory)+1:] + " line " + `line_number` + "
\n")
else:
outfile.write(key[len(top_level_directory)+1:] + " line " + `line_number` + "
\n")
# footer and close
outfile.write(MakeHTMLFooter())
outfile.close()
for package_info in file_info.packageInfoList:
if len(package_info.whereUsed.keys()) == 0:
continue
#open a "where used" file
whereusedfilename = "where_used_" + `package_info.uniqueNumber` + ".html"
outfile = open(html_dir + whereusedfilename, "w")
# write our header
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("" + package_info.packageName + " Where Used List
\n")
# each where used
where_used_keys = package_info.whereUsed.keys()
where_used_keys.sort(CaseInsensitiveComparison)
for key in where_used_keys:
for whereusedtuple in package_info.whereUsed[key]:
line_number = whereusedtuple[1]
unique_number = whereusedtuple[0].uniqueNumber
# only make hypertext references for SQL files for now
if whereusedtuple[0].fileType == "sql":
outfile.write("\n")
outfile.write(key[len(top_level_directory)+1:] + " line " + `line_number` + "
\n")
else:
outfile.write(key[len(top_level_directory)+1:] + " line " + `line_number` + "
\n")
# footer and close
outfile.write(MakeHTMLFooter())
outfile.close()
#look for any of this packages' functions
for function_info in package_info.functionInfoList:
if len(function_info.whereUsed.keys()) == 0:
continue
#open a "where used" file
whereusedfilename = "where_used_" + `function_info.uniqueNumber` + ".html"
outfile = open(html_dir + whereusedfilename, "w")
# write our header
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("" + function_info.functionName.lower() + " from " + package_info.packageName)
outfile.write(" Where Used List
\n")
# each where used
where_used_keys = function_info.whereUsed.keys()
where_used_keys.sort(CaseInsensitiveComparison)
for key in where_used_keys:
for whereusedtuple in function_info.whereUsed[key]:
line_number = whereusedtuple[1]
unique_number = whereusedtuple[0].uniqueNumber
# only make hypertext references for SQL files for now
if whereusedtuple[0].fileType == "sql":
outfile.write("\n")
outfile.write(key[len(top_level_directory)+1:] + " line " + `line_number` + "
\n")
else:
outfile.write(key[len(top_level_directory)+1:] + " line " + `line_number` + "
\n")
# footer and close
outfile.write(MakeHTMLFooter())
outfile.close()
#look for any of this packages procedures
for procedure_info in package_info.procedureInfoList:
if len(procedure_info.whereUsed.keys()) == 0:
continue
#open a "where used" file
whereusedfilename = "where_used_" + `procedure_info.uniqueNumber` + ".html"
outfile = open(html_dir + whereusedfilename, "w")
# write our header
outfile.write(MakeHTMLHeader(meta_info))
outfile.write("" + procedure_info.procedureName.lower() + " from " + package_info.packageName.lower())
outfile.write(" Where Used List
\n")
# each where used
where_used_keys = procedure_info.whereUsed.keys()
where_used_keys.sort(CaseInsensitiveComparison)
for key in where_used_keys:
for whereusedtuple in procedure_info.whereUsed[key]:
line_number = whereusedtuple[1]
unique_number = whereusedtuple[0].uniqueNumber
# only make hypertext references for SQL files for now
if whereusedtuple[0].fileType == "sql":
outfile.write("\n")
outfile.write(key[len(top_level_directory)+1:] + " line " + `line_number` + "
\n")
else:
outfile.write(key[len(top_level_directory)+1:] + " line " + `line_number` + "
\n")
# footer and close
outfile.write(MakeHTMLFooter())
outfile.close()
# print carriage return after last dot
print
if __name__ == "__main__":
# This is the directory under which all files will be scanned
top_level_directory = "g:\\home\\jrp4609\\nightly_build_directory"
# This holds top-level meta information, i.e., lists of filenames, etc.
metaInfo = MetaInfo()
metaInfo.fileWithPathnamesIndex_FileName = "FileNameIndexWithPathnames.html"
metaInfo.fileNoPathnamesIndex_FileName = "FileNameIndexNoPathnames.html"
metaInfo.viewIndex_FileName = "ViewIndex.html"
metaInfo.packageIndex_FileName = "PackageIndex.html"
metaInfo.functionIndex_FileName = "FunctionIndex.html"
metaInfo.procedureIndex_FileName = "ProcedureIndex.html"
metaInfo.packageFuncProdIndex_FileName = "PackagesWithFuncsAndProcsIndex.html"
metaInfo.topLevelDirectory = top_level_directory
metaInfo.scriptName = sys.argv[0]
metaInfo.htmlDir = os.path.split(sys.argv[0])[0] + os.sep + "html" + os.sep
metaInfo.versionString = "1.0"
metaInfo.toDoList = """
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# TO-DO LIST
#
# A) where used does not work for local functions or procedures
# B) block comments are not ignored (/* comment block */)
# C) C++ files need doxygen hyperlinks for where used pages
# D) Scan Java files for where used
#
# If you have an idea for improving hyperSQL, let me know - Randy
#
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
"""
print "Creating file list"
FindFilesAndBuildFileList(metaInfo.topLevelDirectory, metaInfo.fileInfoList, metaInfo)
print "Scanning source files for views and packages"
ScanFilesForViewsAndPackages(metaInfo)
print "Scanning source files for where views and packages are used"
ScanFilesForWhereViewsAndPackagesAreUsed(metaInfo)
print "Creating html subdirectory"
CreateHTMLDirectory(metaInfo)
print "Creating filename by path index"
MakeFileIndexWithPathNames(metaInfo)
print "Creating filename no path index"
MakeFileIndexNoPathNames(metaInfo)
print "Creating view index"
MakeViewIndex(metaInfo)
print "Creating package index"
MakePackageIndex(metaInfo)
print "Creating function index"
MakeFunctionIndex(metaInfo)
print "Creating procedure index"
MakeProcedureIndex(metaInfo)
print "Creating 'package with functions and procedures' index"
MakePackagesWithFuncsAndProcsIndex(metaInfo)
print "Creating 'where used' pages"
CreateWhereUsedPages(metaInfo)
print "Creating hyperlinked source file pages"
CreateHyperlinkedSourceFilePages(metaInfo)
print "Creating site index page"
CreateIndexPage(metaInfo)
print metaInfo.toDoList
print "done"