code: def substitute(s, objlist=(), globals={}, locals={}):
      if not locals:
          locals = getlocals(3)
      backslash = False
      dollar = False
      nparen = 0
      name = ''
      evalstr = ''
      squote = False
      dquote = False
      out = ''
      for tmp in s:
          if backslash:
              out += tmp
              backslash = False
              continue
          if dollar and nparen == 0:
              if tmp == '_' or ('a' <= tmp <= 'z') or ('A' <= tmp <= 'Z'):
                  name += tmp
                  continue
              if '0' <= tmp <= '9' and name != '':
                  name += tmp
                  continue
              if tmp == '(' and name == '':
                  nparen = 1
                  evalstr = ''
                  continue
              out += substitutename(name, objlist, globals, locals)
              dollar = False
          if tmp == '"' and not squote:
              dquote = not dquote
          elif tmp == "'" and not dquote:
              squote = not squote
          if not dquote and not squote:
              if nparen > 0:
                  if tmp == '(':
                      nparen += 1
                  elif tmp == ')':
                      nparen -= 1
                      if nparen == 0:
                          out += substituteexpr(evalstr, globals, locals)
                          dollar = False
                  evalstr += tmp
                  continue
              if tmp == '$':
                  dollar = True
                  name = ''
                  continue
          if nparen == 0:
              out += tmp
          else:
              evalstr += tmp
          if tmp == '\\':
              backslash = True
      if dollar:
          out += substitutename(name, objlist, globals, locals)
      else:
          if nparen > 0:
              out += '$(' + evalstr
      return out