diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index d9f6a37680..4bcd594a09 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -47,14 +47,14 @@ jobs: - name: Run mypy run: | python3 -m mypy --version - python3 -m mypy src/ukify/ukify.py test/integration-test-wrapper.py + python3 -m mypy src/test/generate-sym-test.py src/ukify/ukify.py test/integration-test-wrapper.py - name: Run ruff check run: | ruff --version - ruff check src/ukify/ukify.py test/integration-test-wrapper.py + ruff check src/test/generate-sym-test.py src/ukify/ukify.py test/integration-test-wrapper.py - name: Run ruff format run: | ruff --version - ruff format --check src/ukify/ukify.py test/integration-test-wrapper.py + ruff format --check src/test/generate-sym-test.py src/ukify/ukify.py test/integration-test-wrapper.py diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym index 2c0839b8e5..35f55d0cdd 100644 --- a/src/libsystemd/libsystemd.sym +++ b/src/libsystemd/libsystemd.sym @@ -1062,5 +1062,7 @@ global: LIBSYSTEMD_258 { global: + sd_json_variant_type_from_string; + sd_json_variant_type_to_string; sd_varlink_reset_fds; } LIBSYSTEMD_257; diff --git a/src/libsystemd/sd-json/sd-json.c b/src/libsystemd/sd-json/sd-json.c index a8a5e47761..2f2f6e0d00 100644 --- a/src/libsystemd/sd-json/sd-json.c +++ b/src/libsystemd/sd-json/sd-json.c @@ -5808,4 +5808,4 @@ static const char* const sd_json_variant_type_table[_SD_JSON_VARIANT_TYPE_MAX] = [SD_JSON_VARIANT_NULL] = "null", }; -DEFINE_STRING_TABLE_LOOKUP(sd_json_variant_type, sd_json_variant_type_t); +_DEFINE_STRING_TABLE_LOOKUP(sd_json_variant_type, sd_json_variant_type_t, _public_); diff --git a/src/test/generate-sym-test.py b/src/test/generate-sym-test.py index 2e5177c934..7b5ded936c 100755 --- a/src/test/generate-sym-test.py +++ b/src/test/generate-sym-test.py @@ -1,78 +1,147 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: LGPL-2.1-or-later +# +# ruff: noqa: E501 UP015 import os import re import sys +from typing import IO -def process_sym_file(file): + +def process_sym_file(file: IO[str]) -> None: 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])) + print(f' {{ "{m[1]}", &{m[1]} }},') else: - print(' {{"{0}", {0}}},'.format(m[1])) + print(f' {{ "{m[1]}", {m[1]} }},') -def process_source_file(file): + +def process_header_file(file: IO[str]) -> None: + for line in file: + if ( + line.startswith('#') + or line.startswith('typedef') + or line.startswith('extern "C"') + or line.startswith('__extension__') + or line.startswith('/*') + or ' __inline__ ' in line + or re.search(r'^\s+', line) + ): + continue + + m = re.search(r'^(.*)\s*__attribute__', line) + if m: + line = m[1] + + m = re.search(r'^(.*)\s*_sd_printf_', line) + if m: + line = m[1] + + # Functions + m = re.search(r'^(\S+\s+)+\**(\w+)\s*\(', line) + if m: + print(f' {{ "{m[2]}", {m[2]} }},') + continue + + # Variables + m = re.search(r'^extern\s', line) + if m: + n = line.split()[-1].rstrip(';') + print(f' {{ "{n}", &{n} }},') + continue + + # Functions defined by macro + m = re.search(r'_SD_DEFINE_POINTER_CLEANUP_FUNC\(\w+,\s*(\w+)\)', line) + if m: + print(f' {{ "{m[1]}", {m[1]} }},') + continue + + +def process_source_file(file: IO[str]) -> None: for line in file: # Functions m = re.search(r'^_public_\s+(\S+\s+)+\**(\w+)\s*\(', line) if m: - print(' {{ "{0}", {0} }},'.format(m[2])) + print(f' {{ "{m[2]}", {m[2]} }},') + continue + # Variables m = re.search(r'^_public_\s+(\S+\s+)+\**(\w+)\s*=', line) if m: - print(' {{ "{0}", &{0} }},'.format(m[2])) + print(f' {{ "{m[2]}", &{m[2]} }},') + continue + # 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])) + print(f' {{ "{m[1]}_ref", {m[1]}_ref }},') + continue + 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(f' {{ "{m[1]}_unref", {m[1]}_unref }},') + continue -print('''/* SPDX-License-Identifier: LGPL-2.1-or-later */ + m = re.search(r'^DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC\([^,]+,\s*(\w+)\s*,', line) + if m: + print(f' {{ "{m[1]}_ref", {m[1]}_ref }},') + print(f' {{ "{m[1]}_unref", {m[1]}_unref }},') + continue + + m = re.search(r'^_DEFINE_STRING_TABLE_LOOKUP\((\w+),\s*\w+,\s*_public_\s*\)', line) + if m: + print(f' {{ "{m[1]}_from_string", {m[1]}_from_string }},') + print(f' {{ "{m[1]}_to_string", {m[1]}_to_string }},') + continue + + +print("""/* SPDX-License-Identifier: LGPL-2.1-or-later */ #include #include #include -''') +""") for header in sys.argv[3:]: print('#include "{}"'.format(header.split('/')[-1])) -print(''' +print(""" /* We want to check deprecated symbols too, without complaining */ #pragma GCC diagnostic ignored "-Wdeprecated-declarations" -''') +""") -print(''' +print(""" struct symbol { const char *name; const void *symbol; }; -static struct symbol symbols_from_sym[] = {''') +static struct symbol symbols_from_sym[] = {""") -with open(sys.argv[1], "r") as f: +with open(sys.argv[1], 'r') as f: process_sym_file(f) -print(''' {} -}, symbols_from_source[] = {''') +print(""" {} +}, symbols_from_header[] = {""") + +for header in sys.argv[3:]: + with open(header, 'r') as f: + process_header_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"): + if not filename.endswith('.c') and not filename.endswith('.h'): continue - with open(os.path.join(dirpath, filename), "r") as f: + with open(os.path.join(dirpath, filename), 'r') as f: process_source_file(f) -print(''' {} +print(""" {} }; static int sort_callback(const void *a, const void *b) { @@ -81,34 +150,66 @@ static int sort_callback(const void *a, const void *b) { } int main(void) { - size_t i, j; + size_t size = sizeof(symbols_from_sym[0]), + n_sym = sizeof(symbols_from_sym)/sizeof(symbols_from_sym[0]) - 1, + n_header = sizeof(symbols_from_header)/sizeof(symbols_from_header[0]) - 1, + n_source = sizeof(symbols_from_source)/sizeof(symbols_from_source[0]) - 1; - 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); + qsort(symbols_from_sym, n_sym, size, sort_callback); + qsort(symbols_from_header, n_header, size, sort_callback); + qsort(symbols_from_source, n_source, size, sort_callback); puts("From symbol file:"); - for (i = 0; symbols_from_sym[i].name; i++) + for (size_t i = 0; i < n_sym; i++) printf("%p: %s\\n", symbols_from_sym[i].symbol, symbols_from_sym[i].name); + puts("\\nFrom header files:"); + for (size_t i = 0; i < n_header; i++) + printf("%p: %s\\n", symbols_from_header[i].symbol, symbols_from_header[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); + for (size_t i = 0; i < n_source; i++) + printf("%p: %s\\n", symbols_from_source[i].symbol, symbols_from_source[i].name); puts(""); - printf("Found %zu symbols from symbol file.\\n", i); - printf("Found %zu symbols from source files.\\n", j); + printf("Found %zu symbols from symbol file.\\n", n_sym); + printf("Found %zu symbols from header files.\\n", n_header); + printf("Found %zu symbols from source files.\\n", n_source); - 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) + unsigned n_error = 0; + + for (size_t i = 0; i < n_sym; i++) { + if (!bsearch(symbols_from_sym+i, symbols_from_header, n_header, size, sort_callback)) { + printf("Found in symbol file, but not in headers: %s\\n", symbols_from_sym[i].name); + n_error++; + } + if (!bsearch(symbols_from_sym+i, symbols_from_source, n_source, size, sort_callback)) { printf("Found in symbol file, but not in sources: %s\\n", symbols_from_sym[i].name); + n_error++; + } } - 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); + for (size_t i = 0; i < n_header; i++) { + if (!bsearch(symbols_from_header+i, symbols_from_sym, n_sym, size, sort_callback)) { + printf("Found in header file, but not in symbol file: %s\\n", symbols_from_header[i].name); + n_error++; + } + if (!bsearch(symbols_from_header+i, symbols_from_source, n_source, size, sort_callback)) { + printf("Found in header file, but not in sources: %s\\n", symbols_from_header[i].name); + n_error++; + } } - return i == j ? EXIT_SUCCESS : EXIT_FAILURE; -}''') + for (size_t i = 0; i < n_source; i++) { + if (!bsearch(symbols_from_source+i, symbols_from_sym, n_sym, size, sort_callback)) { + printf("Found in source file, but not in symbol file: %s\\n", symbols_from_source[i].name); + n_error++; + } + if (!bsearch(symbols_from_source+i, symbols_from_header, n_header, size, sort_callback)) { + printf("Found in source file, but not in header: %s\\n", symbols_from_source[i].name); + n_error++; + } + } + + return n_error == 0 ? EXIT_SUCCESS : EXIT_FAILURE; +}""")