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 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
"""
This simple script adds a CALL statement (or, more precisely, whatever
statement you want to add) after each call to ALLOCATE/DEALLOCATE.
Usage:
python instrument.py file_name
this command will create a bkp file (if not present) and a .new file
which contains the print statements.
something like:
files=`sift -i --filename -x f90 -w *allocate | cut -d ':' -f 1 | uniq`
for f in $files
do
python instrument.py $f
mv ${f}.new $f
done
will add print statements to all the files in the directory
restore with
for file in *.bkp; do cp $file ${file%.bkp}; done
"""
from __future__ import print_function
import os, sys, re
from shutil import copyfile
fmt = """ CALL mem_counter ( SIZEOF({0}), {1}, &\n "{0}", &\n "{2}" )
"""
if len(sys.argv) < 2:
print("Specify file name!")
sys.exit(-1)
fname = sys.argv[1]
if not os.path.exists(fname):
print("File does not exists!")
sys.exit(-1)
#if not os.path.exists(fname+".bkp"):
# copyfile(fname, fname+".bkp")
def get_args_list(line):
args = ""
npar = 0
for i, c in enumerate(line):
if c == '(':
npar +=1
continue
if c == ')':
npar -=1
continue
if c == '&':
continue
if c == '\n':
continue
if c == '!':
break
if c == '%':
# copy argument if needed
if npar >= 2:
continue
if line[i-1] == ')':
j = i
while (j>0):
j = j-1 # this can fail but should never happen
if line[j] == '(':
break
args += line[j:i].replace(',','!') # temp replace , with ! to
#avoid confusion in arg splitting.
# btw, we go back in characters so
# there shouldn't be any '!'
if npar == 1:
args += c
return [x.replace('!',',') for x in args.split(',')]
def write_counters(fout, sign, args, sub, tag=[], prepend=""):
for a, arg in enumerate(args):
if 'stat' in arg.lower():
continue
if (a == 0) and (tag != []):
fout.write(tag[0] + ' ')
fout.write(prepend + fmt.format(*[arg, sign, sub]))
with open(fname,'r') as fin:
with open(fname+".new",'w') as fout:
lines = fin.readlines()
i = 0
while (i<len(lines)):
if len(lines[i].strip()) > 0:
# write out comments straight away
if ('!' in lines[i].strip()[0]):
fout.write(lines[i])
i += 1
continue
# same for #ifdefs
if ('#' in lines[i].strip()[0]):
fout.write(lines[i])
i += 1
continue
# possibly get rid of comments
buff = lines[i].split('!')[0]
# add end of line if needed
if buff[-1] != '\n':
buff += '\n'
# merge continuation in single string. Never forget \n
j = 0
while '&' in lines[i+j].strip()[1:]: # line continuation may begin with '&'
j += 1
buff += lines[i+j].split('!')[0]
if buff[-1] != '\n':
buff += '\n'
# find name of subroutine (or program in no subroutine is found)
str_subroutine = re.findall("subroutine", buff.lower())
if (len(str_subroutine) == 0):
str_subroutine = re.findall("program", buff.lower())
if (len(str_subroutine) > 0):
# print("Treating subroutine ",str_subroutine)
sub = buff.split()[1]
# find (de)allocate in strings
str_allocate = re.findall("[\"\'].*?(allocate).*?[\"\']", buff.lower())
# match all allocate
allocate = re.findall(r'\bdeallocate\b', buff.lower()) + re.findall(r'\ballocate\b', buff.lower())
# if no allocate or deallocate present, write all previous lines as they were originally
if ((allocate == []) or (len(str_allocate) >= len(allocate))):
for _ in range(j+1):
fout.write(lines[i])
i += 1
continue
if re.findall(r'\bdeallocate\b', buff.lower()) and re.findall(r'\bif\b', buff.lower()):
# split clause with 'deallocate' as delimiter
ifcls = re.split(r'\bdeallocate\b',buff.lower())
args = get_args_list(ifcls[1])
if (len(args) > 1):
print("WARNING! Multiple deallocate in if clause")
tag = re.findall(r'^\d+', buff.lower().strip())
write_counters(fout, -1, args, sub, tag, ifcls[0] + ' ')
#fout.write(ifcls[0] + ' ' + fmt.format(*[args[0], -1]))
if tag:
fout.write(re.sub("^[ X]*\d+","",buff))
else:
fout.write(buff)
elif re.findall(r'\ballocate\b', buff.lower()) and re.findall(r'\bif\b', buff.lower()):
ifcls = re.split(r'\ballocate\b',buff.lower())
args = get_args_list(ifcls[1])
if (len(args) > 1):
print("WARNING! Multiple allocate in if clause")
# is there a tag?
tag = re.findall(r'^\d+', buff.lower().strip())
if tag:
print("WARNING! allocate with tag! Check (and change?) file " + fname + ".new (original line " + str(i) + ")")
fout.write(ifcls[0] + ' THEN \n ALLOCATE ' + ifcls[1] + '\n ')
write_counters(fout, +1, args, sub)
fout.write( '\n END IF \n')
elif re.findall(r'\bdeallocate\b', buff.lower()):
args = get_args_list(buff)
# is there a tag?
tag = re.findall(r'^\d+', buff.lower().strip())
if tag:
print("WARNING! deallocate with tag! Check (and change?) file " + fname + ".new (original line " + str(i) + ")")
write_counters(fout, -1, args, sub, tag)
if tag:
fout.write(re.sub("^[ X]*\d+","",buff))
else:
fout.write(buff)
elif re.findall(r'\ballocate\b', buff.lower()):
fout.write(buff)
args = get_args_list(buff)
# is there a tag?
tag = re.findall(r'^\d+', buff.lower().strip())
if tag:
print("WARNING! allocate with tag! Check (and change!) file " + fname + ".new (original line " + str(i) + ")")
write_counters(fout, +1, args, sub)
#for arg in args:
# if 'stat' in arg.lower():
# continue
#
# fout.write(fmt.format(*[arg, 1]))
else:
fout.write(buff)
i += 1 + j
continue
fout.write(lines[i])
i += 1
|