1# encoding=utf-8
2# Copyright © 2018 Intel Corporation
3#
4# Permission is hereby granted, free of charge, to any person obtaining a
5# copy of this software and associated documentation files (the "Software"),
6# to deal in the Software without restriction, including without limitation
7# the rights to use, copy, modify, merge, publish, distribute, sublicense,
8# and/or sell copies of the Software, and to permit persons to whom the
9# Software is furnished to do so, subject to the following conditions:
10#
11# The above copyright notice and this permission notice (including the next
12# paragraph) shall be included in all copies or substantial portions of the
13# Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21# IN THE SOFTWARE.
22
23# Converts a file to a C/C++ #include containing a string
24
25from __future__ import unicode_literals
26import argparse
27import io
28import os
29
30
31def get_args():
32    parser = argparse.ArgumentParser()
33    parser.add_argument('input', help="Name of input file")
34    parser.add_argument('output', help="Name of output file")
35    parser.add_argument("-n", "--name",
36                        help="Name of C variable")
37    parser.add_argument("-b", "--binary", dest='binary', action='store_const',
38                        const=True, default=False)
39    args = parser.parse_args()
40    return args
41
42
43def filename_to_C_identifier(n):
44    if n[0] != '_' and not n[0].isalpha():
45        n = "_" + n[1:]
46
47    return "".join([c if c.isalnum() or c == "_" else "_" for c in n])
48
49
50def emit_byte(f, b):
51    f.write("0x{:02x}, ".format(ord(b)).encode('utf-8'))
52
53
54def process_file(args):
55    with io.open(args.input, "rb") as infile:
56        try:
57            with io.open(args.output, "wb") as outfile:
58                # If a name was not specified on the command line, pick one based on the
59                # name of the input file.  If no input filename was specified, use
60                # from_stdin.
61                if args.name is not None:
62                    name = args.name
63                else:
64                    name = filename_to_C_identifier(args.input)
65
66                outfile.write("static const char {}[] = {{\n".format(name).encode('utf-8'))
67
68                linecount = 0
69                while True:
70                    byte = infile.read(1)
71                    if byte == b"":
72                        break
73
74                    if not args.binary:
75                        assert(ord(byte) != 0)
76
77                    emit_byte(outfile, byte)
78                    linecount = linecount + 1
79                    if linecount > 20:
80                        outfile.write(b"\n ")
81                        linecount = 0
82                if not args.binary:
83                    outfile.write(b"\n0")
84                outfile.write(b"\n};\n\n")
85        except Exception:
86            # In the event that anything goes wrong, delete the output file,
87            # then re-raise the exception. Deleteing the output file should
88            # ensure that the build system doesn't try to use the stale,
89            # half-generated file.
90            os.unlink(args.output)
91            raise
92
93
94def main():
95    args = get_args()
96    process_file(args)
97
98
99if __name__ == "__main__":
100    main()
101