~ubuntu-branches/ubuntu/oneiric/enigmail/oneiric-updates

« back to all changes in this revision

Viewing changes to build/pymake/pymake/functions.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexander Sack
  • Date: 2010-04-10 01:42:24 UTC
  • Revision ID: james.westby@ubuntu.com-20100410014224-fbq9ui5x3b0h2t36
Tags: 2:1.0.1-0ubuntu1
* First releaase of enigmail 1.0.1 for tbird/icedove 3
  (LP: #527138)
* redo packaging from scratch 
  + add debian/make-orig target that uses xulrunner provided
    buildsystem + enigmail tarball to produce a proper orig.tar.gz
  + use debhelper 7 with mozilla-devscripts
  + use debian source format 3.0 (quilt)
  + patch enigmail to use frozen API only
    - add debian/patches/frozen_api.diff
  + patch build system to not link against -lxul - which isnt
    available for sdks produced by all-static apps like tbird
    - add debian/patches/build_system_dont_link_libxul.diff
  + add minimal build-depends to control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""
 
2
Makefile functions.
 
3
"""
 
4
 
 
5
import parser, data, util
 
6
import subprocess, os, logging
 
7
from globrelative import glob
 
8
from cStringIO import StringIO
 
9
 
 
10
log = logging.getLogger('pymake.data')
 
11
 
 
12
class Function(object):
 
13
    """
 
14
    An object that represents a function call. This class is always subclassed
 
15
    with the following methods and attributes:
 
16
 
 
17
    minargs = minimum # of arguments
 
18
    maxargs = maximum # of arguments (0 means unlimited)
 
19
 
 
20
    def resolve(self, makefile, variables, fd, setting)
 
21
        Calls the function
 
22
        calls fd.write() with strings
 
23
    """
 
24
 
 
25
    __slots__ = ('_arguments', 'loc')
 
26
 
 
27
    def __init__(self, loc):
 
28
        self._arguments = []
 
29
        self.loc = loc
 
30
        assert self.minargs > 0
 
31
 
 
32
    def __getitem__(self, key):
 
33
        return self._arguments[key]
 
34
 
 
35
    def setup(self):
 
36
        argc = len(self._arguments)
 
37
 
 
38
        if argc < self.minargs:
 
39
            raise data.DataError("Not enough arguments to function %s, requires %s" % (self.name, self.minargs), self.loc)
 
40
 
 
41
        assert self.maxargs == 0 or argc <= self.maxargs, "Parser screwed up, gave us too many args"
 
42
 
 
43
    def append(self, arg):
 
44
        assert isinstance(arg, (data.Expansion, data.StringExpansion))
 
45
        self._arguments.append(arg)
 
46
 
 
47
    def __len__(self):
 
48
        return len(self._arguments)
 
49
 
 
50
class VariableRef(Function):
 
51
    __slots__ = ('vname', 'loc')
 
52
 
 
53
    def __init__(self, loc, vname):
 
54
        self.loc = loc
 
55
        assert isinstance(vname, (data.Expansion, data.StringExpansion))
 
56
        self.vname = vname
 
57
        
 
58
    def setup(self):
 
59
        assert False, "Shouldn't get here"
 
60
 
 
61
    def resolve(self, makefile, variables, fd, setting):
 
62
        vname = self.vname.resolvestr(makefile, variables, setting)
 
63
        if vname in setting:
 
64
            raise data.DataError("Setting variable '%s' recursively references itself." % (vname,), self.loc)
 
65
 
 
66
        flavor, source, value = variables.get(vname)
 
67
        if value is None:
 
68
            log.debug("%s: variable '%s' was not set" % (self.loc, vname))
 
69
            return
 
70
 
 
71
        value.resolve(makefile, variables, fd, setting + [vname])
 
72
 
 
73
class SubstitutionRef(Function):
 
74
    """$(VARNAME:.c=.o) and $(VARNAME:%.c=%.o)"""
 
75
 
 
76
    __slots__ = ('loc', 'vname', 'substfrom', 'substto')
 
77
 
 
78
    def __init__(self, loc, varname, substfrom, substto):
 
79
        self.loc = loc
 
80
        self.vname = varname
 
81
        self.substfrom = substfrom
 
82
        self.substto = substto
 
83
 
 
84
    def setup(self):
 
85
        assert False, "Shouldn't get here"
 
86
 
 
87
    def resolve(self, makefile, variables, fd, setting):
 
88
        vname = self.vname.resolvestr(makefile, variables, setting)
 
89
        if vname in setting:
 
90
            raise data.DataError("Setting variable '%s' recursively references itself." % (vname,), self.loc)
 
91
 
 
92
        substfrom = self.substfrom.resolvestr(makefile, variables, setting)
 
93
        substto = self.substto.resolvestr(makefile, variables, setting)
 
94
 
 
95
        flavor, source, value = variables.get(vname)
 
96
        if value is None:
 
97
            log.debug("%s: variable '%s' was not set" % (self.loc, vname))
 
98
            return
 
99
 
 
100
        f = data.Pattern(substfrom)
 
101
        if not f.ispattern():
 
102
            f = data.Pattern('%' + substfrom)
 
103
            substto = '%' + substto
 
104
 
 
105
        fd.write(' '.join([f.subst(substto, word, False)
 
106
                           for word in value.resolvesplit(makefile, variables, setting + [vname])]))
 
107
 
 
108
class SubstFunction(Function):
 
109
    name = 'subst'
 
110
    minargs = 3
 
111
    maxargs = 3
 
112
 
 
113
    __slots__ = Function.__slots__
 
114
 
 
115
    def resolve(self, makefile, variables, fd, setting):
 
116
        s = self._arguments[0].resolvestr(makefile, variables, setting)
 
117
        r = self._arguments[1].resolvestr(makefile, variables, setting)
 
118
        d = self._arguments[2].resolvestr(makefile, variables, setting)
 
119
        fd.write(d.replace(s, r))
 
120
 
 
121
class PatSubstFunction(Function):
 
122
    name = 'patsubst'
 
123
    minargs = 3
 
124
    maxargs = 3
 
125
 
 
126
    __slots__ = Function.__slots__
 
127
 
 
128
    def resolve(self, makefile, variables, fd, setting):
 
129
        s = self._arguments[0].resolvestr(makefile, variables, setting)
 
130
        r = self._arguments[1].resolvestr(makefile, variables, setting)
 
131
 
 
132
        p = data.Pattern(s)
 
133
        fd.write(' '.join([p.subst(r, word, False)
 
134
                           for word in self._arguments[2].resolvesplit(makefile, variables, setting)]))
 
135
 
 
136
class StripFunction(Function):
 
137
    name = 'strip'
 
138
    minargs = 1
 
139
    maxargs = 1
 
140
 
 
141
    __slots__ = Function.__slots__
 
142
 
 
143
    def resolve(self, makefile, variables, fd, setting):
 
144
        util.joiniter(fd, self._arguments[0].resolvesplit(makefile, variables, setting))
 
145
 
 
146
class FindstringFunction(Function):
 
147
    name = 'findstring'
 
148
    minargs = 2
 
149
    maxargs = 2
 
150
 
 
151
    __slots__ = Function.__slots__
 
152
 
 
153
    def resolve(self, makefile, variables, fd, setting):
 
154
        s = self._arguments[0].resolvestr(makefile, variables, setting)
 
155
        r = self._arguments[1].resolvestr(makefile, variables, setting)
 
156
        if r.find(s) == -1:
 
157
            return
 
158
        fd.write(s)
 
159
 
 
160
class FilterFunction(Function):
 
161
    name = 'filter'
 
162
    minargs = 2
 
163
    maxargs = 2
 
164
 
 
165
    __slots__ = Function.__slots__
 
166
 
 
167
    def resolve(self, makefile, variables, fd, setting):
 
168
        plist = [data.Pattern(p)
 
169
                 for p in self._arguments[0].resolvesplit(makefile, variables, setting)]
 
170
 
 
171
        fd.write(' '.join([w for w in self._arguments[1].resolvesplit(makefile, variables, setting)
 
172
                           if util.any((p.match(w) for p in plist))]))
 
173
 
 
174
class FilteroutFunction(Function):
 
175
    name = 'filter-out'
 
176
    minargs = 2
 
177
    maxargs = 2
 
178
 
 
179
    __slots__ = Function.__slots__
 
180
 
 
181
    def resolve(self, makefile, variables, fd, setting):
 
182
        plist = [data.Pattern(p)
 
183
                 for p in self._arguments[0].resolvesplit(makefile, variables, setting)]
 
184
 
 
185
        fd.write(' '.join([w for w in self._arguments[1].resolvesplit(makefile, variables, setting)
 
186
                           if not util.any((p.match(w) for p in plist))]))
 
187
 
 
188
class SortFunction(Function):
 
189
    name = 'sort'
 
190
    minargs = 1
 
191
    maxargs = 1
 
192
 
 
193
    __slots__ = Function.__slots__
 
194
 
 
195
    def resolve(self, makefile, variables, fd, setting):
 
196
        d = list(self._arguments[0].resolvesplit(makefile, variables, setting))
 
197
        d.sort()
 
198
        util.joiniter(fd, d)
 
199
 
 
200
class WordFunction(Function):
 
201
    name = 'word'
 
202
    minargs = 2
 
203
    maxargs = 2
 
204
 
 
205
    __slots__ = Function.__slots__
 
206
 
 
207
    def resolve(self, makefile, variables, fd, setting):
 
208
        n = self._arguments[0].resolvestr(makefile, variables, setting)
 
209
        # TODO: provide better error if this doesn't convert
 
210
        n = int(n)
 
211
        words = list(self._arguments[1].resolvesplit(makefile, variables, setting))
 
212
        if n < 1 or n > len(words):
 
213
            return
 
214
        fd.write(words[n - 1])
 
215
 
 
216
class WordlistFunction(Function):
 
217
    name = 'wordlist'
 
218
    minargs = 3
 
219
    maxargs = 3
 
220
 
 
221
    __slots__ = Function.__slots__
 
222
 
 
223
    def resolve(self, makefile, variables, fd, setting):
 
224
        nfrom = self._arguments[0].resolvestr(makefile, variables, setting)
 
225
        nto = self._arguments[1].resolvestr(makefile, variables, setting)
 
226
        # TODO: provide better errors if this doesn't convert
 
227
        nfrom = int(nfrom)
 
228
        nto = int(nto)
 
229
 
 
230
        words = list(self._arguments[2].resolvesplit(makefile, variables, setting))
 
231
 
 
232
        if nfrom < 1:
 
233
            nfrom = 1
 
234
        if nto < 1:
 
235
            nto = 1
 
236
 
 
237
        util.joiniter(fd, words[nfrom - 1:nto])
 
238
 
 
239
class WordsFunction(Function):
 
240
    name = 'words'
 
241
    minargs = 1
 
242
    maxargs = 1
 
243
 
 
244
    __slots__ = Function.__slots__
 
245
 
 
246
    def resolve(self, makefile, variables, fd, setting):
 
247
        fd.write(str(len(self._arguments[0].resolvesplit(makefile, variables, setting))))
 
248
 
 
249
class FirstWordFunction(Function):
 
250
    name = 'firstword'
 
251
    minargs = 1
 
252
    maxargs = 1
 
253
 
 
254
    __slots__ = Function.__slots__
 
255
 
 
256
    def resolve(self, makefile, variables, fd, setting):
 
257
        l = self._arguments[0].resolvesplit(makefile, variables, setting)
 
258
        if len(l):
 
259
            fd.write(l[0])
 
260
 
 
261
class LastWordFunction(Function):
 
262
    name = 'lastword'
 
263
    minargs = 1
 
264
    maxargs = 1
 
265
 
 
266
    __slots__ = Function.__slots__
 
267
 
 
268
    def resolve(self, makefile, variables, fd, setting):
 
269
        l = self._arguments[0].resolvesplit(makefile, variables, setting)
 
270
        if len(l):
 
271
            fd.write(l[-1])
 
272
 
 
273
def pathsplit(path, default='./'):
 
274
    """
 
275
    Splits a path into dirpart, filepart on the last slash. If there is no slash, dirpart
 
276
    is ./
 
277
    """
 
278
    dir, slash, file = util.strrpartition(path, '/')
 
279
    if dir == '':
 
280
        return default, file
 
281
 
 
282
    return dir + slash, file
 
283
 
 
284
class DirFunction(Function):
 
285
    name = 'dir'
 
286
    minargs = 1
 
287
    maxargs = 1
 
288
 
 
289
    def resolve(self, makefile, variables, fd, setting):
 
290
        fd.write(' '.join([pathsplit(path)[0]
 
291
                           for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
 
292
 
 
293
class NotDirFunction(Function):
 
294
    name = 'notdir'
 
295
    minargs = 1
 
296
    maxargs = 1
 
297
 
 
298
    __slots__ = Function.__slots__
 
299
 
 
300
    def resolve(self, makefile, variables, fd, setting):
 
301
        fd.write(' '.join([pathsplit(path)[1]
 
302
                           for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
 
303
 
 
304
class SuffixFunction(Function):
 
305
    name = 'suffix'
 
306
    minargs = 1
 
307
    maxargs = 1
 
308
 
 
309
    __slots__ = Function.__slots__
 
310
 
 
311
    @staticmethod
 
312
    def suffixes(words):
 
313
        for w in words:
 
314
            dir, file = pathsplit(w)
 
315
            base, dot, suffix = util.strrpartition(file, '.')
 
316
            if base != '':
 
317
                yield dot + suffix
 
318
 
 
319
    def resolve(self, makefile, variables, fd, setting):
 
320
        util.joiniter(fd, self.suffixes(self._arguments[0].resolvesplit(makefile, variables, setting)))
 
321
 
 
322
class BasenameFunction(Function):
 
323
    name = 'basename'
 
324
    minargs = 1
 
325
    maxargs = 1
 
326
 
 
327
    __slots__ = Function.__slots__
 
328
 
 
329
    @staticmethod
 
330
    def basenames(words):
 
331
        for w in words:
 
332
            dir, file = pathsplit(w, '')
 
333
            base, dot, suffix = util.strrpartition(file, '.')
 
334
            if dot == '':
 
335
                base = suffix
 
336
 
 
337
            yield dir + base
 
338
 
 
339
    def resolve(self, makefile, variables, fd, setting):
 
340
        util.joiniter(fd, self.basenames(self._arguments[0].resolvesplit(makefile, variables, setting)))
 
341
 
 
342
class AddSuffixFunction(Function):
 
343
    name = 'addprefix'
 
344
    minargs = 2
 
345
    maxargs = 2
 
346
 
 
347
    __slots__ = Function.__slots__
 
348
 
 
349
    def resolve(self, makefile, variables, fd, setting):
 
350
        suffix = self._arguments[0].resolvestr(makefile, variables, setting)
 
351
 
 
352
        fd.write(' '.join([w + suffix for w in self._arguments[1].resolvesplit(makefile, variables, setting)]))
 
353
 
 
354
class AddPrefixFunction(Function):
 
355
    name = 'addsuffix'
 
356
    minargs = 2
 
357
    maxargs = 2
 
358
 
 
359
    def resolve(self, makefile, variables, fd, setting):
 
360
        prefix = self._arguments[0].resolvestr(makefile, variables, setting)
 
361
 
 
362
        fd.write(' '.join([prefix + w for w in self._arguments[1].resolvesplit(makefile, variables, setting)]))
 
363
 
 
364
class JoinFunction(Function):
 
365
    name = 'join'
 
366
    minargs = 2
 
367
    maxargs = 2
 
368
 
 
369
    __slots__ = Function.__slots__
 
370
 
 
371
    @staticmethod
 
372
    def iterjoin(l1, l2):
 
373
        for i in xrange(0, max(len(l1), len(l2))):
 
374
            i1 = i < len(l1) and l1[i] or ''
 
375
            i2 = i < len(l2) and l2[i] or ''
 
376
            yield i1 + i2
 
377
 
 
378
    def resolve(self, makefile, variables, fd, setting):
 
379
        list1 = list(self._arguments[0].resolvesplit(makefile, variables, setting))
 
380
        list2 = list(self._arguments[1].resolvesplit(makefile, variables, setting))
 
381
 
 
382
        util.joiniter(fd, self.iterjoin(list1, list2))
 
383
 
 
384
class WildcardFunction(Function):
 
385
    name = 'wildcard'
 
386
    minargs = 1
 
387
    maxargs = 1
 
388
 
 
389
    __slots__ = Function.__slots__
 
390
 
 
391
    def resolve(self, makefile, variables, fd, setting):
 
392
        patterns = self._arguments[0].resolvesplit(makefile, variables, setting)
 
393
 
 
394
        fd.write(' '.join([x.replace('\\','/')
 
395
                           for p in patterns
 
396
                           for x in glob(makefile.workdir, p)]))
 
397
 
 
398
    __slots__ = Function.__slots__
 
399
 
 
400
class RealpathFunction(Function):
 
401
    name = 'realpath'
 
402
    minargs = 1
 
403
    maxargs = 1
 
404
 
 
405
    def resolve(self, makefile, variables, fd, setting):
 
406
        fd.write(' '.join([os.path.realpath(os.path.join(makefile.workdir, path)).replace('\\', '/')
 
407
                           for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
 
408
 
 
409
class AbspathFunction(Function):
 
410
    name = 'abspath'
 
411
    minargs = 1
 
412
    maxargs = 1
 
413
 
 
414
    __slots__ = Function.__slots__
 
415
 
 
416
    def resolve(self, makefile, variables, fd, setting):
 
417
        assert os.path.isabs(makefile.workdir)
 
418
        fd.write(' '.join([os.path.join(makefile.workdir, path).replace('\\', '/')
 
419
                           for path in self._arguments[0].resolvesplit(makefile, variables, setting)]))
 
420
 
 
421
class IfFunction(Function):
 
422
    name = 'if'
 
423
    minargs = 1
 
424
    maxargs = 3
 
425
 
 
426
    __slots__ = Function.__slots__
 
427
 
 
428
    def setup(self):
 
429
        Function.setup(self)
 
430
        self._arguments[0].lstrip()
 
431
        self._arguments[0].rstrip()
 
432
 
 
433
    def resolve(self, makefile, variables, fd, setting):
 
434
        condition = self._arguments[0].resolvestr(makefile, variables, setting)
 
435
 
 
436
        if len(condition):
 
437
            self._arguments[1].resolve(makefile, variables, fd, setting)
 
438
        elif len(self._arguments) > 2:
 
439
            return self._arguments[2].resolve(makefile, variables, fd, setting)
 
440
 
 
441
class OrFunction(Function):
 
442
    name = 'or'
 
443
    minargs = 1
 
444
    maxargs = 0
 
445
 
 
446
    __slots__ = Function.__slots__
 
447
 
 
448
    def resolve(self, makefile, variables, fd, setting):
 
449
        for arg in self._arguments:
 
450
            r = arg.resolvestr(makefile, variables, setting)
 
451
            if r != '':
 
452
                fd.write(r)
 
453
                return
 
454
 
 
455
class AndFunction(Function):
 
456
    name = 'and'
 
457
    minargs = 1
 
458
    maxargs = 0
 
459
 
 
460
    __slots__ = Function.__slots__
 
461
 
 
462
    def resolve(self, makefile, variables, fd, setting):
 
463
        r = ''
 
464
 
 
465
        for arg in self._arguments:
 
466
            r = arg.resolvestr(makefile, variables, setting)
 
467
            if r == '':
 
468
                return
 
469
 
 
470
        fd.write(r)
 
471
 
 
472
class ForEachFunction(Function):
 
473
    name = 'foreach'
 
474
    minargs = 3
 
475
    maxargs = 3
 
476
 
 
477
    __slots__ = Function.__slots__
 
478
 
 
479
    def resolve(self, makefile, variables, fd, setting):
 
480
        vname = self._arguments[0].resolvestr(makefile, variables, setting)
 
481
        e = self._arguments[2]
 
482
 
 
483
        v = data.Variables(parent=variables)
 
484
        firstword = True
 
485
 
 
486
        for w in self._arguments[1].resolvesplit(makefile, variables, setting):
 
487
            if firstword:
 
488
                firstword = False
 
489
            else:
 
490
                fd.write(' ')
 
491
 
 
492
            v.set(vname, data.Variables.FLAVOR_SIMPLE, data.Variables.SOURCE_AUTOMATIC, w)
 
493
            e.resolve(makefile, v, fd, setting)
 
494
 
 
495
class CallFunction(Function):
 
496
    name = 'call'
 
497
    minargs = 1
 
498
    maxargs = 0
 
499
 
 
500
    __slots__ = Function.__slots__
 
501
 
 
502
    def resolve(self, makefile, variables, fd, setting):
 
503
        vname = self._arguments[0].resolvestr(makefile, variables, setting)
 
504
        if vname in setting:
 
505
            raise data.DataError("Recursively setting variable '%s'" % (vname,))
 
506
 
 
507
        v = data.Variables(parent=variables)
 
508
        v.set('0', data.Variables.FLAVOR_SIMPLE, data.Variables.SOURCE_AUTOMATIC, vname)
 
509
        for i in xrange(1, len(self._arguments)):
 
510
            param = self._arguments[i].resolvestr(makefile, variables, setting)
 
511
            v.set(str(i), data.Variables.FLAVOR_SIMPLE, data.Variables.SOURCE_AUTOMATIC, param)
 
512
 
 
513
        flavor, source, e = variables.get(vname)
 
514
 
 
515
        if e is None:
 
516
            return
 
517
 
 
518
        if flavor == data.Variables.FLAVOR_SIMPLE:
 
519
            log.warning("%s: calling variable '%s' which is simply-expanded" % (self.loc, vname))
 
520
 
 
521
        # but we'll do it anyway
 
522
        e.resolve(makefile, v, fd, setting + [vname])
 
523
 
 
524
class ValueFunction(Function):
 
525
    name = 'value'
 
526
    minargs = 1
 
527
    maxargs = 1
 
528
 
 
529
    __slots__ = Function.__slots__
 
530
 
 
531
    def resolve(self, makefile, variables, fd, setting):
 
532
        varname = self._arguments[0].resolvestr(makefile, variables, setting)
 
533
 
 
534
        flavor, source, value = variables.get(varname, expand=False)
 
535
        if value is not None:
 
536
            fd.write(value)
 
537
 
 
538
class EvalFunction(Function):
 
539
    name = 'eval'
 
540
    minargs = 1
 
541
    maxargs = 1
 
542
 
 
543
    def resolve(self, makefile, variables, fd, setting):
 
544
        if makefile.parsingfinished:
 
545
            # GNU make allows variables to be set by recursive expansion during
 
546
            # command execution. This seems really dumb to me, so I don't!
 
547
            raise data.DataError("$(eval) not allowed via recursive expansion after parsing is finished", self.loc)
 
548
 
 
549
        text = StringIO(self._arguments[0].resolvestr(makefile, variables, setting))
 
550
        stmts = parser.parsestream(text, 'evaluation from %s' % self.loc)
 
551
        stmts.execute(makefile)
 
552
 
 
553
class OriginFunction(Function):
 
554
    name = 'origin'
 
555
    minargs = 1
 
556
    maxargs = 1
 
557
 
 
558
    __slots__ = Function.__slots__
 
559
 
 
560
    def resolve(self, makefile, variables, fd, setting):
 
561
        vname = self._arguments[0].resolvestr(makefile, variables, setting)
 
562
 
 
563
        flavor, source, value = variables.get(vname)
 
564
        if source is None:
 
565
            r = 'undefined'
 
566
        elif source == data.Variables.SOURCE_OVERRIDE:
 
567
            r = 'override'
 
568
 
 
569
        elif source == data.Variables.SOURCE_MAKEFILE:
 
570
            r = 'file'
 
571
        elif source == data.Variables.SOURCE_ENVIRONMENT:
 
572
            r = 'environment'
 
573
        elif source == data.Variables.SOURCE_COMMANDLINE:
 
574
            r = 'command line'
 
575
        elif source == data.Variables.SOURCE_AUTOMATIC:
 
576
            r = 'automatic'
 
577
        elif source == data.Variables.SOURCE_IMPLICIT:
 
578
            r = 'default'
 
579
 
 
580
        fd.write(r)
 
581
 
 
582
class FlavorFunction(Function):
 
583
    name = 'flavor'
 
584
    minargs = 1
 
585
    maxargs = 1
 
586
 
 
587
    __slots__ = Function.__slots__
 
588
 
 
589
    def resolve(self, makefile, variables, fd, setting):
 
590
        varname = self._arguments[0].resolvestr(makefile, variables, setting)
 
591
        
 
592
        flavor, source, value = variables.get(varname)
 
593
        if flavor is None:
 
594
            r = 'undefined'
 
595
        elif flavor == data.Variables.FLAVOR_RECURSIVE:
 
596
            r = 'recursive'
 
597
        elif flavor == data.Variables.FLAVOR_SIMPLE:
 
598
            r = 'simple'
 
599
        fd.write(r)
 
600
 
 
601
class ShellFunction(Function):
 
602
    name = 'shell'
 
603
    minargs = 1
 
604
    maxargs = 1
 
605
 
 
606
    __slots__ = Function.__slots__
 
607
 
 
608
    def resolve(self, makefile, variables, fd, setting):
 
609
        #TODO: call this once up-front somewhere and save the result?
 
610
        shell, msys = util.checkmsyscompat()
 
611
        cline = self._arguments[0].resolvestr(makefile, variables, setting)
 
612
 
 
613
        log.debug("%s: running shell command '%s'" % (self.loc, cline))
 
614
        if msys:
 
615
            cline = [shell, "-c", cline]
 
616
        p = subprocess.Popen(cline, shell=not msys, stdout=subprocess.PIPE, cwd=makefile.workdir)
 
617
        stdout, stderr = p.communicate()
 
618
 
 
619
        stdout = stdout.replace('\r\n', '\n')
 
620
        if stdout.endswith('\n'):
 
621
            stdout = stdout[:-1]
 
622
        stdout = stdout.replace('\n', ' ')
 
623
 
 
624
        fd.write(stdout)
 
625
 
 
626
class ErrorFunction(Function):
 
627
    name = 'error'
 
628
    minargs = 1
 
629
    maxargs = 1
 
630
 
 
631
    __slots__ = Function.__slots__
 
632
 
 
633
    def resolve(self, makefile, variables, fd, setting):
 
634
        v = self._arguments[0].resolvestr(makefile, variables, setting)
 
635
        raise data.DataError(v, self.loc)
 
636
 
 
637
class WarningFunction(Function):
 
638
    name = 'warning'
 
639
    minargs = 1
 
640
    maxargs = 1
 
641
 
 
642
    __slots__ = Function.__slots__
 
643
 
 
644
    def resolve(self, makefile, variables, fd, setting):
 
645
        v = self._arguments[0].resolvestr(makefile, variables, setting)
 
646
        log.warning(v)
 
647
 
 
648
class InfoFunction(Function):
 
649
    name = 'info'
 
650
    minargs = 1
 
651
    maxargs = 1
 
652
 
 
653
    __slots__ = Function.__slots__
 
654
 
 
655
    def resolve(self, makefile, variables, fd, setting):
 
656
        v = self._arguments[0].resolvestr(makefile, variables, setting)
 
657
        log.info(v)
 
658
 
 
659
functionmap = {
 
660
    'subst': SubstFunction,
 
661
    'patsubst': PatSubstFunction,
 
662
    'strip': StripFunction,
 
663
    'findstring': FindstringFunction,
 
664
    'filter': FilterFunction,
 
665
    'filter-out': FilteroutFunction,
 
666
    'sort': SortFunction,
 
667
    'word': WordFunction,
 
668
    'wordlist': WordlistFunction,
 
669
    'words': WordsFunction,
 
670
    'firstword': FirstWordFunction,
 
671
    'lastword': LastWordFunction,
 
672
    'dir': DirFunction,
 
673
    'notdir': NotDirFunction,
 
674
    'suffix': SuffixFunction,
 
675
    'basename': BasenameFunction,
 
676
    'addsuffix': AddSuffixFunction,
 
677
    'addprefix': AddPrefixFunction,
 
678
    'join': JoinFunction,
 
679
    'wildcard': WildcardFunction,
 
680
    'realpath': RealpathFunction,
 
681
    'abspath': AbspathFunction,
 
682
    'if': IfFunction,
 
683
    'or': OrFunction,
 
684
    'and': AndFunction,
 
685
    'foreach': ForEachFunction,
 
686
    'call': CallFunction,
 
687
    'value': ValueFunction,
 
688
    'eval': EvalFunction,
 
689
    'origin': OriginFunction,
 
690
    'flavor': FlavorFunction,
 
691
    'shell': ShellFunction,
 
692
    'error': ErrorFunction,
 
693
    'warning': WarningFunction,
 
694
    'info': InfoFunction,
 
695
}