diff --git a/scripts/generate-kernel-patch b/scripts/generate-kernel-patch index 76a6a5c55..c0343f8d5 100755 --- a/scripts/generate-kernel-patch +++ b/scripts/generate-kernel-patch @@ -103,6 +103,16 @@ do done +# Redirect the output of all subsequent commands to the specialize-patch script + +trap "rm -f ${fifo}" EXIT +fifo=/tmp/generate-kernel-patch-fifo.$$ +rm -f "${fifo}" +mkfifo "${fifo}" +"$(dirname $0)/specialize-patch" -v kernel_version="${kernel_version}" \ + < "${fifo}" & +exec >"${fifo}" + # General kernel patches. cat "${kpatch[@]}" diff --git a/scripts/specialize-patch b/scripts/specialize-patch new file mode 100755 index 000000000..d9b3ee31d --- /dev/null +++ b/scripts/specialize-patch @@ -0,0 +1,168 @@ +#!/usr/bin/gawk -f + +############################################################################ +# +# Script that removes preprocessor checks on the kernel version. Somewhat +# related to the v4l-scripts-gentree.pl script. +# +# Copyright (C) 2008 Bart Van Assche +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, version 2 +# of the License. +# +# This program is distributed in the hope that 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. +# +############################################################################ + +# Usage: +# * Specify the kernel version code as follows: -v kernel_version=... +# * Provide the patch to be processed to stdin. +# +# The output of this script will be a patch that is specialized for the +# specified kernel version. + + +# Convert a kernel version in the x.y.z format into numeric form, just like +# the KERNEL_VERSION() macro. + +function version_code(kver) { + match(kver, "([0-9]+).([0-9]+).([0-9]+)", array) + return 65536*array[1] + 256*array[2] + array[3] +} + + +# Evaluate a preprocessor statement via repeated substitutions. +# Mathematicians call this 'term rewriting'. + +function evaluate(stmnt) { + gsub(" *\\/\\*[^*]*\\*\\/ *", "", stmnt) + + gsub("^+ *#", "+#", stmnt) + + gsub("LINUX_VERSION_CODE", LINUX_VERSION_CODE, stmnt) + + pattern="KERNEL_VERSION\\(([0-9]+) *, *([0-9]+) *, *([0-9]+) *\\)" + while (match(stmnt, pattern, ver) != 0) + { + sub(pattern, ver[1]*65536+ver[2]*256+ver[3], stmnt) + } + + pattern="([0-9]+) *(<|<=|>|>=|==) *([0-9]+)" + while (match(stmnt, pattern, op) != 0) + { + result="error" + if (op[2] == "<" ) result = op[1] < op[3] + else if (op[2] == "<=") result = op[1] <= op[3] + else if (op[2] == ">" ) result = op[1] > op[3] + else if (op[2] == ">=") result = op[1] >= op[3] + else if (op[2] == "==") result = op[1] == op[3] + sub(pattern, result, stmnt) + } + + pattern="([0-9]+) *\\&\\& *([0-9]+)" + while (match(stmnt, pattern, op) != 0) + { + sub(pattern, op[1] && op[3], stmnt) + } + + pattern="([0-9]+) *\\|\\| *([0-9]+)" + while (match(stmnt, pattern, op) != 0) + { + sub(pattern, op[1] || op[3], stmnt) + } + + return stmnt +} + + +# Decide whetheror not to print the preprocessor statement $0. + +function process_preprocessor_statement() { + last_if_nesting_level = if_nesting_level + evaluated = evaluate($0) + condition = 1 + if (evaluated ~ "^+#if") + { + output_array[if_nesting_level] = output + if_nesting_level++ + decision[if_nesting_level] = evaluated + output = evaluated != "+#if 0" + } + else if (evaluated ~ "^+#elif") + { + decision[if_nesting_level] = evaluated + output = evaluated != "+#elif 0" + sub("^+#elif ", "+#if ", decision[if_nesting_level]) + } + else if (evaluated ~ "^+#else") + { + output = decision[if_nesting_level] != "+#if 1" + } + else if (evaluated ~ "^+#endif") + { + if_nesting_level-- + if (if_nesting_level >= 0) + { + output = output_array[if_nesting_level] + } + else + { + output = 1 + } + } + else + { + condition = 0 + } + if (evaluated ~ "^+#if [01]$" \ + || condition \ + && evaluated !~ "^+#if" \ + && last_if_nesting_level >= 0 \ + && decision[last_if_nesting_level] ~ "+#if [01]$" \ + || ! condition \ + && last_if_nesting_level >= 0 \ + && decision[last_if_nesting_level] == "+#if 0") + { + print "+" + } + else + { + print $0 + } +} + + +BEGIN { + # Verify arguments. + if (kernel_version == "") + { + printf "Error: kernel_version was not specified.\n" + exit 1 + } + LINUX_VERSION_CODE = version_code(kernel_version) + if (LINUX_VERSION_CODE < 2*65536 || LINUX_VERSION_CODE > 3*65536) + { + printf "Error: kernel version (%s) is out of range.\n", kernel_version + exit 1 + } + + # Variable initialization. + output = 1 + if_nesting_level = -1 +} + + +{ + if (match($0, "^+ *#")) + process_preprocessor_statement() + else if (output) + print $0 + else + print "+" +} +