| OLD | NEW | 
| (Empty) |  | 
 |   1 # Copyright 2016 The Chromium Authors. All rights reserved. | 
 |   2 # Use of this source code is governed by a BSD-style license that can be | 
 |   3 # found in the LICENSE file. | 
 |   4  | 
 |   5 import os | 
 |   6 import struct | 
 |   7 import sys | 
 |   8  | 
 |   9 def Main(args): | 
 |  10   if len(args) < 4: | 
 |  11     print >> sys.stderr, "Usage: %s output.hmap Foo.framework header1.h..." %\ | 
 |  12         (args[0]) | 
 |  13     return 1 | 
 |  14  | 
 |  15   (out, framework, all_headers) = args[1], args[2], args[3:] | 
 |  16  | 
 |  17   framework_name = os.path.basename(framework).split('.')[0] | 
 |  18   all_headers = map(os.path.abspath, all_headers) | 
 |  19   filelist = {} | 
 |  20   for header in all_headers: | 
 |  21     filename = os.path.basename(header) | 
 |  22     filelist[filename] = header | 
 |  23     filelist[os.path.join(framework_name, filename)] = header | 
 |  24   WriteHmap(out, filelist) | 
 |  25   return 0 | 
 |  26  | 
 |  27  | 
 |  28 def NextGreaterPowerOf2(x): | 
 |  29   return 2**(x).bit_length() | 
 |  30  | 
 |  31  | 
 |  32 def WriteHmap(output_name, filelist): | 
 |  33   """Generates a header map based on |filelist|. | 
 |  34  | 
 |  35   Per Mark Mentovai: | 
 |  36     A header map is structured essentially as a hash table, keyed by names used | 
 |  37     in #includes, and providing pathnames to the actual files. | 
 |  38  | 
 |  39   The implementation below and the comment above comes from inspecting: | 
 |  40     http://www.opensource.apple.com/source/distcc/distcc-2503/distcc_dist/includ
    e_server/headermap.py?txt | 
 |  41   while also looking at the implementation in clang in: | 
 |  42     https://llvm.org/svn/llvm-project/cfe/trunk/lib/Lex/HeaderMap.cpp | 
 |  43   """ | 
 |  44   magic = 1751998832 | 
 |  45   version = 1 | 
 |  46   _reserved = 0 | 
 |  47   count = len(filelist) | 
 |  48   capacity = NextGreaterPowerOf2(count) | 
 |  49   strings_offset = 24 + (12 * capacity) | 
 |  50   max_value_length = len(max(filelist.items(), key=lambda (k,v):len(v))[1]) | 
 |  51  | 
 |  52   out = open(output_name, 'wb') | 
 |  53   out.write(struct.pack('<LHHLLLL', magic, version, _reserved, strings_offset, | 
 |  54                         count, capacity, max_value_length)) | 
 |  55  | 
 |  56   # Create empty hashmap buckets. | 
 |  57   buckets = [None] * capacity | 
 |  58   for file, path in filelist.items(): | 
 |  59     key = 0 | 
 |  60     for c in file: | 
 |  61       key += ord(c.lower()) * 13 | 
 |  62  | 
 |  63     # Fill next empty bucket. | 
 |  64     while buckets[key & capacity - 1] is not None: | 
 |  65       key = key + 1 | 
 |  66     buckets[key & capacity - 1] = (file, path) | 
 |  67  | 
 |  68   next_offset = 1 | 
 |  69   for bucket in buckets: | 
 |  70     if bucket is None: | 
 |  71       out.write(struct.pack('<LLL', 0, 0, 0)) | 
 |  72     else: | 
 |  73       (file, path) = bucket | 
 |  74       key_offset = next_offset | 
 |  75       prefix_offset = key_offset + len(file) + 1 | 
 |  76       suffix_offset = prefix_offset + len(os.path.dirname(path) + os.sep) + 1 | 
 |  77       next_offset = suffix_offset + len(os.path.basename(path)) + 1 | 
 |  78       out.write(struct.pack('<LLL', key_offset, prefix_offset, suffix_offset)) | 
 |  79  | 
 |  80   # Pad byte since next offset starts at 1. | 
 |  81   out.write(struct.pack('<x')) | 
 |  82  | 
 |  83   for bucket in buckets: | 
 |  84     if bucket is not None: | 
 |  85       (file, path) = bucket | 
 |  86       out.write(struct.pack('<%ds' % len(file), file)) | 
 |  87       out.write(struct.pack('<s', '\0')) | 
 |  88       base = os.path.dirname(path) + os.sep | 
 |  89       out.write(struct.pack('<%ds' % len(base), base)) | 
 |  90       out.write(struct.pack('<s', '\0')) | 
 |  91       path = os.path.basename(path) | 
 |  92       out.write(struct.pack('<%ds' % len(path), path)) | 
 |  93       out.write(struct.pack('<s', '\0')) | 
 |  94  | 
 |  95  | 
 |  96 if __name__ == '__main__': | 
 |  97   sys.exit(Main(sys.argv)) | 
| OLD | NEW |