1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
#!/usr/bin/env python3
'''
Generate C prototypes for the LAPACK Fortran functions by parsing
doxygen comments in LAPACK's SRC *.f files. Looks for routines in
LAPACK's SRC, INSTALL, and MATGEN directories. (Because MATGEN is the
last directory checked, error messages show that file not found.)
Example usage:
# Assumes $LAPACKDIR is set
lapackpp> echo $LAPACKDIR
/Users/mgates/Documents/lapack
lapackpp> ./tools/header_gen.py {s,d,c,z}posv {s,d}ormqr {c,z}unmqr
generating gen/fortran.h
lapackpp> ./tools/header_gen.py all
reading include/lapack/fortran.h to re-generate all prototypes
generating gen/fortran.h
// skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/slassq.f
// skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/dlassq.f
// skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/classq.f
// skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/zlassq.f
// skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/slartg.f
// skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/dlartg.f
// skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/clartg.f
// skipping, file not found: /Users/mgates/Documents/lapack/TESTING/MATGEN/zlartg.f
'''
from __future__ import print_function
import sys
import re
import os
lapack = os.environ['LAPACKDIR']
if (len( sys.argv ) == 1):
print( 'Usage:', sys.argv[0], '[routine ...]\n' +
' ', sys.argv[0], 'all\n' +
'See script for more details' )
exit(1)
# end
if (sys.argv[1] == 'all'):
#header = lapack + '/LAPACKE/include/lapack.h'
header = 'include/lapack/fortran.h'
print( 'reading', header, 'to re-generate all prototypes' )
funcs = []
f = open( header )
for line in f:
s = re.search( r' +LAPACK_(\w+) +LAPACK_GLOBAL\( *\1', line )
#s = re.search( r'(?:void|float|double) +LAPACK_GLOBAL\((\w+),', line )
if (s):
funcs.append( s.group(1) )
# end
else:
funcs = sys.argv[1:]
# end
output = 'gen/fortran.h'
print( 'generating', output )
output = open( output, 'w' )
intent = None
var = None
vtype = None
dtype = None
typemap = {
'character' : 'char',
'integer' : 'lapack_int',
'real' : 'float',
'double precision' : 'double',
'complex' : 'lapack_complex_float',
'complex*16' : 'lapack_complex_double',
'logical' : 'lapack_logical',
'logical function of two real arguments' : 'LAPACK_S_SELECT2',
'logical function of three real arguments' : 'LAPACK_S_SELECT3',
'logical function of two double precision arguments' : 'LAPACK_D_SELECT2',
'logical function of three double precision arguments' : 'LAPACK_D_SELECT3',
'logical function of one complex argument' : 'LAPACK_C_SELECT1',
'logical function of two complex arguments' : 'LAPACK_C_SELECT2',
'logical function of one complex*16 argument' : 'LAPACK_Z_SELECT1',
'logical function of two complex*16 arguments' : 'LAPACK_Z_SELECT2',
}
for func in funcs:
s = re.search( '\.f', func )
if (s):
filename = func
else:
for subdir in ('SRC', 'INSTALL', 'TESTING/MATGEN'):
filename = lapack + '/' + subdir + '/' + func + '.f'
if (os.path.exists( filename )):
break
# end
# end
# end
if (os.path.exists( filename )):
#print( 'read', filename )
f = open( filename )
args = []
retval = 'void'
for line in f:
s = re.search( r'^\* +\b(.*)\b +FUNCTION +(\w+)', line ) # \( *(.*) *\)
if (s):
retval = typemap[ s.group(1).lower() ]
continue
# end
s = re.search( r'^\*> *\\param\[(in|out|in,out|inout)\] +(\w+)', line )
if (s):
intent = s.group(1).lower()
var = s.group(2)
vtype = var # vtype used as flag to say we have a variable and are looking for its type
continue
# end
if (vtype):
s = (re.search( '^\*> *' + vtype + ' +is +(CHARACTER|INTEGER|REAL|DOUBLE PRECISION|COMPLEX\*16|COMPLEX|LOGICAL)( array)?', line ) or
re.search( '^\*> *\(workspace\) +(CHARACTER|INTEGER|REAL|DOUBLE PRECISION|COMPLEX\*16|COMPLEX|LOGICAL)( array)?', line ) or
re.search( '^\*> *' + vtype + ' +is a (LOGICAL FUNCTION of (?:one|two|three) (?:REAL|DOUBLE PRECISION|COMPLEX\*16|COMPLEX) arguments?)( array)?', line ))
if (s):
dtype = s.group(1).lower()
dtype = typemap[dtype]
array = s.group(2)
vtype = None
# leave arrays uppercase, except work and pivots
if (array and var not in ('WORK', 'RWORK', 'IWORK', 'IPIV', 'JPIV', 'PIV')):
pass #lvar = var
else:
var = var.lower()
if (intent == 'in'):
args.append( dtype + ' const* ' + var )
else:
args.append( dtype + '* ' + var )
continue
# end
# end
# end
print( '#define LAPACK_' + func + ' LAPACK_GLOBAL( ' + func + ', '
+ func.upper() + ' )', file=output )
print( retval + ' LAPACK_' + func + '(\n ' + ', '.join( args )
+ '\n);\n', file=output )
else:
print( '// skipping, file not found:', filename )
print( '// skipping, file not found:', filename, file=output )
print( '// #define LAPACK_' + func + ' LAPACK_GLOBAL(' + func + ','
+ func.upper() + ')', file=output )
print( '// void LAPACK_' + func + '( ... );\n', file=output )
# end
# end
output.close()
|