3 ############################################################################
5 # Script that removes preprocessor checks on the kernel version. Somewhat
6 # related to the v4l-scripts-gentree.pl script.
8 # Copyright (C) 2008 Bart Van Assche <bart.vanassche@gmail.com>
10 # This program is free software; you can redistribute it and/or
11 # modify it under the terms of the GNU General Public License
12 # as published by the Free Software Foundation, version 2
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 ############################################################################
23 # * Specify the kernel version code as follows: -v kernel_version=...
24 # * Provide the patch to be processed to stdin.
26 # The output of this script will be a patch that is specialized for the
27 # specified kernel version.
30 # Convert a kernel version in the x.y.z format into numeric form, just like
31 # the KERNEL_VERSION() macro.
33 function version_code(kver) {
34 match(kver, "([0-9]+).([0-9]+).([0-9]+)", array)
35 return 65536*array[1] + 256*array[2] + array[3]
39 # Evaluate a preprocessor statement via repeated substitutions.
40 # Mathematicians call this algorithm 'term rewriting'.
41 # Note: the order in which the substitutions appear below is important --
42 # it is the same order as the order of operators in C.
44 function evaluate(stmnt) {
45 # Remove C-style comments.
46 gsub(" *\\/\\*[^*]*\\*\\/ *", "", stmnt)
48 # Remove the spaces before the #-sign.
49 gsub("^+ *# *", "+#", stmnt)
51 if (match(stmnt, "^+#ifdef (.*)$", arg))
53 stmnt = "+#if defined(" arg[1] ")"
56 if (match(stmnt, "^+#ifndef (.*)$", arg))
58 stmnt = "+#if ! defined(" arg[1] ")"
61 gsub("LINUX_VERSION_CODE", LINUX_VERSION_CODE, stmnt)
63 gsub("defined\\(INSIDE_KERNEL_TREE\\)", "1", stmnt)
65 gsub("defined\\(BACKPORT_LINUX_WORKQUEUE_TO_2_6_19\\)", "0", stmnt)
68 gsub("defined\\(RHEL_MAJOR\\)", "0", stmnt)
71 gsub("defined\\(RHEL_MAJOR\\)", "1", stmnt)
72 gsub("RHEL_MAJOR", RHEL_MAJOR, stmnt)
76 gsub("defined\\(RHEL_MINOR\\)", "0", stmnt)
79 gsub("defined\\(RHEL_MINOR\\)", "1", stmnt)
80 gsub("RHEL_MINOR", RHEL_MINOR, stmnt)
83 if (RHEL_MAJOR == "" || RHEL_MINOR == "")
85 gsub("defined\\(RHEL_RELEASE_CODE\\)", "0", stmnt)
86 gsub("RHEL_RELEASE_CODE", "", stmnt)
90 gsub("defined\\(RHEL_RELEASE_CODE\\)", "1", stmnt)
91 gsub("RHEL_RELEASE_CODE", RHEL_MAJOR * 256 + RHEL_MINOR, stmnt)
94 gsub("defined *SCSI_EXEC_REQ_FIFO_DEFINED", "1", stmnt)
95 gsub("defined *\\( *SCSI_EXEC_REQ_FIFO_DEFINED *\\)", "1", stmnt)
101 pattern = "! *([0-9]+)"
102 while (match(stmnt, pattern, op) != 0)
104 sub(pattern, op[1] == 0, stmnt)
107 pattern="KERNEL_VERSION\\( *([0-9]+) *, *([0-9]+) *, *([0-9]+) *\\)"
108 while (match(stmnt, pattern, op) != 0)
110 sub(pattern, op[1] * 65536 + op[2] * 256 + op[3], stmnt)
113 pattern="([0-9]+) *(<|<=|>|>=|==) *([0-9]+)"
114 while (match(stmnt, pattern, op) != 0)
117 if (op[2] == "<" ) result = op[1] < op[3]
118 else if (op[2] == "<=") result = op[1] <= op[3]
119 else if (op[2] == ">" ) result = op[1] > op[3]
120 else if (op[2] == ">=") result = op[1] >= op[3]
121 else if (op[2] == "==") result = op[1] == op[3]
122 sub(pattern, result, stmnt)
125 pattern="([0-9]+) *\\&\\& *([0-9]+)"
126 while (match(stmnt, pattern, op) != 0)
128 sub(pattern, (op[1] != 0) && (op[2] != 0), stmnt)
131 pattern="([0-9]+) *\\&\\& *(!* *defined\\([^)]*\\))"
132 while (match(stmnt, pattern, op) != 0)
134 sub(pattern, (op[1] != 0) ? op[2] : "0", stmnt)
137 pattern="([0-9]+) *\\|\\| *([0-9]+)"
138 while (match(stmnt, pattern, op) != 0)
140 sub(pattern, (op[1] != 0) || (op[2] != 0), stmnt)
143 pattern="([0-9]+) *\\|\\| *(!* *defined\\([^)]*\\))"
144 while (match(stmnt, pattern, op) != 0)
146 sub(pattern, (op[1] != 0) ? "1" : op[2], stmnt)
149 pattern="\\(([0-9]+)\\)"
150 while (match(stmnt, pattern, op) != 0)
152 sub(pattern, op[1], stmnt)
154 } while (stmnt != last_stmnt)
161 function invert(stmnt) {
162 sub("^+#if ", "+#if ! ", stmnt)
163 return evaluate(stmnt)
167 # Handle #if or #elif
171 # Only act on preprocessor conditional expressions with regard to the Linux
172 # kernel version, and do not interpret other expressions.
173 if ($0 ~ "LINUX_VERSION_CODE" \
174 || $0 ~ "INSIDE_KERNEL_TREE" \
175 || $0 ~ "RHEL_MAJOR" \
176 || $0 ~ "RHEL_MINOR" \
177 || $0 ~ "RHEL_RELEASE_CODE")
179 #print $0 " -> " evaluated
184 evaluated = "+#if undecided"
186 #printf "%s -> %s\n", $0, evaluated
187 if (evaluated ~ "^+#if")
189 if_stmnt[if_nesting_level] = evaluated
194 sprintf("+#if ! %d \\&\\& ", decision[if_nesting_level]),
196 evaluated = evaluate(evaluated)
198 decision[if_nesting_level] = evaluated
199 matching_if = if_stmnt[if_nesting_level]
203 # Decide whether or not to print the preprocessor statement $0.
205 function process_preprocessor_statement() {
206 last_if_nesting_level = if_nesting_level
207 evaluated = evaluate($0)
209 if (evaluated ~ "^+#if")
214 else if (evaluated ~ "^+#elif")
218 else if (evaluated ~ "^+#else")
220 matching_if = if_stmnt[if_nesting_level]
221 decision[if_nesting_level] = invert(decision[if_nesting_level])
223 else if (evaluated ~ "^+#endif")
225 matching_if = if_stmnt[if_nesting_level]
235 for (i = if_nesting_level; i >= 0; i--)
237 output = output && decision[i] != "+#if 0"
240 if (output && (! condition || condition && matching_if !~ "^+#if [01]") \
241 && ! (evaluated ~ "^+#define SCSI_EXEC_REQ_FIFO_DEFINED$"))
251 function dump_lines() {
253 printf "@@ -%d,%d +%d,%d @@%s\n",h[1],h[2],h[3],h[4]-lines_deleted,h[5]
254 for (i = 0; i < lines; i++)
262 if (kernel_version == "")
264 printf "Error: kernel_version was not specified.\n"
267 LINUX_VERSION_CODE = version_code(kernel_version)
268 if (LINUX_VERSION_CODE < 2*65536 || LINUX_VERSION_CODE > 3*65536)
270 printf "Error: kernel version (%s) is out of range.\n", kernel_version
274 # Variable initialization.
278 if_nesting_level = -1
283 # If the line currently being processed is a hunk header, print all lines
284 # that were stored in the array line[] since the last hunk header was read.
285 if (match($0, "^@@ -([0-9]*),([0-9]*) \\+([0-9]*),([0-9]*) @@(.*)$"))
287 /* print h[1], h[2], h[3], h[4], h[5] */
289 match($0, "^@@ -([0-9]*),([0-9]*) \\+([0-9]*),([0-9]*) @@(.*)$", h)
291 else if (match($0, "^+ *#"))
293 process_preprocessor_statement()
297 # Store the line that was just read.
302 # Discard the last read line.
308 # Dump processed contents of the last read hunk.