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