1 #!/usr/bin/gawk -f 2 # SPDX-License-Identifier: GPL-2.0 3 4 # Script to check sysctl documentation against 5 # 6 # Copyright (c) 2020 Stephen Kitt 7 8 # Example invocation: 9 # scripts/check-sysctl-docs -vtable="ker 10 # Documentation/admin-guide/sysc 11 # $(git grep -l register_sysctl) 12 # 13 # Specify -vdebug=1 to see debugging informati 14 15 BEGIN { 16 if (!table) { 17 print "Please specify the table to loo 18 exit 1 19 } 20 } 21 22 # The following globals are used: 23 # documented: maps documented entries (each ke 24 # entries: maps ctl_table names and procnames 25 # enumerating the subkeys for a given 26 # procnames) 27 # curtable: the name of the current ctl_table 28 # curentry: the name of the current proc entry 29 # a ctl_table, constructed path when 30 31 32 # Remove punctuation from the given value 33 function trimpunct(value) { 34 while (value ~ /^["&]/) { 35 value = substr(value, 2) 36 } 37 while (value ~ /[]["&,}]$/) { 38 value = substr(value, 1, length(value) 39 } 40 return value 41 } 42 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)" 49 } 50 print "" 51 } 52 53 54 # Stage 1: build the list of documented entrie 55 FNR == NR && /^=+$/ { 56 if (prevline ~ /Documentation for/) { 57 # This is the main title 58 next 59 } 60 61 # The previous line is a section title, pa 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 68 } 69 if (!inbrackets && substr($i, 1, 1) == 70 inbrackets = 1 71 } 72 if (!inbrackets) { 73 token = trimpunct($i) 74 if (length(token) > 0 && token != 75 if (debug) print trimpunct($i) 76 documented[trimpunct($i)]++ 77 } 78 } 79 if (inbrackets && substr($i, length($i 80 inbrackets = 0 81 } 82 } 83 } 84 85 FNR == NR { 86 prevline = $0 87 next 88 } 89 90 91 # Stage 2: process each file and find all sysc 92 BEGINFILE { 93 delete entries 94 curtable = "" 95 curentry = "" 96 delete vars 97 if (debug) print "Processing file " FILENA 98 } 99 100 /^static( const)? struct ctl_table/ { 101 match($0, /static( const)? struct ctl_tabl 102 curtable = tables[2] 103 if (debug) print "Processing table " curta 104 } 105 106 /^};$/ { 107 curtable = "" 108 curentry = "" 109 delete vars 110 } 111 112 curtable && /\.procname[\t ]*=[\t ]*".+"/ { 113 match($0, /.procname[\t ]*=[\t ]*"([^"]+)" 114 curentry = names[1] 115 if (debug) print "Adding entry " curentry 116 entries[curtable][curentry]++ 117 file[curentry] = FILENAME 118 } 119 120 /register_sysctl.*/ { 121 match($0, /register_sysctl(|_init|_sz)\("( 122 if (debug) print "Registering table " tabl 123 if (tables[2] == table) { 124 for (entry in entries[tables[3]]) { 125 printentry(entry) 126 } 127 } 128 } 129 130 /kmemdup.*/ { 131 match($0, /([^ \t]+) *= *kmemdup\(([^,]+) 132 if (debug) print "Found variable " names[1 133 if (names[2] in entries) { 134 vars[names[1]] = names[2] 135 } 136 } 137 138 /__register_sysctl_table.*/ { 139 match($0, /__register_sysctl_table\([^,]+, 140 if (debug) print "Registering variable tab 141 if (tables[1] == table && tables[2] in var 142 for (entry in entries[vars[tables[2]]] 143 printentry(entry) 144 } 145 } 146 } 147 148 END { 149 for (entry in documented) { 150 if (!seen[entry]) { 151 print "No implementation for " ent 152 } 153 } 154 }
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.