drm/panthor: Don't add write fences to the shared BOs
[drm/drm-misc.git] / scripts / check-sysctl-docs
blob20274c63e7451a8722137e7077f4456f293f4e54
1 #!/usr/bin/gawk -f
2 # SPDX-License-Identifier: GPL-2.0
4 # Script to check sysctl documentation against source files
6 # Copyright (c) 2020 Stephen Kitt
8 # Example invocation:
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
15 BEGIN {
16 if (!table) {
17 print "Please specify the table to look for using the table variable" > "/dev/stderr"
18 exit 1
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
26 # procnames)
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)
40 return value
43 # Print the information for the given entry
44 function printentry(entry) {
45 seen[entry]++
46 printf "* %s from %s", entry, file[entry]
47 if (documented[entry]) {
48 printf " (documented)"
50 print ""
54 # Stage 1: build the list of documented entries
55 FNR == NR && /^=+$/ {
56 if (prevline ~ /Documentation for/) {
57 # This is the main title
58 next
61 # The previous line is a section title, parse it
62 $0 = prevline
63 if (debug) print "Parsing " $0
64 inbrackets = 0
65 for (i = 1; i <= NF; i++) {
66 if (length($i) == 0) {
67 continue
69 if (!inbrackets && substr($i, 1, 1) == "(") {
70 inbrackets = 1
72 if (!inbrackets) {
73 token = trimpunct($i)
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) == ")") {
80 inbrackets = 0
85 FNR == NR {
86 prevline = $0
87 next
91 # Stage 2: process each file and find all sysctl tables
92 BEGINFILE {
93 delete entries
94 curtable = ""
95 curentry = ""
96 delete vars
97 if (debug) print "Processing file " FILENAME
100 /^static( const)? struct ctl_table/ {
101 match($0, /static( const)? struct ctl_table ([^][]+)/, tables)
102 curtable = tables[2]
103 if (debug) print "Processing table " curtable
106 /^};$/ {
107 curtable = ""
108 curentry = ""
109 delete vars
112 curtable && /\.procname[\t ]*=[\t ]*".+"/ {
113 match($0, /.procname[\t ]*=[\t ]*"([^"]+)"/, names)
114 curentry = names[1]
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]]) {
125 printentry(entry)
130 /kmemdup.*/ {
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]]]) {
143 printentry(entry)
148 END {
149 for (entry in documented) {
150 if (!seen[entry]) {
151 print "No implementation for " entry