def find_all_defns(files):
  patt = re.compile('function\s.*?=?\s*(\w+)\s*(?:\(|;|$)', re.I)
  functions = {}
  for fpath in files.itervalues():
    for _,match in grep(patt,fpath):
      functions[patt.search(match).groups(1)] = fpath
      break  # only the first function counts
  return functions
def find_usages(functions, files, targets):
  adj = numpy.zeros((len(files),len(files)),dtype=int)
  path_inds = dict((p,i) for i,p in enumerate(files.itervalues()))
  for fn,fpath in functions.iteritems():
    i = path_inds[fpath]
    patt = re.compile('(\W|^)%s(\(|;|$)'%fn, re.I)
    for j,fpath2 in enumerate(files.itervalues()):
      if fpath not in targets and fpath2 not in targets:
        continue
      # edge (j,i) = n means i calls j n times
      adj[j,i] = sum(1 for _ in grep(patt,fpath2))
  return adj