📄 scantools.py
字号:
tmp = self.scanmine and self.scanfile self.scanfile = None if tmp: tmp.close() def setoutput(self, spec, defs = None): self.closespec() self.closedefs() if spec: if type(spec) == StringType: file = self.openoutput(spec) mine = 1 else: file = spec mine = 0 self.specfile = file self.specmine = mine if defs: if type(defs) == StringType: file = self.openoutput(defs) mine = 1 else: file = defs mine = 0 self.defsfile = file self.defsmine = mine def openoutput(self, filename): try: file = open(filename, 'w') except IOError, arg: raise IOError, (filename, arg) self.setfiletype(filename) return file def setinput(self, scan = sys.stdin): self.closescan() if scan: if type(scan) == StringType: file = self.openinput(scan) mine = 1 else: file = scan mine = 0 self.scanfile = file self.scanmine = mine self.lineno = 0 def openinput(self, filename): if not os.path.isabs(filename): for dir in self.includepath: fullname = os.path.join(dir, filename) #self.report("trying full name %s", `fullname`) try: return open(fullname, 'r') except IOError: pass # If not on the path, or absolute, try default open() try: return open(filename, 'r') except IOError, arg: raise IOError, (arg, filename) def getline(self): if not self.scanfile: raise Error, "input file not set" self.line = self.scanfile.readline() if not self.line: raise EOFError self.lineno = self.lineno + 1 return self.line def scan(self): if not self.scanfile: self.error("No input file has been specified") return inputname = self.scanfile.name self.report("scanfile = %s", `inputname`) if not self.specfile: self.report("(No interface specifications will be written)") else: self.report("specfile = %s", `self.specfile.name`) self.specfile.write("# Generated from %s\n\n" % `inputname`) if not self.defsfile: self.report("(No symbol definitions will be written)") else: self.report("defsfile = %s", `self.defsfile.name`) self.defsfile.write("# Generated from %s\n\n" % `inputname`) self.writeinitialdefs() self.alreadydone = [] try: while 1: try: line = self.getline() except EOFError: break if self.comment1.match(line) >= 0: line = self.comment1.group('rest') if self.comment2.match(line) >= 0: line = self.comment2.group('rest') if self.defsfile and self.sym.match(line) >= 0: self.dosymdef() continue if self.head.match(line) >= 0: self.dofuncspec() continue except EOFError: self.error("Uncaught EOF error") self.reportusedtypes() def dosymdef(self): name, defn = self.sym.group('name', 'defn') if not name in self.blacklistnames: self.defsfile.write("%s = %s\n" % (name, defn)) else: self.defsfile.write("# %s = %s\n" % (name, defn)) def dofuncspec(self): raw = self.line while self.tail.search(raw) < 0: line = self.getline() raw = raw + line self.processrawspec(raw) def processrawspec(self, raw): if self.whole.search(raw) < 0: self.report("Bad raw spec: %s", `raw`) return type, name, args = self.whole.group('type', 'name', 'args') type = regsub.gsub("\*", " ptr", type) type = regsub.gsub("[ \t]+", "_", type) if name in self.alreadydone: self.report("Name has already been defined: %s", `name`) return self.report("==> %s %s <==", type, name) if self.blacklisted(type, name): self.error("*** %s %s blacklisted", type, name) return returnlist = [(type, name, 'ReturnMode')] returnlist = self.repairarglist(name, returnlist) [(type, name, returnmode)] = returnlist arglist = self.extractarglist(args) arglist = self.repairarglist(name, arglist) if self.unmanageable(type, name, arglist): ##for arg in arglist: ## self.report(" %s", `arg`) self.error("*** %s %s unmanageable", type, name) return self.alreadydone.append(name) self.generate(type, name, arglist) def extractarglist(self, args): args = string.strip(args) if not args or args == "void": return [] parts = map(string.strip, string.splitfields(args, ",")) arglist = [] for part in parts: arg = self.extractarg(part) arglist.append(arg) return arglist def extractarg(self, part): mode = "InMode" if self.asplit.match(part) < 0: self.error("Indecipherable argument: %s", `part`) return ("unknown", part, mode) type, name = self.asplit.group('type', 'name') type = regsub.gsub("\*", " ptr ", type) type = string.strip(type) type = regsub.gsub("[ \t]+", "_", type) return self.modifyarg(type, name, mode) def modifyarg(self, type, name, mode): if type[:6] == "const_": type = type[6:] elif type[-4:] == "_ptr": type = type[:-4] mode = "OutMode" if type[-4:] == "_far": type = type[:-4] return type, name, mode def repairarglist(self, functionname, arglist): arglist = arglist[:] i = 0 while i < len(arglist): for item in self.repairinstructions: if len(item) == 2: pattern, replacement = item functionpat = "*" else: functionpat, pattern, replacement = item if not fnmatch.fnmatchcase(functionname, functionpat): continue n = len(pattern) if i+n > len(arglist): continue current = arglist[i:i+n] for j in range(n): if not self.matcharg(pattern[j], current[j]): break else: # All items of the pattern match new = self.substituteargs( pattern, replacement, current) if new is not None: arglist[i:i+n] = new i = i+len(new) # No recursive substitutions break else: # No patterns match i = i+1 return arglist def matcharg(self, patarg, arg): return len(filter(None, map(fnmatch.fnmatchcase, arg, patarg))) == 3 def substituteargs(self, pattern, replacement, old): new = [] for k in range(len(replacement)): item = replacement[k] newitem = [item[0], item[1], item[2]] for i in range(3): if item[i] == '*': newitem[i] = old[k][i] elif item[i][:1] == '$': index = string.atoi(item[i][1:]) - 1 newitem[i] = old[index][i] new.append(tuple(newitem)) ##self.report("old: %s", `old`) ##self.report("new: %s", `new`) return new def generate(self, type, name, arglist): self.typeused(type, 'return') classname, listname = self.destination(type, name, arglist) if not self.specfile: return self.specfile.write("f = %s(%s, %s,\n" % (classname, type, `name`)) for atype, aname, amode in arglist: self.typeused(atype, amode) self.specfile.write(" (%s, %s, %s),\n" % (atype, `aname`, amode)) self.specfile.write(")\n") self.specfile.write("%s.append(f)\n\n" % listname) def destination(self, type, name, arglist): return "FunctionGenerator", "functions" def blacklisted(self, type, name): if type in self.blacklisttypes: ##self.report("return type %s is blacklisted", type) return 1 if name in self.blacklistnames: ##self.report("function name %s is blacklisted", name) return 1 return 0 def unmanageable(self, type, name, arglist): for atype, aname, amode in arglist: if atype in self.blacklisttypes: self.report("argument type %s is blacklisted", atype) return 1 return 0class Scanner_PreUH3(Scanner): """Scanner for Universal Headers before release 3""" def initpatterns(self): self.head_pat = "^extern pascal[ \t]+" # XXX Mac specific! self.tail_pat = "[;={}]" self.type_pat = "pascal[ \t\n]+\(<type>[a-zA-Z0-9_ \t]*[a-zA-Z0-9_]\)[ \t\n]+" self.name_pat = "\(<name>[a-zA-Z0-9_]+\)[ \t\n]*" self.args_pat = "(\(<args>\([^(;=)]+\|([^(;=)]*)\)*\))" self.whole_pat = self.type_pat + self.name_pat + self.args_pat self.sym_pat = "^[ \t]*\(<name>[a-zA-Z0-9_]+\)[ \t]*=" + \ "[ \t]*\(<defn>[-0-9'\"][^\t\n,;}]*\),?" self.asplit_pat = "^\(<type>.*[^a-zA-Z0-9_]\)\(<name>[a-zA-Z0-9_]+\)$" def test(): input = "D:Development:THINK C:Mac #includes:Apple #includes:AppleEvents.h" output = "@aespecs.py" defsoutput = "@aedefs.py" s = Scanner(input, output, defsoutput) s.scan()if __name__ == '__main__': test()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -