def _parse_makefile(filename, vars=None):
<EOL>_variable_rx = re.compile("<STR_LIT>")<EOL>_findvar1_rx = re.compile(r"<STR_LIT>")<EOL>_findvar2_rx = re.compile(r"<STR_LIT>")<EOL>if vars is None:<EOL><INDENT>vars = {}<EOL><DEDENT>done = {}<EOL>notdone = {}<EOL>with codecs.open(filename, encoding='<STR_LIT:utf-8>', errors="<STR_LIT>") as f:<EOL><INDENT>lines = f.readlines()<EOL><DEDENT>for line in lines:<EOL><INDENT>if line.startswith('<STR_LIT:#>') or line.strip() == '<STR_LIT>':<EOL><INDENT>continue<EOL><DEDENT>m = _variable_rx.match(line)<EOL>if m:<EOL><INDENT>n, v = m.group(<NUM_LIT:1>, <NUM_LIT:2>)<EOL>v = v.strip()<EOL>tmpv = v.replace('<STR_LIT>', '<STR_LIT>')<EOL>if "<STR_LIT:$>" in tmpv:<EOL><INDENT>notdone[n] = v<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>v = int(v)<EOL><DEDENT>except ValueError:<EOL><INDENT>done[n] = v.replace('<STR_LIT>', '<STR_LIT:$>')<EOL><DEDENT>else:<EOL><INDENT>done[n] = v<EOL><DEDENT><DEDENT><DEDENT><DEDENT>variables = list(notdone.keys())<EOL>renamed_variables = ('<STR_LIT>', '<STR_LIT>', '<STR_LIT>')<EOL>while len(variables) > <NUM_LIT:0>:<EOL><INDENT>for name in tuple(variables):<EOL><INDENT>value = notdone[name]<EOL>m = _findvar1_rx.search(value) or _findvar2_rx.search(value)<EOL>if m is not None:<EOL><INDENT>n = m.group(<NUM_LIT:1>)<EOL>found = True<EOL>if n in done:<EOL><INDENT>item = str(done[n])<EOL><DEDENT>elif n in notdone:<EOL><INDENT>found = False<EOL><DEDENT>elif n in os.environ:<EOL><INDENT>item = os.environ[n]<EOL><DEDENT>elif n in renamed_variables:<EOL><INDENT>if (name.startswith('<STR_LIT>') and<EOL>name[<NUM_LIT:3>:] in renamed_variables):<EOL><INDENT>item = "<STR_LIT>"<EOL><DEDENT>elif '<STR_LIT>' + n in notdone:<EOL><INDENT>found = False<EOL><DEDENT>else:<EOL><INDENT>item = str(done['<STR_LIT>' + n])<EOL><DEDENT><DEDENT>else:<EOL><INDENT>done[n] = item = "<STR_LIT>"<EOL><DEDENT>if found:<EOL><INDENT>after = value[m.end():]<EOL>value = value[:m.start()] + item + after<EOL>if "<STR_LIT:$>" in after:<EOL><INDENT>notdone[name] = value<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>value = int(value)<EOL><DEDENT>except ValueError:<EOL><INDENT>done[name] = value.strip()<EOL><DEDENT>else:<EOL><INDENT>done[name] = value<EOL><DEDENT>variables.remove(name)<EOL>if (name.startswith('<STR_LIT>') and<EOL>name[<NUM_LIT:3>:] in renamed_variables):<EOL><INDENT>name = name[<NUM_LIT:3>:]<EOL>if name not in done:<EOL><INDENT>done[name] = value<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>else:<EOL><INDENT>done[name] = value<EOL>variables.remove(name)<EOL><DEDENT><DEDENT><DEDENT>for k, v in done.items():<EOL><INDENT>if isinstance(v, str):<EOL><INDENT>done[k] = v.strip()<EOL><DEDENT><DEDENT>vars.update(done)<EOL>return vars<EOL>
Parse a Makefile-style file.

    A dictionary containing name/value pairs is returned.  If an
    optional dictionary is passed in as the second argument, it is
    used instead of a new dictionary.