1#!/usr/bin/python
2
3from __future__ import print_function
4
5import sys, re
6from structs import unions, structs, defines
7
8# command line arguments
9arch    = sys.argv[1]
10outfile = sys.argv[2]
11infiles = sys.argv[3:]
12
13
14###########################################################################
15# configuration #2: architecture information
16
17inttypes = {}
18header = {}
19footer = {}
20
21#arm
22inttypes["arm32"] = [
23    ("unsigned long", "__danger_unsigned_long_on_arm32"),
24    ("long",          "__danger_long_on_arm32"),
25    ("xen_pfn_t",     "uint64_t"),
26    ("xen_ulong_t",   "uint64_t"),
27    ("uint64_t",      "__align8__ uint64_t"),
28]
29header["arm32"] = """
30#define __arm___ARM32 1
31#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
32# define __DECL_REG(n64, n32) union { uint64_t n64; uint32_t n32; }
33# define __align8__ __attribute__((aligned (8)))
34#else
35# define __DECL_REG(n64, n32) uint64_t n64
36# define __align8__ FIXME
37#endif
38"""
39footer["arm32"] = """
40#undef __DECL_REG
41"""
42
43inttypes["arm64"] = [
44    ("unsigned long", "__danger_unsigned_long_on_arm64"),
45    ("long",          "__danger_long_on_arm64"),
46    ("xen_pfn_t",     "uint64_t"),
47    ("xen_ulong_t",   "uint64_t"),
48    ("uint64_t",      "__align8__ uint64_t"),
49]
50header["arm64"] = """
51#define __aarch64___ARM64 1
52#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
53# define __DECL_REG(n64, n32) union { uint64_t n64; uint32_t n32; }
54# define __align8__ __attribute__((aligned (8)))
55#else
56# define __DECL_REG(n64, n32) uint64_t n64
57# define __align8__ FIXME
58#endif
59"""
60footer["arm64"] = """
61#undef __DECL_REG
62"""
63
64# x86_32
65inttypes["x86_32"] = [
66    ("unsigned long", "uint32_t"),
67    ("long",          "uint32_t"),
68    ("xen_pfn_t",     "uint32_t"),
69    ("xen_ulong_t",   "uint32_t"),
70]
71header["x86_32"] = """
72#define __DECL_REG_LO8(which) uint32_t e ## which ## x
73#define __DECL_REG_LO16(name) uint32_t e ## name
74#define __i386___X86_32 1
75#pragma pack(4)
76"""
77footer["x86_32"] = """
78#undef __DECL_REG_LO8
79#undef __DECL_REG_LO16
80#pragma pack()
81"""
82
83# x86_64
84inttypes["x86_64"] = [
85    ("unsigned long", "__align8__ uint64_t"),
86    ("long",          "__align8__ uint64_t"),
87    ("xen_pfn_t",     "__align8__ uint64_t"),
88    ("xen_ulong_t",   "__align8__ uint64_t"),
89]
90header["x86_64"] = """
91#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
92# define __DECL_REG(name) union { uint64_t r ## name, e ## name; }
93# define __align8__ __attribute__((aligned (8)))
94#else
95# define __DECL_REG(name) uint64_t r ## name
96# define __align8__ FIXME
97#endif
98#define __DECL_REG_LOHI(name) __DECL_REG(name ## x)
99#define __DECL_REG_LO8        __DECL_REG
100#define __DECL_REG_LO16       __DECL_REG
101#define __DECL_REG_HI         __DECL_REG
102#define __x86_64___X86_64 1
103"""
104footer["x86_64"] = """
105#undef __DECL_REG
106#undef __DECL_REG_LOHI
107#undef __DECL_REG_LO8
108#undef __DECL_REG_LO16
109#undef __DECL_REG_HI
110"""
111
112###########################################################################
113# main
114
115input  = ""
116output = ""
117fileid = re.sub("[-.]", "_", "__FOREIGN_%s__" % outfile.upper())
118
119for name in infiles:
120    f = open(name, "r")
121
122    # Sanity check the licence of the input file(s)
123    line = f.readline()
124    if line != "/* SPDX-License-Identifier: MIT */\n":
125        print("Error: %s %s Missing or unexpected SPDX tag '%s'" %
126              (sys.argv[0], name, line.strip()), file=sys.stderr)
127        exit(1)
128
129    input += f.read()
130    f.close()
131
132# replace path in "infiles" by path in '/usr/include' to avoid exposing the
133# build directory path in the generated headers.
134headers_name_list = ""
135public_headers_location = 'xen/include/public/'
136for name in infiles:
137    i = name.rindex(public_headers_location)
138    i += len(public_headers_location)
139    headers_name_list += " xen/%s" % (name[i:])
140
141# add header
142output += """/* SPDX-License-Identifier: MIT */
143/*
144 * public xen defines and struct for %s
145 * generated from%s by %s -- DO NOT EDIT
146 */
147
148#ifndef %s
149#define %s 1
150
151""" % (arch, headers_name_list, sys.argv[0], fileid, fileid)
152
153if arch in header:
154    output += header[arch]
155    output += "\n"
156
157defined = {}
158
159# add defines to output
160for line in re.findall("#define[^\n]+", input):
161    for define in defines:
162        regex = r"#define\s+%s\b" % define
163        match = re.search(regex, line)
164        if None == match:
165            continue
166        defined[define] = 1
167        if define.upper()[0] == define[0]:
168            replace = define + "_" + arch.upper()
169        else:
170            replace = define + "_" + arch
171        regex = r"\b%s\b" % define
172        output += re.sub(regex, replace, line) + "\n"
173output += "\n"
174
175# delete defines, comments, empty lines
176input = re.sub("#define[^\n]+\n", "", input)
177input = re.compile(r"/\*(.*?)\*/", re.S).sub("", input)
178input = re.compile(r"\n\s*\n", re.S).sub("\n", input)
179
180# add unions to output
181for union in unions:
182    regex = r"union\s+%s\s*\{(.*?)\n\};" % union
183    match = re.search(regex, input, re.S)
184    if None == match:
185        output += "#define %s_has_no_%s 1\n" % (arch, union)
186    else:
187        output += "union %s_%s {%s\n};\n" % (union, arch, match.group(1))
188    output += "\n"
189
190# add structs to output
191for struct in structs:
192    regex = r"(?:#ifdef ([A-Z_]+))?\nstruct\s+%s\s*\{(.*?)\n\};" % struct
193    match = re.search(regex, input, re.S)
194    if None == match or \
195           (match.group(1) is not None and match.group(1) not in defined):
196        output += "#define %s_has_no_%s 1\n" % (arch, struct)
197    else:
198        output += "struct %s_%s {%s\n};\n" % (struct, arch, match.group(2))
199        output += "typedef struct %s_%s %s_%s_t;\n" % (struct, arch, struct, arch)
200    output += "\n"
201
202# add footer
203if arch in footer:
204    output += footer[arch]
205    output += "\n"
206output += "#endif /* %s */\n" % fileid
207
208# replace: defines
209for define in defines:
210    if define.upper()[0] == define[0]:
211        replace = define + "_" + arch.upper()
212    else:
213        replace = define + "_" + arch
214    output = re.sub(r"\b%s\b" % define, replace, output)
215
216# replace: unions
217for union in unions:
218    output = re.sub(r"\b(union\s+%s)\b" % union, r"\1_%s" % arch, output)
219
220# replace: structs + struct typedefs
221for struct in structs:
222    output = re.sub(r"\b(struct\s+%s)\b" % struct, r"\1_%s" % arch, output)
223    output = re.sub(r"\b(%s)_t\b" % struct, r"\1_%s_t" % arch, output)
224
225# replace: integer types
226for old, new in inttypes[arch]:
227    output = re.sub(r"\b%s\b" % old, new, output)
228
229# print results
230with open(outfile, "w") as f:
231    f.write(output)
232