1#!/usr/bin/env python3 2# 3# Copyright (C) 2020-2023 by 4# David Turner, Robert Wilhelm, and Werner Lemberg. 5# 6# This file is part of the FreeType project, and may only be used, modified, 7# and distributed under the terms of the FreeType project license, 8# LICENSE.TXT. By continuing to use, modify, or distribute this file you 9# indicate that you have read the license and understand and accept it 10# fully. 11 12"""Toggle settings in `ftoption.h` file based on command-line arguments. 13 14This script takes an `ftoption.h` file as input and rewrites 15`#define`/`#undef` lines in it based on `--enable=CONFIG_VARNAME` or 16`--disable=CONFIG_VARNAME` arguments passed to it, where `CONFIG_VARNAME` is 17configuration variable name, such as `FT_CONFIG_OPTION_USE_LZW`, that may 18appear in the file. 19 20Note that if one of `CONFIG_VARNAME` is not found in the input file, this 21script exits with an error message listing the missing variable names. 22""" 23 24import argparse 25import os 26import re 27import sys 28 29 30def main(): 31 parser = argparse.ArgumentParser(description=__doc__) 32 33 parser.add_argument( 34 "input", metavar="FTOPTION_H", help="Path to input ftoption.h file." 35 ) 36 37 parser.add_argument("--output", help="Output to file instead of stdout.") 38 39 parser.add_argument( 40 "--enable", 41 action="append", 42 default=[], 43 help="Enable a given build option (e.g. FT_CONFIG_OPTION_USE_LZW).", 44 ) 45 46 parser.add_argument( 47 "--disable", 48 action="append", 49 default=[], 50 help="Disable a given build option.", 51 ) 52 53 args = parser.parse_args() 54 55 common_options = set(args.enable) & set(args.disable) 56 if common_options: 57 parser.error( 58 "Options cannot be both enabled and disabled: %s" 59 % sorted(common_options) 60 ) 61 return 1 62 63 with open(args.input) as f: 64 input_file = f.read() 65 66 options_seen = set() 67 68 new_lines = [] 69 for line in input_file.splitlines(): 70 # Expected formats: 71 # #define <CONFIG_VAR> 72 # /* #define <CONFIG_VAR> */ 73 # #undef <CONFIG_VAR> 74 line = line.rstrip() 75 if line.startswith("/* #define ") and line.endswith(" */"): 76 option_name = line[11:-3].strip() 77 option_enabled = False 78 elif line.startswith("#define "): 79 option_name = line[8:].strip() 80 option_enabled = True 81 elif line.startswith("#undef "): 82 option_name = line[7:].strip() 83 option_enabled = False 84 else: 85 new_lines.append(line) 86 continue 87 88 options_seen.add(option_name) 89 if option_enabled and option_name in args.disable: 90 line = "#undef " + option_name 91 elif not option_enabled and option_name in args.enable: 92 line = "#define " + option_name 93 new_lines.append(line) 94 95 result = "\n".join(new_lines) + "\n" 96 97 # Sanity check that all command-line options were actually processed. 98 cmdline_options = set(args.enable) | set(args.disable) 99 assert cmdline_options.issubset( 100 options_seen 101 ), "Could not find options in input file: " + ", ".join( 102 sorted(cmdline_options - options_seen) 103 ) 104 105 if args.output: 106 with open(args.output, "w") as f: 107 f.write(result) 108 else: 109 print(result) 110 111 return 0 112 113 114if __name__ == "__main__": 115 sys.exit(main()) 116