11b37a2a7SPierre Jolivet#!/usr/bin/env python3 23564227fSBarry Smith""" Loops through all the source using doctext to generate the manual pages""" 33564227fSBarry Smith 43564227fSBarry Smithimport os 53564227fSBarry Smithimport re 63564227fSBarry Smithimport subprocess 73564227fSBarry Smithimport pathlib 83564227fSBarry Smith 93564227fSBarry Smithdef findlmansec(file): 103564227fSBarry Smith mansec = None 113564227fSBarry Smith submansec = None 123564227fSBarry Smith with open(file) as mklines: 133564227fSBarry Smith #print(file) 144b64c689SBarry Smith submansecl = [line for line in mklines if (line.find('SUBMANSEC') > -1 and line.find('BFORT') == -1)] 153564227fSBarry Smith if submansecl: 16*34c645fdSBarry Smith submansec = re.sub(r'[ ]*/\* [ ]*SUBMANSEC[ ]*=[ ]*','',submansecl[0]).strip('\n').strip('*/').strip() 173564227fSBarry Smith if submansec == submansecl[0].strip('\n'): 183564227fSBarry Smith submansec = re.sub('SUBMANSEC[ ]*=[ ]*','',submansecl[0]).strip('\n').strip() 193564227fSBarry Smith #print(':SUBMANSEC:'+submansec) 203564227fSBarry Smith return submansec 213564227fSBarry Smith with open(file) as mklines: 223564227fSBarry Smith mansecl = [line for line in mklines if line.startswith('MANSEC')] 233564227fSBarry Smith if mansecl: 243564227fSBarry Smith mansec = re.sub('MANSEC[ ]*=[ ]*','',mansecl[0]).strip('\n').strip() 253564227fSBarry Smith #print(':MANSEC:'+mansec) 263564227fSBarry Smith return mansec 273564227fSBarry Smith return None 283564227fSBarry Smith 293564227fSBarry Smithdef processdir(petsc_dir, dir, doctext): 303564227fSBarry Smith '''Runs doctext on each source file in the directory''' 313564227fSBarry Smith #print('Processing '+dir) 323564227fSBarry Smith #print('build_man_pages: Using doctext '+doctext) 333564227fSBarry Smith loc = os.path.join(petsc_dir,'doc') 343564227fSBarry Smith doctext_path = os.path.join(petsc_dir,'doc','manualpages','doctext') 353564227fSBarry Smith lmansec = None 363564227fSBarry Smith if os.path.isfile(os.path.join(dir,'makefile')): 373564227fSBarry Smith lmansec = findlmansec(os.path.join(dir,'makefile')) 383564227fSBarry Smith 395a0a9f49SBarry Smith numberErrors = 0 403564227fSBarry Smith for file in os.listdir(dir): 413564227fSBarry Smith llmansec = lmansec 423564227fSBarry Smith if os.path.isfile(os.path.join(dir,file)) and pathlib.Path(file).suffix in ['.c', '.cxx', '.h', '.cu', '.cpp', '.hpp']: 433564227fSBarry Smith #print('Processing '+file) 443564227fSBarry Smith if not llmansec: 453564227fSBarry Smith llmansec = findlmansec(os.path.join(dir,file)) 463564227fSBarry Smith if not llmansec: continue 473564227fSBarry Smith if not os.path.isdir(os.path.join(loc,'manualpages',llmansec)): os.mkdir(os.path.join(loc,'manualpages',llmansec)) 483564227fSBarry Smith 493564227fSBarry Smith command = [doctext, 503564227fSBarry Smith '-myst', 513564227fSBarry Smith '-mpath', os.path.join(loc,'manualpages',llmansec), 523564227fSBarry Smith '-heading', 'PETSc', 533564227fSBarry Smith '-defn', os.path.join(loc,'manualpages','doctext','myst.def'), 543564227fSBarry Smith '-indexdir', '../'+llmansec, 553564227fSBarry Smith '-index', os.path.join(loc,'manualpages','manualpages.cit'), 563564227fSBarry Smith '-locdir', dir[len(petsc_dir)+1:]+'/', 573564227fSBarry Smith '-Wargdesc', os.path.join(loc,'manualpages','doctext','doctextcommon.txt'), 583564227fSBarry Smith file] 593564227fSBarry Smith #print(command) 605a0a9f49SBarry Smith sp = subprocess.run(command, cwd=dir, capture_output=True, encoding='UTF-8', check=True) 615a0a9f49SBarry Smith if sp.stdout and sp.stdout.find('WARNING') > -1: 625a0a9f49SBarry Smith print(sp.stdout) 635a0a9f49SBarry Smith numberErrors = numberErrors + 1 645a0a9f49SBarry Smith if sp.stderr and sp.stderr.find('WARNING') > -1: 655a0a9f49SBarry Smith print(sp.stderr) 665a0a9f49SBarry Smith numberErrors = numberErrors + 1 675a0a9f49SBarry Smith return numberErrors 685a0a9f49SBarry Smith 693564227fSBarry Smith 703564227fSBarry Smithdef processkhash(T, t, KeyType, ValType, text): 713564227fSBarry Smith '''Replaces T, t, KeyType, and ValType in text (from include/petsc/private/hashset.txt) with a set of supported values''' 723564227fSBarry Smith import re 733564227fSBarry Smith return re.sub('<ValType>',ValType,re.sub('<KeyType>',KeyType,re.sub('<t>',t,re.sub('<T>',T,text)))) 743564227fSBarry Smith 753564227fSBarry Smithdef main(petsc_dir, doctext): 763564227fSBarry Smith # generate source code for manual pages for PETSc khash functions 773564227fSBarry Smith text = '' 783564227fSBarry Smith for f in ['hashset.txt', 'hashmap.txt']: 793564227fSBarry Smith with open(os.path.join(petsc_dir,'include','petsc','private',f)) as mklines: 803564227fSBarry Smith text = mklines.read() 813564227fSBarry Smith with open(os.path.join(petsc_dir,'include','petsc','private',f+'.h'),mode='w') as khash: 823564227fSBarry Smith khash.write(processkhash('I','i','PetscInt','',text)) 833564227fSBarry Smith khash.write(processkhash('IJ','ij','struct {PetscInt i, j;}','',text)) 843564227fSBarry Smith khash.write(processkhash('I','i','PetscInt','PetscInt',text)) 853564227fSBarry Smith khash.write(processkhash('IJ','ij','struct {PetscInt i, j;}','PetscInt',text)) 863564227fSBarry Smith khash.write(processkhash('IJ','ij','struct {PetscInt i, j;}','PetscScalar',text)) 873564227fSBarry Smith khash.write(processkhash('IV','iv','PetscInt','PetscScalar',text)) 883564227fSBarry Smith khash.write(processkhash('Obj','obj','PetscInt64','PetscObject',text)) 893564227fSBarry Smith 903564227fSBarry Smith # generate the .md files for the manual pages from all the PETSc source code 915a0a9f49SBarry Smith try: 925a0a9f49SBarry Smith os.unlink(os.path.join(petsc_dir,'doc','manualpages','manualpages.cit')) 935a0a9f49SBarry Smith except: 945a0a9f49SBarry Smith pass 955a0a9f49SBarry Smith numberErrors = 0 963564227fSBarry Smith for dirpath, dirnames, filenames in os.walk(os.path.join(petsc_dir),topdown=True): 973564227fSBarry Smith dirnames[:] = [d for d in dirnames if d not in ['tests', 'tutorials', 'doc', 'output', 'ftn-custom', 'f90-custom', 'ftn-auto', 'f90-mod', 'binding', 'binding', 'config', 'lib', '.git', 'share', 'systems'] and not d.startswith('arch')] 985a0a9f49SBarry Smith numberErrors = numberErrors + processdir(petsc_dir,dirpath,doctext) 995a0a9f49SBarry Smith if numberErrors: 1005a0a9f49SBarry Smith raise RuntimeError('Stopping document build since errors were detected in generating manual pages') 1013564227fSBarry Smith 1023564227fSBarry Smith # generate list of all manual pages 1033564227fSBarry Smith with open(os.path.join(petsc_dir,'doc','manualpages','htmlmap'),mode='w') as map: 1043564227fSBarry Smith with open(os.path.join(petsc_dir,'doc','manualpages','manualpages.cit')) as cit: 105*34c645fdSBarry Smith map.write(re.sub(r'man\+../','man+manualpages/',cit.read())) 1063564227fSBarry Smith with open(os.path.join(petsc_dir,'doc','manualpages','mpi.www.index')) as mpi: 1073564227fSBarry Smith map.write(mpi.read()) 1083564227fSBarry Smith 1093564227fSBarry Smithif __name__ == "__main__": 1103564227fSBarry Smith # TODO Accept doctext from command line 1113564227fSBarry Smith main(os.path.abspath(os.environ['PETSC_DIR'])) 112