1# (C) Copyright David Abrahams 2001. Permission to copy, use, modify, sell and 2# distribute this software is granted provided this copyright notice appears in 3# all copies. This software is provided "as is" without express or implied 4# warranty, and with no claim as to its suitability for any purpose. 5 6""" Utility functions to add/remove/get grists. 7 Grists are string enclosed in angle brackets (<>) that are used as prefixes. See Jam for more information. 8""" 9 10import re 11import os 12import bjam 13from b2.exceptions import * 14from b2.util import is_iterable_typed 15 16__re_grist_and_value = re.compile (r'(<[^>]*>)(.*)') 17__re_grist_content = re.compile ('^<(.*)>$') 18__re_backslash = re.compile (r'\\') 19 20def to_seq (value): 21 """ If value is a sequence, returns it. 22 If it is a string, returns a sequence with value as its sole element. 23 """ 24 if not value: 25 return [] 26 27 if isinstance (value, str): 28 return [value] 29 30 else: 31 return value 32 33def replace_references_by_objects (manager, refs): 34 objs = [] 35 for r in refs: 36 objs.append (manager.get_object (r)) 37 return objs 38 39def add_grist (features): 40 """ Transform a string by bracketing it with "<>". If already bracketed, does nothing. 41 features: one string or a sequence of strings 42 return: the gristed string, if features is a string, or a sequence of gristed strings, if features is a sequence 43 """ 44 assert is_iterable_typed(features, basestring) or isinstance(features, basestring) 45 def grist_one (feature): 46 if feature [0] != '<' and feature [len (feature) - 1] != '>': 47 return '<' + feature + '>' 48 else: 49 return feature 50 51 if isinstance (features, str): 52 return grist_one (features) 53 else: 54 return [ grist_one (feature) for feature in features ] 55 56def replace_grist (features, new_grist): 57 """ Replaces the grist of a string by a new one. 58 Returns the string with the new grist. 59 """ 60 assert is_iterable_typed(features, basestring) or isinstance(features, basestring) 61 assert isinstance(new_grist, basestring) 62 # this function is used a lot in the build phase and the original implementation 63 # was extremely slow; thus some of the weird-looking optimizations for this function. 64 single_item = False 65 if isinstance(features, str): 66 features = [features] 67 single_item = True 68 69 result = [] 70 for feature in features: 71 # '<feature>value' -> ('<feature', '>', 'value') 72 # 'something' -> ('something', '', '') 73 # '<toolset>msvc/<feature>value' -> ('<toolset', '>', 'msvc/<feature>value') 74 grist, split, value = feature.partition('>') 75 # if a partition didn't occur, then grist is just 'something' 76 # set the value to be the grist 77 if not value and not split: 78 value = grist 79 result.append(new_grist + value) 80 81 if single_item: 82 return result[0] 83 return result 84 85def get_value (property): 86 """ Gets the value of a property, that is, the part following the grist, if any. 87 """ 88 assert is_iterable_typed(property, basestring) or isinstance(property, basestring) 89 return replace_grist (property, '') 90 91def get_grist (value): 92 """ Returns the grist of a string. 93 If value is a sequence, does it for every value and returns the result as a sequence. 94 """ 95 assert is_iterable_typed(value, basestring) or isinstance(value, basestring) 96 def get_grist_one (name): 97 split = __re_grist_and_value.match (name) 98 if not split: 99 return '' 100 else: 101 return split.group (1) 102 103 if isinstance (value, str): 104 return get_grist_one (value) 105 else: 106 return [ get_grist_one (v) for v in value ] 107 108def ungrist (value): 109 """ Returns the value without grist. 110 If value is a sequence, does it for every value and returns the result as a sequence. 111 """ 112 assert is_iterable_typed(value, basestring) or isinstance(value, basestring) 113 def ungrist_one (value): 114 stripped = __re_grist_content.match (value) 115 if not stripped: 116 raise BaseException ("in ungrist: '%s' is not of the form <.*>" % value) 117 118 return stripped.group (1) 119 120 if isinstance (value, str): 121 return ungrist_one (value) 122 else: 123 return [ ungrist_one (v) for v in value ] 124 125def replace_suffix (name, new_suffix): 126 """ Replaces the suffix of name by new_suffix. 127 If no suffix exists, the new one is added. 128 """ 129 assert isinstance(name, basestring) 130 assert isinstance(new_suffix, basestring) 131 split = os.path.splitext (name) 132 return split [0] + new_suffix 133 134def forward_slashes (s): 135 """ Converts all backslashes to forward slashes. 136 """ 137 assert isinstance(s, basestring) 138 return s.replace('\\', '/') 139 140 141def split_action_id (id): 142 """ Splits an id in the toolset and specific rule parts. E.g. 143 'gcc.compile.c++' returns ('gcc', 'compile.c++') 144 """ 145 assert isinstance(id, basestring) 146 split = id.split ('.', 1) 147 toolset = split [0] 148 name = '' 149 if len (split) > 1: 150 name = split [1] 151 return (toolset, name) 152 153def os_name (): 154 result = bjam.variable("OS") 155 assert(len(result) == 1) 156 return result[0] 157 158def platform (): 159 return bjam.variable("OSPLAT") 160 161def os_version (): 162 return bjam.variable("OSVER") 163 164def on_windows (): 165 """ Returns true if running on windows, whether in cygwin or not. 166 """ 167 if bjam.variable("NT"): 168 return True 169 170 elif bjam.variable("UNIX"): 171 172 uname = bjam.variable("JAMUNAME") 173 if uname and uname[0].startswith("CYGWIN"): 174 return True 175 176 return False 177