3 # GObject-Introspection - a framework for introspecting GObject libraries
4 # Copyright (C) 2008 Red Hat, Inc.
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.
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.
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
22 # The idea here is that we want to compare offset information two ways:
24 # 1) As generated by the compiler
25 # 2) As found in the typelib
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
36 if len(sys.argv) != 2:
37 print >>sys.stderr, "Usage: gen-gitestoffsets INPUT > OUTPUT"
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)
51 # Some regular expressions we use when parsing
53 TOKEN = "(?:[A-Za-z_][A-Za-z_0-9]+)"
56 expr = expr.replace("TOKEN", TOKEN)
57 return re.compile(expr, re.VERBOSE)
59 COMMENT_RE = compile_re("/\*([^*]+|\*[^/])*\*/")
60 STRUCT_DEF_RE = compile_re("struct\s+_(TOKEN)\s*{([^}]*)}")
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*;$")
67 input_f = open(sys.argv[1])
68 input = input_f.read()
72 input = COMMENT_RE.sub("", input)
77 for m in STRUCT_DEF_RE.finditer(input):
83 for line in re.split("\n|\r\n", body):
87 n = FIELD_RE.match(line)
89 print sys.stderr, "Can't parse structure line '%s'" % line
91 fields.append(n.group(1))
93 symbols.append(symbol)
94 symbol_fields[symbol] = fields
96 # Sort for convenience
100 | /* GENERATED FILE. DO NOT EDIT. See gen-gitestoffsets */
106 |#include <girepository.h>
107 |#include "offsets.h"
109 |static GIRepository *repository;
110 |static const char *namespace = "Offsets";
111 |static const char *version = "1.0";
114 |print_field_offset(FILE *outfile,
115 | GIStructInfo *struct_info,
119 | gint n_fields = g_struct_info_get_n_fields (struct_info);
120 | for (i = 0; i < n_fields; i++)
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)
126 | fprintf (outfile, "%%s %%d\n", name, g_field_info_get_offset (field_info));
127 | g_base_info_unref ((GIBaseInfo *)field_info);
131 | g_base_info_unref ((GIBaseInfo *)field_info);
134 | g_error("Can't find field '%%s.%%s' in introspection information",
135 | g_base_info_get_name ((GIBaseInfo *)struct_info), name);
140 for symbol in symbols:
141 fields = symbol_fields[symbol]
143 output({'symbol' : symbol}, r'''
146 | %(symbol)s struct_;
150 |compiled_%(symbol)s (FILE *outfile)
152 | fprintf (outfile, "%(symbol)s: size=%%" G_GSIZE_FORMAT ", alignment=%%ld\n",
153 | sizeof(%(symbol)s),
154 | G_STRUCT_OFFSET(Align%(symbol)s, struct_));
159 output({ 'field' : field, 'symbol' : symbol }, r'''
160 | fprintf (outfile, "%%s %%ld\n", "%(field)s", G_STRUCT_OFFSET(%(symbol)s, %(field)s));
165 | fprintf (outfile, "\n");
170 if not symbol.startswith("Offsets"):
171 print >> sys.stderr, "Symbol '%s' doesn't start with Offsets" % symbol
172 bare_symbol = symbol[len("Offsets"):]
175 output({'symbol' : symbol, 'bare_symbol' : bare_symbol}, r'''
177 |introspected_%(symbol)s (FILE *outfile)
179 | GIStructInfo *struct_info = (GIStructInfo *)g_irepository_find_by_name(repository, namespace,
180 | "%(bare_symbol)s");
182 | g_error ("Can't find GIStructInfo for '%(symbol)s'");
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));
190 output({'field' : field}, '''
191 | print_field_offset(outfile, struct_info, "%(field)s");
196 | fprintf (outfile, "\n");
198 | g_base_info_unref ((GIBaseInfo *)struct_info);
204 |int main(int argc, char **argv)
206 | GError *error = NULL;
210 | g_error ("Usage: gitestoffsets COMPILED_OFFSETS_FILE INTROSPECTED_OFFSETS_FILE");
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);
218 | outfile = fopen (argv[1], "w");
220 | g_error ("Cannot open '%%s': %%s'", argv[1], g_strerror(errno));
224 for symbol in symbols:
225 output({'symbol' : symbol}, '''
226 | compiled_%(symbol)s (outfile);
233 | outfile = fopen (argv[2], "w");
235 | g_error ("Cannot open '%%s': %%s'", argv[1], g_strerror(errno));
240 for symbol in symbols:
241 output({'symbol' : symbol}, '''
242 | introspected_%(symbol)s (outfile);