Statistics
| Branch: | Tag: | Revision:

root / gr-run-waveform / gen-xyzzy @ 5a07519b

History | View | Annotate | Download (5.1 kB)

1 e3ec22b1 Eric Blossom
#!/usr/bin/env python
2 e3ec22b1 Eric Blossom
3 e3ec22b1 Eric Blossom
"""
4 e3ec22b1 Eric Blossom
    usage: gen-xyzzy [-o output] directory...
5 e3ec22b1 Eric Blossom
6 e3ec22b1 Eric Blossom
    Typical usage:
7 e3ec22b1 Eric Blossom
      gen-xyzzy -o filesystem.dat /usr/share/guile/1.8 /usr/local/share/guile/site
8 e3ec22b1 Eric Blossom
9 e3ec22b1 Eric Blossom
    Where /usr/share/guile points to the system guile installation and
10 e3ec22b1 Eric Blossom
    /usr/local/share/guile/site points to the GNU Radio installed guile files
11 e3ec22b1 Eric Blossom
12 e3ec22b1 Eric Blossom
13 e3ec22b1 Eric Blossom
    Build a single file that contains all of the *.scm files from the
14 e3ec22b1 Eric Blossom
    guile installation and from the GR installation.  I figure it's
15 e3ec22b1 Eric Blossom
    basically a table that maps strings to strings.  That is,
16 e3ec22b1 Eric Blossom
    "/foo/bar/filename" -> "file contents".  We could just mmap
17 e3ec22b1 Eric Blossom
    it in read-only, or just read it in.  Reading is more portable,
18 e3ec22b1 Eric Blossom
    let's do that.
19 e3ec22b1 Eric Blossom
20 e3ec22b1 Eric Blossom
    File: [ header | directory | strings ]
21 e3ec22b1 Eric Blossom
22 e3ec22b1 Eric Blossom
    All integers are net-endian.
23 e3ec22b1 Eric Blossom
24 e3ec22b1 Eric Blossom
    struct header {
25 e3ec22b1 Eric Blossom
      char magic[8];
26 e3ec22b1 Eric Blossom
27 e3ec22b1 Eric Blossom
      uint32_t	offset_to_directory;	// byte offset from start of file
28 e3ec22b1 Eric Blossom
      uint32_t	size_of_directory;	// bytes
29 e3ec22b1 Eric Blossom
      uint32_t  number_of_dir_entries;
30 e3ec22b1 Eric Blossom
31 e3ec22b1 Eric Blossom
      uint32_t	offset_to_strings;	// byte offset from start of file
32 e3ec22b1 Eric Blossom
      uint32_t  size_of_strings;	// bytes
33 e3ec22b1 Eric Blossom
    };
34 e3ec22b1 Eric Blossom
35 e3ec22b1 Eric Blossom
    struct directory_entry {
36 e3ec22b1 Eric Blossom
      uint32_t	     offset_to_name;	 // from start of strings
37 e3ec22b1 Eric Blossom
      uint32_t	     offset_to_contents; // from start of strings
38 e3ec22b1 Eric Blossom
    }
39 e3ec22b1 Eric Blossom
40 e3ec22b1 Eric Blossom
    Each string starts with a uint32_t length, followed by length bytes.
41 e3ec22b1 Eric Blossom
    There is no trailing \0 in the string.  Each string entry is followed
42 e3ec22b1 Eric Blossom
    with enough padding to bring it up to a multiple of 4 bytes.
43 e3ec22b1 Eric Blossom
44 e3ec22b1 Eric Blossom
    struct string_entry {
45 e3ec22b1 Eric Blossom
      uint32_t	    length;
46 e3ec22b1 Eric Blossom
      unsigned char c[1];		// 0 is nicer, but not portable.
47 e3ec22b1 Eric Blossom
    }
48 e3ec22b1 Eric Blossom
"""
49 e3ec22b1 Eric Blossom
50 e3ec22b1 Eric Blossom
51 e3ec22b1 Eric Blossom
from optparse import OptionParser
52 e3ec22b1 Eric Blossom
import sys
53 e3ec22b1 Eric Blossom
import os
54 e3ec22b1 Eric Blossom
import os.path
55 e3ec22b1 Eric Blossom
from pprint import pprint
56 e3ec22b1 Eric Blossom
import struct
57 e3ec22b1 Eric Blossom
58 e3ec22b1 Eric Blossom
59 e3ec22b1 Eric Blossom
def main():
60 e3ec22b1 Eric Blossom
   parser = OptionParser(usage="usage: %prog [options] directory...")
61 e3ec22b1 Eric Blossom
   parser.add_option("-o", type="string", default=None, metavar="FILENAME",
62 e3ec22b1 Eric Blossom
                          help="Specify output filename [default=stdout]")
63 e3ec22b1 Eric Blossom
   (options, args) = parser.parse_args()
64 e3ec22b1 Eric Blossom
65 e3ec22b1 Eric Blossom
   if len(args) == 0:
66 e3ec22b1 Eric Blossom
      parser.print_help()
67 e3ec22b1 Eric Blossom
      raise SystemExit, 1
68 e3ec22b1 Eric Blossom
69 e3ec22b1 Eric Blossom
   if options.o:
70 e3ec22b1 Eric Blossom
      output = open(options.o, 'wb')
71 e3ec22b1 Eric Blossom
   else:
72 e3ec22b1 Eric Blossom
      output = sys.stdout
73 e3ec22b1 Eric Blossom
74 e3ec22b1 Eric Blossom
   doit(output, args)
75 e3ec22b1 Eric Blossom
76 e3ec22b1 Eric Blossom
77 e3ec22b1 Eric Blossom
def doit(output, dirs):
78 e3ec22b1 Eric Blossom
   acc = []
79 e3ec22b1 Eric Blossom
   for d in dirs:
80 e3ec22b1 Eric Blossom
      acc.extend(handle_dir(d))
81 e3ec22b1 Eric Blossom
82 e3ec22b1 Eric Blossom
   uniq = {}
83 e3ec22b1 Eric Blossom
   for key, val in acc:
84 e3ec22b1 Eric Blossom
      if key in uniq:
85 e3ec22b1 Eric Blossom
         if val != uniq[key]:
86 e3ec22b1 Eric Blossom
            sys.stderr.write("Duplicate key: %s %s %s\n" % (key, uniq[key], val))
87 e3ec22b1 Eric Blossom
      else:
88 e3ec22b1 Eric Blossom
         uniq[key] = val
89 e3ec22b1 Eric Blossom
90 e3ec22b1 Eric Blossom
   t = uniq.items()
91 e3ec22b1 Eric Blossom
   t.sort()
92 e3ec22b1 Eric Blossom
   write_xyzzy(output, t)
93 e3ec22b1 Eric Blossom
94 e3ec22b1 Eric Blossom
95 e3ec22b1 Eric Blossom
def handle_dir(directory):
96 e3ec22b1 Eric Blossom
   if not directory.endswith(os.sep):
97 e3ec22b1 Eric Blossom
      directory = directory + os.sep
98 e3ec22b1 Eric Blossom
   acc = []
99 e3ec22b1 Eric Blossom
   for root, dirs, files in os.walk(directory, topdown=True):
100 350a427f Eric Blossom
      # scm_files = [f for f in files if f.endswith('.scm')]
101 350a427f Eric Blossom
      scm_files = files
102 e3ec22b1 Eric Blossom
      for f in scm_files:
103 e3ec22b1 Eric Blossom
         full_name = os.path.join(root, f)
104 e3ec22b1 Eric Blossom
         t = (full_name[len(directory):], full_name)
105 e3ec22b1 Eric Blossom
         acc.append(t)
106 e3ec22b1 Eric Blossom
   return acc
107 e3ec22b1 Eric Blossom
108 e3ec22b1 Eric Blossom
109 e3ec22b1 Eric Blossom
def file_length(filename):
110 e3ec22b1 Eric Blossom
   statinfo = os.stat(filename)
111 e3ec22b1 Eric Blossom
   return statinfo.st_size
112 e3ec22b1 Eric Blossom
113 e3ec22b1 Eric Blossom
114 e3ec22b1 Eric Blossom
# return n rounded up to a multiple of 4
115 e3ec22b1 Eric Blossom
def round_up(n):
116 e3ec22b1 Eric Blossom
   return (n + 3) & -4
117 e3ec22b1 Eric Blossom
118 e3ec22b1 Eric Blossom
119 e3ec22b1 Eric Blossom
class string_table(object):
120 e3ec22b1 Eric Blossom
   def __init__(self):
121 e3ec22b1 Eric Blossom
      self._table = ''
122 e3ec22b1 Eric Blossom
      self._padding = '\0\0\0\0'
123 e3ec22b1 Eric Blossom
124 e3ec22b1 Eric Blossom
   def add_string(self, s):
125 e3ec22b1 Eric Blossom
      r = len(self._table)
126 e3ec22b1 Eric Blossom
      len_s = len(s)
127 e3ec22b1 Eric Blossom
      padding = self._padding[0:round_up(len_s) - len_s]
128 e3ec22b1 Eric Blossom
      self._table = ''.join((self._table, struct.pack('>I', len(s)), s, padding))
129 e3ec22b1 Eric Blossom
      return r
130 e3ec22b1 Eric Blossom
131 e3ec22b1 Eric Blossom
132 e3ec22b1 Eric Blossom
def write_xyzzy(f, list_of_tuples):
133 e3ec22b1 Eric Blossom
   # tuples: (name, filename)
134 e3ec22b1 Eric Blossom
   names = [s[0] for s in list_of_tuples]
135 e3ec22b1 Eric Blossom
   number_of_dir_entries = len(list_of_tuples)
136 e3ec22b1 Eric Blossom
   number_of_names = number_of_dir_entries
137 e3ec22b1 Eric Blossom
   number_of_files = number_of_dir_entries
138 e3ec22b1 Eric Blossom
   sizeof_uint32 = 4
139 e3ec22b1 Eric Blossom
140 e3ec22b1 Eric Blossom
   contents = {}
141 e3ec22b1 Eric Blossom
   for name, filename in list_of_tuples:
142 e3ec22b1 Eric Blossom
      t = open(filename, 'rb').read()
143 e3ec22b1 Eric Blossom
      contents[name] = t
144 e3ec22b1 Eric Blossom
145 e3ec22b1 Eric Blossom
   offset_to_directory = 28
146 e3ec22b1 Eric Blossom
   size_of_directory = number_of_dir_entries * 8
147 e3ec22b1 Eric Blossom
   offset_to_strings = offset_to_directory + size_of_directory
148 e3ec22b1 Eric Blossom
149 e3ec22b1 Eric Blossom
   st = string_table()
150 e3ec22b1 Eric Blossom
151 e3ec22b1 Eric Blossom
   # Insert names in string table first to help locality
152 e3ec22b1 Eric Blossom
   name_str_offset = {}
153 e3ec22b1 Eric Blossom
   for name in names:
154 e3ec22b1 Eric Blossom
      name_str_offset[name] = st.add_string(name)
155 e3ec22b1 Eric Blossom
156 e3ec22b1 Eric Blossom
   # Now add file contents
157 e3ec22b1 Eric Blossom
   content_str_offset = {}
158 e3ec22b1 Eric Blossom
   for name in names:
159 e3ec22b1 Eric Blossom
      content_str_offset[name] = st.add_string(contents[name])
160 e3ec22b1 Eric Blossom
161 e3ec22b1 Eric Blossom
   size_of_strings = len(st._table)
162 e3ec22b1 Eric Blossom
163 e3ec22b1 Eric Blossom
   if 0:
164 e3ec22b1 Eric Blossom
      print "offset_to_directory\t", offset_to_directory
165 e3ec22b1 Eric Blossom
      print "size_of_directory\t", size_of_directory
166 e3ec22b1 Eric Blossom
      print "number_of_dir_entries\t", number_of_dir_entries
167 e3ec22b1 Eric Blossom
      print "offset_to_strings\t", offset_to_strings
168 e3ec22b1 Eric Blossom
      print "size_of_strings\t\t", size_of_strings
169 e3ec22b1 Eric Blossom
170 e3ec22b1 Eric Blossom
   magic = '-XyZzY-\0'
171 e3ec22b1 Eric Blossom
172 e3ec22b1 Eric Blossom
   # Write header
173 e3ec22b1 Eric Blossom
   f.write(struct.pack('>8s5I',
174 e3ec22b1 Eric Blossom
                       magic,
175 e3ec22b1 Eric Blossom
                       offset_to_directory,
176 e3ec22b1 Eric Blossom
                       size_of_directory,
177 e3ec22b1 Eric Blossom
                       number_of_dir_entries,
178 e3ec22b1 Eric Blossom
                       offset_to_strings,
179 e3ec22b1 Eric Blossom
                       size_of_strings))
180 e3ec22b1 Eric Blossom
181 e3ec22b1 Eric Blossom
   # Write directory
182 e3ec22b1 Eric Blossom
   for name in names:
183 e3ec22b1 Eric Blossom
      f.write(struct.pack('>2I',
184 e3ec22b1 Eric Blossom
                          name_str_offset[name],
185 e3ec22b1 Eric Blossom
                          content_str_offset[name]))
186 e3ec22b1 Eric Blossom
187 e3ec22b1 Eric Blossom
   # Write string table
188 e3ec22b1 Eric Blossom
   f.write(st._table)
189 e3ec22b1 Eric Blossom
190 e3ec22b1 Eric Blossom
191 e3ec22b1 Eric Blossom
if __name__ == "__main__":
192 e3ec22b1 Eric Blossom
   main()