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-2009 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 if (SCSI_EXEC_REQ_FIFO_DEFINED != "")
96 gsub("defined *SCSI_EXEC_REQ_FIFO_DEFINED",
97 SCSI_EXEC_REQ_FIFO_DEFINED, stmnt)
98 gsub("defined *\\( *SCSI_EXEC_REQ_FIFO_DEFINED *\\)",
99 SCSI_EXEC_REQ_FIFO_DEFINED, stmnt)
102 if (SCST_IO_CONTEXT != "")
104 gsub("defined *SCST_IO_CONTEXT", SCST_IO_CONTEXT, stmnt)
105 gsub("defined *\\( *SCST_IO_CONTEXT *\\)", SCST_IO_CONTEXT, stmnt)
108 if (generating_upstream_patch_defined)
110 gsub("defined *GENERATING_UPSTREAM_PATCH", 1, stmnt)
111 gsub("defined *\\( *GENERATING_UPSTREAM_PATCH *\\)", 1, stmnt)
114 if (config_tcp_zero_copy_transfer_completion_notification_undefined)
116 gsub("defined *CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION", 0, stmnt)
117 gsub("defined *\\( *CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION *\\)", 0, stmnt)
120 if (config_scst_proc_undefined)
122 gsub("defined *CONFIG_SCST_PROC", 0, stmnt)
123 gsub("defined *\\( *CONFIG_SCST_PROC *\\)", 0, stmnt)
130 pattern = "! *([0-9]+)"
131 while (match(stmnt, pattern, op) != 0)
133 sub(pattern, op[1] == 0, stmnt)
136 pattern="KERNEL_VERSION\\( *([0-9]+) *, *([0-9]+) *, *([0-9]+) *\\)"
137 while (match(stmnt, pattern, op) != 0)
139 sub(pattern, op[1] * 65536 + op[2] * 256 + op[3], stmnt)
142 pattern="(-*[0-9]+) *(\\*|/) *(-*[0-9]+)"
143 while (match(stmnt, pattern, op) != 0)
146 if (op[2] == "*") result = op[1] * op[3]
147 else if (op[2] == "/" && op[3] != 0) result = op[1] / op[3]
148 sub(pattern, result, stmnt)
151 pattern="(-*[0-9]+) *(\\+|-) *(-*[0-9]+)"
152 while (match(stmnt, pattern, op) != 0)
155 if (op[2] == "+") result = op[1] * op[3]
156 else if (op[2] == "-") result = op[1] / op[3]
157 sub(pattern, result, stmnt)
160 pattern="(-*[0-9]+) *(<|<=|>|>=|==) *(-*[0-9]+)"
161 while (match(stmnt, pattern, op) != 0)
164 if (op[2] == "<" ) result = op[1] < op[3]
165 else if (op[2] == "<=") result = op[1] <= op[3]
166 else if (op[2] == ">" ) result = op[1] > op[3]
167 else if (op[2] == ">=") result = op[1] >= op[3]
168 else if (op[2] == "==") result = op[1] == op[3]
169 sub(pattern, result, stmnt)
172 pattern="(-*[0-9]+) *\\&\\& *(-*[0-9]+)"
173 while (match(stmnt, pattern, op) != 0)
175 sub(pattern, (op[1] != 0) && (op[2] != 0), stmnt)
178 pattern="(-*[0-9]+) *\\|\\| *(-*[0-9]+)"
179 while (match(stmnt, pattern, op) != 0)
181 sub(pattern, (op[1] != 0) || (op[2] != 0), stmnt)
184 pattern="\\((-*[0-9]+)\\)"
185 while (match(stmnt, pattern, op) != 0)
187 sub(pattern, op[1], stmnt)
189 } while (stmnt != last_stmnt)
196 function invert(stmnt) {
197 sub("^+#if ", "+#if ! ", stmnt)
198 return evaluate(stmnt)
202 # Handle #if or #elif
206 # Only act on preprocessor conditional expressions with regard to the Linux
207 # kernel version, and do not interpret other expressions.
208 if ($0 ~ "LINUX_VERSION_CODE" \
209 || $0 ~ "INSIDE_KERNEL_TREE" \
210 || $0 ~ "RHEL_MAJOR" \
211 || $0 ~ "RHEL_MINOR" \
212 || $0 ~ "RHEL_RELEASE_CODE" \
213 || $0 ~ "GENERATING_UPSTREAM_PATCH" \
214 || $0 ~ "CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION" \
215 || ($0 ~ "CONFIG_SCST_PROC" && config_scst_proc_undefined) \
216 || ($0 ~ "SCSI_EXEC_REQ_FIFO_DEFINED" && SCSI_EXEC_REQ_FIFO_DEFINED!="") \
217 || ($0 ~ "SCST_IO_CONTEXT" && SCST_IO_CONTEXT != ""))
219 #print $0 " -> " evaluated
224 evaluated = "+#if undecided"
226 #printf "%s -> %s\n", $0, evaluated
227 if (evaluated ~ "^+#if")
229 if_stmnt[if_nesting_level] = evaluated
230 any_section_output[if_nesting_level] = 0
235 sprintf("+#if ! %d \\&\\& ", decision[if_nesting_level]),
237 evaluated = evaluate(evaluated)
239 decision[if_nesting_level] = evaluated
240 matching_if = if_stmnt[if_nesting_level]
244 # Decide whether or not to print the preprocessor statement $0.
246 function process_preprocessor_statement() {
247 last_if_nesting_level = if_nesting_level
249 evaluated = evaluate($0)
251 delete_next_blank_line = 0
252 if (evaluated ~ "^+#if")
257 else if (evaluated ~ "^+#elif")
261 else if (evaluated ~ "^+#else")
263 matching_if = if_stmnt[if_nesting_level]
264 decision[if_nesting_level] = invert(decision[if_nesting_level])
266 else if (evaluated ~ "^+#endif")
268 matching_if = if_stmnt[if_nesting_level]
269 delete_next_blank_line = ! any_section_output[if_nesting_level]
279 for (i = if_nesting_level; i >= 0; i--)
281 output = output && decision[i] != "+#if 0"
284 any_section_output[if_nesting_level] = 1
286 if (evaluated ~ "^+#define SCSI_EXEC_REQ_FIFO_DEFINED$" \
287 && SCSI_EXEC_REQ_FIFO_DEFINED != "" \
288 || evaluated ~ "^+#define SCST_IO_CONTEXT$" \
289 && SCST_IO_CONTEXT != "" \
290 || (evaluated ~ "^+#define CONFIG_SCST_PROC$" \
291 && config_scst_proc_undefined))
293 if (blank_deleted_code)
294 for (i = 0; i < input_line_count; i++)
298 lines_deleted += input_line_count
299 delete_next_blank_line = 1
302 else if (output && (! condition || condition && matching_if !~ "^+#if [01]"))
304 for (i = 0; i < input_line_count; i++)
305 line[lines++] = input_line[i]
309 if (blank_deleted_code)
310 for (i = 0; i < input_line_count; i++)
313 lines_deleted += input_line_count
317 function reset_hunk_state_variables() {
321 if_nesting_level = -1
322 delete_next_blank_line = 0
325 function dump_lines() {
328 for (i = 0; i < lines; i++)
330 if (line[i] ~ "^[+-]")
337 # Dump line[] as a hunk, but only if the hunk is not empty.
338 if (first_modif >= 0)
341 printf "@@ -%d,%d +%d,%d @@%s\n",h[1],h[2],h[3],h[4]-lines_deleted,h[5]
342 for (i = 0; i < lines; i++)
345 reset_hunk_state_variables()
350 if (kernel_version == "")
352 printf "Error: kernel_version was not specified.\n"
355 LINUX_VERSION_CODE = version_code(kernel_version)
356 if (LINUX_VERSION_CODE < 2*65536 || LINUX_VERSION_CODE > 3*65536)
358 printf "Error: kernel version (%s) is out of range.\n", kernel_version
361 if (blank_deleted_code != 0 && blank_deleted_code != 1)
362 blank_deleted_code = 0
363 if (generating_upstream_patch_defined != 0 && generating_upstream_patch_defined != 1)
364 generating_upstream_patch_defined = 0
365 if (config_tcp_zero_copy_transfer_completion_notification_undefined != 0 && config_tcp_zero_copy_transfer_completion_notification_undefined != 1)
366 config_tcp_zero_copy_transfer_completion_notification_undefined = 0
367 if (config_scst_proc_undefined != 0 && config_scst_proc_undefined != 1)
368 config_scst_proc_undefined = 0
370 # Variable initialization.
371 reset_hunk_state_variables()
378 # Join continued lines before processing these.
379 while (match($0, "\\\\$"))
382 sub("\\\\$", "", previous_line)
384 input_line[input_line_count++] = $0
386 $0 = previous_line $0
389 # If the line currently being processed is a hunk header, print all lines
390 # that were stored in the array line[] since the last hunk header was read.
391 if (match($0, "^@@ -([0-9]*),([0-9]*) \\+([0-9]*),([0-9]*) @@(.*)$"))
393 /* print h[1], h[2], h[3], h[4], h[5] */
395 match($0, "^@@ -([0-9]*),([0-9]*) \\+([0-9]*),([0-9]*) @@(.*)$", h)
397 else if (delete_next_blank_line && match($0, "^+$"))
399 if (blank_deleted_code)
400 for (i = 0; i < input_line_count; i++)
404 lines_deleted += input_line_count
405 delete_next_blank_line = 0
410 delete_next_blank_line = 0
411 if (match($0, "^+ *#"))
413 process_preprocessor_statement()
417 # Store the lines that were just read.
418 for (i = 0; i < input_line_count; i++)
419 line[lines++] = input_line[i]
420 # Delete double blank lines from the input.
421 if (line[lines-1] == "+")
422 delete_next_blank_line = 1
426 # Discard the last read lines.
427 if (blank_deleted_code)
429 for (i = 0; i < input_line_count; i++)
433 lines_deleted += input_line_count
439 # Dump processed contents of the last read hunk.