| 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 |