1f06ee5fa072931fc807527535c91a46c149a6746Guido van Rossum#! /usr/bin/env python 27faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum 37faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# Selectively preprocess #ifdef / #ifndef statements. 47faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# Usage: 57faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# ifdef [-Dname] ... [-Uname] ... [file] ... 670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters# 77faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# This scans the file(s), looking for #ifdef and #ifndef preprocessor 87faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# commands that test for one of the names mentioned in the -D and -U 97faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# options. On standard output it writes a copy of the input file(s) 107faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# minus those code sections that are suppressed by the selected 117faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# combination of defined/undefined symbols. The #if(n)def/#else/#else 126d0f0f299b014e79f6079901b560e938e0c5d8dfEzio Melotti# lines themselves (if the #if(n)def tests for one of the mentioned 137faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# names) are removed as well. 147faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum 157faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# Features: Arbitrary nesting of recognized and unrecognized 166d0f0f299b014e79f6079901b560e938e0c5d8dfEzio Melotti# preprocessor statements works correctly. Unrecognized #if* commands 177faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# are left in place, so it will never remove too much, only too 187faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# little. It does accept whitespace around the '#' character. 197faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum 207faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# Restrictions: There should be no comments or other symbols on the 217faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# #if(n)def lines. The effect of #define/#undef commands in the input 227faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# file or in included files is not taken into account. Tests using 237faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# #if and the defined() pseudo function are not recognized. The #elif 247faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# command is not recognized. Improperly nesting is not detected. 257faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# Lines that look like preprocessor commands but which are actually 267faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# part of comments or string literals will be mistaken for 277faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum# preprocessor commands. 287faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum 297faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossumimport sys 307faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossumimport getopt 317faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum 327faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossumdefs = [] 337faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossumundefs = [] 347faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum 357faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossumdef main(): 3670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters opts, args = getopt.getopt(sys.argv[1:], 'D:U:') 3770c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters for o, a in opts: 3870c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if o == '-D': 3970c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters defs.append(a) 4070c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if o == '-U': 4170c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters undefs.append(a) 4270c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if not args: 4370c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters args = ['-'] 44ac6df95d07aa3951f8bfc6febce132e09850db73Andrew M. Kuchling for filename in args: 45ac6df95d07aa3951f8bfc6febce132e09850db73Andrew M. Kuchling if filename == '-': 4670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters process(sys.stdin, sys.stdout) 4770c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters else: 48ac6df95d07aa3951f8bfc6febce132e09850db73Andrew M. Kuchling f = open(filename, 'r') 4970c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters process(f, sys.stdout) 5070c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters f.close() 517faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum 527faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossumdef process(fpi, fpo): 5370c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters keywords = ('if', 'ifdef', 'ifndef', 'else', 'endif') 5470c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters ok = 1 5570c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters stack = [] 5670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters while 1: 5770c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters line = fpi.readline() 5870c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if not line: break 5970c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters while line[-2:] == '\\\n': 6070c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters nextline = fpi.readline() 6170c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if not nextline: break 6270c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters line = line + nextline 63aaab30e00cc3e8d90c71b8657c284feeb4ac1413Walter Dörwald tmp = line.strip() 6470c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if tmp[:1] != '#': 6570c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if ok: fpo.write(line) 6670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters continue 67aaab30e00cc3e8d90c71b8657c284feeb4ac1413Walter Dörwald tmp = tmp[1:].strip() 68aaab30e00cc3e8d90c71b8657c284feeb4ac1413Walter Dörwald words = tmp.split() 6970c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters keyword = words[0] 7070c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if keyword not in keywords: 7170c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if ok: fpo.write(line) 7270c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters continue 7370c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if keyword in ('ifdef', 'ifndef') and len(words) == 2: 7470c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if keyword == 'ifdef': 7570c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters ko = 1 7670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters else: 7770c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters ko = 0 7870c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters word = words[1] 7970c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if word in defs: 8070c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters stack.append((ok, ko, word)) 8170c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if not ko: ok = 0 8270c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters elif word in undefs: 8370c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters stack.append((ok, not ko, word)) 8470c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if ko: ok = 0 8570c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters else: 8670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters stack.append((ok, -1, word)) 8770c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if ok: fpo.write(line) 8870c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters elif keyword == 'if': 8970c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters stack.append((ok, -1, '')) 9070c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if ok: fpo.write(line) 9170c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters elif keyword == 'else' and stack: 9270c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters s_ok, s_ko, s_word = stack[-1] 9370c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if s_ko < 0: 9470c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if ok: fpo.write(line) 9570c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters else: 9670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters s_ko = not s_ko 9770c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters ok = s_ok 9870c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if not s_ko: ok = 0 9970c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters stack[-1] = s_ok, s_ko, s_word 10070c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters elif keyword == 'endif' and stack: 10170c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters s_ok, s_ko, s_word = stack[-1] 10270c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if s_ko < 0: 10370c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if ok: fpo.write(line) 10470c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters del stack[-1] 10570c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters ok = s_ok 10670c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters else: 10770c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters sys.stderr.write('Unknown keyword %s\n' % keyword) 10870c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters if stack: 10970c4378dbcfdcbeef6fb3aa348f32ed862fe8eb7Tim Peters sys.stderr.write('stack: %s\n' % stack) 1107faf67caf563d0e379f41d3b3a24b87b9ec47bd9Guido van Rossum 111e236b38731823aeb87bb6d101062f54a72044954Andrew M. Kuchlingif __name__ == '__main__': 112e236b38731823aeb87bb6d101062f54a72044954Andrew M. Kuchling main() 113