OLD | NEW |
1 """SCons.Subst | 1 """SCons.Subst |
2 | 2 |
3 SCons string substitution. | 3 SCons string substitution. |
4 | 4 |
5 """ | 5 """ |
6 | 6 |
7 # | 7 # |
8 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundat
ion | 8 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 The SCons F
oundation |
9 # | 9 # |
10 # Permission is hereby granted, free of charge, to any person obtaining | 10 # Permission is hereby granted, free of charge, to any person obtaining |
11 # a copy of this software and associated documentation files (the | 11 # a copy of this software and associated documentation files (the |
12 # "Software"), to deal in the Software without restriction, including | 12 # "Software"), to deal in the Software without restriction, including |
13 # without limitation the rights to use, copy, modify, merge, publish, | 13 # without limitation the rights to use, copy, modify, merge, publish, |
14 # distribute, sublicense, and/or sell copies of the Software, and to | 14 # distribute, sublicense, and/or sell copies of the Software, and to |
15 # permit persons to whom the Software is furnished to do so, subject to | 15 # permit persons to whom the Software is furnished to do so, subject to |
16 # the following conditions: | 16 # the following conditions: |
17 # | 17 # |
18 # The above copyright notice and this permission notice shall be included | 18 # The above copyright notice and this permission notice shall be included |
19 # in all copies or substantial portions of the Software. | 19 # in all copies or substantial portions of the Software. |
20 # | 20 # |
21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY | 21 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY |
22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE | 22 # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE |
23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | 23 # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | 24 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
25 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | 25 # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
26 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | 26 # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | 27 # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
28 # | 28 # |
29 | 29 |
30 __revision__ = "src/engine/SCons/Subst.py 3842 2008/12/20 22:59:52 scons" | 30 __revision__ = "src/engine/SCons/Subst.py 3897 2009/01/13 06:45:54 scons" |
31 | 31 |
32 import re | 32 import re |
33 import string | 33 import string |
34 import types | 34 import types |
35 import UserList | 35 import UserList |
36 import UserString | 36 import UserString |
37 | 37 |
38 import SCons.Errors | 38 import SCons.Errors |
39 | 39 |
40 from SCons.Util import is_String, is_Sequence | 40 from SCons.Util import is_String, is_Sequence |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 nl = self.nl._create_nodelist() | 246 nl = self.nl._create_nodelist() |
247 if nl: | 247 if nl: |
248 return str(nl[0]) | 248 return str(nl[0]) |
249 return '' | 249 return '' |
250 def __repr__(self): | 250 def __repr__(self): |
251 nl = self.nl._create_nodelist() | 251 nl = self.nl._create_nodelist() |
252 if nl: | 252 if nl: |
253 return repr(nl[0]) | 253 return repr(nl[0]) |
254 return '' | 254 return '' |
255 | 255 |
| 256 class NullNodeList(SCons.Util.NullSeq): |
| 257 def __call__(self, *args, **kwargs): return '' |
| 258 def __str__(self): return '' |
| 259 # TODO(1.5): unneeded after new-style classes introduce iterators |
| 260 def __getitem__(self, i): |
| 261 raise IndexError |
| 262 |
| 263 NullNodesList = NullNodeList() |
| 264 |
256 def subst_dict(target, source): | 265 def subst_dict(target, source): |
257 """Create a dictionary for substitution of special | 266 """Create a dictionary for substitution of special |
258 construction variables. | 267 construction variables. |
259 | 268 |
260 This translates the following special arguments: | 269 This translates the following special arguments: |
261 | 270 |
262 target - the target (object or array of objects), | 271 target - the target (object or array of objects), |
263 used to generate the TARGET and TARGETS | 272 used to generate the TARGET and TARGETS |
264 construction variables | 273 construction variables |
265 | 274 |
266 source - the source (object or array of objects), | 275 source - the source (object or array of objects), |
267 used to generate the SOURCES and SOURCE | 276 used to generate the SOURCES and SOURCE |
268 construction variables | 277 construction variables |
269 """ | 278 """ |
270 dict = {} | 279 dict = {} |
271 | 280 |
272 if target: | 281 if target: |
273 def get_tgt_subst_proxy(thing): | 282 def get_tgt_subst_proxy(thing): |
274 try: | 283 try: |
275 subst_proxy = thing.get_subst_proxy() | 284 subst_proxy = thing.get_subst_proxy() |
276 except AttributeError: | 285 except AttributeError: |
277 subst_proxy = thing # probably a string, just return it | 286 subst_proxy = thing # probably a string, just return it |
278 return subst_proxy | 287 return subst_proxy |
279 tnl = NLWrapper(target, get_tgt_subst_proxy) | 288 tnl = NLWrapper(target, get_tgt_subst_proxy) |
280 dict['TARGETS'] = Targets_or_Sources(tnl) | 289 dict['TARGETS'] = Targets_or_Sources(tnl) |
281 dict['TARGET'] = Target_or_Source(tnl) | 290 dict['TARGET'] = Target_or_Source(tnl) |
| 291 |
| 292 # This is a total cheat, but hopefully this dictionary goes |
| 293 # away soon anyway. We just let these expand to $TARGETS |
| 294 # because that's "good enough" for the use of ToolSurrogates |
| 295 # (see test/ToolSurrogate.py) to generate documentation. |
| 296 dict['CHANGED_TARGETS'] = '$TARGETS' |
| 297 dict['UNCHANGED_TARGETS'] = '$TARGETS' |
282 else: | 298 else: |
283 dict['TARGETS'] = None | 299 dict['TARGETS'] = NullNodesList |
284 dict['TARGET'] = None | 300 dict['TARGET'] = NullNodesList |
285 | 301 |
286 if source: | 302 if source: |
287 def get_src_subst_proxy(node): | 303 def get_src_subst_proxy(node): |
288 try: | 304 try: |
289 rfile = node.rfile | 305 rfile = node.rfile |
290 except AttributeError: | 306 except AttributeError: |
291 pass | 307 pass |
292 else: | 308 else: |
293 node = rfile() | 309 node = rfile() |
294 try: | 310 try: |
295 return node.get_subst_proxy() | 311 return node.get_subst_proxy() |
296 except AttributeError: | 312 except AttributeError: |
297 return node # probably a String, just return it | 313 return node # probably a String, just return it |
298 snl = NLWrapper(source, get_src_subst_proxy) | 314 snl = NLWrapper(source, get_src_subst_proxy) |
299 dict['SOURCES'] = Targets_or_Sources(snl) | 315 dict['SOURCES'] = Targets_or_Sources(snl) |
300 dict['SOURCE'] = Target_or_Source(snl) | 316 dict['SOURCE'] = Target_or_Source(snl) |
| 317 |
| 318 # This is a total cheat, but hopefully this dictionary goes |
| 319 # away soon anyway. We just let these expand to $TARGETS |
| 320 # because that's "good enough" for the use of ToolSurrogates |
| 321 # (see test/ToolSurrogate.py) to generate documentation. |
| 322 dict['CHANGED_SOURCES'] = '$SOURCES' |
| 323 dict['UNCHANGED_SOURCES'] = '$SOURCES' |
301 else: | 324 else: |
302 dict['SOURCES'] = None | 325 dict['SOURCES'] = NullNodesList |
303 dict['SOURCE'] = None | 326 dict['SOURCE'] = NullNodesList |
304 | 327 |
305 return dict | 328 return dict |
306 | 329 |
307 # Constants for the "mode" parameter to scons_subst_list() and | 330 # Constants for the "mode" parameter to scons_subst_list() and |
308 # scons_subst(). SUBST_RAW gives the raw command line. SUBST_CMD | 331 # scons_subst(). SUBST_RAW gives the raw command line. SUBST_CMD |
309 # gives a command line suitable for passing to a shell. SUBST_SIG | 332 # gives a command line suitable for passing to a shell. SUBST_SIG |
310 # gives a command line appropriate for calculating the signature | 333 # gives a command line appropriate for calculating the signature |
311 # of a command line...if this changes, we should rebuild. | 334 # of a command line...if this changes, we should rebuild. |
312 SUBST_CMD = 0 | 335 SUBST_CMD = 0 |
313 SUBST_RAW = 1 | 336 SUBST_RAW = 1 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 if type(strSubst) == types.StringType and string.find(strSubst, '$') < 0: | 402 if type(strSubst) == types.StringType and string.find(strSubst, '$') < 0: |
380 return strSubst | 403 return strSubst |
381 | 404 |
382 class StringSubber: | 405 class StringSubber: |
383 """A class to construct the results of a scons_subst() call. | 406 """A class to construct the results of a scons_subst() call. |
384 | 407 |
385 This binds a specific construction environment, mode, target and | 408 This binds a specific construction environment, mode, target and |
386 source with two methods (substitute() and expand()) that handle | 409 source with two methods (substitute() and expand()) that handle |
387 the expansion. | 410 the expansion. |
388 """ | 411 """ |
389 def __init__(self, env, mode, target, source, conv, gvars): | 412 def __init__(self, env, mode, conv, gvars): |
390 self.env = env | 413 self.env = env |
391 self.mode = mode | 414 self.mode = mode |
392 self.target = target | |
393 self.source = source | |
394 self.conv = conv | 415 self.conv = conv |
395 self.gvars = gvars | 416 self.gvars = gvars |
396 | 417 |
397 def expand(self, s, lvars): | 418 def expand(self, s, lvars): |
398 """Expand a single "token" as necessary, returning an | 419 """Expand a single "token" as necessary, returning an |
399 appropriate string containing the expansion. | 420 appropriate string containing the expansion. |
400 | 421 |
401 This handles expanding different types of things (strings, | 422 This handles expanding different types of things (strings, |
402 lists, callables) appropriately. It calls the wrapper | 423 lists, callables) appropriately. It calls the wrapper |
403 substitute() method to re-expand things as necessary, so that | 424 substitute() method to re-expand things as necessary, so that |
(...skipping 16 matching lines...) Expand all Loading... |
420 if key[0] == '{' or string.find(key, '.') >= 0: | 441 if key[0] == '{' or string.find(key, '.') >= 0: |
421 if key[0] == '{': | 442 if key[0] == '{': |
422 key = key[1:-1] | 443 key = key[1:-1] |
423 try: | 444 try: |
424 s = eval(key, self.gvars, lvars) | 445 s = eval(key, self.gvars, lvars) |
425 except KeyboardInterrupt: | 446 except KeyboardInterrupt: |
426 raise | 447 raise |
427 except Exception, e: | 448 except Exception, e: |
428 if e.__class__ in AllowableExceptions: | 449 if e.__class__ in AllowableExceptions: |
429 return '' | 450 return '' |
430 raise_exception(e, self.target, s) | 451 raise_exception(e, lvars['TARGETS'], s) |
431 else: | 452 else: |
432 if lvars.has_key(key): | 453 if lvars.has_key(key): |
433 s = lvars[key] | 454 s = lvars[key] |
434 elif self.gvars.has_key(key): | 455 elif self.gvars.has_key(key): |
435 s = self.gvars[key] | 456 s = self.gvars[key] |
436 elif not NameError in AllowableExceptions: | 457 elif not NameError in AllowableExceptions: |
437 raise_exception(NameError(key), self.target, s) | 458 raise_exception(NameError(key), lvars['TARGETS'], s) |
438 else: | 459 else: |
439 return '' | 460 return '' |
440 | 461 |
441 # Before re-expanding the result, handle | 462 # Before re-expanding the result, handle |
442 # recursive expansion by copying the local | 463 # recursive expansion by copying the local |
443 # variable dictionary and overwriting a null | 464 # variable dictionary and overwriting a null |
444 # string for the value of the variable name | 465 # string for the value of the variable name |
445 # we just expanded. | 466 # we just expanded. |
446 # | 467 # |
447 # This could potentially be optimized by only | 468 # This could potentially be optimized by only |
448 # copying lvars when s contains more expansions, | 469 # copying lvars when s contains more expansions, |
449 # but lvars is usually supposed to be pretty | 470 # but lvars is usually supposed to be pretty |
450 # small, and deeply nested variable expansions | 471 # small, and deeply nested variable expansions |
451 # are probably more the exception than the norm, | 472 # are probably more the exception than the norm, |
452 # so it should be tolerable for now. | 473 # so it should be tolerable for now. |
453 lv = lvars.copy() | 474 lv = lvars.copy() |
454 var = string.split(key, '.')[0] | 475 var = string.split(key, '.')[0] |
455 lv[var] = '' | 476 lv[var] = '' |
456 return self.substitute(s, lv) | 477 return self.substitute(s, lv) |
457 elif is_Sequence(s): | 478 elif is_Sequence(s): |
458 def func(l, conv=self.conv, substitute=self.substitute, lvars=lv
ars): | 479 def func(l, conv=self.conv, substitute=self.substitute, lvars=lv
ars): |
459 return conv(substitute(l, lvars)) | 480 return conv(substitute(l, lvars)) |
460 return map(func, s) | 481 return map(func, s) |
461 elif callable(s): | 482 elif callable(s): |
462 try: | 483 try: |
463 s = s(target=self.target, | 484 s = s(target=lvars['TARGETS'], |
464 source=self.source, | 485 source=lvars['SOURCES'], |
465 env=self.env, | 486 env=self.env, |
466 for_signature=(self.mode != SUBST_CMD)) | 487 for_signature=(self.mode != SUBST_CMD)) |
467 except TypeError: | 488 except TypeError: |
468 # This probably indicates that it's a callable | 489 # This probably indicates that it's a callable |
469 # object that doesn't match our calling arguments | 490 # object that doesn't match our calling arguments |
470 # (like an Action). | 491 # (like an Action). |
471 if self.mode == SUBST_RAW: | 492 if self.mode == SUBST_RAW: |
472 return s | 493 return s |
473 s = self.conv(s) | 494 s = self.conv(s) |
474 return self.substitute(s, lvars) | 495 return self.substitute(s, lvars) |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 | 533 |
513 # Doing this every time is a bit of a waste, since the Executor | 534 # Doing this every time is a bit of a waste, since the Executor |
514 # has typically already populated the OverrideEnvironment with | 535 # has typically already populated the OverrideEnvironment with |
515 # $TARGET/$SOURCE variables. We're keeping this (for now), though, | 536 # $TARGET/$SOURCE variables. We're keeping this (for now), though, |
516 # because it supports existing behavior that allows us to call | 537 # because it supports existing behavior that allows us to call |
517 # an Action directly with an arbitrary target+source pair, which | 538 # an Action directly with an arbitrary target+source pair, which |
518 # we use in Tool/tex.py to handle calling $BIBTEX when necessary. | 539 # we use in Tool/tex.py to handle calling $BIBTEX when necessary. |
519 # If we dropped that behavior (or found another way to cover it), | 540 # If we dropped that behavior (or found another way to cover it), |
520 # we could get rid of this call completely and just rely on the | 541 # we could get rid of this call completely and just rely on the |
521 # Executor setting the variables. | 542 # Executor setting the variables. |
522 d = subst_dict(target, source) | 543 if not lvars.has_key('TARGET'): |
523 if d: | 544 d = subst_dict(target, source) |
524 lvars = lvars.copy() | 545 if d: |
525 lvars.update(d) | 546 lvars = lvars.copy() |
| 547 lvars.update(d) |
526 | 548 |
527 # We're (most likely) going to eval() things. If Python doesn't | 549 # We're (most likely) going to eval() things. If Python doesn't |
528 # find a __builtins__ value in the global dictionary used for eval(), | 550 # find a __builtins__ value in the global dictionary used for eval(), |
529 # it copies the current global values for you. Avoid this by | 551 # it copies the current global values for you. Avoid this by |
530 # setting it explicitly and then deleting, so we don't pollute the | 552 # setting it explicitly and then deleting, so we don't pollute the |
531 # construction environment Dictionary(ies) that are typically used | 553 # construction environment Dictionary(ies) that are typically used |
532 # for expansion. | 554 # for expansion. |
533 gvars['__builtins__'] = __builtins__ | 555 gvars['__builtins__'] = __builtins__ |
534 | 556 |
535 ss = StringSubber(env, mode, target, source, conv, gvars) | 557 ss = StringSubber(env, mode, conv, gvars) |
536 result = ss.substitute(strSubst, lvars) | 558 result = ss.substitute(strSubst, lvars) |
537 | 559 |
538 try: | 560 try: |
539 del gvars['__builtins__'] | 561 del gvars['__builtins__'] |
540 except KeyError: | 562 except KeyError: |
541 pass | 563 pass |
542 | 564 |
543 if is_String(result): | 565 if is_String(result): |
544 # Remove $(-$) pairs and any stuff in between, | 566 # Remove $(-$) pairs and any stuff in between, |
545 # if that's appropriate. | 567 # if that's appropriate. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 | 604 |
583 In addition, however, this class is used to track the state of | 605 In addition, however, this class is used to track the state of |
584 the result(s) we're gathering so we can do the appropriate thing | 606 the result(s) we're gathering so we can do the appropriate thing |
585 whenever we have to append another word to the result--start a new | 607 whenever we have to append another word to the result--start a new |
586 line, start a new word, append to the current word, etc. We do | 608 line, start a new word, append to the current word, etc. We do |
587 this by setting the "append" attribute to the right method so | 609 this by setting the "append" attribute to the right method so |
588 that our wrapper methods only need ever call ListSubber.append(), | 610 that our wrapper methods only need ever call ListSubber.append(), |
589 and the rest of the object takes care of doing the right thing | 611 and the rest of the object takes care of doing the right thing |
590 internally. | 612 internally. |
591 """ | 613 """ |
592 def __init__(self, env, mode, target, source, conv, gvars): | 614 def __init__(self, env, mode, conv, gvars): |
593 UserList.UserList.__init__(self, []) | 615 UserList.UserList.__init__(self, []) |
594 self.env = env | 616 self.env = env |
595 self.mode = mode | 617 self.mode = mode |
596 self.target = target | |
597 self.source = source | |
598 self.conv = conv | 618 self.conv = conv |
599 self.gvars = gvars | 619 self.gvars = gvars |
600 | 620 |
601 if self.mode == SUBST_RAW: | 621 if self.mode == SUBST_RAW: |
602 self.add_strip = lambda x, s=self: s.append(x) | 622 self.add_strip = lambda x, s=self: s.append(x) |
603 else: | 623 else: |
604 self.add_strip = lambda x, s=self: None | 624 self.add_strip = lambda x, s=self: None |
605 self.in_strip = None | 625 self.in_strip = None |
606 self.next_line() | 626 self.next_line() |
607 | 627 |
(...skipping 28 matching lines...) Expand all Loading... |
636 if key[0] == '{' or string.find(key, '.') >= 0: | 656 if key[0] == '{' or string.find(key, '.') >= 0: |
637 if key[0] == '{': | 657 if key[0] == '{': |
638 key = key[1:-1] | 658 key = key[1:-1] |
639 try: | 659 try: |
640 s = eval(key, self.gvars, lvars) | 660 s = eval(key, self.gvars, lvars) |
641 except KeyboardInterrupt: | 661 except KeyboardInterrupt: |
642 raise | 662 raise |
643 except Exception, e: | 663 except Exception, e: |
644 if e.__class__ in AllowableExceptions: | 664 if e.__class__ in AllowableExceptions: |
645 return | 665 return |
646 raise_exception(e, self.target, s) | 666 raise_exception(e, lvars['TARGETS'], s) |
647 else: | 667 else: |
648 if lvars.has_key(key): | 668 if lvars.has_key(key): |
649 s = lvars[key] | 669 s = lvars[key] |
650 elif self.gvars.has_key(key): | 670 elif self.gvars.has_key(key): |
651 s = self.gvars[key] | 671 s = self.gvars[key] |
652 elif not NameError in AllowableExceptions: | 672 elif not NameError in AllowableExceptions: |
653 raise_exception(NameError(), self.target, s) | 673 raise_exception(NameError(), lvars['TARGETS'], s) |
654 else: | 674 else: |
655 return | 675 return |
656 | 676 |
657 # Before re-expanding the result, handle | 677 # Before re-expanding the result, handle |
658 # recursive expansion by copying the local | 678 # recursive expansion by copying the local |
659 # variable dictionary and overwriting a null | 679 # variable dictionary and overwriting a null |
660 # string for the value of the variable name | 680 # string for the value of the variable name |
661 # we just expanded. | 681 # we just expanded. |
662 lv = lvars.copy() | 682 lv = lvars.copy() |
663 var = string.split(key, '.')[0] | 683 var = string.split(key, '.')[0] |
664 lv[var] = '' | 684 lv[var] = '' |
665 self.substitute(s, lv, 0) | 685 self.substitute(s, lv, 0) |
666 self.this_word() | 686 self.this_word() |
667 elif is_Sequence(s): | 687 elif is_Sequence(s): |
668 for a in s: | 688 for a in s: |
669 self.substitute(a, lvars, 1) | 689 self.substitute(a, lvars, 1) |
670 self.next_word() | 690 self.next_word() |
671 elif callable(s): | 691 elif callable(s): |
672 try: | 692 try: |
673 s = s(target=self.target, | 693 s = s(target=lvars['TARGETS'], |
674 source=self.source, | 694 source=lvars['SOURCES'], |
675 env=self.env, | 695 env=self.env, |
676 for_signature=(self.mode != SUBST_CMD)) | 696 for_signature=(self.mode != SUBST_CMD)) |
677 except TypeError: | 697 except TypeError: |
678 # This probably indicates that it's a callable | 698 # This probably indicates that it's a callable |
679 # object that doesn't match our calling arguments | 699 # object that doesn't match our calling arguments |
680 # (like an Action). | 700 # (like an Action). |
681 if self.mode == SUBST_RAW: | 701 if self.mode == SUBST_RAW: |
682 self.append(s) | 702 self.append(s) |
683 return | 703 return |
684 s = self.conv(s) | 704 s = self.conv(s) |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 | 827 |
808 # Doing this every time is a bit of a waste, since the Executor | 828 # Doing this every time is a bit of a waste, since the Executor |
809 # has typically already populated the OverrideEnvironment with | 829 # has typically already populated the OverrideEnvironment with |
810 # $TARGET/$SOURCE variables. We're keeping this (for now), though, | 830 # $TARGET/$SOURCE variables. We're keeping this (for now), though, |
811 # because it supports existing behavior that allows us to call | 831 # because it supports existing behavior that allows us to call |
812 # an Action directly with an arbitrary target+source pair, which | 832 # an Action directly with an arbitrary target+source pair, which |
813 # we use in Tool/tex.py to handle calling $BIBTEX when necessary. | 833 # we use in Tool/tex.py to handle calling $BIBTEX when necessary. |
814 # If we dropped that behavior (or found another way to cover it), | 834 # If we dropped that behavior (or found another way to cover it), |
815 # we could get rid of this call completely and just rely on the | 835 # we could get rid of this call completely and just rely on the |
816 # Executor setting the variables. | 836 # Executor setting the variables. |
817 d = subst_dict(target, source) | 837 if not lvars.has_key('TARGET'): |
818 if d: | 838 d = subst_dict(target, source) |
819 lvars = lvars.copy() | 839 if d: |
820 lvars.update(d) | 840 lvars = lvars.copy() |
| 841 lvars.update(d) |
821 | 842 |
822 # We're (most likely) going to eval() things. If Python doesn't | 843 # We're (most likely) going to eval() things. If Python doesn't |
823 # find a __builtins__ value in the global dictionary used for eval(), | 844 # find a __builtins__ value in the global dictionary used for eval(), |
824 # it copies the current global values for you. Avoid this by | 845 # it copies the current global values for you. Avoid this by |
825 # setting it explicitly and then deleting, so we don't pollute the | 846 # setting it explicitly and then deleting, so we don't pollute the |
826 # construction environment Dictionary(ies) that are typically used | 847 # construction environment Dictionary(ies) that are typically used |
827 # for expansion. | 848 # for expansion. |
828 gvars['__builtins__'] = __builtins__ | 849 gvars['__builtins__'] = __builtins__ |
829 | 850 |
830 ls = ListSubber(env, mode, target, source, conv, gvars) | 851 ls = ListSubber(env, mode, conv, gvars) |
831 ls.substitute(strSubst, lvars, 0) | 852 ls.substitute(strSubst, lvars, 0) |
832 | 853 |
833 try: | 854 try: |
834 del gvars['__builtins__'] | 855 del gvars['__builtins__'] |
835 except KeyError: | 856 except KeyError: |
836 pass | 857 pass |
837 | 858 |
838 return ls.data | 859 return ls.data |
839 | 860 |
840 def scons_subst_once(strSubst, env, key): | 861 def scons_subst_once(strSubst, env, key): |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
875 result.append(arg) | 896 result.append(arg) |
876 else: | 897 else: |
877 result.append(_dollar_exps.sub(sub_match, arg)) | 898 result.append(_dollar_exps.sub(sub_match, arg)) |
878 else: | 899 else: |
879 result.append(arg) | 900 result.append(arg) |
880 return result | 901 return result |
881 elif is_String(strSubst): | 902 elif is_String(strSubst): |
882 return _dollar_exps.sub(sub_match, strSubst) | 903 return _dollar_exps.sub(sub_match, strSubst) |
883 else: | 904 else: |
884 return strSubst | 905 return strSubst |
OLD | NEW |