code: def __write_appender(t, name):
      t.write(
          name,
          r"""# Copyright 2012 Jurko Gospodnetic
  # Distributed under the Boost Software License, Version 1.0.
  # (See accompanying file LICENSE_1_0.txt or copy at
  # http://www.boost.org/LICENSE_1_0.txt)
  
  #   Support for registering test generators that construct their targets by
  # simply appending their given input data, e.g. list of sources & targets.
  
  import "class" : new ;
  import generators ;
  import modules ;
  import sequence ;
  
  rule register ( id composing ? : source-types + : target-types + )
  {
      local caller-module = [ CALLER_MODULE ] ;
      id = $(caller-module).$(id) ;
      local g = [ new generator $(id) $(composing) : $(source-types) :
          $(target-types) ] ;
      $(g).set-rule-name $(__name__).appender ;
      generators.register $(g) ;
      return $(id) ;
  }
  
  if [ modules.peek : NT ]
  {
      X = ")" ;
      ECHO_CMD = (echo. ;
  }
  else
  {
      X = \" ;
      ECHO_CMD = "echo $(X)" ;
  }
  
  local appender-runs ;
  
  # We set up separate actions for building each target in order to avoid having
  # to iterate over them in action (i.e. shell) code. We have to be extra careful
  # though to achieve the exact same effect as if doing all the work in just one
  # action. Otherwise Boost Jam might, under some circumstances, run only some of
  # our actions. To achieve this we register a series of actions for all the
  # targets (since they all have the same target list - either all or none of them
  # get run independent of which target actually needs to get built), each
  # building only a single target. Since all our actions use the same targets, we
  # can not use 'on-target' parameters to pass data to a specific action so we
  # pass them using the second 'sources' parameter which our actions then know how
  # to interpret correctly. This works well since Boost Jam does not automatically
  # add dependency relations between specified action targets & sources and so the
  # second argument, even though most often used to pass in a list of sources, can
  # actually be used for passing in any type of information.
  rule appender ( targets + : sources + : properties * )
  {
      appender-runs = [ CALC $(appender-runs:E=0) + 1 ] ;
      local target-index = 0 ;
      local target-count = [ sequence.length $(targets) ] ;
      local original-targets ;
      for t in $(targets)
      {
          target-index = [ CALC $(target-index) + 1 ] ;
          local appender-run = $(appender-runs) ;
          if $(targets[2])-defined
          {
              appender-run += "[$(target-index)/$(target-count)]" ;
          }
          append $(targets) : $(appender-run:J=" ") $(t) $(sources) ;
      }
  }
  
  actions append
  {
      $(ECHO_CMD)-------------------------------------------------$(X)
      $(ECHO_CMD)Appender run: $(>[1])$(X)
      $(ECHO_CMD)Appender run: $(>[1])$(X)>> "$(>[2])"
      $(ECHO_CMD)Target group: $(<:J=' ')$(X)
      $(ECHO_CMD)Target group: $(<:J=' ')$(X)>> "$(>[2])"
      $(ECHO_CMD)      Target: '$(>[2])'$(X)
      $(ECHO_CMD)      Target: '$(>[2])'$(X)>> "$(>[2])"
      $(ECHO_CMD)     Sources: '$(>[3-]:J=' ')'$(X)
      $(ECHO_CMD)     Sources: '$(>[3-]:J=' ')'$(X)>> "$(>[2])"
      $(ECHO_CMD)=================================================$(X)
      $(ECHO_CMD)-------------------------------------------------$(X)>> "$(>[2])"
  }
  """,
      )
  
imports: import BoostBuild
  import re
label_desc: Use image node_id 4 for calling a global function with example usage: __write_appender(t, name) without return types