Initial packaging for Tizen
[profile/ivi/gobject-introspection.git] / tests / offsets / gen-gitestoffsets
1 #!/bin/env python
2 # -*- Mode: Python -*-
3 # GObject-Introspection - a framework for introspecting GObject libraries
4 # Copyright (C) 2008  Red Hat, Inc.
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 # 02110-1301, USA.
20 #
21
22 # The idea here is that we want to compare offset information two ways:
23 #
24 #  1) As generated by the compiler
25 #  2) As found in the typelib
26 #
27 # So we find all the structures in the input file (offsets.h), parse out
28 # fields within the structure and generate code that outputs the field
29 # offsets using G_STRUCT_OFFSET() to one file and the field offsets using
30 # the typelib to the another file. We can then diff the two files to see
31 # if they are the same
32
33 import re
34 import sys
35
36 if len(sys.argv) != 2:
37     print >>sys.stderr, "Usage: gen-gitestoffsets INPUT > OUTPUT"
38     sys.exit(1)
39
40 # Helper function that we use to generate source. It does substitions
41 # from a dictionary, removes white space at the ends and removes a
42 # leading '|' from each line
43 STRIP_AROUND_RE = re.compile("^[ \t]*\n?(.*?)[ \t]*$", re.DOTALL)
44 STRIP_LEADER_RE = re.compile("^\|", re.MULTILINE)
45 def output(args, format):
46     format = STRIP_AROUND_RE.sub(r"\1", format)
47     format = STRIP_LEADER_RE.sub(r"", format)
48     sys.stdout.write(format % args)
49
50 #
51 # Some regular expressions we use when parsing
52 #
53 TOKEN = "(?:[A-Za-z_][A-Za-z_0-9]+)"
54
55 def compile_re(expr):
56     expr = expr.replace("TOKEN", TOKEN)
57     return re.compile(expr, re.VERBOSE)
58
59 COMMENT_RE = compile_re("/\*([^*]+|\*[^/])*\*/")
60 STRUCT_DEF_RE = compile_re("struct\s+_(TOKEN)\s*{([^}]*)}")
61
62 # This certainly can't handle all type declarations, but it only
63 # needs to handle the ones we use in the test cases
64 FIELD_RE = compile_re(r"^(?:const\s+)?TOKEN(?:[\s*]+)(TOKEN)\s*(?:\[([0-9]*)\])?\s*;$")
65
66
67 input_f = open(sys.argv[1])
68 input = input_f.read()
69 input_f.close()
70
71 # Strip comments
72 input = COMMENT_RE.sub("", input)
73
74 symbols = []
75 symbol_fields = {}
76
77 for m in STRUCT_DEF_RE.finditer(input):
78     symbol = m.group(1)
79
80     fields = []
81
82     body = m.group(2)
83     for line in re.split("\n|\r\n", body):
84         line = line.strip()
85         if line == "":
86             continue
87         n = FIELD_RE.match(line)
88         if not n:
89             print sys.stderr, "Can't parse structure line '%s'" % line
90             sys.exit(1)
91         fields.append(n.group(1))
92
93     symbols.append(symbol)
94     symbol_fields[symbol] = fields
95
96 # Sort for convenience
97 symbols.sort()
98
99 output({}, r'''
100 | /* GENERATED FILE. DO NOT EDIT. See gen-gitestoffsets */
101 |
102 |#include <errno.h>
103 |#include <stdio.h>
104 |#include <string.h>
105 |#include <glib.h>
106 |#include <girepository.h>
107 |#include "offsets.h"
108 |
109 |static GIRepository *repository;
110 |static const char *namespace = "Offsets";
111 |static const char *version = "1.0";
112 |
113 |static void
114 |print_field_offset(FILE         *outfile,
115 |                   GIStructInfo *struct_info,
116 |                   const gchar  *name)
117 |{
118 |   gint i;
119 |   gint n_fields = g_struct_info_get_n_fields (struct_info);
120 |   for (i = 0; i < n_fields; i++)
121 |     {
122 |       GIFieldInfo *field_info = g_struct_info_get_field (struct_info, i);
123 |       const char *field_name = g_base_info_get_name ((GIBaseInfo *)field_info);
124 |       if (strcmp (field_name, name) == 0)
125 |         {
126 |           fprintf (outfile, "%%s %%d\n", name, g_field_info_get_offset (field_info));
127 |           g_base_info_unref ((GIBaseInfo *)field_info);
128 |           return;
129 |         }
130 |
131 |       g_base_info_unref ((GIBaseInfo *)field_info);
132 |     }
133 |
134 |   g_error("Can't find field '%%s.%%s' in introspection information",
135 |           g_base_info_get_name ((GIBaseInfo *)struct_info), name);
136 |}
137 |
138 ''')
139
140 for symbol in symbols:
141     fields = symbol_fields[symbol]
142
143     output({'symbol' : symbol}, r'''
144 |typedef struct {
145 |   char dummy;
146 |   %(symbol)s struct_;
147 |} Align%(symbol)s;
148 |
149 |static void
150 |compiled_%(symbol)s (FILE *outfile)
151 |{
152 |  fprintf (outfile, "%(symbol)s: size=%%" G_GSIZE_FORMAT ", alignment=%%ld\n",
153 |           sizeof(%(symbol)s),
154 |           G_STRUCT_OFFSET(Align%(symbol)s, struct_));
155 |
156            ''')
157
158     for field in fields:
159         output({ 'field' : field, 'symbol' : symbol }, r'''
160 |  fprintf (outfile, "%%s %%ld\n", "%(field)s", G_STRUCT_OFFSET(%(symbol)s, %(field)s));
161                ''')
162
163     output({}, r'''
164 |
165 |  fprintf (outfile, "\n");
166 |}
167 |
168            ''')
169
170     if not symbol.startswith("Offsets"):
171         print >> sys.stderr, "Symbol '%s' doesn't start with Offsets" % symbol
172     bare_symbol = symbol[len("Offsets"):]
173
174
175     output({'symbol' : symbol, 'bare_symbol' : bare_symbol}, r'''
176 |static void
177 |introspected_%(symbol)s (FILE *outfile)
178 |{
179 |  GIStructInfo *struct_info = (GIStructInfo *)g_irepository_find_by_name(repository, namespace,
180 |                                                                         "%(bare_symbol)s");
181 |  if (!struct_info)
182 |     g_error ("Can't find GIStructInfo for '%(symbol)s'");
183 |
184 |  fprintf (outfile, "%(symbol)s: size=%%" G_GSIZE_FORMAT ", alignment=%%" G_GSIZE_FORMAT "\n",
185 |           g_struct_info_get_size (struct_info),
186 |           g_struct_info_get_alignment (struct_info));
187 |
188            ''')
189     for field in fields:
190         output({'field' : field}, '''
191 |  print_field_offset(outfile, struct_info, "%(field)s");
192                ''')
193
194     output({}, r'''
195 |
196 |  fprintf (outfile, "\n");
197 |
198 |  g_base_info_unref ((GIBaseInfo *)struct_info);
199 |}
200            ''')
201
202 output({}, r'''
203 |
204 |int main(int argc, char **argv)
205 |{
206 |  GError *error = NULL;
207 |  FILE *outfile;
208 |
209 |  if (argc != 3)
210 |    g_error ("Usage: gitestoffsets COMPILED_OFFSETS_FILE INTROSPECTED_OFFSETS_FILE");
211 |
212 |  g_type_init ();
213 |
214 |  repository = g_irepository_get_default ();
215 |  if (!g_irepository_require (repository, namespace, version, 0, &error))
216 |     g_error ("Failed to load %%s-%%s.typelib: %%s", namespace, version, error->message);
217 |
218 |  outfile = fopen (argv[1], "w");
219 |  if (!outfile)
220 |    g_error ("Cannot open '%%s': %%s'", argv[1], g_strerror(errno));
221 |
222 ''')
223
224 for symbol in symbols:
225     output({'symbol' : symbol}, '''
226 |  compiled_%(symbol)s (outfile);
227    ''')
228
229 output({}, '''
230 |
231 |  fclose (outfile);
232 |
233 |  outfile = fopen (argv[2], "w");
234 |  if (!outfile)
235 |    g_error ("Cannot open '%%s': %%s'", argv[1], g_strerror(errno));
236 |
237 ''')
238
239
240 for symbol in symbols:
241     output({'symbol' : symbol}, '''
242 |  introspected_%(symbol)s (outfile);
243 ''')
244
245 output({}, r'''
246 |
247 |  fclose (outfile);
248 |
249 |  return 0;
250 }
251 ''')