2 # SPDX-License-Identifier: GPL-2.0
4 # Script to check sysctl documentation against source files
6 # Copyright (c) 2020 Stephen Kitt
9 # scripts/check-sysctl-docs -vtable="kernel" \
10 # Documentation/admin-guide/sysctl/kernel.rst \
11 # $(git grep -l register_sysctl)
13 # Specify -vdebug=1 to see debugging information
17 print "Please specify the table to look for using the table variable" > "/dev/stderr"
22 # The following globals are used:
23 # documented: maps documented entries (each key is an entry)
24 # entries: maps ctl_table names and procnames to counts (so
25 # enumerating the subkeys for a given ctl_table lists its
27 # curtable: the name of the current ctl_table struct
28 # curentry: the name of the current proc entry (procname when parsing
29 # a ctl_table, constructed path when parsing a ctl_path)
32 # Remove punctuation from the given value
33 function trimpunct
(value
) {
34 while (value ~
/^
["&]/) {
35 value = substr(value, 2)
37 while (value ~ /[]["&,}]$
/) {
38 value =
substr(value
, 1, length(value
) - 1)
43 # Print the information for the given entry
44 function printentry
(entry
) {
46 printf "* %s from %s", entry
, file
[entry
]
47 if (documented
[entry
]) {
48 printf " (documented)"
54 # Stage 1: build the list of documented entries
56 if (prevline ~
/Documentation
for/) {
57 # This is the main title
61 # The previous line is a section title, parse it
63 if (debug
) print "Parsing " $
0
65 for (i =
1; i
<=
NF; i
++) {
66 if (length($i
) ==
0) {
69 if (!inbrackets
&& substr($i
, 1, 1) ==
"(") {
74 if (length(token
) > 0 && token
!= "and") {
75 if (debug
) print trimpunct
($i
)
76 documented
[trimpunct
($i
)]++
79 if (inbrackets
&& substr($i
, length($i
), 1) ==
")") {
91 # Stage 2: process each file and find all sysctl tables
97 if (debug
) print "Processing file " FILENAME
100 /^static
( const
)? struct ctl_table
/ {
101 match($
0, /static
( const
)? struct ctl_table
([^
][]+)/, tables
)
103 if (debug
) print "Processing table " curtable
112 curtable
&& /\.procname
[\t ]*=
[\t ]*".+"/ {
113 match($
0, /.procname
[\t ]*=
[\t ]*"([^"]+)"/, names)
115 if (debug) print "Adding entry
" curentry " to table
" curtable
116 entries[curtable][curentry]++
117 file[curentry] = FILENAME
120 /register_sysctl.*/ {
121 match($0, /register_sysctl(|_init|_sz)\("([^
"]+)" *, *([^
,)]+)/, tables
)
122 if (debug
) print "Registering table " tables
[3] " at " tables
[2]
123 if (tables
[2] == table
) {
124 for (entry in entries
[tables
[3]]) {
131 match($
0, /([^
\t]+) *=
*kmemdup\
(([^
,]+) *,/, names
)
132 if (debug
) print "Found variable " names
[1] " for table " names
[2]
133 if (names
[2] in entries
) {
134 vars
[names
[1]] = names
[2]
138 /__register_sysctl_table.
*/ {
139 match($
0, /__register_sysctl_table\
([^
,]+, *"([^"]+)" *, *([^,]+)/, tables)
140 if (debug) print "Registering variable table
" tables[2] " at
" tables[1]
141 if (tables[1] == table && tables[2] in vars) {
142 for (entry in entries[vars[tables[2]]]) {
149 for (entry in documented) {
151 print "No implementation
for " entry