source: svn/newcon3bcm2_21bu/nexus/lib/ipc/build/bipc_build.pl @ 43

Last change on this file since 43 was 43, checked in by megakiss, 11 years ago

광주방송 OTC 주파수 369Mhz로 변경

  • Property svn:executable set to *
File size: 18.9 KB
Line 
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#############################################################################
55use strict;
56
57use bapi_parse_c;
58my $file;
59my @funcs;
60my %structs;
61
62if ($#ARGV == -1) {
63    print "Usage: perl bipc_build.pl file1.h file2.h ...\n";
64    exit -1;
65}
66
67
68
69sub is_handle 
70{
71    my $type = shift;
72    ($type =~ /_Handle$/ || $type =~ /_t$/);
73}
74
75sub 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
157sub 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
171sub 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
213sub 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
223sub 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}
235sub 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
247my $ipc_field = "_b_ipc_id";
248my $ipc_data = "_b_ipc_data";
249my $ipc_result = "_b_ipc_result";
250
251sub 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
312sub 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
334sub 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
347sub 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
506my $server_file = shift @ARGV;
507my $client_file = shift @ARGV;
508
509for $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}
519my @funcrefs = parse_funcs @funcs;
520
521my $classes = group_api @funcrefs;
522
523make_ipc $classes,  1, $server_file;
524make_ipc $classes,  0, $client_file;
525
Note: See TracBrowser for help on using the repository browser.