Make tools/*.py scripts Git aware
[helenos.git] / tools / autogen.py
blob29117639e51af311e0e797b061964d70104df51d
1 #!/usr/bin/env python
3 # Copyright (c) 2014 Jakub Jermar
4 # All rights reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
10 # - Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # - Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in the
14 # documentation and/or other materials provided with the distribution.
15 # - The name of the author may not be used to endorse or promote products
16 # derived from this software without specific prior written permission.
18 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 import sys
31 import yaml
32 import re
34 def usage():
35 print("%s - Automated structure and offsets generator" % sys.argv[0])
36 print("%s file.ag depend|probe|generate struct.ag" % sys.argv[0])
37 sys.exit()
39 def depend(struct):
40 deps = ""
41 for include in struct['includes']:
42 if 'depends' in include.keys():
43 deps = deps + include['depends'] + "\n"
44 return deps.strip()
46 def generate_includes(struct):
47 code = ""
48 for include in struct['includes']:
49 if 'guard' in include.keys():
50 code = code + "#ifdef %s\n" % include['guard']
51 if 'negative-guard' in include.keys():
52 code = code + "#ifndef %s\n" % include['negative-guard']
53 code = code + "#include %s\n" % include['include']
54 if 'guard' in include.keys():
55 code = code + "#endif\n"
56 if 'negative-guard' in include.keys():
57 code = code + "#endif\n"
58 return code.strip()
60 def generate_struct(struct):
61 packed = ""
62 if ('packed' in struct.keys() and struct['packed']):
63 packed = "__attribute__ ((packed)) "
64 code = "typedef struct %s {\n" % struct['name']
65 for i in range(len(struct['members'])):
66 member = struct['members'][i]
67 if 'elements' in member.keys():
68 code = code + "\t%s %s[%d];\n" % (member['type'], member['name'], member['elements'])
69 else:
70 code = code + "\t%s %s;\n" % (member['type'], member['name'])
71 code = code + "} %s%s_t;" % (packed, struct['name'])
72 return code
74 def generate_probes(struct):
75 code = ""
76 for i in range(len(struct['members'])):
77 member = struct['members'][i]
78 code = code + ("\temit_constant(%s_OFFSET_%s, offsetof(%s_t, %s));\n" %
79 (struct['name'].upper(), member['name'].upper(), struct['name'],
80 member['name']))
81 code = code + ("\temit_constant(%s_SIZE_%s, sizeof(((%s_t *) 0)->%s));\n" %
82 (struct['name'].upper(), member['name'].upper(), struct['name'],
83 member['name']))
84 if 'elements' in member.keys():
85 code = code + ("\temit_constant(%s_%s_ITEM_SIZE, sizeof(%s));\n" %
86 (struct['name'].upper(), member['name'].upper(), member['type']))
88 return code
90 def probe(struct):
91 name = struct['name']
92 typename = struct['name'] + "_t"
94 code = """
97 #define str(s) #s
98 #define emit_constant(n, v) \
99 asm volatile ("EMITTED_CONSTANT " str(n) \" = %%0\" :: \"i\" (v))
100 #undef offsetof
101 #define offsetof(t, m) ((size_t) &(((t *) 0)->m))
105 extern int main(int, char *[]);
107 int main(int argc, char *argv[])
110 emit_constant(%s_SIZE, sizeof(%s));
111 return 0;
113 """ % (generate_includes(struct), generate_struct(struct),
114 generate_probes(struct), name.upper(), typename)
116 return code
118 def generate_defines(pairs):
119 code = ""
120 for pair in pairs:
121 code = code + "#define %s %s\n" % (pair[0], pair[1])
122 return code.strip()
124 def generate(struct, lines):
125 code = """
126 /*****************************************************************************
127 * AUTO-GENERATED FILE, DO NOT EDIT!!!
128 * Generated by: tools/autogen.py
129 * Generated from: %s
130 *****************************************************************************/
132 #ifndef AUTOGEN_%s_H
133 #define AUTOGEN_%s_H
135 #ifndef __ASM__
137 #endif
141 #ifndef __ASM__
143 #endif
145 #endif
146 """ % (sys.argv[2], struct['name'].upper(), struct['name'].upper(),
147 generate_includes(struct), generate_defines(lines),
148 generate_struct(struct))
150 return code
152 def filter_pairs(lines):
153 pattern = re.compile("^\tEMITTED_CONSTANT ([A-Z_][A-Z0-9_]*) = (\$|#)?([0-9]+)$");
154 pairs = []
155 for line in lines:
156 res = pattern.match(line)
157 if res == None:
158 continue
159 pairs = pairs + [res.group(1, 3)]
160 return pairs
163 def run():
164 if len(sys.argv) != 3:
165 usage()
167 with open(sys.argv[2], "rb") as fp:
168 struct = yaml.load(fp)
170 if sys.argv[1] == "depend":
171 deps = depend(struct)
172 print(deps)
173 elif sys.argv[1] == "probe":
174 code = probe(struct)
175 print(code)
176 elif sys.argv[1] == "generate":
177 lines = sys.stdin.readlines()
178 pairs = filter_pairs(lines)
179 code = generate(struct, pairs)
180 print(code)
181 else:
182 usage()
184 run()