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
|
import os
import glob
from filetypes.ctypefiles import scanincludes
from filetypes.makefiles import scanmakefile
from filetypes.makefilecom import expand
from filetypes.autoconf import scanac
from filetypes.automake import initscan
def scandirfor(dir, filetypes):
"""Scans recursivly the supplied dir for provided filetypes.
And return a list of files found
"""
files = []
dirs = [f for f in os.listdir(dir)
if os.path.isdir(os.path.join(dir, f))]
for filetype in filetypes:
files += glob.glob(dir + "/*" + filetype)
for dir_path in dirs:
files += scandirfor(dir + "/" + dir_path, filetypes)
return files
def scanmakefiledeps(makefile):
"""Scans makefile for what files it would compile.
returns a list of files to scan for deps,
binaries build with the first makefile option,
additional includeflags and what the 'targets : deps'
are in the makefile
"""
curdir = os.path.split(makefile)[0] + "/"
olddir = os.getcwd()
makefile = openfile(makefile)
binaries = set() #the binaries that the .o file create
filestoscan = set()
impfiles = [] #look for these files
moptions = [] #make options scan these for -I... flags
os.chdir(curdir) #so makefiles commands can execute in the correct dir
targets,variables = scanmakefile(makefile)
deps = targets[0][1] #Use first make target
while deps != []:
newdeps = []
for dep in deps:
for target in targets:
if target[0] == dep:
newdeps += target[1]
if ".o" in dep or dep in impfiles:
impfiles += target[1]
moptions += target[2]
elif ".o" in target[1][0]:
binaries.add(target[0])
moptions += target[2]
deps = newdeps
#print(impfiles)
for impfile in impfiles:
filestoscan.add(curdir + impfile)
incflags = set()
for item in expand(moptions,variables):
if item[0:2] == "-I":
incflags.add(item[2:])
#print(filestoscan)
os.chdir(olddir)
return filestoscan,binaries,incflags,targets
def scanautotoolsdeps(acfile,amfile):
"""Scans autoconf file for useflags and the automake file in the same dir.
Scans the provided autoconf file and then looks for a automakefile in the
same dir. Autoconf scan returns a dict with useflags and a list with variables
that gets defined by those useflags.
Call the automake scan with the am file (that is in the same dir as the ac file)
and the list of variables from the autoconf scan and it will return a list of
default source files and a dict of files that gets pulled in by the useflag it
returns.
"""
#these are not really useflags yet. So perhaps change name?
topdir = os.path.split(amfile)[0] + "/"
useflags, iflst = scanac(openfile(acfile),topdir)
srcfiles, src_useflag, src_incflag = initscan(amfile, iflst)
#print(iflst)
#print(srcfiles)
#standard includes
includes = scanfilelist(srcfiles,src_incflag)
def inter_useflag(uselst):
if uselst[1] == "yes" or uselst[1] == "!no":
usearg = uselst[0]
elif uselst[1] == "no" or uselst[1] == "!yes":
usearg = "!" + uselst[1]
else:
usearg = uselst[0] + "=" + uselst[1]
return usearg
#useflag includes
useargs = {}
for src in src_useflag:
usearg = inter_useflag(src_useflag[src])
if usearg in useargs:
useargs[usearg] += [src]
else:
useargs[usearg] = [src]
for usearg in useargs:
useargs[usearg] = scanfilelist(useargs[usearg],src_incflag)
#print(useargs)
#print(includes)
return useflags,includes,useargs
def scanfilelist(filelist,src_incflag):
""" Scan files in filelist for #includes
returns a includes list with this structure:
[set(),set(),dict()]
There the first two sets contains global and local includes
and the dict contains variables that can pull in additional includes
with the same structure as above
"""
global_hfiles = set()
local_hfiles = set()
inclst = [global_hfiles,local_hfiles,{}]
for file in filelist:
#print(file)
incpaths = src_incflag[file]
filestring = openfile(file)
if not filestring == None:
inclst = scanincludes(filestring,inclst,os.path.split(file)[0],incpaths)
return(inclst)
def scanproject(dir,projecttype):
"""Scan a project (source) dir for files that may build it
This tries to guess which kind of project it is. IE
autotools? makefile?
"""
if projecttype == "guess":
filestolookfor = ["Makefile","makefile",
"configure.ac","configure.in"] #add more later
elif projecttype == "makefile":
filestolookfor = ["Makefile","makefile"]
elif projecttype == "autotools":
filestolookfor = ["configure.ac","configure.in"]
mfile = scandirfor(dir, filestolookfor)[0] #use first file found
print(mfile)
if mfile == "Makefile" or mfile == "makefile":
(scanlist,binaries,incflags,targets) = scanmakefiledeps(mfile)
#this is broken now... rewrite
return scanfilelist(scanlist),binaries,incflags,targets
else:
amfile = os.path.split(mfile)[0] + "/" + "Makefile.am"
return scanautotoolsdeps(mfile,amfile)
def openfile(file):
"""Open a file and return the content as a string.
Returns nothing and print an error if the file cannot be read
"""
try:
with open(file, encoding="utf-8", errors="replace") as inputfile:
return inputfile.read()
except IOError:
print('cannot open', file)
|