| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 1 | #!/usr/bin/env python3 | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 2 |  | 
|  | 3 | # This program is free software; you can redistribute it and/or modify | 
|  | 4 | # it under the terms of the GNU General Public License as published by | 
|  | 5 | # the Free Software Foundation; either version 2 of the License, or | 
|  | 6 | # (at your option) any later version. | 
|  | 7 | # | 
|  | 8 | # This program is distributed in the hope that it will be useful, | 
|  | 9 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | 10 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|  | 11 | # GNU General Public License for more details. | 
|  | 12 | # | 
|  | 13 | # You should have received a copy of the GNU General Public License | 
|  | 14 | # along with this program; if not, write to the Free Software | 
|  | 15 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 
|  | 16 | # | 
|  | 17 | # Copyright (C) Darren Hart <dvhart@linux.intel.com>, 2010 | 
|  | 18 |  | 
|  | 19 |  | 
|  | 20 | import sys | 
|  | 21 | import getopt | 
|  | 22 | import os | 
|  | 23 | import os.path | 
|  | 24 | import re | 
|  | 25 |  | 
|  | 26 | def usage(): | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 27 | print('Usage: %s -d FILENAME [-d FILENAME]* -m METADIR [-m MATADIR]*' % os.path.basename(sys.argv[0])) | 
|  | 28 | print('  -d FILENAME         documentation file to search') | 
|  | 29 | print('  -h, --help          display this help and exit') | 
|  | 30 | print('  -m METADIR          meta directory to search for recipes') | 
|  | 31 | print('  -t FILENAME         documentation config file (for doc tags)') | 
|  | 32 | print('  -T                  Only display variables with doc tags (requires -t)') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 33 |  | 
|  | 34 | def recipe_bbvars(recipe): | 
|  | 35 | ''' Return a unique set of every bbvar encountered in the recipe ''' | 
|  | 36 | prog = re.compile("[A-Z_]+") | 
|  | 37 | vset = set() | 
|  | 38 | try: | 
|  | 39 | r = open(recipe) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 40 | except IOError as err: | 
|  | 41 | print('WARNING: Failed to open recipe ', recipe) | 
|  | 42 | print(err.args[1]) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 43 |  | 
|  | 44 | for line in r: | 
|  | 45 | # Strip any comments from the line | 
|  | 46 | line = line.rsplit('#')[0] | 
|  | 47 | vset = vset.union(set(prog.findall(line))) | 
|  | 48 | r.close() | 
|  | 49 |  | 
|  | 50 | bbvars = {} | 
|  | 51 | for v in vset: | 
|  | 52 | bbvars[v] = 1 | 
|  | 53 |  | 
|  | 54 | return bbvars | 
|  | 55 |  | 
|  | 56 | def collect_bbvars(metadir): | 
|  | 57 | ''' Walk the metadir and collect the bbvars from each recipe found ''' | 
|  | 58 | bbvars = {} | 
|  | 59 | for root,dirs,files in os.walk(metadir): | 
|  | 60 | for name in files: | 
|  | 61 | if name.find(".bb") >= 0: | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 62 | for key in recipe_bbvars(os.path.join(root,name)).keys(): | 
|  | 63 | if key in bbvars: | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 64 | bbvars[key] = bbvars[key] + 1 | 
|  | 65 | else: | 
|  | 66 | bbvars[key] = 1 | 
|  | 67 | return bbvars | 
|  | 68 |  | 
|  | 69 | def bbvar_is_documented(var, docfiles): | 
|  | 70 | prog = re.compile(".*($|[^A-Z_])%s([^A-Z_]|$)" % (var)) | 
|  | 71 | for doc in docfiles: | 
|  | 72 | try: | 
|  | 73 | f = open(doc) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 74 | except IOError as err: | 
|  | 75 | print('WARNING: Failed to open doc ', doc) | 
|  | 76 | print(err.args[1]) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 77 | for line in f: | 
|  | 78 | if prog.match(line): | 
|  | 79 | return True | 
|  | 80 | f.close() | 
|  | 81 | return False | 
|  | 82 |  | 
|  | 83 | def bbvar_doctag(var, docconf): | 
|  | 84 | prog = re.compile('^%s\[doc\] *= *"(.*)"' % (var)) | 
|  | 85 | if docconf == "": | 
|  | 86 | return "?" | 
|  | 87 |  | 
|  | 88 | try: | 
|  | 89 | f = open(docconf) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 90 | except IOError as err: | 
|  | 91 | return err.args[1] | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 92 |  | 
|  | 93 | for line in f: | 
|  | 94 | m = prog.search(line) | 
|  | 95 | if m: | 
|  | 96 | return m.group(1) | 
|  | 97 |  | 
|  | 98 | f.close() | 
|  | 99 | return "" | 
|  | 100 |  | 
|  | 101 | def main(): | 
|  | 102 | docfiles = [] | 
|  | 103 | metadirs = [] | 
|  | 104 | bbvars = {} | 
|  | 105 | undocumented = [] | 
|  | 106 | docconf = "" | 
|  | 107 | onlydoctags = False | 
|  | 108 |  | 
|  | 109 | # Collect and validate input | 
|  | 110 | try: | 
|  | 111 | opts, args = getopt.getopt(sys.argv[1:], "d:hm:t:T", ["help"]) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 112 | except getopt.GetoptError as err: | 
|  | 113 | print('%s' % str(err)) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 114 | usage() | 
|  | 115 | sys.exit(2) | 
|  | 116 |  | 
|  | 117 | for o, a in opts: | 
|  | 118 | if o in ('-h', '--help'): | 
|  | 119 | usage() | 
|  | 120 | sys.exit(0) | 
|  | 121 | elif o == '-d': | 
|  | 122 | if os.path.isfile(a): | 
|  | 123 | docfiles.append(a) | 
|  | 124 | else: | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 125 | print('ERROR: documentation file %s is not a regular file' % a) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 126 | sys.exit(3) | 
|  | 127 | elif o == '-m': | 
|  | 128 | if os.path.isdir(a): | 
|  | 129 | metadirs.append(a) | 
|  | 130 | else: | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 131 | print('ERROR: meta directory %s is not a directory' % a) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 132 | sys.exit(4) | 
|  | 133 | elif o == "-t": | 
|  | 134 | if os.path.isfile(a): | 
|  | 135 | docconf = a | 
|  | 136 | elif o == "-T": | 
|  | 137 | onlydoctags = True | 
|  | 138 | else: | 
|  | 139 | assert False, "unhandled option" | 
|  | 140 |  | 
|  | 141 | if len(docfiles) == 0: | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 142 | print('ERROR: no docfile specified') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 143 | usage() | 
|  | 144 | sys.exit(5) | 
|  | 145 |  | 
|  | 146 | if len(metadirs) == 0: | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 147 | print('ERROR: no metadir specified') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 148 | usage() | 
|  | 149 | sys.exit(6) | 
|  | 150 |  | 
|  | 151 | if onlydoctags and docconf == "": | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 152 | print('ERROR: no docconf specified') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 153 | usage() | 
|  | 154 | sys.exit(7) | 
|  | 155 |  | 
|  | 156 | # Collect all the variable names from the recipes in the metadirs | 
|  | 157 | for m in metadirs: | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 158 | for key,cnt in collect_bbvars(m).items(): | 
|  | 159 | if key in bbvars: | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 160 | bbvars[key] = bbvars[key] + cnt | 
|  | 161 | else: | 
|  | 162 | bbvars[key] = cnt | 
|  | 163 |  | 
|  | 164 | # Check each var for documentation | 
|  | 165 | varlen = 0 | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 166 | for v in bbvars.keys(): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 167 | if len(v) > varlen: | 
|  | 168 | varlen = len(v) | 
|  | 169 | if not bbvar_is_documented(v, docfiles): | 
|  | 170 | undocumented.append(v) | 
|  | 171 | undocumented.sort() | 
|  | 172 | varlen = varlen + 1 | 
|  | 173 |  | 
|  | 174 | # Report all undocumented variables | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 175 | print('Found %d undocumented bb variables (out of %d):' % (len(undocumented), len(bbvars))) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 176 | header = '%s%s%s' % (str("VARIABLE").ljust(varlen), str("COUNT").ljust(6), str("DOCTAG").ljust(7)) | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 177 | print(header) | 
|  | 178 | print(str("").ljust(len(header), '=')) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 179 | for v in undocumented: | 
|  | 180 | doctag = bbvar_doctag(v, docconf) | 
|  | 181 | if not onlydoctags or not doctag == "": | 
| Patrick Williams | c0f7c04 | 2017-02-23 20:41:17 -0600 | [diff] [blame] | 182 | print('%s%s%s' % (v.ljust(varlen), str(bbvars[v]).ljust(6), doctag)) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 183 |  | 
|  | 184 |  | 
|  | 185 | if __name__ == "__main__": | 
|  | 186 | main() |