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