(moderator please reject my other message - wrong email)
The subject says it all :)
Given a valid regex (pcre) as an argument, the script will search
inside every *.ops file for an opcode name that matches, and dumps
both its arguments and its description. If no argument is passed every
opcode found is dumped.
Example:
./search-ops.py find_n
----------------------------------------------------------------------
File: string.ops - String Operations (1 matches)
----------------------------------------------------------------------
find_not_cclass(out INT, in INT, in STR, in INT, in INT)
Set $1 to the offset of the first codepoint not matching the character
class(es) given by $2 in string $3, starting at offset $4 for up to $5
codepoints. If the substring consists entirely of matching
characters, set $1 to (offset + count).
----------------------------------------------------------------------
File: var.ops - Variable Ops (1 matches)
----------------------------------------------------------------------
find_name(out PMC, in STR)
Find the name $2 in lexical, current, global, or builtin namespace and
store it in $1. If the name doesn't exist either throws an exception
or sets $1 to PMCNULL, depending on current errors settings. See
B<errorson>.
---------------------------------------------------------------------
The script will work right away if you place it inside
<trunk>/tools/util. Otherwise edit and change the 'path' as you wish.
If you think that's a useful development tool, feel free to add it to
the existing ones. I've done it in python I hope there's no problem
with that.
Cheers,
João
#!/usr/bin/python
import os, re
from sys import argv, exit
path = "../../src/ops/" # path to the ops source folder
def wrap(text, width):
return reduce(lambda line, word, width=width: '%s%s%s' %
(line,
' \n'[(len(line)-line.rfind('\n')-1
+ len(word.split('\n',1)[0]
) >= width)],
word),
text.split(' ')
)
query = ""
if len(argv) > 1:
query = argv[1]
try:
query = re.compile(query)
except:
print "Invalid opcode regex"
exit()
path = path.replace("\\", "/")
if len(path) > 0 and path[-1] != "/":
path = path + "/"
try:
opFiles = os.listdir(path)
except:
print "Path not found"
exit()
p = re.compile("\.ops$")
opFiles = filter(lambda file: p.search(file) is not None, opFiles)
matches = []
for file in opFiles:
results = []
opsc = open(path+file, "r").read()
p = re.compile("^=item\sB<(\w+)>\(([^)]+)\)\n\n(?=(.*?)\n\n)",
re.MULTILINE|re.DOTALL)
for m in p.findall(opsc):
if query.search(m[0]) is None:
continue
if re.compile("=item").match(m[2]) is not None:
m = list(m)
m[2] = None
results.append(m)
if len(results) > 0:
title = re.compile("^=head1\sNAME\n\n(.*)",
re.MULTILINE).search(opsc).group(1)
matches.append({"f": title, "rs": results})
if len(matches) == 0:
print "No matches were found"
else:
for v in matches:
print "\n" + "-"*70 + "\nFile: %s (%d matches)\n" %
(v["f"],len(v["rs"])) + "-"*70 + "\n"
for m in v["rs"]:
print "%s(%s)" % tuple(m[:2])
if m[2] is not None:
print wrap(m[2].replace("\n", " "), 70)+"\n"