1818from ppci .common import CompilerError
1919from ppci .lang .c import COptions , create_ast
2020from ppci .lang .c .nodes import declarations
21+ from ppci .utils .htmlgen import Document
2122
2223this_path = Path (__file__ ).resolve ().parent
2324root_path = this_path .parent
@@ -35,14 +36,30 @@ def main():
3536 analyze_sources (args .source_dir , defines )
3637
3738
38- def get_tag (filename : Path ) -> str :
39- return filename .stem
40-
41-
4239def analyze_sources (source_dir : Path , defines ):
4340 """Analyze a directory with sourcecode"""
4441
4542 # Phase 1: acquire ast's:
43+ asts = read_sources (source_dir , defines )
44+
45+ # Phase 2: do some bad-ass analysis:
46+ global_variables = []
47+ functions = []
48+ for _source_filename , _source_code , ast in asts :
49+ for decl in ast .declarations :
50+ if isinstance (decl , declarations .VariableDeclaration ):
51+ global_variables .append (decl )
52+ elif isinstance (decl , declarations .FunctionDeclaration ):
53+ if decl .body is not None and decl .storage_class != "static" :
54+ functions .append (decl )
55+
56+ functions .sort (key = lambda d : d .name )
57+
58+ # Phase 3: generate html report?
59+ gen_report (functions , asts )
60+
61+
62+ def read_sources (source_dir : Path , defines ):
4663 arch_info = get_arch ("x86_64" ).info
4764 coptions = COptions ()
4865 # TODO: infer defines from code:
@@ -65,100 +82,73 @@ def analyze_sources(source_dir: Path, defines):
6582 else :
6683 asts .append ((source_filename , source_code , ast ))
6784 logger .info ("Got %s ast's" , len (asts ))
85+ return asts
6886
69- # Phase 2: do some bad-ass analysis:
70- global_variables = []
71- functions = []
72- for _source_filename , _source_code , ast in asts :
73- for decl in ast .declarations :
74- if isinstance (decl , declarations .VariableDeclaration ):
75- global_variables .append (decl )
76- elif isinstance (decl , declarations .FunctionDeclaration ):
77- if decl .body is not None and decl .storage_class != "static" :
78- functions .append (decl )
7987
80- functions .sort (key = lambda d : d .name )
88+ def get_tag (filename : Path ) -> str :
89+ return filename .stem
8190
82- # Phase 3: generate html report?
91+
92+ def gen_report (functions , asts ):
8393 html_filename = "analyze_report.html"
8494 html_path = (
8595 build_path / html_filename
8696 if build_path .exists ()
8797 else Path (html_filename )
8898 )
8999 logger .info (f"Creating { html_path } " )
90- with open (html_path , "w" ) as f :
91- c_lexer = CLexer ()
100+ with open (html_path , "w" ) as f , Document (f ) as doc :
92101 formatter = HtmlFormatter (lineanchors = "fubar" , linenos = "inline" )
93- print (
94- f"""<html>
95- <head>
96- <style>
97- { formatter .get_style_defs ()}
98- </style>
99- </head>
100- <body>
101- """ ,
102- file = f ,
103- )
104-
105- print ("<h1>Overview</h1>" , file = f )
106- print ("<table>" , file = f )
107- print ("<tr><th>Name</th><th>Location</th><th>typ</th></tr>" , file = f )
108- for func in functions :
109- tagname = get_tag (func .location .filename )
110- name = f'<a href="#{ tagname } -{ func .location .row } ">{ func .name } </a>'
111- print (
112- "<tr><td>{}</td><td>{}</td><td>{}</td></tr>" .format (
113- name , "" , ""
114- ),
115- file = f ,
102+ with doc .head () as head :
103+ head .title ("Analyzed C code" )
104+ head .style (formatter .get_style_defs ())
105+
106+ with doc .body () as body :
107+ body .h1 ("Overview" )
108+ with body .table () as table :
109+ table .header ("Name" , "Location" )
110+ for func in functions :
111+ tagname = get_tag (func .location .filename )
112+ tagname = f"{ tagname } -{ func .location .row } "
113+ name = f'<a href="#{ tagname } ">{ func .name } </a>'
114+ location = str (func .location )
115+ table .row (name , location , escape = False )
116+
117+ body .h1 ("Files" )
118+ for source_filename , source_code , ast in asts :
119+ report_single_file (body , source_filename , source_code , ast )
120+
121+
122+ def report_single_file (body , source_filename , source_code , ast ):
123+ tagname = get_tag (source_filename )
124+ body .h2 (str (source_filename ))
125+ with body .table () as table :
126+ table .header ("Name" , "Location" , "typ" , "storage_class" )
127+ for decl in ast .declarations :
128+ if isinstance (decl , declarations .VariableDeclaration ):
129+ tp = "var"
130+ elif isinstance (decl , declarations .FunctionDeclaration ):
131+ tp = "func"
132+ else :
133+ tp = "other"
134+
135+ if source_filename == decl .location .filename :
136+ anchor = f"{ tagname } -{ decl .location .row } "
137+ name = f'<a href="#{ anchor } ">{ decl .name } </a>'
138+ else :
139+ name = decl .name
140+ table .row (
141+ name ,
142+ str (decl .location ),
143+ tp ,
144+ str (decl .storage_class ),
145+ escape = False ,
116146 )
117147
118- print ("</table>" , file = f )
119- print ("<h1>Files</h1>" , file = f )
120-
121- for source_filename , source_code , ast in asts :
122- tagname = get_tag (source_filename )
123- formatter = HtmlFormatter (lineanchors = tagname , linenos = "inline" )
124- print (f"<h2>{ source_filename } </h2>" , file = f )
125- print ("<table>" , file = f )
126- print (
127- "<tr><th>Name</th><th>Location</th><th>typ</th></tr>" , file = f
128- )
129- for decl in ast .declarations :
130- if isinstance (decl , declarations .VariableDeclaration ):
131- tp = "var"
132- elif isinstance (decl , declarations .FunctionDeclaration ):
133- tp = "func"
134- else :
135- tp = "other"
136-
137- tp += str (decl .storage_class )
138-
139- if source_filename == decl .location .filename :
140- anchor = f"{ tagname } -{ decl .location .row } "
141- name = f'<a href="#{ anchor } ">{ decl .name } </a>'
142- else :
143- name = decl .name
144-
145- print (
146- f"<tr><td>{ name } </td>"
147- f"<td>{ decl .location } </td>"
148- f"<td>{ tp } </td></tr>" ,
149- file = f ,
150- )
151- print ("</table>" , file = f )
152- print (""" <div>""" , file = f )
153- print (highlight (source_code , c_lexer , formatter ), file = f )
154- print (""" </div>""" , file = f )
155-
156- print (
157- """</body>
158- </html>
159- """ ,
160- file = f ,
161- )
148+ c_lexer = CLexer ()
149+ formatter = HtmlFormatter (lineanchors = tagname , linenos = "inline" )
150+ with body .tag ("div" ):
151+ print (highlight (source_code , c_lexer , formatter ), file = body ._f )
162152
163153
164154if __name__ == "__main__" :
0 commit comments