diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:16:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-09 13:16:35 +0000 |
commit | e2bbf175a2184bd76f6c54ccf8456babeb1a46fc (patch) | |
tree | f0b76550d6e6f500ada964a3a4ee933a45e5a6f1 /python/makevars.py | |
parent | Initial commit. (diff) | |
download | frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.tar.xz frr-e2bbf175a2184bd76f6c54ccf8456babeb1a46fc.zip |
Adding upstream version 9.1.upstream/9.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'python/makevars.py')
-rw-r--r-- | python/makevars.py | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/python/makevars.py b/python/makevars.py new file mode 100644 index 0000000..951cd34 --- /dev/null +++ b/python/makevars.py @@ -0,0 +1,100 @@ +# +# helper class to grab variables from FRR's Makefile +# + +import os +import subprocess +import re + + +class MakeVarsBase(object): + """ + common code between MakeVars and MakeReVars + """ + + def __init__(self): + self._data = dict() + + def __getitem__(self, k): + if k not in self._data: + self.getvars([k]) + return self._data[k] + + def get(self, k, defval=None): + if k not in self._data: + self.getvars([k]) + return self._data.get(k) or defval + + +class MakeVars(MakeVarsBase): + """ + makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile + + This variant works by invoking make as a subprocess, i.e. Makefile must + be valid and working. (This is sometimes a problem if depfiles have not + been generated.) + """ + + def getvars(self, varlist): + """ + get a batch list of variables from make. faster than individual calls. + """ + rdfd, wrfd = os.pipe() + + shvars = ["shvar-%s" % s for s in varlist] + make = subprocess.Popen( + ["make", "-s", "VARFD=%d" % wrfd] + shvars, pass_fds=[wrfd] + ) + os.close(wrfd) + data = b"" + + rdf = os.fdopen(rdfd, "rb") + while True: + rdata = rdf.read() + if len(rdata) == 0: + break + data += rdata + + del rdf + make.wait() + + data = data.decode("US-ASCII").strip().split("\n") + for row in data: + k, v = row.split("=", 1) + v = v[1:-1] + self._data[k] = v + + +class MakeReVars(MakeVarsBase): + """ + makevars['FOO_CFLAGS'] gets you "FOO_CFLAGS" from Makefile + + This variant works by regexing through Makefile. This means the Makefile + does not need to be fully working, but on the other hand it doesn't support + fancy complicated make expressions. + """ + + var_re = re.compile( + r"^([^=#\n\s]+)[ \t]*=[ \t]*([^#\n]*)(?:#.*)?$", flags=re.MULTILINE + ) + repl_re = re.compile(r"\$(?:([A-Za-z])|\(([^\)]+)\))") + + def __init__(self, maketext): + super(MakeReVars, self).__init__() + self._vars = dict(self.var_re.findall(maketext.replace("\\\n", ""))) + + def replacevar(self, match): + varname = match.group(1) or match.group(2) + return self._vars.get(varname, "") + + def getvars(self, varlist): + for varname in varlist: + if varname not in self._vars: + continue + + val, prevval = self._vars[varname], None + while val != prevval: + prevval = val + val = self.repl_re.sub(self.replacevar, val) + + self._data[varname] = val |