| 
									
										
										
										
											2010-03-11 22:53:45 +00:00
										 |  |  | #! /usr/bin/env python3 | 
					
						
							| 
									
										
										
										
											1994-05-09 14:52:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | # Selectively preprocess #ifdef / #ifndef statements. | 
					
						
							|  |  |  | # Usage: | 
					
						
							|  |  |  | # ifdef [-Dname] ... [-Uname] ... [file] ... | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  | # | 
					
						
							| 
									
										
										
										
											1994-05-09 14:52:41 +00:00
										 |  |  | # 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 | 
					
						
							| 
									
										
										
										
											2013-08-26 01:32:56 +03:00
										 |  |  | # lines themselves (if the #if(n)def tests for one of the mentioned | 
					
						
							| 
									
										
										
										
											1994-05-09 14:52:41 +00:00
										 |  |  | # names) are removed as well. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Features: Arbitrary nesting of recognized and unrecognized | 
					
						
							| 
									
										
										
										
											2013-08-26 01:32:56 +03:00
										 |  |  | # preprocessor statements works correctly.  Unrecognized #if* commands | 
					
						
							| 
									
										
										
										
											1994-05-09 14:52:41 +00:00
										 |  |  | # 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 getopt | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | defs = [] | 
					
						
							|  |  |  | undefs = [] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def main(): | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |     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 = ['-'] | 
					
						
							| 
									
										
										
										
											2003-05-13 18:14:25 +00:00
										 |  |  |     for filename in args: | 
					
						
							|  |  |  |         if filename == '-': | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |             process(sys.stdin, sys.stdout) | 
					
						
							|  |  |  |         else: | 
					
						
							| 
									
										
										
										
											2019-03-30 08:33:02 +02:00
										 |  |  |             with open(filename) as f: | 
					
						
							|  |  |  |                 process(f, sys.stdout) | 
					
						
							| 
									
										
										
										
											1994-05-09 14:52:41 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | def process(fpi, fpo): | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |     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 | 
					
						
							| 
									
										
										
										
											2002-09-11 20:36:02 +00:00
										 |  |  |         tmp = line.strip() | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |         if tmp[:1] != '#': | 
					
						
							|  |  |  |             if ok: fpo.write(line) | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2002-09-11 20:36:02 +00:00
										 |  |  |         tmp = tmp[1:].strip() | 
					
						
							|  |  |  |         words = tmp.split() | 
					
						
							| 
									
										
										
										
											2001-01-17 08:48:39 +00:00
										 |  |  |         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) | 
					
						
							| 
									
										
										
										
											1994-05-09 14:52:41 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2004-08-09 17:27:55 +00:00
										 |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     main() |