+# $Id$
# A script for building kernel config from multiarch config file.
# It also has some file merging facilities.
#
# usage:
-# awk -v arch=%{_target_base_arch} -f path/to/kernel-config.awk \
-# kernel-multiarch.config kernel-%{arch}.config kernel-%{some_feature}.config \
+# awk -v basearch=%{_target_base_arch} -v arch=%{_target_cpu} -f path/to/kernel-config.awk \
+# kernel-important.config kernel-multiarch.config \
+# kernel-%{arch}.config kernel-%{some_feature}.config \
# > .config
#
+# Authors:
+# - Przemysław Iskra <sparky@pld-linux.org>
+# parts based on kernel-config.py, by:
+# - arekm@pld-linux.org
+# - glen@pld-linux.org
+#
# TODO:
-# - check value correctness, should allow only:
-# y, m, n, -[0-9]+, 0x[0-9A-Fa-f]+, ".*"
-# - smarter arch split, there could be strings with spaces
-# ( kernel-config.py does not suppoty it either )
# - use as many warnings as possible, we want our configs to be clean
-# - allow more multiarch configs
+
+# no:
+# CONFIG_SOMETHING=n
+# SOMETHING=n
+# CONFIG_SOMETHING all=n
+# SOMETHING all=n
+# # CONFIG_SOMETHING is not set -- special case
+
+# yes/module/other
+# CONFIG_SOMETHING=y
+# SOMETHING=y
+# CONFIG_SOMETHING all=y
+# SOMETHING all=y
+
+
+# return actual file name (without path) and line number
+function fileLine() {
+ f = FILENAME
+ sub( /^.*\//, "", f ) # strip path
+
+ return f " (" FNR ")"
+}
function warn( msg ) {
- print FILENAME " (" FNR "): " msg > "/dev/stderr"
+ print fileLine() ": " msg > "/dev/stderr"
}
BEGIN {
if ( ! arch ) {
- warn( "arch= must be specified" )
+ print "arch= must be specified" > "/dev/stderr"
exit 1
}
- firstfile = 1
+ split( arch, Archs )
+ for (i = 1; i in Archs; i++) {
+ targetLevel[ Archs[ i ] ] = i
+ }
+
+ shouldDie = 0
+
+ lastFile = ""
+}
+
+function dieLater( code ) {
+ if ( shouldDie < code )
+ shouldDie = code
}
{
- # remember first file name
- if ( ! file )
- file = FILENAME
-
- else if ( file != FILENAME ) { # second and following files
- if ( match( $0, /CONFIG_[A-Za-z0-9_-]+/ ) ) {
- option = substr( $0, RSTART, RLENGTH )
- if ( $0 ~ "^" option "=.+$" || $0 ~ "^# " option " is not set$" ) {
- if ( option in outputArray )
- warn( option " already defined in: " outputArray[ option ] )
- else {
- print
- outputArray[ option ] = FILENAME " (" FNR ")"
- }
- } else {
- if ( ! /^#/ )
- warn( "Incorrect line: " $0 )
- }
- } else if ( ! /^\s*$/ && ! /^#/ ) {
- warn( "Incorrect line: " $0 )
- }
- next
+ f = FILENAME
+ sub( /^.*\//, "", f ) # strip path
+ if ( f != lastFile ) {
+ print "\n# file: " f
+ lastFile = f
}
}
-# multiarch file proxessing
+# convert special case:
+# # CONFIG_SOMETHING it not set
+# to:
+# SOMETHING all=n
+/^# CONFIG_[A-Za-z0-9_]+ is not set$/ {
+ match( $0, /CONFIG_[A-Za-z0-9_]+/ )
+ option = substr( $0, RSTART, RLENGTH)
+ $0 = option " all=n"
+}
+# ignore all the comments and empty lines
/^#/ || /^\s*$/ {
next
}
-/^CONFIG_/ {
- warn( "Options should not start with CONFIG_" )
- gsub( /^CONFIG_/, "" )
+!/^[A-Za-z0-9_]+(=|[ \t]+[A-Za-z0-9_-]+=)/ {
+ warn( "ERROR: Incorrect line: " $0 )
+ dieLater( 3 )
+ next
+}
+
+!/^CONFIG_/ {
+ $0 = "CONFIG_" $0
}
{
option = $1
line = $0
+ value = ""
if ( option ~ /=/ ) {
- warn( $0 " should have explicit ` all='" )
- gsub( /=.*$/, "", option )
- gsub( /^[^=]*=/, "", line )
- line = "all=" line
+ sub( /=.*$/, "", option )
+ sub( /^[^=]*=/, "", line )
+ value = line
} else {
- gsub( "^" option, "", line )
- }
- split( line, archs )
+ sub( "^" option, "", line )
+ sub( /^[ \t]*/, "", line )
- dest = ""
- for ( inx in archs ) {
- split( archs[inx], opt, "=" );
- if ( opt[1] == "all" )
- dest = opt[2]
+ delete archs
+ if ( line ~ /"/ ) {
+ # there can be white spaces
+ i = 0
+ while ( match( line, /^[^=]+="([^"]|\\")*"/ ) ) {
+ archs[ (++i) ] = substr( line, RSTART, RLENGTH )
+ line = substr( line, RSTART + RLENGTH )
+ sub( /^[ \t]*/, "", line )
+ }
+ } else {
+ split( line, archs )
+ }
- if ( opt[1] == arch ) {
- dest = opt[2]
- break
+ level = 0
+ for ( i in archs ) {
+ arch = val = archs[ i ]
+ sub( /=.*$/, "", arch )
+ sub( /^[^=]*=/, "", val )
+ tl = targetLevel[ arch ]
+ if ( tl > level ) {
+ value = val
+ level = tl
+ }
}
}
- if ( length( dest ) ) {
- option = "CONFIG_" option
- if ( dest == "n" )
- out = "# " option " is not set"
- else
- out = option "=" dest
- print out
+ # completely ignore lines with no value
+ if ( length( value ) == 0 )
+ next
+
+ fileOption = FILENAME "/" option
+ if ( fileOption in outputByFile ) {
+ warn( "ERROR: " option " already defined in this file at line " outputByFile[ fileOption ] )
+ dieLater( 2 )
+ next
+ } else
+ outputByFile[ fileOption ] = FNR
- outputArray[ option ] = FILENAME " (" FNR ")"
+ if ( option in outputArray ) {
+ warn( "Warning: " option " already defined in: " outputArray[ option ] )
+ next
+ } else
+ outputArray[ option ] = fileLine()
+
+ if ( value == "n" )
+ out = "# " option " is not set"
+ else {
+ out = option "=" value
+
+ if ( value == "y" || value == "m" )
+ ; # OK
+ else if ( value ~ /^"([^"]|\\")*"$/ )
+ ; # OK
+ else if ( value ~ /^-?[0-9]+$/ || value ~ /^0x[0-9A-Fa-f]+$/ )
+ ; # OK
+ else {
+ warn( "ERROR: Incorrect value: " $0 )
+ dieLater( 1 )
+ }
}
+
+ print out
}
END {
+ exit shouldDie
}