#! /usr/bin/python #+ # NAME: # www_help_dep # PURPOSE: # Provides dependence tree information for # software in the SMEI tree # CALLING SEQUENCE: # www_help_dep -db= -dest= -show # INPUTS: # module name of program, function or procedure # (default: ipsdt) # db.txt name of data base file containing the # dependency information. # (default: for.txt) # (this is created as part of the # www_help system). # name of an empty, existing directory # if specified, this is where copies # of all files are written. # If omitted information is written # to screen only. # -show displays a list of file names on the screen # -html displays html file # LIMITATIONS: # Works for Fortran and IDL code only # PROCEDURE: # MODIFICATION HISTORY: # SEP-2007, Paul Hick (UCSD/CASS) #- import sys, os, cgi csay = 'www_help_dep' # ========== # Reads list of top directories # Entries in tops have the form $NAME=full_directory def read_toplist(file): tops = (open('www_help.lst', 'r')).read().split() for top in tops: name = top.split('=') if file.find(name[0]) == 0: break else: name = file.split('/') print 'Do not know where ',name[0],' is' return '' name = name[1]+file[len(name[0]):] return name def www_help_blank_module(): # Only the following entries are processed for each module blank = dict( { 'file' : '' , 'calls' : '' , 'include': '' , 'external': '' } ) return blank def www_help_get_db(db_file): # Read file with dependence info. Drop trailing empty element after split() db_table = (open(db_file, 'r')).read().split('\n')[0:-1] db = dict() i = 0 n = len(db_table) ndb = 0 # The data base contains groups of elements # module: AdjustJDCar # file: $SMEI/for/lib/adjustjdcar.f # include: sun # external: EARTH # see also: Array_Info # calls: EARTH,FLINT8,Julian,MAP_TZERO,N_CARRINGTON # The "module" and "file" elements are always present (name of # function/subroutine/procedure, and the file that contains it) # The others are not always present. while i < n: # Split at semi-colon key, line = db_table[i].split(':') line = line.strip() if key == 'module': # New module found # Add completed module to db if ndb > 0: db[module] = module_dict # Start a new entry ndb += 1 module = line module_dict = www_help_blank_module() else: # Process module elements if module_dict.has_key(key): if line != '(none)': # Add another element to the module if module_dict[key] == '': module_dict[key] = line else: module_dict[key] += ','+line # Next line in db_table i += 1 # Add the last module if ndb > 0: db[module] = module_dict return db if __name__ == '__main__': form = cgi.FieldStorage() if form.has_key('html'): sys.stderr = sys.stdout print 'Content-type: text/html\n' html = True top_module = form['html'].value db_file = form['db' ].value db_top = read_toplist('$DB') db_file = os.path.join( db_top, db_file[len('$DB')+1:] ) else: import tiny args = tiny.args(sys.argv) if len(args) == 1: top_module = 'ipsdt' else: top_module = args[1] show = tiny.is_there('-show',sys.argv) html = tiny.is_there('-html',sys.argv) db_file = tiny.start('-db=',sys.argv) if db_file == '': db_file = os.path.join(os.environ['HOME'],'public_html','help','smei','for.txt') if not os.path.exists(db_file): tiny.say(csay, 'E', db_file, 'file does not exist') sys.exit(1) destination = tiny.start('-dest=',sys.argv) if destination != '': if not os.path.isdir(destination): tiny.say(csay, 'E', destination, 'directory does not exist') sys.exit(1) if len(os.listdir(destination)) != 0: tiny.say(csay, 'E', destination, 'directory is not empty') sys.exit(1) # Get the list of module with dependency info # (calls, external, include) db = www_help_get_db(db_file) if not db.has_key(top_module): if html: print 'top module not found: '+top_module else: tiny.say(csay, 'E',top_module, 'top module not found') all_modules = [top_module] all_pairs = [] i = 0 while i < len(all_modules): module = all_modules[i] # Next module to be checked if db.has_key(module): # Check if module in db # If module in data base append pair # (module name, file name) to all_pairs list all_pairs.append( (module,db[module]['file']) ) # Accumulate all dependencies in add_modules add_modules = [] tmp = db[module]['calls'] if tmp != '': add_modules.extend( tmp.split(',') ) tmp = db[module]['include'] if tmp != '': add_modules.extend( tmp.split(',') ) tmp = db[module]['external'] if tmp != '': add_modules.extend( tmp.split(',') ) # Add new modules to all_modules for new_module in add_modules: if all_modules.count(new_module) == 0: all_modules.append(new_module) else: all_pairs.append( (module,'') ) i +=1 # Pick up Fits functions fits_archive = '$SMEI/cpp/cfitsio3030/cfitsio3030.tar.gz' fits = [] # List of Fits functions i = 0 while i < len(all_pairs): pair = all_pairs[i] if (os.path.split(pair[1]))[1] == 'forfits.f': fits.append(pair[0]) # Name of Fits function del all_pairs[i] else: i += 1 # Pick up include files. The file names are accumulated in # the incl list. incl = [] i = 0 while i < len(all_pairs): pair = all_pairs[i] if (os.path.splitext(pair[1]))[1] == '.h': incl.append(pair[1]) del all_pairs[i] else: i += 1 # Pick up unresolved references. # BListFnc and BReadFnc don't really exist. anon = [] i = 0 while i < len(all_pairs): pair = all_pairs[i] if pair[1] == '': if pair[0] != 'BListFnc' and pair[0] != 'BReadFnc': anon.append(pair[0]) del all_pairs[i] else: i += 1 # Accumulate all the file names in all_pairs # (note that include files are not present anymore) all_files = [] for pair in all_pairs: if all_files.count(pair[1]) == 0: all_files.append(pair[1]) # If forfits.f is on the list then apparently Fits # routines are being used. # Replace with the Fits tar archive. if len(fits) > 0: all_files.append(fits_archive) # Remove logmod.f (logmod_linux.f should be on the # list already. this = '$SMEI/ucsd/gen/for/os/logmod.f' if all_files.count(this) != 0: all_files.remove(this) if html: print '\n' \ '\n' \ 'www_help dependencies, version 2.6\n' \ '\n\n' \ '\n\n' \ '
\n\n' print '\n' \ '' print ' ' \ %(top_module,len(all_modules),len(all_files)) print '\n' \ '
%s uses %d modules from %d files
\n' \ '
\n\n' print '' for pair in all_pairs: print '' print ' '%pair[0] print ' '%pair[1] print '' print '
%s%s
\n\n' if len(incl) > 0: print '
\n' \ '\n'\ '' print ' '% \ (top_module,len(incl)) print '\n' \ '
%s depends on %d include files
\n\n' print '
\n' \ '' for this in incl: print '' print ' '%this print '' print '
%s
\n\n' if len(anon) > 0: print '
\n' \ '\n' \ '' print ' '% \ (top_module,len(anon)) print '\n' \ '
%s has %d unresolved reference
\n\n' print '
\n' \ '' for this in anon: print '' print ' '%this print '' print '
%s
\n\n' if len(fits) > 0: print '
\n' \ '\n' \ '' print ' '% \ (top_module,len(fits),fits_archive) print '\n' \ '
%s depends on %d Fits routines from %s
\n\n' print '
\n' \ '' for this in fits: print '' print ' '%this print '' print '
%s
\n\n' print '
\n\n' \ '\n' \ '\n' elif destination != '': # Add include files to all_files list for f in incl: all_files.append(f) for f in all_files: near_file = os.path.expandvars(f) far_file = os.path.join(destination,os.path.basename(near_file)) sts = os.spawnlp(os.P_WAIT, 'cp','cp','-vpf', near_file, far_file) anon_file = os.path.join(destination,'anon.txt') anon = '\n'.join(anon)+'\n' open(anon_file,'w').write(anon) tiny.say(csay,'I','total', '%d modules in %d files'%(len(all_modules),len(all_files))) elif show: for pair in all_pairs: print '%-30s %s'%pair for this in incl: print '%-30s %s'%('',this) for this in anon: tiny.say(csay,'W','module not found,', this) tiny.say(csay,'I','total', '%d modules in %d files'%(len(all_modules),len(all_files))) else: for this in anon: tiny.say(csay,'W','module not found,', this) tiny.say(csay,'I','total', '%d modules in %d files'%(len(all_modules),len(all_files))) sys.exit(0)