📄 mkcpp.py
字号:
#!/usr/bin/env python
"""
Make C++
C to C++ tools - (c) 2001 by D.G. Sureau
Convert C sources to C++ ones, from classes in header files
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
webmaster@scriptol.org
http://www.scriptol.org
This program requires a list of all headers files in the
project, that you can create with allhead.py
Processing:
- Functions are defined now as methods.
- Global variable are unchanged. The "static" modifier
is removed for any variable in source file.
- Variables previously defined without initializer
in the C source, are removed from the C++ source.
- Variable defined with an initializer are declared
as static in the new header file. In the source,
they get the class:: prefix.
- Calls to functions become references to methods inside
any function, but the class. prefix is not added inside
other methods of the same class.
- An instance of the class is defined into the source
and declared into the header.
- #include statements are updated for .hpp extensions.
- Missing #include are inserted into the source, any function
now refers to a class, whose the declaration is required.
"""
import os
import sys
import string
import wstring
import lexer
FALSE = 0
TRUE = 1
DEBUG = 0
counter = 0
linenumber = 0
lastinclude = 0 # Set position of the last include statement
vclass = {} # Dictionary of variables and their class
fclass = {} # Dictionary of functions and their class
dclass = {} # Dictionary of all above
locals = [] # List of local idents of vars in the current block
included = [] # List of external included header files
omitted = [] # List of external used classes (and therefore header)
allclasses = {} # Dictionary of each class and file that contains it
allheaders = {} # Dictionary of each header and class it contains
withoutpath = {} # I need the dict above with filenames only
#---------------------------------- Step 1: make dictionaries
def build(classfile):
global dclass
global vclass
global fclass
global allclasses
global allheaders
global withoutpath
#print "adding", classfile + "'s members to dictionary"
# Reading the header file
f = open(classfile, 'r')
lines = f.readlines()
f.close()
vlist = [] # List of members and methods
classname = ""
COMMENT = FALSE
INMACRO = FALSE
INRECORD = FALSE
INCLASS = FALSE
for line in lines:
line = wstring.chop(line) # Remove line separators
if wstring.strip(line) == "": continue
if not INCLASS: INCLASS = lexer.openclass(line)
if not INCLASS: continue
INCLASS = lexer.closeclass(line)
if not INCLASS: continue
# Skip typedef and struct blocks
if not INRECORD: INRECORD = lexer.openrecord(line)
if INRECORD:
INRECORD = lexer.closerecord(line)
continue
# If we are inside a macro or pragma block, skip it
if not INMACRO: INMACRO = lexer.opendef(line)
if INMACRO:
INMACRO = lexer.closedef(line)
continue
words = string.split(line)
if len(words) > 1:
w = words[0]
if w == "class": # First of new class found
if len(vlist) > 0:
if classname == "":
print "Error, members without class", vlist
sys.exit(0)
classname = words[1]
if classname not in allclasses:
allclasses[classname] = classfile
if classfile not in allheaders:
allheaders[classfile] = classname
dummy, fname = os.path.split(classfile)
withoutpath[fname] = classname
print "class", classname, "in", classfile
INCLASS = TRUE
continue
# Processing comment block
if not COMMENT:
if not lexer.embeddedcomment(line):
COMMENT = lexer.opencomment(line)
else:
test = lexer.removecomment(line)
if wstring.strip(test) == "": continue
# Inside a multi-line comment
if COMMENT: # Comment opened
COMMENT = lexer.closecomment(line) # Always inside comment?
# End of multi-line comment
if not COMMENT: # Terminator reached
i = string.find(line, "*/")
if i == -1:
print "Error in parsing header"
sys.exit(0)
line = line[i + 2:] # Keeping the code is exists
# Start of multi-line comment
if COMMENT:
i = string.find(line, "/*")
if i != -1:
line = line[:i]
else:
continue
line = wstring.strip(line)
if line == "": continue
# Define statement are ignored
if line[0:7] == "#define": continue
if lexer.isdeclaration(line):
# Processing simple var declarations
if lexer.isvardecl(line):
nlist = lexer.splitvardecl(line)
for n in nlist:
vlist.append(n)
n = lexer.getident(n)
vclass[n] = classname
dclass[n] = classname
#print "append var", n
continue
# Processing function declaration
if lexer.isprototype(line):
f = lexer.prototype
vlist.append(f)
fkey = lexer.getident(f)
fclass[fkey] = classname
dclass[fkey] = classname
#print "append function", f
continue
# End for
#-------------------- Step 2: move variables'name, transform functions
# Creates a method name from a function interface
# Input: interface of a function in a string with format: type function()
# Output: same line with the format: type class::function()
def setmethod(line):
id = lexer.getident(line)
# Is it in the dictionary of classes as a method?
if not fclass.has_key(id):
print "* method", id, "not in directory"
return line, ""
classname = fclass[id]
# Is it a function?
if not lexer.isfunction(line):
print "Error,", line, "not a function"
sys.exit(0)
method = lexer.makemethod(line, classname)
#print "line", line
if DEBUG: print "method:", method
method = lexer.removestatic(method)
return method, classname # Adding tail part, returning also class
# this is for the "main" function only
def getclass(name):
# Is it in the dictionary of classes as a method?
if not fclass.has_key(name):
print "* method \"" + name + "\" not in directory"
return ""
classname = fclass[name]
return classname
# Make a definition of member, from a variable
def setmember(line):
id = lexer.getident(line)
if not vclass.has_key(id):
# either a global (static) variable or an error
if not lexer.isstatic(line):
print "* member", id, "not in directory"
return line
classname = vclass[id]
member = lexer.makemethod(line, classname)
#print "line", line
j = string.find(member, "=")
if j != -1:
id = member[:j] + ";"
else:
id = member
if DEBUG: print "definition:", id
return member # A definition of an attribute
# Change a C reference to a C++ one, for a line
# for methods and attributes (functions and variables)
# subline is the part of the line inside a block
# and without comment
def cppreference(line, subline, classname):
global omitted
start = string.find(line, subline)
if start == -1:
print "Error,", subline, "not found in", line
sys.exit(0)
end = start + len(subline)
words = wstring.getidents(subline) # get idents but labels
#if "goto" in words: print words
#already = []
gotoflag = FALSE
for id in words:
if gotoflag: # this id is skipped, it follows a goto
gotoflag = FALSE
#print id
continue
if id == "goto":
#print id
gotoflag = TRUE # this will skip the following ident
continue
#if id in already: continue # all replacements already done
#already.append(id)
#if not lexer.isident(id): continue
#print "id=", id, "old=", line
if id in locals:
#print id, "in locals"
continue
if dclass.has_key(id):
cname = dclass[id]
# if not inside a method of the class that is referenced
if cname != classname:
#print id, "in", cname
newident = cname + "Obj" + '.' + id
subline = wstring.replaceident(subline, id, newident, TRUE)
if not cname in omitted:
omitted.append(cname)
#print ">>>", newident, cname, " (in" + classname +")"
line = line[:start] + subline + line[end:]
# if flag: print "ref updated", line
return line
# Process local variables inside functions
def processlocals(blocklist):
global locals
COMMENT = FALSE # This flag is true inside a comment
INSBLK = FALSE # This one inside a function's body
INSMAC = FALSE
#print "processlocals"
for line in blocklist:
line = wstring.chop(line) # Removing line separators
line = wstring.strip(line) # Removing spaces (with better strip)
if len(line) == 0: continue # Empty line ignored
# If we enter a comment block, append it and
# process other code on the same line
if not COMMENT:
if not lexer.embeddedcomment(line):
COMMENT = lexer.opencomment(line)
else:
test = lexer.removecomment(line)
if wstring.strip(test) == "": # Simple one-line comment
continue
# Inside a comment block if multi-lines
if COMMENT: # Comment opened
COMMENT = lexer.closecomment(line) # Always inside comment?
# End of multi-line comment
if not COMMENT: # Terminator reached
i = string.find(line, "*/")
if i == -1:
print "Error in parsing header"
sys.exit(0)
line = line[i + 2:] # Keeping the code is exists
# Start of multi-line comment
if COMMENT:
i = string.find(line, "/*")
if i != -1: line = line[:i]
else: continue
if line is None: continue
line = wstring.strip(line)
if line == "": continue
# If we are inside a macro or pragma block, skip it
if not INSMAC: INSMAC = lexer.opendef(line)
if INSMAC:
INSMAC = lexer.closedef(line)
continue
# A declaration
if lexer.islocalvar(line):
nlist = []
if lexer.multivar(line):
nlist = lexer.splitvardef(line)
else:
nlist.append(line)
for n in nlist:
id = lexer.getident(n)
locals.append(id)
#print "is local", id
continue
if lexer.isarray(line):
id = lexer.getident(line)
locals.append(id)
#print "is array local", id
continue
if lexer.isprototype(line):
continue
# end of the main for loop
# end of processlocals
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -