• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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