summaryrefslogtreecommitdiff
path: root/symbol_analyzer/main.py
blob: f137cfb6925fc2c44f37776c7c1d75e4dec4e04f (plain)
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
# this code was written to work, not to be maintained
# don't touch my trash

import os
import json

from extractor import parse_file
from parser import parse_definition_tokens
from symbols import symbols_from_struct_tokens, symbols_from_enum_tokens

stdlibs = [
    "stdlib.h", "assert.h", "stdio.h", "stdint.h",
    "inttypes.h", "mman.h", "stdatomic.h", "string.h", "unistd.h",
    "fcntl.h", "pthread.h"
]

files_content = {
    "stdbool.h": {
        "symbols": ["bool"],
        "usage": [],
        "imports": []
    }
}

def handle(file):
    files_content[file] = {}
    file_symbols = ["int", "char"]
    definitions, _ = parse_file(root + "/" + file)
    structs, enums, functions, typedefs, imports, usage = \
        parse_definition_tokens(
            definitions,
            file_symbols
        )
    file_symbols.extend(symbols_from_struct_tokens(structs))
    file_symbols.extend(symbols_from_struct_tokens(structs))
    file_symbols.extend(symbols_from_enum_tokens(enums))
    file_symbols.extend(functions)
    file_symbols.extend(typedefs)
    files_content[file]["symbols"] = set()
    files_content[file]["imports"] = list(map(lambda x: x[1:-1] ,imports))
    files_content[file]["usage"] = usage
    for item in file_symbols:
        if item.isnumeric():
            continue
        if "".join(item.split("_")).isalnum():
            files_content[file]["symbols"].add(item)

for root, subdirs, files in os.walk("include"):
    for file in files:
        handle(file)
for root, subdirs, files in os.walk("src"):
    for file in files:
        handle(file)

for file in files_content.keys():
    final_imports = set()
    to_resolve = []
    for imported_file in files_content[file]["imports"]:
        x = imported_file.split("/")[-1]
        to_resolve.append(x)
        final_imports.add(x)

    while len(to_resolve) > 0:
        f = to_resolve.pop()
        if f not in files_content:
            if f not in stdlibs:
                print(f)
            assert f in stdlibs
            continue
        new_items = files_content[f]["imports"]
        for new_item in new_items:
            x = new_item.split("/")[-1]
            to_resolve.append(x)
            final_imports.add(x)

    files_content[file]["imports"] = final_imports


for file, file_content in files_content.items():
    symbols = list(file_content["symbols"])
    for imported_file in file_content["imports"]:
        imported_file = imported_file.split("/")[-1]
        if imported_file not in files_content:
            assert imported_file in stdlibs
            continue
        symbols.extend(files_content[imported_file]["symbols"])
    symbols = set(symbols)
    usage_set = set(file_content["usage"])
    files_content[file]["unused"] = symbols - usage_set
    files_content[file]["used"] = symbols.intersection(usage_set)

output = []
for file in files_content.keys():
    output.append({
        "name": file,
        "imports": list(files_content[file]["imports"]),
        "symbols": list(files_content[file]["symbols"]),
        "unused": list(files_content[file]["unused"]),
        "used": list(files_content[file]["used"])
    })

with open("symbol_analyzer/analysis.js", "w") as f:
    f.write("data = ")
    json.dump(output, f)