17db96d56Sopenharmony_ci#! /usr/bin/env python3 27db96d56Sopenharmony_ci 37db96d56Sopenharmony_ci# Selectively preprocess #ifdef / #ifndef statements. 47db96d56Sopenharmony_ci# Usage: 57db96d56Sopenharmony_ci# ifdef [-Dname] ... [-Uname] ... [file] ... 67db96d56Sopenharmony_ci# 77db96d56Sopenharmony_ci# This scans the file(s), looking for #ifdef and #ifndef preprocessor 87db96d56Sopenharmony_ci# commands that test for one of the names mentioned in the -D and -U 97db96d56Sopenharmony_ci# options. On standard output it writes a copy of the input file(s) 107db96d56Sopenharmony_ci# minus those code sections that are suppressed by the selected 117db96d56Sopenharmony_ci# combination of defined/undefined symbols. The #if(n)def/#else/#else 127db96d56Sopenharmony_ci# lines themselves (if the #if(n)def tests for one of the mentioned 137db96d56Sopenharmony_ci# names) are removed as well. 147db96d56Sopenharmony_ci 157db96d56Sopenharmony_ci# Features: Arbitrary nesting of recognized and unrecognized 167db96d56Sopenharmony_ci# preprocessor statements works correctly. Unrecognized #if* commands 177db96d56Sopenharmony_ci# are left in place, so it will never remove too much, only too 187db96d56Sopenharmony_ci# little. It does accept whitespace around the '#' character. 197db96d56Sopenharmony_ci 207db96d56Sopenharmony_ci# Restrictions: There should be no comments or other symbols on the 217db96d56Sopenharmony_ci# #if(n)def lines. The effect of #define/#undef commands in the input 227db96d56Sopenharmony_ci# file or in included files is not taken into account. Tests using 237db96d56Sopenharmony_ci# #if and the defined() pseudo function are not recognized. The #elif 247db96d56Sopenharmony_ci# command is not recognized. Improperly nesting is not detected. 257db96d56Sopenharmony_ci# Lines that look like preprocessor commands but which are actually 267db96d56Sopenharmony_ci# part of comments or string literals will be mistaken for 277db96d56Sopenharmony_ci# preprocessor commands. 287db96d56Sopenharmony_ci 297db96d56Sopenharmony_ciimport sys 307db96d56Sopenharmony_ciimport getopt 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_cidefs = [] 337db96d56Sopenharmony_ciundefs = [] 347db96d56Sopenharmony_ci 357db96d56Sopenharmony_cidef main(): 367db96d56Sopenharmony_ci opts, args = getopt.getopt(sys.argv[1:], 'D:U:') 377db96d56Sopenharmony_ci for o, a in opts: 387db96d56Sopenharmony_ci if o == '-D': 397db96d56Sopenharmony_ci defs.append(a) 407db96d56Sopenharmony_ci if o == '-U': 417db96d56Sopenharmony_ci undefs.append(a) 427db96d56Sopenharmony_ci if not args: 437db96d56Sopenharmony_ci args = ['-'] 447db96d56Sopenharmony_ci for filename in args: 457db96d56Sopenharmony_ci if filename == '-': 467db96d56Sopenharmony_ci process(sys.stdin, sys.stdout) 477db96d56Sopenharmony_ci else: 487db96d56Sopenharmony_ci with open(filename) as f: 497db96d56Sopenharmony_ci process(f, sys.stdout) 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_cidef process(fpi, fpo): 527db96d56Sopenharmony_ci keywords = ('if', 'ifdef', 'ifndef', 'else', 'endif') 537db96d56Sopenharmony_ci ok = 1 547db96d56Sopenharmony_ci stack = [] 557db96d56Sopenharmony_ci while 1: 567db96d56Sopenharmony_ci line = fpi.readline() 577db96d56Sopenharmony_ci if not line: break 587db96d56Sopenharmony_ci while line[-2:] == '\\\n': 597db96d56Sopenharmony_ci nextline = fpi.readline() 607db96d56Sopenharmony_ci if not nextline: break 617db96d56Sopenharmony_ci line = line + nextline 627db96d56Sopenharmony_ci tmp = line.strip() 637db96d56Sopenharmony_ci if tmp[:1] != '#': 647db96d56Sopenharmony_ci if ok: fpo.write(line) 657db96d56Sopenharmony_ci continue 667db96d56Sopenharmony_ci tmp = tmp[1:].strip() 677db96d56Sopenharmony_ci words = tmp.split() 687db96d56Sopenharmony_ci keyword = words[0] 697db96d56Sopenharmony_ci if keyword not in keywords: 707db96d56Sopenharmony_ci if ok: fpo.write(line) 717db96d56Sopenharmony_ci continue 727db96d56Sopenharmony_ci if keyword in ('ifdef', 'ifndef') and len(words) == 2: 737db96d56Sopenharmony_ci if keyword == 'ifdef': 747db96d56Sopenharmony_ci ko = 1 757db96d56Sopenharmony_ci else: 767db96d56Sopenharmony_ci ko = 0 777db96d56Sopenharmony_ci word = words[1] 787db96d56Sopenharmony_ci if word in defs: 797db96d56Sopenharmony_ci stack.append((ok, ko, word)) 807db96d56Sopenharmony_ci if not ko: ok = 0 817db96d56Sopenharmony_ci elif word in undefs: 827db96d56Sopenharmony_ci stack.append((ok, not ko, word)) 837db96d56Sopenharmony_ci if ko: ok = 0 847db96d56Sopenharmony_ci else: 857db96d56Sopenharmony_ci stack.append((ok, -1, word)) 867db96d56Sopenharmony_ci if ok: fpo.write(line) 877db96d56Sopenharmony_ci elif keyword == 'if': 887db96d56Sopenharmony_ci stack.append((ok, -1, '')) 897db96d56Sopenharmony_ci if ok: fpo.write(line) 907db96d56Sopenharmony_ci elif keyword == 'else' and stack: 917db96d56Sopenharmony_ci s_ok, s_ko, s_word = stack[-1] 927db96d56Sopenharmony_ci if s_ko < 0: 937db96d56Sopenharmony_ci if ok: fpo.write(line) 947db96d56Sopenharmony_ci else: 957db96d56Sopenharmony_ci s_ko = not s_ko 967db96d56Sopenharmony_ci ok = s_ok 977db96d56Sopenharmony_ci if not s_ko: ok = 0 987db96d56Sopenharmony_ci stack[-1] = s_ok, s_ko, s_word 997db96d56Sopenharmony_ci elif keyword == 'endif' and stack: 1007db96d56Sopenharmony_ci s_ok, s_ko, s_word = stack[-1] 1017db96d56Sopenharmony_ci if s_ko < 0: 1027db96d56Sopenharmony_ci if ok: fpo.write(line) 1037db96d56Sopenharmony_ci del stack[-1] 1047db96d56Sopenharmony_ci ok = s_ok 1057db96d56Sopenharmony_ci else: 1067db96d56Sopenharmony_ci sys.stderr.write('Unknown keyword %s\n' % keyword) 1077db96d56Sopenharmony_ci if stack: 1087db96d56Sopenharmony_ci sys.stderr.write('stack: %s\n' % stack) 1097db96d56Sopenharmony_ci 1107db96d56Sopenharmony_ciif __name__ == '__main__': 1117db96d56Sopenharmony_ci main() 112