@ -1,36 +1,31 @@
#!/usr/bin/env python
""" Find Kconfig identifiere s that are referenced but not defined. """
""" Find Kconfig identifiers that are referenced but not defined. """
# Copyright (C ) 2014 Valentin Rothberg <valentinrothberg@gmail.com>
# Copyright (C ) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
# (c ) 2014 Valentin Rothberg <valentinrothberg@gmail.com>
# (c ) 2014 Stefan Hengelein <stefan.hengelein@fau.de>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
# Licensed under the terms of the GNU GPL License version 2
import os
import re
from subprocess import Popen , PIPE , STDOUT
# REGEX EXPRESSIONS
# regex expressions
OPERATORS = r " &| \ (| \ )| \ || \ ! "
FEATURE = r " \ w*[A-Z] {1} \ w* "
CONFIG_ DEF = r " ^ \ s*(?:menu) { ,1}config \ s+( " + FEATURE + r " ) \ s* "
FEATURE = r " (?: \ w*[A-Z0-9] \ w*) { 2,} "
DEF = r " ^ \ s*(?:menu) { ,1}config \ s+( " + FEATURE + r " ) \ s* "
EXPR = r " (?: " + OPERATORS + r " | \ s| " + FEATURE + r " )+ "
STMT = r " ^ \ s*(?:if|select|depends \ s+on) \ s+ " + EXPR
SOURCE_FEATURE = r " (?: \ W| \ b)+[D] { ,1}CONFIG_( " + FEATURE + r " ) "
# REGEX OBJECTS
# regex objects
REGEX_FILE_KCONFIG = re . compile ( r " .*Kconfig[ \ . \ w+ \ -]*$ " )
REGEX_FEATURE = re . compile ( r " ( " + FEATURE + r " ) " )
REGEX_SOURCE_FEATURE = re . compile ( r " (?:D| \ W| \ b)+CONFIG_( " + FEATURE + r " ) " )
REGEX_KCONFIG_DEF = re . compile ( CONFIG_ DEF)
REGEX_SOURCE_FEATURE = re . compile ( SOURCE_FEATURE )
REGEX_KCONFIG_DEF = re . compile ( DEF )
REGEX_KCONFIG_EXPR = re . compile ( EXPR )
REGEX_KCONFIG_STMT = re . compile ( STMT )
REGEX_KCONFIG_HELP = re . compile ( r " ^ \ s+(help|---help---) \ s*$ " )
@ -42,7 +37,7 @@ def main():
source_files = [ ]
kconfig_files = [ ]
defined_features = set ( )
referenced_features = dict ( )
referenced_features = dict ( ) # {feature: [files]}
# use 'git ls-files' to get the worklist
pop = Popen ( " git ls-files " , stdout = PIPE , stderr = STDOUT , shell = True )
@ -52,12 +47,12 @@ def main():
for gitfile in stdout . rsplit ( " \n " ) :
if " .git " in gitfile or " ChangeLog " in gitfile or \
os . path . isdir ( gitfile ) :
" .log " in gitfile or os . path . isdir ( gitfile ) :
continue
if REGEX_FILE_KCONFIG . match ( gitfile ) :
kconfig_files . append ( gitfile )
else :
# A ll non-Kconfig files are checked for consistency
# a ll non-Kconfig files are checked for consistency
source_files . append ( gitfile )
for sfile in source_files :
@ -68,15 +63,17 @@ def main():
print " Undefined symbol used \t File list "
for feature in sorted ( referenced_features ) :
# filter some false positives
if feature == " FOO " or feature == " BAR " or \
feature == " FOO_BAR " or feature == " XXX " :
continue
if feature not in defined_features :
if feature . endswith ( " _MODULE " ) :
# Avoid false positives for kernel modules
# a void false positives for kernel modules
if feature [ : - len ( " _MODULE " ) ] in defined_features :
continue
if " FOO " in feature or " BAR " in feature :
continue
files = referenced_features . get ( feature )
print " %s : \t %s " % ( feature , " , " . join ( files ) )
print " %s \t %s " % ( feature , " , " . join ( files ) )
def parse_source_file ( sfile , referenced_features ) :
@ -92,9 +89,9 @@ def parse_source_file(sfile, referenced_features):
for feature in features :
if not REGEX_FILTER_FEATURES . search ( feature ) :
continue
path s = referenced_features . get ( feature , set ( ) )
path s. add ( sfile )
referenced_features [ feature ] = path s
sfile s = referenced_features . get ( feature , set ( ) )
sfile s. add ( sfile )
referenced_features [ feature ] = sfile s
def get_features_in_line ( line ) :
@ -113,7 +110,7 @@ def parse_kconfig_file(kfile, defined_features, referenced_features):
for i in range ( len ( lines ) ) :
line = lines [ i ]
line = line . strip ( ' \n ' )
line = line . split ( " # " ) [ 0 ] # Ignore Kconfig comments
line = line . split ( " # " ) [ 0 ] # ignore comments
if REGEX_KCONFIG_DEF . match ( line ) :
feature_def = REGEX_KCONFIG_DEF . findall ( line )
@ -122,11 +119,11 @@ def parse_kconfig_file(kfile, defined_features, referenced_features):
elif REGEX_KCONFIG_HELP . match ( line ) :
skip = True
elif skip :
# I gnore content of help messages
# i gnore content of help messages
pass
elif REGEX_KCONFIG_STMT . match ( line ) :
features = get_features_in_line ( line )
# M ulti-line statements
# m ulti-line statements
while line . endswith ( " \\ " ) :
i + = 1
line = lines [ i ]