flags_util.py revision e896dfd76014af3c399d1b54be022fb1663a105b
1# Copyright (c) 2013 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Utility functions to explore the neighbor flags. 6 7Part of the Chrome build flags optimization. 8""" 9 10__author__ = 'yuhenglong@google.com (Yuheng Long)' 11 12 13import flags 14from flags import Flag 15 16 17def ClimbNext(flags_dict, climb_spec): 18 """Get the flags that are different from |flags_dict| by |climb_spec|. 19 20 Given a set of flags, |flags_dict|, return a new set of flags that are 21 adjacent along the flag spec |climb_spec|. 22 23 An example flags_dict is {foo=[1-9]:foo=5, bar=[1-5]:bar=2} and climb_spec is 24 bar=[1-5]. This method changes the flag that contains the spec bar=[1-5]. The 25 results are its neighbors dictionaries, i.e., {foo=[1-9]:foo=5, 26 bar=[1-5]:bar=1} and {foo=[1-9]:foo=5, bar=[1-5]:bar=3}. 27 28 Args: 29 flags_dict: The dictionary containing the original flags whose neighbors are 30 to be explored. 31 climb_spec: The spec in the flags_dict is to be changed. The spec is a 32 definition in the little language, a string with escaped sequences of the 33 form [<start>-<end>] where start and end is an positive integer for a 34 fillable value. An example of a spec is "foo[0-9]". 35 36 Returns: 37 List of dictionaries of neighbor flags. 38 """ 39 40 # This method searches for a pattern [start-end] in the spec. If the spec 41 # contains this pattern, it is a numeric flag. Otherwise it is a boolean flag. 42 # For example, -finline-limit=[1-1000] is a numeric flag and -falign-jumps is 43 # a boolean flag. 44 numeric_flag_match = flags.Search(climb_spec) 45 46 # If the flags do not contain the spec. 47 if climb_spec not in flags_dict: 48 results = flags_dict.copy() 49 50 if numeric_flag_match: 51 # Numeric flags. 52 results[climb_spec] = Flag(climb_spec, 53 int(numeric_flag_match.group('start'))) 54 else: 55 # Boolean flags. 56 results[climb_spec] = Flag(climb_spec) 57 58 return [results] 59 60 # The flags contain the spec. 61 if not numeric_flag_match: 62 # Boolean flags. 63 results = flags_dict.copy() 64 65 # Turn off the flag. A flag is turned off if it is not presented in the 66 # flags_dict. 67 del results[climb_spec] 68 return [results] 69 70 # Numeric flags. 71 flag = flags_dict[climb_spec] 72 73 # The value of the flag having spec. 74 value = flag.GetValue() 75 results = [] 76 77 if value + 1 < int(numeric_flag_match.group('end')): 78 # If the value is not the end value, explore the value that is 1 larger than 79 # the current value. 80 neighbor = flags_dict.copy() 81 neighbor[climb_spec] = Flag(climb_spec, value + 1) 82 results.append(neighbor) 83 84 if value > int(numeric_flag_match.group('start')): 85 # If the value is not the start value, explore the value that is 1 lesser 86 # than the current value. 87 neighbor = flags_dict.copy() 88 neighbor[climb_spec] = Flag(climb_spec, value - 1) 89 results.append(neighbor) 90 else: 91 # Delete the value, i.e., turn off the flag. A flag is turned off if it is 92 # not presented in the flags_dict. 93 neighbor = flags_dict.copy() 94 del neighbor[climb_spec] 95 results.append(neighbor) 96 97 return results 98