1#  This file is part of darktable,
2#  copyright (c) 2013-2020 tobias ellinghaus.
3#
4#  darktable is free software: you can redistribute it and/or modify
5#  it under the terms of the GNU General Public License as published by
6#  the Free Software Foundation, either version 3 of the License, or
7#  (at your option) any later version.
8#
9#  darktable is distributed in the hope that it will be useful,
10#  but WITHOUT ANY WARRANTY; without even the implied warranty of
11#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12#  GNU General Public License for more details.
13#
14#  You should have received a copy of the GNU General Public License
15#  along with darktable.  If not, see <http://www.gnu.org/licenses/>.
16
17use ast;
18
19package code_gen;
20
21my $DT_INTROSPECTION_VERSION = 8;
22
23my $is_old_gplusplus = "defined(__cplusplus) && !defined(__clang__) && defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) <= 406)";
24my $is_not_old_gplusplus = "!( defined(__cplusplus) && !defined(__clang__) && defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) <= 406) )";
25
26sub print_fallback
27{
28  my ($OUT, $input_file, $version, $params_type) = @_;
29
30  print $OUT <<END;
31/*
32 * this code is auto generated. do not edit. change the sources in tools/introspection/ instead.
33 * there were errors when generating this code. giving up
34 */
35#warning "could not generate introspection for $input_file"
36
37#include "$input_file"
38
39#ifdef __cplusplus
40extern "C"
41{
42#endif
43
44#include "common/introspection.h"
45
46static dt_introspection_field_t introspection_linear[2]
47#if $is_not_old_gplusplus
48= {
49  { .Opaque = { {DT_INTROSPECTION_TYPE_OPAQUE, (char*)"", (char*)"", (char*)"", (char*)"", sizeof($params_type), 0, NULL}, } },
50  { .header = {DT_INTROSPECTION_TYPE_NONE, NULL, NULL, NULL, NULL, 0, 0, NULL} }
51}
52#endif
53;
54
55
56static dt_introspection_t introspection = {
57  $DT_INTROSPECTION_VERSION,
58  $version,
59  "$params_type",
60  sizeof($params_type),
61  &introspection_linear[0],
62  sizeof(dt_iop_module_t),
63  G_STRUCT_OFFSET(dt_iop_module_t, default_params)
64};
65
66dt_introspection_field_t* get_introspection_linear()
67{
68  return introspection_linear;
69}
70
71dt_introspection_t* get_introspection()
72{
73  return &introspection;
74}
75
76int introspection_init(struct dt_iop_module_so_t *self, int api_version)
77{
78  // here we check that the generated code matches the api at compile time and also at runtime
79  if(introspection.api_version != DT_INTROSPECTION_VERSION || api_version != DT_INTROSPECTION_VERSION)
80    return 1;
81
82#if $is_old_gplusplus
83  introspection_linear[0].Opaque = { {DT_INTROSPECTION_TYPE_OPAQUE, (char*)"", (char*)"", (char*)"", sizeof($params_type), 0, NULL}, };
84  introspection_linear[1].header = {DT_INTROSPECTION_TYPE_NONE, NULL, NULL, NULL, NULL, 0, 0, NULL};
85#endif
86
87  for(int i = 0; i <= 1; i++)
88    introspection_linear[i].header.so = self;
89
90  return 0;
91}
92
93void * get_p(const void * param, const char * name)
94{
95  return NULL;
96}
97
98dt_introspection_field_t * get_f(const char * name)
99{
100  return NULL;
101}
102
103#ifdef __cplusplus
104}
105#endif
106
107END
108
109}
110
111sub print_code
112{
113  my ($OUT, $root, $input_file, $version, $params_type) = @_;
114
115  # in our model we want the params to be a typedef of a struct
116  return 0 if(ref $root ne "ast_typedef_node");
117  my $start_node = $root->{type};
118  return 0 if(ref $start_node ne "ast_type_struct_node");
119
120  # collect data from the ast
121  $root->get_introspection_code("", $params_type);
122
123  my $max_linear = @ast::linear;
124
125  # print c code
126  print $OUT <<END;
127/*
128 * this code is auto generated. do not edit. change the sources in tools/introspection/ instead.
129 *
130 * the parse tree:
131 *
132END
133  ast::print_tree($OUT, $root, " * ");
134  print $OUT <<END;
135 *
136 */
137
138#include "$input_file"
139
140#ifdef __cplusplus
141extern "C"
142{
143#endif
144
145#include <string.h>
146#include "common/introspection.h"
147
148static dt_introspection_field_t introspection_linear[$max_linear+1]
149#if $is_not_old_gplusplus
150= {
151END
152
153  foreach(@ast::linear)
154  {
155    print $OUT "{\n  $_\n},\n";
156  }
157  print $OUT <<END;
158  { .header = {DT_INTROSPECTION_TYPE_NONE, NULL, NULL, NULL, NULL, 0, 0, NULL} }
159}
160#endif
161;
162
163static dt_introspection_t introspection = {
164  $DT_INTROSPECTION_VERSION,
165  $version,
166  "$params_type",
167  sizeof($params_type),
168  &introspection_linear[$max_linear-1],
169  sizeof(dt_iop_module_t),
170  G_STRUCT_OFFSET(dt_iop_module_t, default_params)
171};
172
173dt_introspection_field_t* get_introspection_linear()
174{
175  return introspection_linear;
176}
177
178dt_introspection_t* get_introspection()
179{
180  return &introspection;
181}
182
183int introspection_init(struct dt_iop_module_so_t *self, int api_version)
184{
185  // here we check that the generated code matches the api at compile time and also at runtime
186  if(introspection.api_version != DT_INTROSPECTION_VERSION || api_version != DT_INTROSPECTION_VERSION)
187    return 1;
188
189#if $is_old_gplusplus
190END
191  my $i = 0;
192  foreach(@ast::linear)
193  {
194    print $OUT "  introspection_linear[$i]$_;\n";
195    $i++;
196  }
197  print $OUT <<END;
198  introspection_linear[$max_linear].header = {DT_INTROSPECTION_TYPE_NONE, NULL, NULL, NULL, NULL, 0, 0, NULL};
199#endif
200
201  for(int i = 0; i <= $max_linear; i++)
202    introspection_linear[i].header.so = self;
203
204END
205
206  foreach(@ast::arrays)
207  {
208    print $OUT "  $_\n";
209  }
210  print $OUT "\n";
211
212  foreach(@ast::assignments)
213  {
214    print $OUT "  $_\n";
215  }
216
217  print $OUT <<END;
218
219  return 0;
220}
221
222void * get_p(const void * param, const char * name)
223{
224  $params_type * p = ($params_type*)param;
225END
226  print $OUT " ";
227  foreach(@ast::varnames)
228  {
229    print $OUT " if(!strcmp(name, \"@$_[1]\"))\n    return &(p->@$_[1]);\n  else";
230  }
231  print $OUT <<END;
232
233    return NULL;
234}
235
236dt_introspection_field_t * get_f(const char * name)
237{
238END
239  print $OUT " ";
240  foreach(@ast::varnames)
241  {
242    print $OUT " if(!strcmp(name, \"@$_[1]\"))\n    return &(introspection_linear[@$_[0]]);\n  else";
243  }
244  print $OUT <<END;
245
246    return NULL;
247}
248
249#ifdef __cplusplus
250}
251#endif
252
253END
254  return 1;
255}
256
2571;
258
259# modelines: These editor modelines have been set for all relevant files by tools/update_modelines.sh
260# vim: shiftwidth=2 expandtab tabstop=2 cindent
261# kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-space on;
262