code: def read_setup_file(filename):  # noqa: C901
      """Reads a Setup file and returns Extension instances."""
      from distutils.sysconfig import (
          parse_makefile,
          expand_makefile_vars,
          _variable_rx,
      )
  
      from distutils.text_file import TextFile
      from distutils.util import split_quoted
  
      # First pass over the file to gather "VAR = VALUE" assignments.
      vars = parse_makefile(filename)
  
      # Second pass to gobble up the real content: lines of the form
      #   <module> ... [<sourcefile> ...] [<cpparg> ...] [<library> ...]
      file = TextFile(
          filename,
          strip_comments=1,
          skip_blanks=1,
          join_lines=1,
          lstrip_ws=1,
          rstrip_ws=1,
      )
      try:
          extensions = []
  
          while True:
              line = file.readline()
              if line is None:  # eof
                  break
              if _variable_rx.match(
                  line
              ):  # VAR=VALUE, handled in first pass
                  continue
  
              if line[0] == line[-1] == "*":
                  file.warn("'%s' lines not handled yet" % line)
                  continue
  
              line = expand_makefile_vars(line, vars)
              words = split_quoted(line)
  
              # NB. this parses a slightly different syntax than the old
              # makesetup script: here, there must be exactly one extension per
              # line, and it must be the first word of the line.  I have no idea
              # why the old syntax supported multiple extensions per line, as
              # they all wind up being the same.
  
              module = words[0]
              ext = Extension(module, [])
              append_next_word = None
  
              for word in words[1:]:
                  if append_next_word is not None:
                      append_next_word.append(word)
                      append_next_word = None
                      continue
  
                  suffix = os.path.splitext(word)[1]
                  switch = word[0:2]
                  value = word[2:]
  
                  if suffix in (
                      ".c",
                      ".cc",
                      ".cpp",
                      ".cxx",
                      ".c++",
                      ".m",
                      ".mm",
                  ):
                      # hmm, should we do something about C vs. C++ sources?
                      # or leave it up to the CCompiler implementation to
                      # worry about?
                      ext.sources.append(word)
                  elif switch == "-I":
                      ext.include_dirs.append(value)
                  elif switch == "-D":
                      equals = value.find("=")
                      if equals == -1:  # bare "-DFOO" -- no value
                          ext.define_macros.append((value, None))
                      else:  # "-DFOO=blah"
                          ext.define_macros.append(
                              (value[0:equals], value[equals + 2 :])
                          )
                  elif switch == "-U":
                      ext.undef_macros.append(value)
                  elif (
                      switch == "-C"
                  ):  # only here 'cause makesetup has it!
                      ext.extra_compile_args.append(word)
                  elif switch == "-l":
                      ext.libraries.append(value)
                  elif switch == "-L":
                      ext.library_dirs.append(value)
                  elif switch == "-R":
                      ext.runtime_library_dirs.append(value)
                  elif word == "-rpath":
                      append_next_word = ext.runtime_library_dirs
                  elif word == "-Xlinker":
                      append_next_word = ext.extra_link_args
                  elif word == "-Xcompiler":
                      append_next_word = ext.extra_compile_args
                  elif switch == "-u":
                      ext.extra_link_args.append(word)
                      if not value:
                          append_next_word = ext.extra_link_args
                  elif suffix in (".a", ".so", ".sl", ".o", ".dylib"):
                      # NB. a really faithful emulation of makesetup would
                      # append a .o file to extra_objects only if it
                      # had a slash in it; otherwise, it would s/.o/.c/
                      # and append it to sources.  Hmmmm.
                      ext.extra_objects.append(word)
                  else:
                      file.warn("unrecognized argument '%s'" % word)
  
              extensions.append(ext)
      finally:
          file.close()
  
      return extensions
  
imports: import os
  import warnings
label_desc: Use image node_id 1 for calling a global function with example usage: read_setup_file(filename) and returns: extensions