Patch from Bart Van Assche <bart.vanassche@gmail.com>:
authorvlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Wed, 21 May 2008 15:48:02 +0000 (15:48 +0000)
committervlnb <vlnb@d57e44dd-8a1f-0410-8b47-8ef2f437770f>
Wed, 21 May 2008 15:48:02 +0000 (15:48 +0000)
The patch below contains a script that removes C preprocessor tests on the
LINUX_VERSION_CODE macro, depending on the kernel version that was passed as
an argument to that script. Furthermore, the generate-kernel-patch script has
been modified such that its output is filtered by the specialize-patch script.
This eliminates another class of checkpatch errors.

Note: due to the way the specialize-patch script is implemented, #if 0 and
#if 1 statements are also processed.

The patch below has been verified as follows:
- Checked that checkpatch does no longer complain about LINUX_VERSION_CODE
  on the generated patch.
- Checked that the generated kernel patch applies cleanly to the 2.6.25.4
  kernel.
- Checked that the patched kernel compiles and installs cleanly, and that
  after reboot it was possible to load the iscsi-scst and ib_srpt kernel modules.

I will wait with sending more patches until this and the previous two patches
have been reviewed and/or applied.

Signed-off-by: Bart Van Assche <bart.vanassche@gmail.com>
git-svn-id: https://scst.svn.sourceforge.net/svnroot/scst/trunk@384 d57e44dd-8a1f-0410-8b47-8ef2f437770f

scripts/generate-kernel-patch
scripts/specialize-patch [new file with mode: 0755]

index 76a6a5c..c0343f8 100755 (executable)
@@ -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 (executable)
index 0000000..d9b3ee3
--- /dev/null
@@ -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 <bart.vanassche@gmail.com>
+#
+# 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 "+"
+}
+