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
|
#!/usr/bin/env python3
# SPDX-License-Identifier: LGPL-2.1-or-later
import os
import re
import sys
def process_sym_file(file):
for line in file:
m = re.search(r'^ +([a-zA-Z0-9_]+);', line)
if m:
if m[1] == 'sd_bus_object_vtable_format':
print(' {{"{0}", &{0}}},'.format(m[1]))
else:
print(' {{"{0}", {0}}},'.format(m[1]))
def process_source_file(file):
for line in file:
# Functions
m = re.search(r'^_public_\s+(\S+\s+)+\**(\w+)\s*\(', line)
if m:
print(' {{ "{0}", {0} }},'.format(m[2]))
# Variables
m = re.search(r'^_public_\s+(\S+\s+)+\**(\w+)\s*=', line)
if m:
print(' {{ "{0}", &{0} }},'.format(m[2]))
# Functions defined through a macro
m = re.search(r'^DEFINE_PUBLIC_TRIVIAL_REF_FUNC\([^,]+,\s*(\w+)\s*\)', line)
if m:
print(' {{ "{0}_ref", {0}_ref }},'.format(m[1]))
m = re.search(r'^DEFINE_PUBLIC_TRIVIAL_UNREF_FUNC\([^,]+,\s*(\w+)\s*,', line)
if m:
print(' {{ "{0}_unref", {0}_unref }},'.format(m[1]))
m = re.search(r"^DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC\([^,]+,\s*(\w+)\s*,", line)
if m:
print(' {{ "{0}_ref", {0}_ref }},'.format(m[1]))
print(' {{ "{0}_unref", {0}_unref }},'.format(m[1]))
print('''/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
''')
for header in sys.argv[3:]:
print('#include "{}"'.format(header.split('/')[-1]))
print('''
/* We want to check deprecated symbols too, without complaining */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
''')
print('''
struct symbol {
const char *name;
const void *symbol;
};
static struct symbol symbols_from_sym[] = {''')
with open(sys.argv[1], "r") as f:
process_sym_file(f)
print(''' {}
}, symbols_from_source[] = {''')
for dirpath, _, filenames in sorted(os.walk(sys.argv[2])):
for filename in sorted(filenames):
if not filename.endswith(".c") and not filename.endswith(".h"):
continue
with open(os.path.join(dirpath, filename), "r") as f:
process_source_file(f)
print(''' {}
};
static int sort_callback(const void *a, const void *b) {
const struct symbol *x = a, *y = b;
return strcmp(x->name, y->name);
}
int main(void) {
size_t i, j;
qsort(symbols_from_sym, sizeof(symbols_from_sym)/sizeof(symbols_from_sym[0])-1, sizeof(symbols_from_sym[0]), sort_callback);
qsort(symbols_from_source, sizeof(symbols_from_source)/sizeof(symbols_from_source[0])-1, sizeof(symbols_from_source[0]), sort_callback);
puts("From symbol file:");
for (i = 0; symbols_from_sym[i].name; i++)
printf("%p: %s\\n", symbols_from_sym[i].symbol, symbols_from_sym[i].name);
puts("\\nFrom source files:");
for (j = 0; symbols_from_source[j].name; j++)
printf("%p: %s\\n", symbols_from_source[j].symbol, symbols_from_source[j].name);
puts("");
printf("Found %zu symbols from symbol file.\\n", i);
printf("Found %zu symbols from source files.\\n", j);
for (i = 0; symbols_from_sym[i].name; i++) {
struct symbol *n = bsearch(symbols_from_sym+i, symbols_from_source, sizeof(symbols_from_source)/sizeof(symbols_from_source[0])-1, sizeof(symbols_from_source[0]), sort_callback);
if (!n)
printf("Found in symbol file, but not in sources: %s\\n", symbols_from_sym[i].name);
}
for (j = 0; symbols_from_source[j].name; j++) {
struct symbol *n = bsearch(symbols_from_source+j, symbols_from_sym, sizeof(symbols_from_sym)/sizeof(symbols_from_sym[0])-1, sizeof(symbols_from_sym[0]), sort_callback);
if (!n)
printf("Found in sources, but not in symbol file: %s\\n", symbols_from_source[j].name);
}
return i == j ? EXIT_SUCCESS : EXIT_FAILURE;
}''')
|