📄 mover.py
字号:
#!/usr/bin/env python
"""
Mover - (c) D.G. Sureau 2001-2004
Comes along with the C to C++ translator pack.
Requires python (www.python.org)
This python script moves all c files and their headers
from a set of directories to another set of directories.
"#include" statements inside the files are updated...
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
"""
import os
import sys
import string
import wstring
import lexer
VERSION = "1.1.0"
TRUE = 1
FALSE = 0
sources = []
dico = {}
counter = 0
# Replaces the ../ string by the absolute equivalent path
def decrease(oldpath, absdir):
flag = 0
while oldpath[ : 3] in [ "../", "..\\" ]:
oldpath = oldpath[ 3: ]
if(oldpath[ len(oldpath) - 1] in [ "/", "\\" ]):
oldpath = oldpath[ : -1 ]
if (absdir[-1] in [ "/", "\\" ]) : absdir = absdir[ : -1 ]
absdir, dummy = os.path.split(absdir)
flag = 1
if flag == 1: oldpath = os.path.join(absdir , oldpath)
return oldpath
# This function updates the '#include' statement
# by replacing the old path by the new given one
# the line and the path of the file are given as argument
# the ../ relative path is replaced by the absolute path
def update(line, abspath):
i = string.find(line, "#include ")
if i == -1:
print "which?"
sys.exit(0)
i = i + 9
lindex = i
rindex = i
sline = line[i:]
first = FALSE
second = FALSE
# scanning the line for delimiters
for c in sline:
if c == '<' : # test for left delimiter
lindex = i
first = TRUE
return line # standard libraries include unchanged
if c == '\"':
if first : # test for right delimiter
rindex = i
second = TRUE
break
lindex = i + 1 # test for left delimiter
first = TRUE
i = i + 1
if (rindex <= lindex) | (not first) | (not second):
print "error, unrecognized statenent", line
sys.exit(0)
# extracting the header filename
sline = line[lindex:rindex]
sline = wstring.localize(sline) # change separators for the os
# occurence of header with the old path replaced by
# the header with the new path found in the dictionary
oldpath, name = os.path.split(sline)
if oldpath == "": return line # simple filename without path
oldpath = decrease(oldpath, abspath) # replace ../
if dico.has_key(oldpath):
newpath = os.path.join(dico[oldpath], name)
else:
print oldpath, "not in dictionary of paths"
newpath = oldpath
line = line[ : lindex] + newpath + line[rindex: ]
return line
# This function copies a file
# and updates any '#include' statement embedded
def move(oldpath, newpath):
if not os.path.exists(oldpath): return 0
path, name = os.path.split(newpath)
opath, oname = os.path.split(oldpath)
if not os.path.exists(path):
os.mkdir(path)
print path, "created"
o = open(oldpath, 'r')
n = open(newpath, 'w')
while(1):
line = o.readline()
if not line: break
line = wstring.chop(line)
i = string.find(line, "#include ")
if i != -1:
line = update(line, opath)
n.write(line + "\n")
o.close()
n.close()
return 1
# This function changes the path of a file
def changepath(f):
path, name = os.path.split(f)
if dico.has_key(path):
np = dico[path]
return os.path.join(np , name)
else:
return f
"""
Contructs a list of all headers included in a project
from the main source file.
"""
# Add header file to the list
# test if already inside the list,
# filenames are compared without case under Windows
def add(hpath, filedir):
global counter
global sources
hpath = hpath[1:-1] # Removing ""
if hpath is None:
print "Error"
sys.exit(0)
# if no dir in the path, the path of the main file
# if added to, as it is presumed to be the location
# when compiling the project
hpath = wstring.localize(hpath)
filedir = wstring.localize(filedir)
p, n = os.path.split(hpath)
if p == "":
hpath = os.path.join(filedir, n) # adding the default path
hpath = decrease(hpath, filedir)
Windows = (os.name == "nt") | (os.name == "dos")
if Windows: hname = string.lower(hpath)
if hpath in sources: return # already here
sources.append(hpath)
counter = counter + 1
return
# Change a .h header name into .c source name
def makesource(name):
node, ext = os.path.splitext(name)
ext = string.lower(ext)
if ext == ".h":
nname = node + ".c"
if os.path.exists(nname): name = nname
return name
# Is the file a c source?
def iscode(name):
node, ext = os.path.splitext(name)
ext = string.lower(ext)
return (ext == ".c")
# Scans a source file for included headers files
# and adds them to the list
def hprocess(name, filedir):
name = decrease(name, filedir)
print "processing", name
f = open(name, 'r')
lines = f.readlines()
f.close()
if not lines: return
for l in lines:
if len(l) < 10: continue
if l[0] != '#': continue
if l[:9] != "#include ": continue
hpath = l[9:]
hpath = wstring.chop(hpath)
hpath = lexer.removecomment(hpath)
hpath = wstring.strip(hpath)
if hpath[-1] == ';': hpath = hpath[:-1]
if len(hpath) < 3: continue # minimum is: "a"
if lexer.isheader(hpath): # Has the format "name" or <name>
add(hpath, filedir)
# End for
return
# Process a header file
def processheader(mainfile, startsource):
p, n = os.path.split(mainfile)
hprocess(mainfile, p)
index = 0
while(1):
if index >= len(sources): break
nextfile = sources[index];
nextfile = makesource(nextfile)
if iscode(nextfile):
hprocess(nextfile, p)
index = index + 1
startsource.extend(sources)
"""
Contructs the list of all c sources included in a project
from the file holding the main function
"""
notexist = []
mainpath = ""
# Add to the list the name of a header file to include
# Windows ignore case, so case is ignored under Windows.
# The .h header filename is transformed into .c source filename
# and added to the list if c the source exists
def addc(hpath, filedir):
global counter
global notexist
global sources
if hpath is None: return None
if len(hpath) < 3: return None
hpath = hpath[1:-1] # removing markers, quotes or angles
# if filedir not in the path, the path of the main file
# if added to, as it is presumed to be the location
# when compiling the project
hpath = wstring.localize(hpath) # converting antislash or slash
filedir = wstring.localize(filedir)
p, n = os.path.split(hpath)
if p == "":
hpath = os.path.join(filedir, n) # adding the default path
hpath = decrease(hpath, filedir)
node, ext = os.path.splitext(hpath)
if lexer.iswindows(): ext = string.lower(ext)
if ext == ".h":
if lexer.iswindows(): node = string.lower(node)
hpath = node + ".c"
# Converting local relative path into absolute path
if string.find(hpath, mainpath) == -1: # path not in include
hpath = os.path.join(mainpath, hpath) # add it
#print hpath
if hpath in sources: return None # Already here
if os.path.exists(hpath):
sources.append(hpath)
counter = counter + 1
#print "added", hpath
return hpath
else:
if hpath not in notexist :
notexist.append(hpath)
return None
# Process a c file for include statements
# The c file is added to a list and
# included headers are their c sources processed recursively.
def cprocess(name, filedir):
if name is None: return
name = decrease(name, filedir)
print "processing", name
f = open(name, 'r')
lines = f.readlines()
f.close()
if not lines: return
for l in lines:
if len(l) < 12: continue # minimum length 12, ex: #include "a"
if l[0] != '#': continue # not a directive, pass
if l[:9] != "#include ": continue # not an include statement, pass
hpath = l[8:] # remove the '#include' string
hpath = wstring.chop(hpath) # remove separators
hpath = lexer.removecomment(hpath) # remove comments
hpath = wstring.strip(hpath) # remove extra whitespaces
if hpath[-1] == ';': hpath = hpath[:-1] # ignore useless delimiter
if len(hpath) < 3: continue # minimum is: "a"
if lexer.isheader(hpath): # test the format
cfile = addc(hpath, filedir) # add to the list of headers
cprocess(cfile, filedir)
# End for
return
# Process a list of c sources
# Arguments are the main file and the current list of c sources
# updates the list of c sources according to dependancies
def processource(mainfile, startsource):
p, n = os.path.split(mainfile)
cprocess(mainfile, p)
index = 0
while(1):
if index >= len(sources): break
nextfile = sources[index];
nextfile = makesource(nextfile)
if iscode(nextfile):
cprocess(nextfile, p)
index = index + 1
startsource.extend(sources)
# Print the version
def version():
print VERSION
sys.exit()
# Displays options
def usage():
print """
Move Project - C to C++ converter - Scriptet.com
usage: mover mainfile.c oldpath@newpath [oldpath@newpath] etc...
or: mover mainfile.c @list_in_file
- mainfile.c (holds the main function), type the full path.
- oldpaths are current paths of c files.
- newpaths are new locations where to copy them into.
- you can type also: python mover.py
Example:
mover \lister\list.c \lister@\cpplist \gui@\cpplist
Under Unix the slash symbol is used instead.
All sources are copied and "#include" directives inside are updated.
"""
sys.exit()
def main():
global sources
global dico
param = sys.argv
paramlen = len(param)
if paramlen < 3:
usage()
replacements = [] # list of couples olddir:newdir
offset = 0
temp, pname = os.path.split(param[0])
if pname == "python" : offset += 1
mainfile = param[offset] # main file
temp, pname = os.path.split(mainfile)
if pname == "mover.py":
offset += 1
mainfile = param[offset]
if (len(mainfile) < 3):
usage()
if (mainfile[0] == '-'):
if (mainfile[1] == 'v'):
version()
usage()
listof = param[offset] # couple or file of couples
if listof[0] == '@': # reading list from file
listof = listof[1:]
f = open(listof, 'r')
replacements = f.readlines()
f.close()
else: # reading list from params
paths = []
offset += 1
while offset < paramlen:
couple = param[offset]
replacements.append(couple)
offset += 1
# separating old and new paths in couples
print "Directories..."
for couple in replacements:
if wstring.chop(couple) == "" : break
i = string.find(couple, '@')
old = couple[:i]
if lexer.iswindows():
old = string.lower(old)
dico[old] = couple[i + 1:]
print "from", old, "to", dico[old]
processheader(mainfile, sources)
processource(mainfile, sources) # extracting headers filenames
if len(sources) == 0:
sources.append(mainfile)
else:
print len(sources), " files found"
# moving files
for f in sources:
newf = changepath(f) # define a new path
if newf <> f:
print f, "-->", newf
move(f, newf) # move, and update include directives inside
return 0
main()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -