1 from c_parser import (
2 parse_files as _parse_files,
3 )
4 from c_parser.info import (
5 KIND,
6 TypeDeclaration,
7 resolve_parsed,
8 )
9 from c_parser.match import (
10 filter_by_kind,
11 group_by_kinds,
12 )
13 from . import (
14 analyze as _analyze,
15 datafiles as _datafiles,
16 )
17 from .info import Analysis
18
19
20 def analyze(filenmes, **kwargs):
21 results = iter_analyis_results(filenames, **kwargs)
22 return Analysis.from_results(results)
23
24
25 def iter_analysis_results(filenmes, *,
26 known=None,
27 **kwargs
28 ):
29 decls = iter_decls(filenames, **kwargs)
30 yield from analyze_decls(decls, known)
31
32
33 def iter_decls(filenames, *,
34 kinds=None,
35 parse_files=_parse_files,
36 **kwargs
37 ):
38 kinds = KIND.DECLS if kinds is None else (KIND.DECLS & set(kinds))
39 parse_files = parse_files or _parse_files
40
41 parsed = parse_files(filenames, **kwargs)
42 parsed = filter_by_kind(parsed, kinds)
43 for item in parsed:
44 yield resolve_parsed(item)
45
46
47 def analyze_decls(decls, known, *,
48 analyze_resolved=None,
49 handle_unresolved=True,
50 relroot=None,
51 ):
52 knowntypes, knowntypespecs = _datafiles.get_known(
53 known,
54 handle_unresolved=handle_unresolved,
55 analyze_resolved=analyze_resolved,
56 relroot=relroot,
57 )
58
59 decls = list(decls)
60 collated = group_by_kinds(decls)
61
62 types = {decl: None for decl in collated['type']}
63 typespecs = _analyze.get_typespecs(types)
64
65 def analyze_decl(decl):
66 return _analyze.analyze_decl(
67 decl,
68 typespecs,
69 knowntypespecs,
70 types,
71 knowntypes,
72 analyze_resolved=analyze_resolved,
73 )
74 _analyze.analyze_type_decls(types, analyze_decl, handle_unresolved)
75 for decl in decls:
76 if decl in types:
77 resolved = types[decl]
78 else:
79 resolved = analyze_decl(decl)
80 if resolved and handle_unresolved:
81 typedeps, _ = resolved
82 if not isinstance(typedeps, TypeDeclaration):
83 if not typedeps or None in typedeps:
84 raise NotImplementedError((decl, resolved))
85
86 yield decl, resolved
87
88
89 #######################################
90 # checks
91
92 def check_all(analysis, checks, *, failfast=False):
93 for check in checks or ():
94 for data, failure in check(analysis):
95 if failure is None:
96 continue
97
98 yield data, failure
99 if failfast:
100 yield None, None
101 break
102 else:
103 continue
104 # We failed fast.
105 break