| 1 | #!/usr/bin/perl |
|---|
| 2 | # (c)2011 Broadcom Corporation |
|---|
| 3 | # |
|---|
| 4 | # This program is the proprietary software of Broadcom Corporation and/or its licensors, |
|---|
| 5 | # and may only be used, duplicated, modified or distributed pursuant to the terms and |
|---|
| 6 | # conditions of a separate, written license agreement executed between you and Broadcom |
|---|
| 7 | # (an "Authorized License"). Except as set forth in an Authorized License, Broadcom grants |
|---|
| 8 | # no license (express or implied), right to use, or waiver of any kind with respect to the |
|---|
| 9 | # Software, and Broadcom expressly reserves all rights in and to the Software and all |
|---|
| 10 | # intellectual property rights therein. IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU |
|---|
| 11 | # HAVE NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY |
|---|
| 12 | # NOTIFY BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE. |
|---|
| 13 | # |
|---|
| 14 | # Except as expressly set forth in the Authorized License, |
|---|
| 15 | # |
|---|
| 16 | # 1. This program, including its structure, sequence and organization, constitutes the valuable trade |
|---|
| 17 | # secrets of Broadcom, and you shall use all reasonable efforts to protect the confidentiality thereof, |
|---|
| 18 | # and to use this information only in connection with your use of Broadcom integrated circuit products. |
|---|
| 19 | # |
|---|
| 20 | # 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" |
|---|
| 21 | # AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR |
|---|
| 22 | # WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO |
|---|
| 23 | # THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND ALL IMPLIED WARRANTIES |
|---|
| 24 | # OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, |
|---|
| 25 | # LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION |
|---|
| 26 | # OR CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF |
|---|
| 27 | # USE OR PERFORMANCE OF THE SOFTWARE. |
|---|
| 28 | # |
|---|
| 29 | # 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR ITS |
|---|
| 30 | # LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT, OR |
|---|
| 31 | # EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY WAY RELATING TO YOUR |
|---|
| 32 | # USE OF OR INABILITY TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF |
|---|
| 33 | # THE POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT |
|---|
| 34 | # ACTUALLY PAID FOR THE SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE |
|---|
| 35 | # LIMITATIONS SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF |
|---|
| 36 | # ANY LIMITED REMEDY. |
|---|
| 37 | # |
|---|
| 38 | # $brcm_Workfile: bipc_build.pl $ |
|---|
| 39 | # $brcm_Revision: 2 $ |
|---|
| 40 | # $brcm_Date: 10/28/11 2:04p $ |
|---|
| 41 | # |
|---|
| 42 | # File Description: |
|---|
| 43 | # |
|---|
| 44 | # Revision History: |
|---|
| 45 | # |
|---|
| 46 | # $brcm_Log: /nexus/lib/ipc/build/bipc_build.pl $ |
|---|
| 47 | # |
|---|
| 48 | # 2 10/28/11 2:04p erickson |
|---|
| 49 | # SW7425-1364: add typecasts for C++ compilers |
|---|
| 50 | # |
|---|
| 51 | # 1 10/4/11 5:44p vsilyaev |
|---|
| 52 | # SW7425-1364: Reference applicaion IPC and reference server |
|---|
| 53 | # |
|---|
| 54 | ############################################################################# |
|---|
| 55 | use strict; |
|---|
| 56 | |
|---|
| 57 | use bapi_parse_c; |
|---|
| 58 | my $file; |
|---|
| 59 | my @funcs; |
|---|
| 60 | my %structs; |
|---|
| 61 | |
|---|
| 62 | if ($#ARGV == -1) { |
|---|
| 63 | print "Usage: perl bipc_build.pl file1.h file2.h ...\n"; |
|---|
| 64 | exit -1; |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | |
|---|
| 68 | |
|---|
| 69 | sub is_handle |
|---|
| 70 | { |
|---|
| 71 | my $type = shift; |
|---|
| 72 | ($type =~ /_Handle$/ || $type =~ /_t$/); |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | sub parse_func |
|---|
| 76 | { |
|---|
| 77 | my $prototype = shift; |
|---|
| 78 | my %func; |
|---|
| 79 | my $more; |
|---|
| 80 | my @params; # this is a list of a param hash |
|---|
| 81 | |
|---|
| 82 | # comment out the attr hint int the actual prototype |
|---|
| 83 | my $actual_prototype = $prototype; |
|---|
| 84 | $actual_prototype =~ s/(attr{.+?})/\/* $1 *\//sg; |
|---|
| 85 | $func{PROTOTYPE} = $actual_prototype; |
|---|
| 86 | # print "'$actual_prototype'\n"; |
|---|
| 87 | |
|---|
| 88 | |
|---|
| 89 | ($func{RETTYPE}, $more) = $prototype =~ /(.*?)\s*([\s*\*])\w+\s*\(/; |
|---|
| 90 | if ($more eq "*") { |
|---|
| 91 | $func{RETTYPE} .= $more; |
|---|
| 92 | } |
|---|
| 93 | $func{RETTYPE_ISHANDLE} = is_handle $func{RETTYPE}; |
|---|
| 94 | ($func{FUNCNAME}) = $prototype =~ /(\w+)\s*\(/; |
|---|
| 95 | |
|---|
| 96 | # get the params into a raw list |
|---|
| 97 | $prototype =~ /\(\s*(attr{(.+?)})?(.*?)\)$/s; |
|---|
| 98 | my $params=$3; |
|---|
| 99 | if(defined $2) { |
|---|
| 100 | $func{ATTR} = parse_attr $2; |
|---|
| 101 | } |
|---|
| 102 | if ($params eq "void") { |
|---|
| 103 | $params = undef; |
|---|
| 104 | } |
|---|
| 105 | my @rawparams = split /,/, $params; |
|---|
| 106 | my $p; |
|---|
| 107 | |
|---|
| 108 | for $p (@rawparams) { |
|---|
| 109 | my %paramhash; |
|---|
| 110 | |
|---|
| 111 | # See if we have a attr hint and grab it now |
|---|
| 112 | # This also removes that hint from the variable |
|---|
| 113 | if ($p =~ s/attr{(.+?)}//) { |
|---|
| 114 | # print "$func{FUNCNAME} attr = $1\n"; |
|---|
| 115 | $paramhash{ATTR} = parse_attr $1; |
|---|
| 116 | } |
|---|
| 117 | |
|---|
| 118 | # parse type and name |
|---|
| 119 | my ($type, $name) = $p =~ /(\w[\w\s]*[\s\*]+)(\w+)/; |
|---|
| 120 | # strip leading and trailing whitespace |
|---|
| 121 | $type =~ s/^\s*(.*?)\s*$/$1/; |
|---|
| 122 | |
|---|
| 123 | $paramhash{NAME} = $name; |
|---|
| 124 | $paramhash{TYPE} = $type; |
|---|
| 125 | # a pointer in the type means the data is passed by reference |
|---|
| 126 | $paramhash{ISREF} = ($type =~ /\*\s*$/); |
|---|
| 127 | |
|---|
| 128 | if ($paramhash{ISREF}) { |
|---|
| 129 | # a const pointer is assumed to be an input parameter, |
|---|
| 130 | # note that "const void **" is parsed as a non-const pointer to "const void *", so it's out |
|---|
| 131 | # nexus does not parse [out] |
|---|
| 132 | $paramhash{INPARAM} = ($type =~ /^\s*const/) && !($type =~ /\*\s*\*/); |
|---|
| 133 | if ($paramhash{INPARAM}) { |
|---|
| 134 | ($paramhash{BASETYPE}) = ($type =~ /^\s*const\s*(.*?)\s*\*\s*$/); |
|---|
| 135 | } |
|---|
| 136 | else { |
|---|
| 137 | ($paramhash{BASETYPE}) = ($type =~ /^\s*(.*?)\s*\*\s*$/); |
|---|
| 138 | |
|---|
| 139 | # non-const void* params w/ attr{nelem_out} are out params, otherwise they are actually in params |
|---|
| 140 | if ($paramhash{BASETYPE} eq 'void' && !defined $paramhash{ATTR}->{'nelem_out'}) { |
|---|
| 141 | $paramhash{INPARAM} = 1; |
|---|
| 142 | } |
|---|
| 143 | } |
|---|
| 144 | } |
|---|
| 145 | else { |
|---|
| 146 | # if not by-reference, then by-value, which is always in in param |
|---|
| 147 | $paramhash{INPARAM} = 1; |
|---|
| 148 | } |
|---|
| 149 | push @params, \%paramhash; |
|---|
| 150 | } |
|---|
| 151 | $func{PARAMS} = \@params; |
|---|
| 152 | |
|---|
| 153 | # Return a reference to the func hash |
|---|
| 154 | return \%func; |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | sub parse_funcs |
|---|
| 158 | { |
|---|
| 159 | my $func; |
|---|
| 160 | my @funcrefs; |
|---|
| 161 | for $func (@_) { |
|---|
| 162 | my $funcref = parse_func $func; |
|---|
| 163 | |
|---|
| 164 | push @funcrefs, $funcref; |
|---|
| 165 | } |
|---|
| 166 | @funcrefs; |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | #use Data::Dumper; |
|---|
| 170 | |
|---|
| 171 | sub group_api |
|---|
| 172 | { |
|---|
| 173 | my $func; |
|---|
| 174 | my %classes; |
|---|
| 175 | |
|---|
| 176 | for $func (@_) { |
|---|
| 177 | my $name = $func->{FUNCNAME}; |
|---|
| 178 | if( ($name =~ /^(\w+)_create$/) || ($name =~ /^(\w+)_Create$/) || ($name =~ /^(\w+)_open$/) || ($name =~ /^(\w+)_Open$/)) { |
|---|
| 179 | my %class; |
|---|
| 180 | my $name = $1; |
|---|
| 181 | if($func->{RETTYPE_ISHANDLE} && ($func->{RETTYPE} =~ /^(\w+)_Handle/ || $func->{RETTYPE} =~ /^(\w+)_t/)) { |
|---|
| 182 | $class{NAME} = $name; |
|---|
| 183 | $class{TYPE} = $1; |
|---|
| 184 | $class{CONSTRUCTOR} = $func; |
|---|
| 185 | $classes{$name} = \%class; |
|---|
| 186 | } else { |
|---|
| 187 | die "Invalid constructor $func->{PROTOTYPE}"; |
|---|
| 188 | } |
|---|
| 189 | } |
|---|
| 190 | } |
|---|
| 191 | for $func (@_) { |
|---|
| 192 | my $name = $func->{FUNCNAME}; |
|---|
| 193 | my $classname; |
|---|
| 194 | for $classname (keys %classes) { |
|---|
| 195 | if($name =~ /^${classname}_(\w+)$/) { |
|---|
| 196 | my $method = lc $1; |
|---|
| 197 | my $class = $classes{$classname}; |
|---|
| 198 | next if $name eq $class->{CONSTRUCTOR}->{FUNCNAME}; |
|---|
| 199 | if($method eq 'close' || $method eq 'destroy') { |
|---|
| 200 | $class->{DESTRUCTOR} = $func; |
|---|
| 201 | } else { |
|---|
| 202 | my $methods = $class->{METHODS}; |
|---|
| 203 | push @$methods, $func; |
|---|
| 204 | $class->{METHODS} = $methods; |
|---|
| 205 | } |
|---|
| 206 | } |
|---|
| 207 | } |
|---|
| 208 | } |
|---|
| 209 | # print Dumper(\%classes); |
|---|
| 210 | return \%classes; |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | sub append_code { |
|---|
| 214 | my $dest = shift; |
|---|
| 215 | my $code = shift; |
|---|
| 216 | my $ident = shift; |
|---|
| 217 | |
|---|
| 218 | for(@$code) { |
|---|
| 219 | push @$dest, "$ident$_"; |
|---|
| 220 | } |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | sub print_code |
|---|
| 224 | { |
|---|
| 225 | my $file = shift; |
|---|
| 226 | my $code = shift; |
|---|
| 227 | my $ident = shift; |
|---|
| 228 | |
|---|
| 229 | if(defined $code) { |
|---|
| 230 | for(@$code) { |
|---|
| 231 | print $file "$ident$_\n"; |
|---|
| 232 | } |
|---|
| 233 | } |
|---|
| 234 | } |
|---|
| 235 | sub append_structure { |
|---|
| 236 | my $dest = shift; |
|---|
| 237 | my $name = shift; |
|---|
| 238 | my $code = shift; |
|---|
| 239 | |
|---|
| 240 | if(scalar @$code) { |
|---|
| 241 | push @$dest, "struct {"; |
|---|
| 242 | append_code $dest,$code," "; |
|---|
| 243 | push @$dest, "} $name;"; |
|---|
| 244 | } |
|---|
| 245 | } |
|---|
| 246 | |
|---|
| 247 | my $ipc_field = "_b_ipc_id"; |
|---|
| 248 | my $ipc_data = "_b_ipc_data"; |
|---|
| 249 | my $ipc_result = "_b_ipc_result"; |
|---|
| 250 | |
|---|
| 251 | sub process_function_args { |
|---|
| 252 | my $ipc = shift; |
|---|
| 253 | my $class = shift; |
|---|
| 254 | my $func = shift; |
|---|
| 255 | my $type = shift; |
|---|
| 256 | my @data_in; |
|---|
| 257 | my @data_out; |
|---|
| 258 | my @server_args; |
|---|
| 259 | my @client_in; |
|---|
| 260 | my @client_out; |
|---|
| 261 | my $params = $func->{PARAMS}; |
|---|
| 262 | my $param; |
|---|
| 263 | my $data = "$ipc_data -> $func->{FUNCNAME}"; |
|---|
| 264 | my $cnt = 0; |
|---|
| 265 | for $param (@$params) { |
|---|
| 266 | if($cnt == 0) { |
|---|
| 267 | push @server_args, "* $ipc_field"; |
|---|
| 268 | if( $type eq 'CONSTRUCTOR') { |
|---|
| 269 | die "Invalid constructor $func->{PROTOTYPE}" unless $param->{TYPE} eq 'bipc_t'; |
|---|
| 270 | push @data_in, "bipc_interface_descriptor $ipc_field;"; |
|---|
| 271 | push @data_out, "unsigned $ipc_result;"; |
|---|
| 272 | push @client_in, "$data . in. $ipc_field = bipc_${class}_descriptor;"; |
|---|
| 273 | push @client_out, "$ipc_result -> id = $data . out. $ipc_result;"; |
|---|
| 274 | } else { |
|---|
| 275 | die "Invalid function $func->{PROTOTYPE}" unless is_handle $param->{TYPE}; |
|---|
| 276 | } |
|---|
| 277 | } elsif ($param->{ISREF}) { |
|---|
| 278 | if ($param->{INPARAM}) { |
|---|
| 279 | push @server_args, "& $data .in. $param->{NAME}"; |
|---|
| 280 | push @data_in, "$param->{BASETYPE} $param->{NAME};"; |
|---|
| 281 | push @client_in, "$data .in. $param->{NAME} = * $param->{NAME};" |
|---|
| 282 | } else { |
|---|
| 283 | push @server_args, "& $data .out. $param->{NAME}"; |
|---|
| 284 | push @data_out, "$param->{BASETYPE} $param->{NAME};"; |
|---|
| 285 | push @client_out, "* $param->{NAME} = $data . out. $param->{NAME};"; |
|---|
| 286 | } |
|---|
| 287 | } else { |
|---|
| 288 | push @server_args, "$data .in. $param->{NAME}"; |
|---|
| 289 | push @data_in, "$param->{TYPE} $param->{NAME};"; |
|---|
| 290 | push @client_in, "$data .in. $param->{NAME} = $param->{NAME};" |
|---|
| 291 | } |
|---|
| 292 | $cnt++; |
|---|
| 293 | } |
|---|
| 294 | if($func->{RETTYPE} ne 'void' && $type ne 'CONSTRUCTOR') { |
|---|
| 295 | push @data_out, "$func->{RETTYPE} $ipc_result;"; |
|---|
| 296 | push @client_out, "$ipc_result = $data . out. $ipc_result;"; |
|---|
| 297 | } |
|---|
| 298 | if(0 == scalar @data_in) { |
|---|
| 299 | push @data_in, "unsigned _b_ipc_unused;"; |
|---|
| 300 | } |
|---|
| 301 | $ipc->{$func->{FUNCNAME}} = { |
|---|
| 302 | 'SERVER_ARGS' => \@server_args, |
|---|
| 303 | 'DATA_IN' => \@data_in, |
|---|
| 304 | 'DATA_OUT' => \@data_out, |
|---|
| 305 | 'CLIENT_IN' => \@client_in, |
|---|
| 306 | 'CLIENT_OUT' => \@client_out, |
|---|
| 307 | 'TYPE' => $type, |
|---|
| 308 | 'FUNC' => $func |
|---|
| 309 | } |
|---|
| 310 | } |
|---|
| 311 | |
|---|
| 312 | sub make_class_ipc_data |
|---|
| 313 | { |
|---|
| 314 | my %ipc; |
|---|
| 315 | my $class = shift; |
|---|
| 316 | my $name = $class->{NAME}; |
|---|
| 317 | process_function_args \%ipc, $name, $class->{CONSTRUCTOR}, 'CONSTRUCTOR'; |
|---|
| 318 | process_function_args \%ipc, $name, $class->{DESTRUCTOR}, 'DESTRUCTOR'; |
|---|
| 319 | for (@{$class->{METHODS}}) { |
|---|
| 320 | process_function_args \%ipc, $name, $_; |
|---|
| 321 | } |
|---|
| 322 | # print Dumper(\%ipc); |
|---|
| 323 | return \%ipc; |
|---|
| 324 | } |
|---|
| 325 | |
|---|
| 326 | |
|---|
| 327 | |
|---|
| 328 | # Print out the perl datastructure |
|---|
| 329 | #bapi_parse_c::print_api @funcrefs; |
|---|
| 330 | #bapi_parse_c::print_struct \%structs; |
|---|
| 331 | |
|---|
| 332 | |
|---|
| 333 | |
|---|
| 334 | sub send_offset_and_size { |
|---|
| 335 | my $name = shift; |
|---|
| 336 | my $func_ipc = shift; |
|---|
| 337 | my $offset='0'; |
|---|
| 338 | my $size='0'; |
|---|
| 339 | |
|---|
| 340 | if(scalar @{$func_ipc->{CLIENT_OUT}}) { |
|---|
| 341 | $size = " sizeof($ipc_data ->$func_ipc->{FUNC}->{FUNCNAME} . out)"; |
|---|
| 342 | $offset = " offsetof(union b_ipc_${name}_data, $func_ipc->{FUNC}->{FUNCNAME} . out ) - offsetof(union b_ipc_${name}_data, $func_ipc->{FUNC}->{FUNCNAME})"; |
|---|
| 343 | } |
|---|
| 344 | ($offset, $size); |
|---|
| 345 | } |
|---|
| 346 | |
|---|
| 347 | sub make_ipc |
|---|
| 348 | { |
|---|
| 349 | my $classes = shift; |
|---|
| 350 | my $server = shift; |
|---|
| 351 | my $file = shift; |
|---|
| 352 | |
|---|
| 353 | |
|---|
| 354 | open FILE, ">${file}"; |
|---|
| 355 | print FILE "/*********************************\n"; |
|---|
| 356 | print FILE "*\n"; |
|---|
| 357 | print FILE "* This file is autogenerated by the IPC script .\n"; |
|---|
| 358 | print FILE "*\n"; |
|---|
| 359 | |
|---|
| 360 | for (values %$classes) { |
|---|
| 361 | my $f; |
|---|
| 362 | my $ipc = make_class_ipc_data $_; |
|---|
| 363 | my @methods = keys %$ipc; |
|---|
| 364 | my @enums; |
|---|
| 365 | my $name= $_->{NAME}; |
|---|
| 366 | my $constructor = $_->{CONSTRUCTOR}->{FUNCNAME}; |
|---|
| 367 | my $destructor = $_->{DESTRUCTOR}->{FUNCNAME}; |
|---|
| 368 | printf STDOUT "%s IPC $name\n", ($server?"server":"client"); |
|---|
| 369 | if($server) { |
|---|
| 370 | print FILE "* This file contains function that accesse data over the IPC channel and routes execution to local implementation.\n"; |
|---|
| 371 | } else { |
|---|
| 372 | print FILE "* This file contains stub for every API function that intercepts call and routes it the server via IPC channel.\n"; |
|---|
| 373 | } |
|---|
| 374 | print FILE "*\n"; |
|---|
| 375 | print FILE "*********************************/\n"; |
|---|
| 376 | append_code \@enums, \@methods, "\tb_ipc_"; |
|---|
| 377 | print FILE "enum b_ipc_${name}_methods {\n"; |
|---|
| 378 | print FILE join(",\n",sort(@enums)); |
|---|
| 379 | print FILE "\n};\n"; |
|---|
| 380 | print FILE "union b_ipc_${name}_data {\n"; |
|---|
| 381 | for (keys %$ipc) { |
|---|
| 382 | my @data; |
|---|
| 383 | append_structure \@data, "in", $ipc->{$_}->{DATA_IN}; |
|---|
| 384 | append_structure \@data, "out", $ipc->{$_}->{DATA_OUT}; |
|---|
| 385 | print FILE " struct {\n"; |
|---|
| 386 | print_code \*FILE, \@data, " "; |
|---|
| 387 | print FILE " } $_;\n"; |
|---|
| 388 | } |
|---|
| 389 | print FILE "};\n"; |
|---|
| 390 | if(not $server) { |
|---|
| 391 | print FILE "const bipc_interface_descriptor bipc_${name}_descriptor = {\n"; |
|---|
| 392 | print FILE " \"$name\",\n"; |
|---|
| 393 | print FILE " \"$name\",\n"; |
|---|
| 394 | print FILE " sizeof(union b_ipc_${name}_data)\n"; |
|---|
| 395 | print FILE "};\n"; |
|---|
| 396 | print FILE "struct $_->{TYPE} {\n"; |
|---|
| 397 | print FILE " bipc_t ipc;\n"; |
|---|
| 398 | print FILE " unsigned id;\n"; |
|---|
| 399 | print FILE "};\n"; |
|---|
| 400 | print FILE "#include \"bipc_client_priv.h\"\n"; |
|---|
| 401 | print FILE "#include \"bkni.h\"\n"; |
|---|
| 402 | |
|---|
| 403 | # Build client portion |
|---|
| 404 | for (keys %$ipc) { |
|---|
| 405 | my $func_ipc = $ipc->{$_}; |
|---|
| 406 | print FILE "$func_ipc->{FUNC}->{PROTOTYPE}\n\{\n"; |
|---|
| 407 | my $params = $func_ipc->{FUNC}->{PARAMS}; |
|---|
| 408 | my $handle = @$params[0]->{NAME}; |
|---|
| 409 | print FILE " union b_ipc_${name}_data * $ipc_data;\n"; |
|---|
| 410 | if($func_ipc->{FUNC}->{RETTYPE} ne 'void') { |
|---|
| 411 | print FILE " $func_ipc->{FUNC}->{RETTYPE} $ipc_result;\n"; |
|---|
| 412 | if($func_ipc->{FUNC}->{RETTYPE_ISHANDLE}) { |
|---|
| 413 | print FILE " $ipc_result = NULL;\n"; |
|---|
| 414 | } else { |
|---|
| 415 | print FILE " $ipc_result = -1;\n"; |
|---|
| 416 | } |
|---|
| 417 | } |
|---|
| 418 | my $ipc_arg; |
|---|
| 419 | my $ipc_id; |
|---|
| 420 | if($func_ipc->{TYPE} eq 'CONSTRUCTOR') { |
|---|
| 421 | $ipc_arg = $handle; |
|---|
| 422 | $ipc_id = "BIPC_INSTANCE_ID_NEW"; |
|---|
| 423 | print FILE " $ipc_data = (union b_ipc_${name}_data *)bipc_client_begin($ipc_arg, &bipc_${name}_descriptor);\n"; |
|---|
| 424 | } else { |
|---|
| 425 | $ipc_arg = "$handle -> ipc"; |
|---|
| 426 | $ipc_id = "$handle -> id"; |
|---|
| 427 | print FILE " $ipc_data = (union b_ipc_${name}_data *)bipc_client_begin($ipc_arg, NULL);\n"; |
|---|
| 428 | } |
|---|
| 429 | print_code \*FILE, $func_ipc->{CLIENT_IN}, " "; |
|---|
| 430 | my ($send_offset,$send_size) = send_offset_and_size $name, $func_ipc; |
|---|
| 431 | print FILE " if(bipc_client_send($ipc_arg, $ipc_id, b_ipc_$_ , sizeof( $ipc_data ->$func_ipc->{FUNC}->{FUNCNAME} . in ) , $send_offset, $send_size)==0) {\n"; |
|---|
| 432 | if($func_ipc->{TYPE} eq 'CONSTRUCTOR') { |
|---|
| 433 | print FILE " if($ipc_data->$func_ipc->{FUNC}->{FUNCNAME} . out . $ipc_result == BIPC_INSTANCE_ID_NEW) { goto done;}\n"; |
|---|
| 434 | print FILE " $ipc_result = ($func_ipc->{FUNC}->{RETTYPE}) BKNI_Malloc(sizeof( * $ipc_result));\n"; |
|---|
| 435 | print FILE " $ipc_result->ipc = $handle;\n"; |
|---|
| 436 | } |
|---|
| 437 | print_code \*FILE, $func_ipc->{CLIENT_OUT}, " "; |
|---|
| 438 | print FILE " } else {\n"; |
|---|
| 439 | print FILE " }\n"; |
|---|
| 440 | print FILE " goto done;\n"; |
|---|
| 441 | print FILE "done:\n"; |
|---|
| 442 | print FILE " bipc_client_end($ipc_arg);\n"; |
|---|
| 443 | if($func_ipc->{FUNC}->{RETTYPE} ne 'void') { |
|---|
| 444 | print FILE " return $ipc_result;\n"; |
|---|
| 445 | } |
|---|
| 446 | print FILE "}\n"; |
|---|
| 447 | } |
|---|
| 448 | } else { |
|---|
| 449 | # Build server portion |
|---|
| 450 | print FILE "#include \"bipc_server.h\"\n\n"; |
|---|
| 451 | |
|---|
| 452 | |
|---|
| 453 | print FILE "static int b_ipc_${name}_process( void **$ipc_field, unsigned entry, void *buf, size_t recv_size, size_t *send_offset, size_t *send_size)\n"; |
|---|
| 454 | print FILE "{\n"; |
|---|
| 455 | print FILE " int rc=0;\n"; |
|---|
| 456 | print FILE " union b_ipc_${name}_data * $ipc_data = buf;\n"; |
|---|
| 457 | print FILE " switch(entry) {\n"; |
|---|
| 458 | for (keys %$ipc) { |
|---|
| 459 | my $func_ipc = $ipc->{$_}; |
|---|
| 460 | print FILE " case b_ipc_$_:\n"; |
|---|
| 461 | print FILE " if(recv_size == sizeof( $ipc_data ->$func_ipc->{FUNC}->{FUNCNAME} . in )) {\n"; |
|---|
| 462 | my ($send_offset,$send_size) = send_offset_and_size $name, $func_ipc; |
|---|
| 463 | if($func_ipc->{TYPE} eq 'CONSTRUCTOR') { |
|---|
| 464 | print FILE " $func_ipc->{FUNC}->{RETTYPE} $ipc_result = \n"; |
|---|
| 465 | } elsif($func_ipc->{FUNC}->{RETTYPE} ne 'void') { |
|---|
| 466 | print FILE " $ipc_data -> $func_ipc->{FUNC}->{FUNCNAME} .out. $ipc_result = \n"; |
|---|
| 467 | } |
|---|
| 468 | print FILE " $_(\n"; |
|---|
| 469 | print FILE " "; |
|---|
| 470 | print FILE join(",\n ",@{$func_ipc->{SERVER_ARGS}}); |
|---|
| 471 | print FILE "\n );\n"; |
|---|
| 472 | if($func_ipc->{TYPE} eq 'CONSTRUCTOR') { |
|---|
| 473 | print FILE " * $ipc_field = $ipc_result;\n"; |
|---|
| 474 | print FILE " $ipc_data -> $func_ipc->{FUNC}->{FUNCNAME} .out. $ipc_result = $ipc_result!=NULL ? *send_offset : BIPC_INSTANCE_ID_NEW;\n"; |
|---|
| 475 | } |
|---|
| 476 | print FILE " *send_offset = $send_offset;\n"; |
|---|
| 477 | print FILE " *send_size = $send_size;\n"; |
|---|
| 478 | print FILE " } else { \n"; |
|---|
| 479 | print FILE " rc = -1; \n"; |
|---|
| 480 | print FILE " };\n"; |
|---|
| 481 | print FILE " break;\n"; |
|---|
| 482 | } |
|---|
| 483 | print FILE " default:\n"; |
|---|
| 484 | print FILE " rc = -1;\n"; |
|---|
| 485 | print FILE " break;\n"; |
|---|
| 486 | print FILE " }\n"; |
|---|
| 487 | print FILE " return rc;\n"; |
|---|
| 488 | print FILE "}\n"; |
|---|
| 489 | |
|---|
| 490 | print FILE "const bipc_server_descriptor bipc_${name}_server_descriptor = {\n"; |
|---|
| 491 | print FILE " {\n"; |
|---|
| 492 | print FILE " \"$name\",\n"; |
|---|
| 493 | print FILE " \"$name\",\n"; |
|---|
| 494 | print FILE " sizeof(union b_ipc_${name}_data)\n"; |
|---|
| 495 | print FILE " },\n"; |
|---|
| 496 | print FILE " b_ipc_${constructor},\n"; |
|---|
| 497 | print FILE " b_ipc_${destructor},\n"; |
|---|
| 498 | print FILE " b_ipc_${name}_process\n"; |
|---|
| 499 | print FILE "};\n"; |
|---|
| 500 | } |
|---|
| 501 | |
|---|
| 502 | } |
|---|
| 503 | close FILE; |
|---|
| 504 | } |
|---|
| 505 | |
|---|
| 506 | my $server_file = shift @ARGV; |
|---|
| 507 | my $client_file = shift @ARGV; |
|---|
| 508 | |
|---|
| 509 | for $file (@ARGV) { |
|---|
| 510 | push @funcs, bapi_parse_c::get_func_prototypes $file; |
|---|
| 511 | |
|---|
| 512 | my $file_structs = bapi_parse_c::parse_struct $file; |
|---|
| 513 | my $name; |
|---|
| 514 | my $members; |
|---|
| 515 | while (($name, $members) = each %$file_structs) { |
|---|
| 516 | $structs{$name} = $members; |
|---|
| 517 | } |
|---|
| 518 | } |
|---|
| 519 | my @funcrefs = parse_funcs @funcs; |
|---|
| 520 | |
|---|
| 521 | my $classes = group_api @funcrefs; |
|---|
| 522 | |
|---|
| 523 | make_ipc $classes, 1, $server_file; |
|---|
| 524 | make_ipc $classes, 0, $client_file; |
|---|
| 525 | |
|---|