17750ad47SMarcel Moolenaar#!/usr/bin/env python 27750ad47SMarcel Moolenaar 310ea6facSSimon J. Gerratyfrom __future__ import print_function 410ea6facSSimon J. Gerraty 57750ad47SMarcel Moolenaar""" 67750ad47SMarcel MoolenaarThis script parses each "meta" file and extracts the 77750ad47SMarcel Moolenaarinformation needed to deduce build and src dependencies. 87750ad47SMarcel Moolenaar 97750ad47SMarcel MoolenaarIt works much the same as the original shell script, but is 107750ad47SMarcel Moolenaar*much* more efficient. 117750ad47SMarcel Moolenaar 127750ad47SMarcel MoolenaarThe parsing work is handled by the class MetaFile. 137750ad47SMarcel MoolenaarWe only pay attention to a subset of the information in the 147750ad47SMarcel Moolenaar"meta" files. Specifically: 157750ad47SMarcel Moolenaar 167750ad47SMarcel Moolenaar'CWD' to initialize our notion. 177750ad47SMarcel Moolenaar 187750ad47SMarcel Moolenaar'C' to track chdir(2) on a per process basis 197750ad47SMarcel Moolenaar 207750ad47SMarcel Moolenaar'R' files read are what we really care about. 217750ad47SMarcel Moolenaar directories read, provide a clue to resolving 227750ad47SMarcel Moolenaar subsequent relative paths. That is if we cannot find 237750ad47SMarcel Moolenaar them relative to 'cwd', we check relative to the last 247750ad47SMarcel Moolenaar dir read. 257750ad47SMarcel Moolenaar 267750ad47SMarcel Moolenaar'W' files opened for write or read-write, 277750ad47SMarcel Moolenaar for filemon V3 and earlier. 287750ad47SMarcel Moolenaar 297750ad47SMarcel Moolenaar'E' files executed. 307750ad47SMarcel Moolenaar 317750ad47SMarcel Moolenaar'L' files linked 327750ad47SMarcel Moolenaar 337750ad47SMarcel Moolenaar'V' the filemon version, this record is used as a clue 347750ad47SMarcel Moolenaar that we have reached the interesting bit. 357750ad47SMarcel Moolenaar 367750ad47SMarcel Moolenaar""" 377750ad47SMarcel Moolenaar 387750ad47SMarcel Moolenaar""" 397750ad47SMarcel MoolenaarRCSid: 40b47b9f6bSSimon J. Gerraty $FreeBSD$ 416d4f05fdSSimon J. Gerraty $Id: meta2deps.py,v 1.24 2017/02/08 22:17:10 sjg Exp $ 427750ad47SMarcel Moolenaar 434ed4429cSSimon J. Gerraty Copyright (c) 2011-2013, Juniper Networks, Inc. 444ed4429cSSimon J. Gerraty All rights reserved. 457750ad47SMarcel Moolenaar 467750ad47SMarcel Moolenaar Redistribution and use in source and binary forms, with or without 477750ad47SMarcel Moolenaar modification, are permitted provided that the following conditions 487750ad47SMarcel Moolenaar are met: 497750ad47SMarcel Moolenaar 1. Redistributions of source code must retain the above copyright 507750ad47SMarcel Moolenaar notice, this list of conditions and the following disclaimer. 517750ad47SMarcel Moolenaar 2. Redistributions in binary form must reproduce the above copyright 527750ad47SMarcel Moolenaar notice, this list of conditions and the following disclaimer in the 537750ad47SMarcel Moolenaar documentation and/or other materials provided with the distribution. 547750ad47SMarcel Moolenaar 557750ad47SMarcel Moolenaar THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 567750ad47SMarcel Moolenaar "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 577750ad47SMarcel Moolenaar LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 587750ad47SMarcel Moolenaar A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 597750ad47SMarcel Moolenaar OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 607750ad47SMarcel Moolenaar SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 617750ad47SMarcel Moolenaar LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 627750ad47SMarcel Moolenaar DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 637750ad47SMarcel Moolenaar THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 647750ad47SMarcel Moolenaar (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 657750ad47SMarcel Moolenaar OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 667750ad47SMarcel Moolenaar 677750ad47SMarcel Moolenaar""" 687750ad47SMarcel Moolenaar 697750ad47SMarcel Moolenaarimport os, re, sys 707750ad47SMarcel Moolenaar 717750ad47SMarcel Moolenaardef getv(dict, key, d=None): 727750ad47SMarcel Moolenaar """Lookup key in dict and return value or the supplied default.""" 737750ad47SMarcel Moolenaar if key in dict: 747750ad47SMarcel Moolenaar return dict[key] 757750ad47SMarcel Moolenaar return d 767750ad47SMarcel Moolenaar 777750ad47SMarcel Moolenaardef resolve(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 787750ad47SMarcel Moolenaar """ 797750ad47SMarcel Moolenaar Return an absolute path, resolving via cwd or last_dir if needed. 807750ad47SMarcel Moolenaar """ 817750ad47SMarcel Moolenaar if path.endswith('/.'): 827750ad47SMarcel Moolenaar path = path[0:-2] 83d5ddb276SSimon J. Gerraty if len(path) > 0 and path[0] == '/': 847750ad47SMarcel Moolenaar return path 857750ad47SMarcel Moolenaar if path == '.': 867750ad47SMarcel Moolenaar return cwd 877750ad47SMarcel Moolenaar if path.startswith('./'): 887750ad47SMarcel Moolenaar return cwd + path[1:] 897750ad47SMarcel Moolenaar if last_dir == cwd: 907750ad47SMarcel Moolenaar last_dir = None 917750ad47SMarcel Moolenaar for d in [last_dir, cwd]: 927750ad47SMarcel Moolenaar if not d: 937750ad47SMarcel Moolenaar continue 947750ad47SMarcel Moolenaar p = '/'.join([d,path]) 957750ad47SMarcel Moolenaar if debug > 2: 9610ea6facSSimon J. Gerraty print("looking for:", p, end=' ', file=debug_out) 977750ad47SMarcel Moolenaar if not os.path.exists(p): 987750ad47SMarcel Moolenaar if debug > 2: 9910ea6facSSimon J. Gerraty print("nope", file=debug_out) 1007750ad47SMarcel Moolenaar p = None 1017750ad47SMarcel Moolenaar continue 1027750ad47SMarcel Moolenaar if debug > 2: 10310ea6facSSimon J. Gerraty print("found:", p, file=debug_out) 1047750ad47SMarcel Moolenaar return p 1057750ad47SMarcel Moolenaar return None 1067750ad47SMarcel Moolenaar 1076d4f05fdSSimon J. Gerratydef cleanpath(path): 1086d4f05fdSSimon J. Gerraty """cleanup path without using realpath(3)""" 1096d4f05fdSSimon J. Gerraty if path.startswith('/'): 1106d4f05fdSSimon J. Gerraty r = '/' 1116d4f05fdSSimon J. Gerraty else: 1126d4f05fdSSimon J. Gerraty r = '' 1136d4f05fdSSimon J. Gerraty p = [] 1146d4f05fdSSimon J. Gerraty w = path.split('/') 1156d4f05fdSSimon J. Gerraty for d in w: 1166d4f05fdSSimon J. Gerraty if not d or d == '.': 1176d4f05fdSSimon J. Gerraty continue 1186d4f05fdSSimon J. Gerraty if d == '..': 1196d4f05fdSSimon J. Gerraty p.pop() 1206d4f05fdSSimon J. Gerraty continue 1216d4f05fdSSimon J. Gerraty p.append(d) 1226d4f05fdSSimon J. Gerraty 1236d4f05fdSSimon J. Gerraty return r + '/'.join(p) 1246d4f05fdSSimon J. Gerraty 1257750ad47SMarcel Moolenaardef abspath(path, cwd, last_dir=None, debug=0, debug_out=sys.stderr): 1267750ad47SMarcel Moolenaar """ 1277750ad47SMarcel Moolenaar Return an absolute path, resolving via cwd or last_dir if needed. 1286d4f05fdSSimon J. Gerraty this gets called a lot, so we try to avoid calling realpath. 1297750ad47SMarcel Moolenaar """ 130d5ddb276SSimon J. Gerraty rpath = resolve(path, cwd, last_dir, debug, debug_out) 131d5ddb276SSimon J. Gerraty if rpath: 132d5ddb276SSimon J. Gerraty path = rpath 133ccfb9654SSimon J. Gerraty if (path.find('/') < 0 or 134ccfb9654SSimon J. Gerraty path.find('./') > 0 or 1356d4f05fdSSimon J. Gerraty path.endswith('/..')): 1366d4f05fdSSimon J. Gerraty path = cleanpath(path) 1377750ad47SMarcel Moolenaar return path 1387750ad47SMarcel Moolenaar 1397750ad47SMarcel Moolenaardef sort_unique(list, cmp=None, key=None, reverse=False): 1407750ad47SMarcel Moolenaar list.sort(cmp, key, reverse) 1417750ad47SMarcel Moolenaar nl = [] 1427750ad47SMarcel Moolenaar le = None 1437750ad47SMarcel Moolenaar for e in list: 1447750ad47SMarcel Moolenaar if e == le: 1457750ad47SMarcel Moolenaar continue 1466d4f05fdSSimon J. Gerraty le = e 1477750ad47SMarcel Moolenaar nl.append(e) 1487750ad47SMarcel Moolenaar return nl 1497750ad47SMarcel Moolenaar 150bf062775SSimon J. Gerratydef add_trims(x): 151bf062775SSimon J. Gerraty return ['/' + x + '/', 152bf062775SSimon J. Gerraty '/' + x, 153bf062775SSimon J. Gerraty x + '/', 154bf062775SSimon J. Gerraty x] 155bf062775SSimon J. Gerraty 1567750ad47SMarcel Moolenaarclass MetaFile: 1577750ad47SMarcel Moolenaar """class to parse meta files generated by bmake.""" 1587750ad47SMarcel Moolenaar 1597750ad47SMarcel Moolenaar conf = None 1607750ad47SMarcel Moolenaar dirdep_re = None 1617750ad47SMarcel Moolenaar host_target = None 1627750ad47SMarcel Moolenaar srctops = [] 1637750ad47SMarcel Moolenaar objroots = [] 164ccfb9654SSimon J. Gerraty excludes = [] 1657750ad47SMarcel Moolenaar seen = {} 1667750ad47SMarcel Moolenaar obj_deps = [] 1677750ad47SMarcel Moolenaar src_deps = [] 1687750ad47SMarcel Moolenaar file_deps = [] 1697750ad47SMarcel Moolenaar 1707750ad47SMarcel Moolenaar def __init__(self, name, conf={}): 1717750ad47SMarcel Moolenaar """if name is set we will parse it now. 1727750ad47SMarcel Moolenaar conf can have the follwing keys: 1737750ad47SMarcel Moolenaar 1747750ad47SMarcel Moolenaar SRCTOPS list of tops of the src tree(s). 1757750ad47SMarcel Moolenaar 1767750ad47SMarcel Moolenaar CURDIR the src directory 'bmake' was run from. 1777750ad47SMarcel Moolenaar 1787750ad47SMarcel Moolenaar RELDIR the relative path from SRCTOP to CURDIR 1797750ad47SMarcel Moolenaar 1807750ad47SMarcel Moolenaar MACHINE the machine we built for. 1817750ad47SMarcel Moolenaar set to 'none' if we are not cross-building. 18251048477SSimon J. Gerraty More specifically if machine cannot be deduced from objdirs. 1837750ad47SMarcel Moolenaar 184bf062775SSimon J. Gerraty TARGET_SPEC 185bf062775SSimon J. Gerraty Sometimes MACHINE isn't enough. 186bf062775SSimon J. Gerraty 1877750ad47SMarcel Moolenaar HOST_TARGET 188ccfb9654SSimon J. Gerraty when we build for the pseudo machine 'host' 1897750ad47SMarcel Moolenaar the object tree uses HOST_TARGET rather than MACHINE. 1907750ad47SMarcel Moolenaar 1917750ad47SMarcel Moolenaar OBJROOTS a list of the common prefix for all obj dirs it might 1927750ad47SMarcel Moolenaar end in '/' or '-'. 1937750ad47SMarcel Moolenaar 1947750ad47SMarcel Moolenaar DPDEPS names an optional file to which per file dependencies 1957750ad47SMarcel Moolenaar will be appended. 1967750ad47SMarcel Moolenaar For example if 'some/path/foo.h' is read from SRCTOP 1977750ad47SMarcel Moolenaar then 'DPDEPS_some/path/foo.h +=' "RELDIR" is output. 1987750ad47SMarcel Moolenaar This can allow 'bmake' to learn all the dirs within 1997750ad47SMarcel Moolenaar the tree that depend on 'foo.h' 2007750ad47SMarcel Moolenaar 201ccfb9654SSimon J. Gerraty EXCLUDES 202ccfb9654SSimon J. Gerraty A list of paths to ignore. 203ccfb9654SSimon J. Gerraty ccache(1) can otherwise be trouble. 204ccfb9654SSimon J. Gerraty 2057750ad47SMarcel Moolenaar debug desired debug level 2067750ad47SMarcel Moolenaar 2077750ad47SMarcel Moolenaar debug_out open file to send debug output to (sys.stderr) 2087750ad47SMarcel Moolenaar 2097750ad47SMarcel Moolenaar """ 2107750ad47SMarcel Moolenaar 2117750ad47SMarcel Moolenaar self.name = name 2127750ad47SMarcel Moolenaar self.debug = getv(conf, 'debug', 0) 2137750ad47SMarcel Moolenaar self.debug_out = getv(conf, 'debug_out', sys.stderr) 2147750ad47SMarcel Moolenaar 2154ed4429cSSimon J. Gerraty self.machine = getv(conf, 'MACHINE', '') 216bf062775SSimon J. Gerraty self.machine_arch = getv(conf, 'MACHINE_ARCH', '') 217bf062775SSimon J. Gerraty self.target_spec = getv(conf, 'TARGET_SPEC', '') 21851048477SSimon J. Gerraty self.curdir = getv(conf, 'CURDIR') 21951048477SSimon J. Gerraty self.reldir = getv(conf, 'RELDIR') 22051048477SSimon J. Gerraty self.dpdeps = getv(conf, 'DPDEPS') 221d5ddb276SSimon J. Gerraty self.line = 0 2224ed4429cSSimon J. Gerraty 2237750ad47SMarcel Moolenaar if not self.conf: 2247750ad47SMarcel Moolenaar # some of the steps below we want to do only once 2257750ad47SMarcel Moolenaar self.conf = conf 2267750ad47SMarcel Moolenaar self.host_target = getv(conf, 'HOST_TARGET') 2277750ad47SMarcel Moolenaar for srctop in getv(conf, 'SRCTOPS', []): 2287750ad47SMarcel Moolenaar if srctop[-1] != '/': 2297750ad47SMarcel Moolenaar srctop += '/' 2307750ad47SMarcel Moolenaar if not srctop in self.srctops: 2317750ad47SMarcel Moolenaar self.srctops.append(srctop) 232fbc1b149SSimon J. Gerraty _srctop = os.path.realpath(srctop) 233fbc1b149SSimon J. Gerraty if _srctop[-1] != '/': 234fbc1b149SSimon J. Gerraty _srctop += '/' 235fbc1b149SSimon J. Gerraty if not _srctop in self.srctops: 236fbc1b149SSimon J. Gerraty self.srctops.append(_srctop) 2377750ad47SMarcel Moolenaar 238bf062775SSimon J. Gerraty trim_list = add_trims(self.machine) 2398c95c434SSimon J. Gerraty if self.machine == 'host': 240bf062775SSimon J. Gerraty trim_list += add_trims(self.host_target) 241bf062775SSimon J. Gerraty if self.target_spec: 242bf062775SSimon J. Gerraty trim_list += add_trims(self.target_spec) 243876336c8SSimon J. Gerraty 2447750ad47SMarcel Moolenaar for objroot in getv(conf, 'OBJROOTS', []): 2458c95c434SSimon J. Gerraty for e in trim_list: 2464ed4429cSSimon J. Gerraty if objroot.endswith(e): 2474ed4429cSSimon J. Gerraty # this is not what we want - fix it 2484ed4429cSSimon J. Gerraty objroot = objroot[0:-len(e)] 249b47b9f6bSSimon J. Gerraty 250b47b9f6bSSimon J. Gerraty if objroot[-1] != '/': 2514ed4429cSSimon J. Gerraty objroot += '/' 2527750ad47SMarcel Moolenaar if not objroot in self.objroots: 2537750ad47SMarcel Moolenaar self.objroots.append(objroot) 2547750ad47SMarcel Moolenaar _objroot = os.path.realpath(objroot) 2557750ad47SMarcel Moolenaar if objroot[-1] == '/': 2567750ad47SMarcel Moolenaar _objroot += '/' 2577750ad47SMarcel Moolenaar if not _objroot in self.objroots: 2587750ad47SMarcel Moolenaar self.objroots.append(_objroot) 2597750ad47SMarcel Moolenaar 2604ed4429cSSimon J. Gerraty # we want the longest match 2614ed4429cSSimon J. Gerraty self.srctops.sort(reverse=True) 2624ed4429cSSimon J. Gerraty self.objroots.sort(reverse=True) 2634ed4429cSSimon J. Gerraty 264ccfb9654SSimon J. Gerraty self.excludes = getv(conf, 'EXCLUDES', []) 265ccfb9654SSimon J. Gerraty 2667750ad47SMarcel Moolenaar if self.debug: 26710ea6facSSimon J. Gerraty print("host_target=", self.host_target, file=self.debug_out) 26810ea6facSSimon J. Gerraty print("srctops=", self.srctops, file=self.debug_out) 26910ea6facSSimon J. Gerraty print("objroots=", self.objroots, file=self.debug_out) 270ccfb9654SSimon J. Gerraty print("excludes=", self.excludes, file=self.debug_out) 2717750ad47SMarcel Moolenaar 2727750ad47SMarcel Moolenaar self.dirdep_re = re.compile(r'([^/]+)/(.+)') 2737750ad47SMarcel Moolenaar 2747750ad47SMarcel Moolenaar if self.dpdeps and not self.reldir: 2757750ad47SMarcel Moolenaar if self.debug: 27610ea6facSSimon J. Gerraty print("need reldir:", end=' ', file=self.debug_out) 2777750ad47SMarcel Moolenaar if self.curdir: 2787750ad47SMarcel Moolenaar srctop = self.find_top(self.curdir, self.srctops) 2797750ad47SMarcel Moolenaar if srctop: 2807750ad47SMarcel Moolenaar self.reldir = self.curdir.replace(srctop,'') 2817750ad47SMarcel Moolenaar if self.debug: 28210ea6facSSimon J. Gerraty print(self.reldir, file=self.debug_out) 2837750ad47SMarcel Moolenaar if not self.reldir: 2847750ad47SMarcel Moolenaar self.dpdeps = None # we cannot do it? 2857750ad47SMarcel Moolenaar 286876336c8SSimon J. Gerraty self.cwd = os.getcwd() # make sure this is initialized 287ccfb9654SSimon J. Gerraty self.last_dir = self.cwd 288876336c8SSimon J. Gerraty 2897750ad47SMarcel Moolenaar if name: 290d5ddb276SSimon J. Gerraty self.try_parse() 2917750ad47SMarcel Moolenaar 2927750ad47SMarcel Moolenaar def reset(self): 2937750ad47SMarcel Moolenaar """reset state if we are being passed meta files from multiple directories.""" 2947750ad47SMarcel Moolenaar self.seen = {} 2957750ad47SMarcel Moolenaar self.obj_deps = [] 2967750ad47SMarcel Moolenaar self.src_deps = [] 2977750ad47SMarcel Moolenaar self.file_deps = [] 2987750ad47SMarcel Moolenaar 2997750ad47SMarcel Moolenaar def dirdeps(self, sep='\n'): 3007750ad47SMarcel Moolenaar """return DIRDEPS""" 3017750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.obj_deps) 3027750ad47SMarcel Moolenaar 3037750ad47SMarcel Moolenaar def src_dirdeps(self, sep='\n'): 3047750ad47SMarcel Moolenaar """return SRC_DIRDEPS""" 3057750ad47SMarcel Moolenaar return sep.strip() + sep.join(self.src_deps) 3067750ad47SMarcel Moolenaar 3077750ad47SMarcel Moolenaar def file_depends(self, out=None): 3087750ad47SMarcel Moolenaar """Append DPDEPS_${file} += ${RELDIR} 3097750ad47SMarcel Moolenaar for each file we saw, to the output file.""" 3107750ad47SMarcel Moolenaar if not self.reldir: 3117750ad47SMarcel Moolenaar return None 3127750ad47SMarcel Moolenaar for f in sort_unique(self.file_deps): 31310ea6facSSimon J. Gerraty print('DPDEPS_%s += %s' % (f, self.reldir), file=out) 314b47b9f6bSSimon J. Gerraty # these entries provide for reverse DIRDEPS lookup 315b47b9f6bSSimon J. Gerraty for f in self.obj_deps: 316b47b9f6bSSimon J. Gerraty print('DEPDIRS_%s += %s' % (f, self.reldir), file=out) 3177750ad47SMarcel Moolenaar 3187750ad47SMarcel Moolenaar def seenit(self, dir): 3197750ad47SMarcel Moolenaar """rememer that we have seen dir.""" 3207750ad47SMarcel Moolenaar self.seen[dir] = 1 3217750ad47SMarcel Moolenaar 3227750ad47SMarcel Moolenaar def add(self, list, data, clue=''): 3237750ad47SMarcel Moolenaar """add data to list if it isn't already there.""" 3247750ad47SMarcel Moolenaar if data not in list: 3257750ad47SMarcel Moolenaar list.append(data) 3267750ad47SMarcel Moolenaar if self.debug: 32710ea6facSSimon J. Gerraty print("%s: %sAdd: %s" % (self.name, clue, data), file=self.debug_out) 3287750ad47SMarcel Moolenaar 3297750ad47SMarcel Moolenaar def find_top(self, path, list): 330ccfb9654SSimon J. Gerraty """the logical tree may be split across multiple trees""" 3317750ad47SMarcel Moolenaar for top in list: 3327750ad47SMarcel Moolenaar if path.startswith(top): 3337750ad47SMarcel Moolenaar if self.debug > 2: 33410ea6facSSimon J. Gerraty print("found in", top, file=self.debug_out) 3357750ad47SMarcel Moolenaar return top 3367750ad47SMarcel Moolenaar return None 3377750ad47SMarcel Moolenaar 3387750ad47SMarcel Moolenaar def find_obj(self, objroot, dir, path, input): 3397750ad47SMarcel Moolenaar """return path within objroot, taking care of .dirdep files""" 3407750ad47SMarcel Moolenaar ddep = None 3417750ad47SMarcel Moolenaar for ddepf in [path + '.dirdep', dir + '/.dirdep']: 3427750ad47SMarcel Moolenaar if not ddep and os.path.exists(ddepf): 34310ea6facSSimon J. Gerraty ddep = open(ddepf, 'r').readline().strip('# \n') 3447750ad47SMarcel Moolenaar if self.debug > 1: 34510ea6facSSimon J. Gerraty print("found %s: %s\n" % (ddepf, ddep), file=self.debug_out) 3467750ad47SMarcel Moolenaar if ddep.endswith(self.machine): 3477750ad47SMarcel Moolenaar ddep = ddep[0:-(1+len(self.machine))] 348bf062775SSimon J. Gerraty elif self.target_spec and ddep.endswith(self.target_spec): 349bf062775SSimon J. Gerraty ddep = ddep[0:-(1+len(self.target_spec))] 3507750ad47SMarcel Moolenaar 3517750ad47SMarcel Moolenaar if not ddep: 3527750ad47SMarcel Moolenaar # no .dirdeps, so remember that we've seen the raw input 3537750ad47SMarcel Moolenaar self.seenit(input) 3547750ad47SMarcel Moolenaar self.seenit(dir) 3557750ad47SMarcel Moolenaar if self.machine == 'none': 3567750ad47SMarcel Moolenaar if dir.startswith(objroot): 3577750ad47SMarcel Moolenaar return dir.replace(objroot,'') 3587750ad47SMarcel Moolenaar return None 3597750ad47SMarcel Moolenaar m = self.dirdep_re.match(dir.replace(objroot,'')) 3607750ad47SMarcel Moolenaar if m: 3617750ad47SMarcel Moolenaar ddep = m.group(2) 3627750ad47SMarcel Moolenaar dmachine = m.group(1) 3637750ad47SMarcel Moolenaar if dmachine != self.machine: 3647750ad47SMarcel Moolenaar if not (self.machine == 'host' and 3657750ad47SMarcel Moolenaar dmachine == self.host_target): 3667750ad47SMarcel Moolenaar if self.debug > 2: 36710ea6facSSimon J. Gerraty print("adding .%s to %s" % (dmachine, ddep), file=self.debug_out) 3687750ad47SMarcel Moolenaar ddep += '.' + dmachine 3697750ad47SMarcel Moolenaar 3707750ad47SMarcel Moolenaar return ddep 3717750ad47SMarcel Moolenaar 372d5ddb276SSimon J. Gerraty def try_parse(self, name=None, file=None): 373d5ddb276SSimon J. Gerraty """give file and line number causing exception""" 374d5ddb276SSimon J. Gerraty try: 375d5ddb276SSimon J. Gerraty self.parse(name, file) 376d5ddb276SSimon J. Gerraty except: 377d5ddb276SSimon J. Gerraty # give a useful clue 37810ea6facSSimon J. Gerraty print('{}:{}: '.format(self.name, self.line), end=' ', file=sys.stderr) 379d5ddb276SSimon J. Gerraty raise 380d5ddb276SSimon J. Gerraty 3817750ad47SMarcel Moolenaar def parse(self, name=None, file=None): 3827750ad47SMarcel Moolenaar """A meta file looks like: 3837750ad47SMarcel Moolenaar 3847750ad47SMarcel Moolenaar # Meta data file "path" 3857750ad47SMarcel Moolenaar CMD "command-line" 3867750ad47SMarcel Moolenaar CWD "cwd" 3877750ad47SMarcel Moolenaar TARGET "target" 3887750ad47SMarcel Moolenaar -- command output -- 3897750ad47SMarcel Moolenaar -- filemon acquired metadata -- 3907750ad47SMarcel Moolenaar # buildmon version 3 3917750ad47SMarcel Moolenaar V 3 3927750ad47SMarcel Moolenaar C "pid" "cwd" 3937750ad47SMarcel Moolenaar E "pid" "path" 3947750ad47SMarcel Moolenaar F "pid" "child" 3957750ad47SMarcel Moolenaar R "pid" "path" 3967750ad47SMarcel Moolenaar W "pid" "path" 3977750ad47SMarcel Moolenaar X "pid" "status" 3987750ad47SMarcel Moolenaar D "pid" "path" 3997750ad47SMarcel Moolenaar L "pid" "src" "target" 4007750ad47SMarcel Moolenaar M "pid" "old" "new" 4017750ad47SMarcel Moolenaar S "pid" "path" 4027750ad47SMarcel Moolenaar # Bye bye 4037750ad47SMarcel Moolenaar 4047750ad47SMarcel Moolenaar We go to some effort to avoid processing a dependency more than once. 4057750ad47SMarcel Moolenaar Of the above record types only C,E,F,L,R,V and W are of interest. 4067750ad47SMarcel Moolenaar """ 4077750ad47SMarcel Moolenaar 4087750ad47SMarcel Moolenaar version = 0 # unknown 4097750ad47SMarcel Moolenaar if name: 4107750ad47SMarcel Moolenaar self.name = name; 4117750ad47SMarcel Moolenaar if file: 4127750ad47SMarcel Moolenaar f = file 413ccfb9654SSimon J. Gerraty cwd = self.last_dir = self.cwd 4147750ad47SMarcel Moolenaar else: 41510ea6facSSimon J. Gerraty f = open(self.name, 'r') 4167750ad47SMarcel Moolenaar skip = True 4177750ad47SMarcel Moolenaar pid_cwd = {} 4187750ad47SMarcel Moolenaar pid_last_dir = {} 4197750ad47SMarcel Moolenaar last_pid = 0 4207750ad47SMarcel Moolenaar 421d5ddb276SSimon J. Gerraty self.line = 0 4227750ad47SMarcel Moolenaar if self.curdir: 4237750ad47SMarcel Moolenaar self.seenit(self.curdir) # we ignore this 4247750ad47SMarcel Moolenaar 4257750ad47SMarcel Moolenaar interesting = 'CEFLRV' 4267750ad47SMarcel Moolenaar for line in f: 427d5ddb276SSimon J. Gerraty self.line += 1 4287750ad47SMarcel Moolenaar # ignore anything we don't care about 4297750ad47SMarcel Moolenaar if not line[0] in interesting: 4307750ad47SMarcel Moolenaar continue 4317750ad47SMarcel Moolenaar if self.debug > 2: 43210ea6facSSimon J. Gerraty print("input:", line, end=' ', file=self.debug_out) 4337750ad47SMarcel Moolenaar w = line.split() 4347750ad47SMarcel Moolenaar 4357750ad47SMarcel Moolenaar if skip: 4367750ad47SMarcel Moolenaar if w[0] == 'V': 4377750ad47SMarcel Moolenaar skip = False 4387750ad47SMarcel Moolenaar version = int(w[1]) 4397750ad47SMarcel Moolenaar """ 4407750ad47SMarcel Moolenaar if version < 4: 4417750ad47SMarcel Moolenaar # we cannot ignore 'W' records 4427750ad47SMarcel Moolenaar # as they may be 'rw' 4437750ad47SMarcel Moolenaar interesting += 'W' 4447750ad47SMarcel Moolenaar """ 4457750ad47SMarcel Moolenaar elif w[0] == 'CWD': 446ccfb9654SSimon J. Gerraty self.cwd = cwd = self.last_dir = w[1] 4477750ad47SMarcel Moolenaar self.seenit(cwd) # ignore this 4487750ad47SMarcel Moolenaar if self.debug: 44910ea6facSSimon J. Gerraty print("%s: CWD=%s" % (self.name, cwd), file=self.debug_out) 4507750ad47SMarcel Moolenaar continue 4517750ad47SMarcel Moolenaar 4527750ad47SMarcel Moolenaar pid = int(w[1]) 4537750ad47SMarcel Moolenaar if pid != last_pid: 4547750ad47SMarcel Moolenaar if last_pid: 455ccfb9654SSimon J. Gerraty pid_last_dir[last_pid] = self.last_dir 4567750ad47SMarcel Moolenaar cwd = getv(pid_cwd, pid, self.cwd) 457ccfb9654SSimon J. Gerraty self.last_dir = getv(pid_last_dir, pid, self.cwd) 4587750ad47SMarcel Moolenaar last_pid = pid 4597750ad47SMarcel Moolenaar 4607750ad47SMarcel Moolenaar # process operations 4617750ad47SMarcel Moolenaar if w[0] == 'F': 4627750ad47SMarcel Moolenaar npid = int(w[2]) 4637750ad47SMarcel Moolenaar pid_cwd[npid] = cwd 4647750ad47SMarcel Moolenaar pid_last_dir[npid] = cwd 4657750ad47SMarcel Moolenaar last_pid = npid 4667750ad47SMarcel Moolenaar continue 4677750ad47SMarcel Moolenaar elif w[0] == 'C': 4687750ad47SMarcel Moolenaar cwd = abspath(w[2], cwd, None, self.debug, self.debug_out) 4697750ad47SMarcel Moolenaar if cwd.endswith('/.'): 4707750ad47SMarcel Moolenaar cwd = cwd[0:-2] 471b47b9f6bSSimon J. Gerraty self.last_dir = pid_last_dir[pid] = cwd 472b47b9f6bSSimon J. Gerraty pid_cwd[pid] = cwd 4737750ad47SMarcel Moolenaar if self.debug > 1: 47410ea6facSSimon J. Gerraty print("cwd=", cwd, file=self.debug_out) 4757750ad47SMarcel Moolenaar continue 4767750ad47SMarcel Moolenaar 4777750ad47SMarcel Moolenaar if w[2] in self.seen: 4787750ad47SMarcel Moolenaar if self.debug > 2: 47910ea6facSSimon J. Gerraty print("seen:", w[2], file=self.debug_out) 4807750ad47SMarcel Moolenaar continue 4817750ad47SMarcel Moolenaar # file operations 4827750ad47SMarcel Moolenaar if w[0] in 'ML': 483ccfb9654SSimon J. Gerraty # these are special, tread src as read and 484ccfb9654SSimon J. Gerraty # target as write 485ccfb9654SSimon J. Gerraty self.parse_path(w[1].strip("'"), cwd, 'R', w) 486ccfb9654SSimon J. Gerraty self.parse_path(w[2].strip("'"), cwd, 'W', w) 487ccfb9654SSimon J. Gerraty continue 488ccfb9654SSimon J. Gerraty elif w[0] in 'ERWS': 4897750ad47SMarcel Moolenaar path = w[2] 490ccfb9654SSimon J. Gerraty self.parse_path(path, cwd, w[0], w) 491ccfb9654SSimon J. Gerraty 492ccfb9654SSimon J. Gerraty if not file: 493ccfb9654SSimon J. Gerraty f.close() 494ccfb9654SSimon J. Gerraty 495*c0339e7dSSimon J. Gerraty def is_src(self, base, dir, rdir): 496*c0339e7dSSimon J. Gerraty """is base in srctop""" 497*c0339e7dSSimon J. Gerraty for dir in [dir,rdir]: 498*c0339e7dSSimon J. Gerraty if not dir: 499*c0339e7dSSimon J. Gerraty continue 500*c0339e7dSSimon J. Gerraty path = '/'.join([dir,base]) 501*c0339e7dSSimon J. Gerraty srctop = self.find_top(path, self.srctops) 502*c0339e7dSSimon J. Gerraty if srctop: 503*c0339e7dSSimon J. Gerraty if self.dpdeps: 504*c0339e7dSSimon J. Gerraty self.add(self.file_deps, path.replace(srctop,''), 'file') 505*c0339e7dSSimon J. Gerraty self.add(self.src_deps, dir.replace(srctop,''), 'src') 506*c0339e7dSSimon J. Gerraty self.seenit(dir) 507*c0339e7dSSimon J. Gerraty return True 508*c0339e7dSSimon J. Gerraty return False 509*c0339e7dSSimon J. Gerraty 510ccfb9654SSimon J. Gerraty def parse_path(self, path, cwd, op=None, w=[]): 511ccfb9654SSimon J. Gerraty """look at a path for the op specified""" 512ccfb9654SSimon J. Gerraty 513ccfb9654SSimon J. Gerraty if not op: 514ccfb9654SSimon J. Gerraty op = w[0] 515ccfb9654SSimon J. Gerraty 516fbc1b149SSimon J. Gerraty # we are never interested in .dirdep files as dependencies 517fbc1b149SSimon J. Gerraty if path.endswith('.dirdep'): 518ccfb9654SSimon J. Gerraty return 519ccfb9654SSimon J. Gerraty for p in self.excludes: 520ccfb9654SSimon J. Gerraty if p and path.startswith(p): 521ccfb9654SSimon J. Gerraty if self.debug > 2: 522e1dfa657SBryan Drewery print("exclude:", p, path, file=self.debug_out) 523ccfb9654SSimon J. Gerraty return 5247750ad47SMarcel Moolenaar # we don't want to resolve the last component if it is 5257750ad47SMarcel Moolenaar # a symlink 526ccfb9654SSimon J. Gerraty path = resolve(path, cwd, self.last_dir, self.debug, self.debug_out) 5277750ad47SMarcel Moolenaar if not path: 528ccfb9654SSimon J. Gerraty return 5297750ad47SMarcel Moolenaar dir,base = os.path.split(path) 5307750ad47SMarcel Moolenaar if dir in self.seen: 5317750ad47SMarcel Moolenaar if self.debug > 2: 53210ea6facSSimon J. Gerraty print("seen:", dir, file=self.debug_out) 533ccfb9654SSimon J. Gerraty return 5347750ad47SMarcel Moolenaar # we can have a path in an objdir which is a link 5357750ad47SMarcel Moolenaar # to the src dir, we may need to add dependencies for each 5367750ad47SMarcel Moolenaar rdir = dir 537ccfb9654SSimon J. Gerraty dir = abspath(dir, cwd, self.last_dir, self.debug, self.debug_out) 5386d4f05fdSSimon J. Gerraty rdir = os.path.realpath(dir) 539*c0339e7dSSimon J. Gerraty if rdir == dir: 540*c0339e7dSSimon J. Gerraty rdir = None 5417750ad47SMarcel Moolenaar # now put path back together 5427750ad47SMarcel Moolenaar path = '/'.join([dir,base]) 5437750ad47SMarcel Moolenaar if self.debug > 1: 54410ea6facSSimon J. Gerraty print("raw=%s rdir=%s dir=%s path=%s" % (w[2], rdir, dir, path), file=self.debug_out) 545ccfb9654SSimon J. Gerraty if op in 'RWS': 546ccfb9654SSimon J. Gerraty if path in [self.last_dir, cwd, self.cwd, self.curdir]: 5477750ad47SMarcel Moolenaar if self.debug > 1: 54810ea6facSSimon J. Gerraty print("skipping:", path, file=self.debug_out) 549ccfb9654SSimon J. Gerraty return 5507750ad47SMarcel Moolenaar if os.path.isdir(path): 551ccfb9654SSimon J. Gerraty if op in 'RW': 552ccfb9654SSimon J. Gerraty self.last_dir = path; 5537750ad47SMarcel Moolenaar if self.debug > 1: 554ccfb9654SSimon J. Gerraty print("ldir=", self.last_dir, file=self.debug_out) 555ccfb9654SSimon J. Gerraty return 5567750ad47SMarcel Moolenaar 557ccfb9654SSimon J. Gerraty if op in 'ERW': 5587750ad47SMarcel Moolenaar # finally, we get down to it 5597750ad47SMarcel Moolenaar if dir == self.cwd or dir == self.curdir: 560ccfb9654SSimon J. Gerraty return 561*c0339e7dSSimon J. Gerraty if self.is_src(base, dir, rdir): 5627750ad47SMarcel Moolenaar self.seenit(w[2]) 563*c0339e7dSSimon J. Gerraty if not rdir: 564ccfb9654SSimon J. Gerraty return 5657750ad47SMarcel Moolenaar 5667750ad47SMarcel Moolenaar objroot = None 5677750ad47SMarcel Moolenaar for dir in [dir,rdir]: 5687750ad47SMarcel Moolenaar if not dir: 5697750ad47SMarcel Moolenaar continue 5707750ad47SMarcel Moolenaar objroot = self.find_top(dir, self.objroots) 5717750ad47SMarcel Moolenaar if objroot: 5727750ad47SMarcel Moolenaar break 5737750ad47SMarcel Moolenaar if objroot: 5747750ad47SMarcel Moolenaar ddep = self.find_obj(objroot, dir, path, w[2]) 5757750ad47SMarcel Moolenaar if ddep: 5767750ad47SMarcel Moolenaar self.add(self.obj_deps, ddep, 'obj') 577b47b9f6bSSimon J. Gerraty if self.dpdeps and objroot.endswith('/stage/'): 578b47b9f6bSSimon J. Gerraty sp = '/'.join(path.replace(objroot,'').split('/')[1:]) 579b47b9f6bSSimon J. Gerraty self.add(self.file_deps, sp, 'file') 5807750ad47SMarcel Moolenaar else: 5817750ad47SMarcel Moolenaar # don't waste time looking again 5827750ad47SMarcel Moolenaar self.seenit(w[2]) 5837750ad47SMarcel Moolenaar self.seenit(dir) 5847750ad47SMarcel Moolenaar 5857750ad47SMarcel Moolenaar 5867750ad47SMarcel Moolenaardef main(argv, klass=MetaFile, xopts='', xoptf=None): 5877750ad47SMarcel Moolenaar """Simple driver for class MetaFile. 5887750ad47SMarcel Moolenaar 5897750ad47SMarcel Moolenaar Usage: 5907750ad47SMarcel Moolenaar script [options] [key=value ...] "meta" ... 5917750ad47SMarcel Moolenaar 5927750ad47SMarcel Moolenaar Options and key=value pairs contribute to the 5937750ad47SMarcel Moolenaar dictionary passed to MetaFile. 5947750ad47SMarcel Moolenaar 5957750ad47SMarcel Moolenaar -S "SRCTOP" 5967750ad47SMarcel Moolenaar add "SRCTOP" to the "SRCTOPS" list. 5977750ad47SMarcel Moolenaar 5987750ad47SMarcel Moolenaar -C "CURDIR" 5997750ad47SMarcel Moolenaar 6007750ad47SMarcel Moolenaar -O "OBJROOT" 6017750ad47SMarcel Moolenaar add "OBJROOT" to the "OBJROOTS" list. 6027750ad47SMarcel Moolenaar 6037750ad47SMarcel Moolenaar -m "MACHINE" 6047750ad47SMarcel Moolenaar 605bf062775SSimon J. Gerraty -a "MACHINE_ARCH" 606bf062775SSimon J. Gerraty 6077750ad47SMarcel Moolenaar -H "HOST_TARGET" 6087750ad47SMarcel Moolenaar 6097750ad47SMarcel Moolenaar -D "DPDEPS" 6107750ad47SMarcel Moolenaar 6117750ad47SMarcel Moolenaar -d bumps debug level 6127750ad47SMarcel Moolenaar 6137750ad47SMarcel Moolenaar """ 6147750ad47SMarcel Moolenaar import getopt 6157750ad47SMarcel Moolenaar 6167750ad47SMarcel Moolenaar # import Psyco if we can 6177750ad47SMarcel Moolenaar # it can speed things up quite a bit 6187750ad47SMarcel Moolenaar have_psyco = 0 6197750ad47SMarcel Moolenaar try: 6207750ad47SMarcel Moolenaar import psyco 6217750ad47SMarcel Moolenaar psyco.full() 6227750ad47SMarcel Moolenaar have_psyco = 1 6237750ad47SMarcel Moolenaar except: 6247750ad47SMarcel Moolenaar pass 6257750ad47SMarcel Moolenaar 6267750ad47SMarcel Moolenaar conf = { 6277750ad47SMarcel Moolenaar 'SRCTOPS': [], 6287750ad47SMarcel Moolenaar 'OBJROOTS': [], 629ccfb9654SSimon J. Gerraty 'EXCLUDES': [], 6307750ad47SMarcel Moolenaar } 6317750ad47SMarcel Moolenaar 6327750ad47SMarcel Moolenaar try: 6337750ad47SMarcel Moolenaar machine = os.environ['MACHINE'] 6347750ad47SMarcel Moolenaar if machine: 6357750ad47SMarcel Moolenaar conf['MACHINE'] = machine 636bf062775SSimon J. Gerraty machine_arch = os.environ['MACHINE_ARCH'] 637bf062775SSimon J. Gerraty if machine_arch: 638bf062775SSimon J. Gerraty conf['MACHINE_ARCH'] = machine_arch 6397750ad47SMarcel Moolenaar srctop = os.environ['SB_SRC'] 6407750ad47SMarcel Moolenaar if srctop: 6417750ad47SMarcel Moolenaar conf['SRCTOPS'].append(srctop) 6427750ad47SMarcel Moolenaar objroot = os.environ['SB_OBJROOT'] 6437750ad47SMarcel Moolenaar if objroot: 6447750ad47SMarcel Moolenaar conf['OBJROOTS'].append(objroot) 6457750ad47SMarcel Moolenaar except: 6467750ad47SMarcel Moolenaar pass 6477750ad47SMarcel Moolenaar 6487750ad47SMarcel Moolenaar debug = 0 6497750ad47SMarcel Moolenaar output = True 6507750ad47SMarcel Moolenaar 651ccfb9654SSimon J. Gerraty opts, args = getopt.getopt(argv[1:], 'a:dS:C:O:R:m:D:H:qT:X:' + xopts) 6527750ad47SMarcel Moolenaar for o, a in opts: 653bf062775SSimon J. Gerraty if o == '-a': 654bf062775SSimon J. Gerraty conf['MACHINE_ARCH'] = a 655bf062775SSimon J. Gerraty elif o == '-d': 6567750ad47SMarcel Moolenaar debug += 1 6577750ad47SMarcel Moolenaar elif o == '-q': 6587750ad47SMarcel Moolenaar output = False 6597750ad47SMarcel Moolenaar elif o == '-H': 6607750ad47SMarcel Moolenaar conf['HOST_TARGET'] = a 6617750ad47SMarcel Moolenaar elif o == '-S': 6627750ad47SMarcel Moolenaar if a not in conf['SRCTOPS']: 6637750ad47SMarcel Moolenaar conf['SRCTOPS'].append(a) 6647750ad47SMarcel Moolenaar elif o == '-C': 6657750ad47SMarcel Moolenaar conf['CURDIR'] = a 6667750ad47SMarcel Moolenaar elif o == '-O': 6677750ad47SMarcel Moolenaar if a not in conf['OBJROOTS']: 6687750ad47SMarcel Moolenaar conf['OBJROOTS'].append(a) 6697750ad47SMarcel Moolenaar elif o == '-R': 6707750ad47SMarcel Moolenaar conf['RELDIR'] = a 6717750ad47SMarcel Moolenaar elif o == '-D': 6727750ad47SMarcel Moolenaar conf['DPDEPS'] = a 6737750ad47SMarcel Moolenaar elif o == '-m': 6747750ad47SMarcel Moolenaar conf['MACHINE'] = a 675bf062775SSimon J. Gerraty elif o == '-T': 676bf062775SSimon J. Gerraty conf['TARGET_SPEC'] = a 677ccfb9654SSimon J. Gerraty elif o == '-X': 678ccfb9654SSimon J. Gerraty if a not in conf['EXCLUDES']: 679ccfb9654SSimon J. Gerraty conf['EXCLUDES'].append(a) 6807750ad47SMarcel Moolenaar elif xoptf: 6817750ad47SMarcel Moolenaar xoptf(o, a, conf) 6827750ad47SMarcel Moolenaar 6837750ad47SMarcel Moolenaar conf['debug'] = debug 6847750ad47SMarcel Moolenaar 6857750ad47SMarcel Moolenaar # get any var=val assignments 6867750ad47SMarcel Moolenaar eaten = [] 6877750ad47SMarcel Moolenaar for a in args: 6887750ad47SMarcel Moolenaar if a.find('=') > 0: 6897750ad47SMarcel Moolenaar k,v = a.split('=') 6907750ad47SMarcel Moolenaar if k in ['SRCTOP','OBJROOT','SRCTOPS','OBJROOTS']: 6917750ad47SMarcel Moolenaar if k == 'SRCTOP': 6927750ad47SMarcel Moolenaar k = 'SRCTOPS' 6937750ad47SMarcel Moolenaar elif k == 'OBJROOT': 6947750ad47SMarcel Moolenaar k = 'OBJROOTS' 6957750ad47SMarcel Moolenaar if v not in conf[k]: 6967750ad47SMarcel Moolenaar conf[k].append(v) 6977750ad47SMarcel Moolenaar else: 6987750ad47SMarcel Moolenaar conf[k] = v 6997750ad47SMarcel Moolenaar eaten.append(a) 7007750ad47SMarcel Moolenaar continue 7017750ad47SMarcel Moolenaar break 7027750ad47SMarcel Moolenaar 7037750ad47SMarcel Moolenaar for a in eaten: 7047750ad47SMarcel Moolenaar args.remove(a) 7057750ad47SMarcel Moolenaar 7067750ad47SMarcel Moolenaar debug_out = getv(conf, 'debug_out', sys.stderr) 7077750ad47SMarcel Moolenaar 7087750ad47SMarcel Moolenaar if debug: 70910ea6facSSimon J. Gerraty print("config:", file=debug_out) 71010ea6facSSimon J. Gerraty print("psyco=", have_psyco, file=debug_out) 71110ea6facSSimon J. Gerraty for k,v in list(conf.items()): 71210ea6facSSimon J. Gerraty print("%s=%s" % (k,v), file=debug_out) 7137750ad47SMarcel Moolenaar 714ccfb9654SSimon J. Gerraty m = None 7157750ad47SMarcel Moolenaar for a in args: 716d5ddb276SSimon J. Gerraty if a.endswith('.meta'): 717ccfb9654SSimon J. Gerraty if not os.path.exists(a): 718ccfb9654SSimon J. Gerraty continue 7197750ad47SMarcel Moolenaar m = klass(a, conf) 720d5ddb276SSimon J. Gerraty elif a.startswith('@'): 721d5ddb276SSimon J. Gerraty # there can actually multiple files per line 722d5ddb276SSimon J. Gerraty for line in open(a[1:]): 723d5ddb276SSimon J. Gerraty for f in line.strip().split(): 724ccfb9654SSimon J. Gerraty if not os.path.exists(f): 725ccfb9654SSimon J. Gerraty continue 726d5ddb276SSimon J. Gerraty m = klass(f, conf) 7277750ad47SMarcel Moolenaar 728ccfb9654SSimon J. Gerraty if output and m: 72910ea6facSSimon J. Gerraty print(m.dirdeps()) 7307750ad47SMarcel Moolenaar 73110ea6facSSimon J. Gerraty print(m.src_dirdeps('\nsrc:')) 7327750ad47SMarcel Moolenaar 7337750ad47SMarcel Moolenaar dpdeps = getv(conf, 'DPDEPS') 7347750ad47SMarcel Moolenaar if dpdeps: 7357750ad47SMarcel Moolenaar m.file_depends(open(dpdeps, 'wb')) 7367750ad47SMarcel Moolenaar 7377750ad47SMarcel Moolenaar return m 7387750ad47SMarcel Moolenaar 7397750ad47SMarcel Moolenaarif __name__ == '__main__': 7407750ad47SMarcel Moolenaar try: 7417750ad47SMarcel Moolenaar main(sys.argv) 7427750ad47SMarcel Moolenaar except: 7437750ad47SMarcel Moolenaar # yes, this goes to stdout 74410ea6facSSimon J. Gerraty print("ERROR: ", sys.exc_info()[1]) 7457750ad47SMarcel Moolenaar raise 7467750ad47SMarcel Moolenaar 747