diff options
-rwxr-xr-x | Tools/scripts/ifdef.py | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/Tools/scripts/ifdef.py b/Tools/scripts/ifdef.py new file mode 100755 index 0000000..9d74be2 --- /dev/null +++ b/Tools/scripts/ifdef.py @@ -0,0 +1,113 @@ +#! /usr/local/bin/python + +# Selectively preprocess #ifdef / #ifndef statements. +# Usage: +# ifdef [-Dname] ... [-Uname] ... [file] ... +# +# This scans the file(s), looking for #ifdef and #ifndef preprocessor +# commands that test for one of the names mentioned in the -D and -U +# options. On standard output it writes a copy of the input file(s) +# minus those code sections that are suppressed by the selected +# combination of defined/undefined symbols. The #if(n)def/#else/#else +# lines themselfs (if the #if(n)def tests for one of the mentioned +# names) are removed as well. + +# Features: Arbitrary nesting of recognized and unrecognized +# preprocesor statements works correctly. Unrecognized #if* commands +# are left in place, so it will never remove too much, only too +# little. It does accept whitespace around the '#' character. + +# Restrictions: There should be no comments or other symbols on the +# #if(n)def lines. The effect of #define/#undef commands in the input +# file or in included files is not taken into account. Tests using +# #if and the defined() pseudo function are not recognized. The #elif +# command is not recognized. Improperly nesting is not detected. +# Lines that look like preprocessor commands but which are actually +# part of comments or string literals will be mistaken for +# preprocessor commands. + +import sys +import regex +import getopt +import string + +defs = [] +undefs = [] + +def main(): + opts, args = getopt.getopt(sys.argv[1:], 'D:U:') + for o, a in opts: + if o == '-D': + defs.append(a) + if o == '-U': + undefs.append(a) + if not args: + args = ['-'] + for file in args: + if file == '-': + process(sys.stdin, sys.stdout) + else: + f = open(file, 'r') + process(f, sys.stdout) + f.close() + +def process(fpi, fpo): + keywords = ('if', 'ifdef', 'ifndef', 'else', 'endif') + ok = 1 + stack = [] + while 1: + line = fpi.readline() + if not line: break + while line[-2:] == '\\\n': + nextline = fpi.readline() + if not nextline: break + line = line + nextline + tmp = string.strip(line) + if tmp[:1] != '#': + if ok: fpo.write(line) + continue + tmp = string.strip(tmp[1:]) + words = string.split(tmp) + keyword = words[0] + if keyword not in keywords: + if ok: fpo.write(line) + continue + if keyword in ('ifdef', 'ifndef') and len(words) == 2: + if keyword == 'ifdef': + ko = 1 + else: + ko = 0 + word = words[1] + if word in defs: + stack.append(ok, ko, word) + if not ko: ok = 0 + elif word in undefs: + stack.append(ok, not ko, word) + if ko: ok = 0 + else: + stack.append(ok, -1, word) + if ok: fpo.write(line) + elif keyword == 'if': + stack.append(ok, -1, '') + if ok: fpo.write(line) + elif keyword == 'else' and stack: + s_ok, s_ko, s_word = stack[-1] + if s_ko < 0: + if ok: fpo.write(line) + else: + s_ko = not s_ko + ok = s_ok + if not s_ko: ok = 0 + stack[-1] = s_ok, s_ko, s_word + elif keyword == 'endif' and stack: + s_ok, s_ko, s_word = stack[-1] + if s_ko < 0: + if ok: fpo.write(line) + del stack[-1] + ok = s_ok + else: + sys.stderr.write('Unknown keyword %s\n' % keyword) + if stack: + sys.stderr.write('stack: %s\n' % stack) + +main() |