source: svn/trunk/newcon3bcm2_21bu/nexus/build/tools/common/bapi_parse_c.pm

Last change on this file was 2, checked in by jglee, 11 years ago

first commit

  • Property svn:executable set to *
File size: 14.8 KB
Line 
1#!/usr/bin/perl
2#     (c)2003-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: bapi_parse_c.pm $
39# $brcm_Revision: 15 $
40# $brcm_Date: 11/4/11 8:54p $
41#
42# File Description:
43#
44# Revision History:
45#
46# $brcm_Log: /nexus/build/tools/common/bapi_parse_c.pm $
47#
48# 15   11/4/11 8:54p bandrews
49# SW7420-1123: whitespace stripping op must come after function attribute
50#  check as it replaces positionals
51#
52# 14   11/4/11 5:14p erickson
53# SW7420-1123: strip whitespace to correctly parse void foo( void )
54#
55# 13   7/28/11 3:08p erickson
56# SW7425-1029: set ISHANDLE and RETTYPE_ISHANDLE for NEXUS_VideoInput,
57#  etc.
58#
59# 12   3/1/11 9:32a erickson
60# SW7420-1123: add naming convention test
61#
62# 11   2/16/11 4:00p erickson
63# SW7420-1507: fix callback registration in Open functions
64#
65# 10   2/15/11 2:24p erickson
66# SW7420-1123: set INPARAM correctly for all PARAMS, clarify that [out]
67#  is not parsed
68#
69# 9   11/4/09 1:07p erickson
70# SW7405-3340: rework regex for parsing functions to allow whitespace
71#  between function name and param list
72#
73# 7   3/13/09 2:07p erickson
74# PR53223: trim multiple spaces between struct member types and names
75#
76# 6   1/31/08 5:02p vsilyaev
77# PR 38682: Added function level attributes
78#
79# 5   1/31/08 12:45p vsilyaev
80# PR 38682: Build proxy for the core module
81#
82# 4   1/29/08 5:55p vsilyaev
83# PR 38682: Support of callbacks in the linux kernel/user proxy
84#  environment
85#
86# 3   1/28/08 12:33p vsilyaev
87# PR 38682: Added support for attribute tags applied to structure
88#  members.
89#
90# 2   1/25/08 2:35p vsilyaev
91# PR 38682: Added handling of 'attr' to the function arguments
92#
93# 1   1/18/08 2:15p jgarrett
94# PR 38808: Merging to main branch
95#
96# Nexus_Devel/2   1/11/08 4:27p vsilyaev
97# PR 38682: Adding kernel support
98#
99# Nexus_Devel/1   9/27/07 1:33p erickson
100# PR35395: initial impl
101#
102# 2   3/15/06 4:51p vsilyaev
103# PR20221: NetIF DMA interface
104#
105# 1   2/7/05 6:56p dlwin
106# Merge down for release 2005_REFSW_MERGETOMAIN:
107#
108# Irvine_BSEAVSW_Devel/4   6/29/04 11:26a erickson
109# PR11135: const void ** is not an out parameter. Take this into account.
110#
111# Irvine_BSEAVSW_Devel/3   6/16/04 5:15p erickson
112# PR11135: added callback support
113#
114# Irvine_BSEAVSW_Devel/2   6/1/04 11:28a erickson
115# PR11135: added support for strings (const char *)
116#
117# Irvine_BSEAVSW_Devel/1   5/17/04 11:13a erickson
118# PR11135: added initial linux proxy impl
119#
120#############################################################################
121use strict;
122
123package bapi_parse_c;
124
125local *FILE;
126
127sub writeDebug
128{
129    print "@_\n";
130}
131
132sub get_file_text
133{
134    my $filename = shift;
135    open FILE, $filename;
136    my $text = join '',<FILE>;
137
138    # pack preprocessor line continutation
139    $text =~ s/\\\s+(\w)/$1/sg;
140    # remove preprocessor stuff that can cause parsing problems
141    $text =~ s/#\w+.*?\n//g;
142
143    # Grab all attr{} hints and move them out of comment
144    # Blow away the comment because it isn't going to stay anyway.
145    $text =~ s/
146        \/\*            # start of a comment
147        [^\/]*           # inside comment
148        (attr{[^}]+})   # keep attr{..}
149        .*?             # rest of stuff
150        \*\/            # end of the comment
151        /$1/sgx;
152
153    # Remove all comments
154    # No nested comments allowed
155    $text =~ s/\/\*.*?\*\///sg;
156
157    return $text;
158}
159
160sub get_func_prototypes
161{
162    my $filename = shift;
163    my $text = get_file_text $filename;
164
165    # If we have any ", attr", reverse the order. Much easier to parse later.
166    $text =~ s/(,)\s*(attr{[^}]+})/ $2$1/sg;
167
168    # Parse functions
169    my @funcs = $text =~ /(
170        \w[\w\s]+   # return type
171        [\s\*]      # whitespace between return type & function name, or * for pointer
172        \w+         # function name
173        \s*         # possible whitespace between function name and param list. this violates coding convention, but should not break the function parsing.
174        \([^\)]*?\)) # parameters. excluding ) avoids detecting "typedef int (*function)(param);" as return type of "typedef" and function name of "int".
175        \s*;        # must terminate with ;
176        /xsg;
177
178    @funcs;
179}
180
181sub checksum
182{
183    my $sum = 0;
184    my $str;
185    for $str (@_) {
186        $sum += unpack("%16C*", $str);
187    }
188    return $sum;
189}
190
191
192# parse_attr
193#
194# parse attributes in the comma separated name=value pairs
195# store result in the hash
196sub parse_attr
197{
198    my $attr = shift;
199    my %attrs;
200
201
202#   print "ATTR -> $attr\n";
203   for(split(';',$attr)) {
204        if (/(\w+)\s*=\s*(\S+)/) {
205             $attrs{$1}=$2;
206#            print "attr '$1' -> '$2'\n";
207        }
208   }
209   return \%attrs;
210}
211
212sub print_attr
213{
214    my $attr = shift;
215    my ($name, $value);
216    if(defined $attr) {
217        print "attr{";
218        while (($name, $value) = each %$attr) {
219            print " $name = $value  ";
220        }
221        print "}\n";
222    }
223}
224
225sub version_attr
226{
227    my $attr = shift;
228    my ($name, $value);
229    my $sum = 0;
230    if(defined $attr) {
231        while (($name, $value) = each %$attr) {
232            $sum += checksum $name, $value;
233        }
234    }
235    $sum;
236}
237
238sub print_struct
239{
240    my $struct = shift;
241    my $name;
242    my $fields;
243    while (($name, $fields) = each %$struct) {
244        my $field;
245        print "structure $name: \n";
246        for $field (@$fields) {
247            print "  field: $field->{TYPE} $field->{NAME}\n";
248            print_attr $field->{ATTR};
249        }
250    }
251}
252
253
254sub parse_struct
255{
256    my $filename = shift;
257    my $text = get_file_text $filename;
258    my %struct;
259
260    while ($text =~  /
261        typedef\s+struct\s+(\w+)\s*{  # typedef
262        (.+?)}                 # body
263        \s*\1                   # termination
264        \s*;                      # must terminate with ;
265        /xgs) {
266        my @params; # this is a list of a param hash
267        my @level; # fields on the current level
268        my $name= $1;
269        my $body = $2;
270#        print "structure $1\n";
271        $struct{$name} = \@params;
272        while($body =~ /(struct\s+{)|(union\s+{)|(}[^;]+;)|((\w[\w\s]*[\s\*]+)(\w+));\s*(attr{([^}]+)})?/sg) {
273
274#            print "'$3' '$5' '$6' '$8'\n";
275            if(defined $5) {
276                my %paramhash;
277                my $type= $5;
278                if(defined $8) {
279                    $paramhash{ATTR} = parse_attr $8;
280                }
281                $paramhash{NAME} = $6;
282                $type =~ s/\s+$//s;
283                $paramhash{TYPE} = $type;
284                push @level, \%paramhash;
285            } elsif (defined $1 || defined $2) {
286                push @params, @level;
287                @level = ();
288            } elsif (defined $3) {
289                my $fields = $3;
290                while($fields =~ /(\w+)/sg) {
291                    # append structure name to each field (note, single level only)
292                    my $name = $1;
293                    my $field;
294                    for $field (@level) {
295                        my %paramhash = %$field; # copy hash
296                        $paramhash{NAME} = "$name.$paramhash{NAME}";
297                        push @params, \%paramhash;
298                    }
299                }
300                @level = ();
301            }
302        }
303        push @params, @level;
304    }
305
306#    print_struct \%struct;
307
308    return \%struct;
309}
310
311sub version_struct
312{
313    my $struct = shift;
314    my $sum = 0;
315    my $name;
316    my $fields;
317    my $field;
318
319    while (($name, $fields) = each %$struct) {
320        $sum += unpack("%32C*", $name);
321        for $field (@$fields) {
322            $sum += checksum $field->{TYPE} , $field->{NAME};
323            $sum += version_attr $field->{ATTR};
324        }
325    }
326    return $sum;
327}
328
329
330
331# parse_func
332#
333# The function data structure is a hash with the following members:
334# PROTOTYPE = string, the original prototype
335# RETTYPE = string, the return type
336# FUNCNAME = string, the function name
337# PARAMS = reference to array of hash references
338#   Each hash reference is a single parameter with the following members:
339#     NAME
340#     TYPE
341#
342# This subroutine returns a reference to the function hash.
343#
344sub parse_func
345{
346    my $prototype = shift;
347    my %func;
348    my $more;
349    my @params; # this is a list of a param hash
350
351    # comment out the attr hint int the actual prototype
352    my $actual_prototype = $prototype;
353    $actual_prototype =~ s/(attr{.+?})/\/* $1 *\//sg;
354    $func{PROTOTYPE} = $actual_prototype;
355#    print "'$actual_prototype'\n";
356
357
358    ($func{RETTYPE}, $more) = $prototype =~ /(.*?)\s*([\s*\*])\w+\s*\(/;
359    if ($more eq "*") {
360        $func{RETTYPE} .= $more;
361    }
362    $func{RETTYPE_ISHANDLE} = ($func{RETTYPE} =~ /Handle$/ ||
363                               $func{RETTYPE} =~ /NEXUS_(Video|Audio)(Input|Output)/
364                               );
365    ($func{FUNCNAME}) = $prototype =~ /(\w+)\s*\(/;
366
367    if (!($func{FUNCNAME} =~ /^NEXUS_\w+$/)) {
368        print "ERROR: $func{FUNCNAME} does not follow coding convention\n";
369    }
370
371    # get the attributes and params into a raw list
372    $prototype =~ /\(\s*(attr{(.+?)})?(.*?)\)$/s;
373    # function attribute check
374    if(defined $2) {
375        $func{ATTR} = parse_attr $2;
376    }
377    my $params=$3;
378    # strip whitespace
379    $params =~ s/^\s*(.*?)\s*$/$1/;
380    if ($params eq "void") {
381        $params = undef;
382    }
383    my @rawparams = split /,/, $params;
384    my $p;
385
386    for $p (@rawparams) {
387        my %paramhash;
388
389        # See if we have a attr hint and grab it now
390        # This also removes that hint from the variable
391        if ($p =~ s/attr{(.+?)}//) {
392#            print "$func{FUNCNAME} attr = $1\n";
393            $paramhash{ATTR} = parse_attr $1;
394        }
395
396        # parse type and name
397        my ($type, $name) = $p =~ /(\w[\w\s]*[\s\*]+)(\w+)/;
398        # strip leading and trailing whitespace
399        $type =~ s/^\s*(.*?)\s*$/$1/;
400
401        $paramhash{NAME} = $name;
402        $paramhash{TYPE} = $type;
403        # a pointer in the type means the data is passed by reference
404        $paramhash{ISREF} = ($type =~ /\*\s*$/);
405
406        if ($paramhash{ISREF}) {
407            # a const pointer is assumed to be an input parameter,
408            # note that "const void **" is parsed as a non-const pointer to "const void *", so it's out
409            # nexus does not parse [out]
410            $paramhash{INPARAM} = ($type =~ /^\s*const/) && !($type =~ /\*\s*\*/);
411            if ($paramhash{INPARAM}) {
412                ($paramhash{BASETYPE}) = ($type =~ /^\s*const\s*(.*?)\s*\*\s*$/);
413            }
414            else {
415                ($paramhash{BASETYPE}) = ($type =~ /^\s*(.*?)\s*\*\s*$/);
416
417                # non-const void* params w/ attr{nelem_out} are out params, otherwise they are actually in params
418                if ($paramhash{BASETYPE} eq 'void' && !defined $paramhash{ATTR}->{'nelem_out'}) {
419                    $paramhash{INPARAM} = 1;
420                }
421            }
422        }
423        else {
424            # if not by-reference, then by-value, which is always in in param
425            $paramhash{INPARAM} = 1;
426            $paramhash{ISHANDLE} = ($paramhash{TYPE} =~ /Handle$/ ||
427                                    $paramhash{TYPE} =~ /NEXUS_(Video|Audio)(Input|Output)/
428                                    );
429        }
430        push @params, \%paramhash;
431    }
432    $func{PARAMS} = \@params;
433
434    # The only case this is needed is bsettop_uninit (no return code, no parameters)
435    # and this is a special exception. But I'm leaving it in for completeness.
436    if ($#params == -1 && $func{RETTYPE} eq "void") {
437        $func{NOSTRUCT} = 1;
438    }
439
440    # Return a reference to the func hash
441    return \%func;
442}
443
444# this is the main function of the module
445# it takes an array of functions as input
446# and returns an array of function data structures
447sub parse_funcs
448{
449    my $func;
450    my @funcrefs;
451    for $func (@_) {
452        my $funcref = parse_func $func;
453
454        push @funcrefs, $funcref;
455
456#       print_api($funcref);
457    }
458    @funcrefs;
459}
460
461#
462# debug printout
463#
464sub print_api
465{
466    my $func;
467    for $func (@_) {
468        my $params = $func->{PARAMS};
469        my $param;
470        print "Function: $func->{RETTYPE} $func->{FUNCNAME}\n";
471        print_attr $func->{ATTR};
472        for $param (@$params) {
473            print "  Param: $param->{TYPE} $param->{NAME}\n";
474            print "    isref:    $param->{ISREF}\n";
475            print "    inparam:  $param->{INPARAM}\n";
476            print "    basetype: $param->{BASETYPE}\n";
477            print_attr $param->{ATTR};
478        }
479    }
480}
481
482sub version_api
483{
484    my $sum = 0;
485    my $func;
486    for $func (@_) {
487        my $params = $func->{PARAMS};
488        my $param;
489
490        $sum += checksum $func->{RETTYPE}, $func->{FUNCNAME};
491        for $param (@$params) {
492            $sum += checksum $param->{TYPE}, $param->{NAME}, $param->{ISREF}, $param->{INPARAM}, $param->{BASETYPE};
493            $sum += version_attr $param->{ATTR};
494        }
495    }
496    return $sum;
497}
498
4991;
Note: See TracBrowser for help on using the repository browser.