| 1 | #!/usr/bin/perl |
|---|
| 2 | ############################################################################# |
|---|
| 3 | # |
|---|
| 4 | # Copyright (c) 2003-2009, Broadcom Corporation. |
|---|
| 5 | # All rights reserved. |
|---|
| 6 | # Confidential Property of Broadcom Corporation. |
|---|
| 7 | # |
|---|
| 8 | # THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE |
|---|
| 9 | # AGREEMENT BETWEEN THE USER AND BROADCOM. YOU HAVE NO RIGHT TO USE OR |
|---|
| 10 | # EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT. |
|---|
| 11 | # |
|---|
| 12 | # $brcm_Workfile: bapi_parse_c.pm $ |
|---|
| 13 | # $brcm_Revision: 3 $ |
|---|
| 14 | # $brcm_Date: 7/2/09 10:47a $ |
|---|
| 15 | # |
|---|
| 16 | # File Description: |
|---|
| 17 | # |
|---|
| 18 | # Revision History: |
|---|
| 19 | # |
|---|
| 20 | # $brcm_Log: /BSEAV/api/build/proxy/bapi_parse_c.pm $ |
|---|
| 21 | # |
|---|
| 22 | # 3 7/2/09 10:47a erickson |
|---|
| 23 | # PR56558: add bsettop_set_init_settings and bsettop_init_frontend |
|---|
| 24 | # |
|---|
| 25 | # 2 3/15/06 4:51p vsilyaev |
|---|
| 26 | # PR20221: NetIF DMA interface |
|---|
| 27 | # |
|---|
| 28 | # 1 2/7/05 6:56p dlwin |
|---|
| 29 | # Merge down for release 2005_REFSW_MERGETOMAIN: |
|---|
| 30 | # |
|---|
| 31 | # Irvine_BSEAVSW_Devel/4 6/29/04 11:26a erickson |
|---|
| 32 | # PR11135: const void ** is not an out parameter. Take this into account. |
|---|
| 33 | # |
|---|
| 34 | # Irvine_BSEAVSW_Devel/3 6/16/04 5:15p erickson |
|---|
| 35 | # PR11135: added callback support |
|---|
| 36 | # |
|---|
| 37 | # Irvine_BSEAVSW_Devel/2 6/1/04 11:28a erickson |
|---|
| 38 | # PR11135: added support for strings (const char *) |
|---|
| 39 | # |
|---|
| 40 | # Irvine_BSEAVSW_Devel/1 5/17/04 11:13a erickson |
|---|
| 41 | # PR11135: added initial linux proxy impl |
|---|
| 42 | # |
|---|
| 43 | ############################################################################# |
|---|
| 44 | use strict; |
|---|
| 45 | |
|---|
| 46 | package bapi_parse_c; |
|---|
| 47 | |
|---|
| 48 | local *FILE; |
|---|
| 49 | |
|---|
| 50 | sub writeDebug |
|---|
| 51 | { |
|---|
| 52 | print "@_\n"; |
|---|
| 53 | } |
|---|
| 54 | |
|---|
| 55 | sub get_func_prototypes |
|---|
| 56 | { |
|---|
| 57 | my $filename = shift; |
|---|
| 58 | open FILE, $filename; |
|---|
| 59 | my $text = join '',<FILE>; |
|---|
| 60 | |
|---|
| 61 | # pack preprocessor line continutation |
|---|
| 62 | $text =~ s/\\\s+(\w)/$1/sg; |
|---|
| 63 | # remove preprocessor stuff that can cause parsing problems |
|---|
| 64 | $text =~ s/#\w+.*?\n//g; |
|---|
| 65 | |
|---|
| 66 | # Grab all size_is() hints and move them out of comment temporarily |
|---|
| 67 | # Blow away the comment because it isn't going to stay anyway. |
|---|
| 68 | $text =~ s/ |
|---|
| 69 | \/\* # start of a comment |
|---|
| 70 | \s* \[ [\w,]* # Valid hints before a possible size_is. |
|---|
| 71 | (size_is\(\w+\)) # Here's what we need to keep |
|---|
| 72 | .*? |
|---|
| 73 | \*\/ # end of the comment |
|---|
| 74 | /$1/sgx; |
|---|
| 75 | |
|---|
| 76 | # Remove all comments |
|---|
| 77 | # No nested comments allowed |
|---|
| 78 | $text =~ s/\/\*.*?\*\///sg; |
|---|
| 79 | |
|---|
| 80 | # If we have any ", size_is", reverse the order. Much easier to parse later. |
|---|
| 81 | $text =~ s/(,)\s*(size_is\(\w+\))/ $2$1/sg; |
|---|
| 82 | |
|---|
| 83 | # Parse functions |
|---|
| 84 | my @funcs = $text =~ /( |
|---|
| 85 | \w[\w\s]+ # return type |
|---|
| 86 | [\s\*] # delimiter or \s or * |
|---|
| 87 | \w+ # function name |
|---|
| 88 | \(.*?\)) # parameters |
|---|
| 89 | \s*; # must terminate with ; |
|---|
| 90 | /xsg; |
|---|
| 91 | |
|---|
| 92 | @funcs; |
|---|
| 93 | } |
|---|
| 94 | |
|---|
| 95 | # parse_func |
|---|
| 96 | # |
|---|
| 97 | # The function data structure is a hash with the following members: |
|---|
| 98 | # PROTOTYPE = string, the original prototype |
|---|
| 99 | # RETTYPE = string, the return type |
|---|
| 100 | # FUNCNAME = string, the function name |
|---|
| 101 | # PARAMS = reference to array of hash references |
|---|
| 102 | # Each hash reference is a single parameter with the following members: |
|---|
| 103 | # NAME |
|---|
| 104 | # TYPE |
|---|
| 105 | # |
|---|
| 106 | # This subroutine returns a reference to the function hash. |
|---|
| 107 | # |
|---|
| 108 | sub parse_func |
|---|
| 109 | { |
|---|
| 110 | my $prototype = shift; |
|---|
| 111 | my %func; |
|---|
| 112 | my $more; |
|---|
| 113 | my @params; # this is a list of a param hash |
|---|
| 114 | |
|---|
| 115 | # remove the size_is hint from the actual prototype |
|---|
| 116 | my $actual_prototype = $prototype; |
|---|
| 117 | $actual_prototype =~ s/size_is\(\w+\)//sg; |
|---|
| 118 | $func{PROTOTYPE} = $actual_prototype; |
|---|
| 119 | |
|---|
| 120 | ($func{RETTYPE}, $more) = $prototype =~ /(.*?)\s*([\s*\*])\w+\s*\(/; |
|---|
| 121 | if ($more eq "*") { |
|---|
| 122 | $func{RETTYPE} .= $more; |
|---|
| 123 | } |
|---|
| 124 | ($func{FUNCNAME}) = $prototype =~ /(\w+)\s*\(/; |
|---|
| 125 | |
|---|
| 126 | #print "$prototype\n"; |
|---|
| 127 | |
|---|
| 128 | # get the params into a raw list |
|---|
| 129 | my ($params) = $prototype =~ /\((.*?)\)$/s; |
|---|
| 130 | if ($params eq "void") { |
|---|
| 131 | $params = undef; |
|---|
| 132 | } |
|---|
| 133 | my @rawparams = split /,/, $params; |
|---|
| 134 | my $p; |
|---|
| 135 | |
|---|
| 136 | for $p (@rawparams) { |
|---|
| 137 | my %paramhash; |
|---|
| 138 | |
|---|
| 139 | # See if we have a size_is hint and grab it now |
|---|
| 140 | # This also removes that hint from the variable |
|---|
| 141 | if ($p =~ s/size_is\((\w+)\)//) { |
|---|
| 142 | $paramhash{ARRAYLENGTH} = $1; |
|---|
| 143 | } |
|---|
| 144 | |
|---|
| 145 | # parse type and name |
|---|
| 146 | my ($type, $name) = $p =~ /(\w[\w\s]*[\s\*]+)(\w+)/; |
|---|
| 147 | # strip leading and trailing whitespace |
|---|
| 148 | $type =~ s/^\s*(.*?)\s*$/$1/; |
|---|
| 149 | |
|---|
| 150 | $paramhash{NAME} = $name; |
|---|
| 151 | $paramhash{TYPE} = $type; |
|---|
| 152 | # a pointer in the type means the data is passed by reference |
|---|
| 153 | $paramhash{ISREF} = ($type =~ /\*\s*$/); |
|---|
| 154 | |
|---|
| 155 | if ($paramhash{ISREF}) { |
|---|
| 156 | # a const pointer is assumed to be an input parameter, |
|---|
| 157 | # unless it's a **. Yes, this is a big stretch. |
|---|
| 158 | # TODO: Should we depend on [out] instead? |
|---|
| 159 | $paramhash{INPARAM} = ($type =~ /^\s*const/) && !($type =~ /\*\s*\*/); |
|---|
| 160 | if ($paramhash{INPARAM}) { |
|---|
| 161 | ($paramhash{BASETYPE}) = ($type =~ /^\s*const\s*(.*?)\s*\*\s*$/); |
|---|
| 162 | |
|---|
| 163 | # const char * is a special type: string. |
|---|
| 164 | # if size_is is not specified, use a default size and pass the |
|---|
| 165 | # string. |
|---|
| 166 | if (($paramhash{BASETYPE} eq "char") && !$paramhash{ARRAYLENGTH}) { |
|---|
| 167 | $paramhash{ARRAYLENGTH} = "__maxstringlength"; |
|---|
| 168 | } |
|---|
| 169 | } |
|---|
| 170 | else { |
|---|
| 171 | ($paramhash{BASETYPE}) = ($type =~ /^\s*(.*?)\s*\*\s*$/); |
|---|
| 172 | } |
|---|
| 173 | |
|---|
| 174 | # void * is assumed to be a byte array, so convert |
|---|
| 175 | if ($paramhash{BASETYPE} eq "void") { |
|---|
| 176 | $paramhash{BASETYPE} = "unsigned char"; |
|---|
| 177 | } |
|---|
| 178 | } |
|---|
| 179 | push @params, \%paramhash; |
|---|
| 180 | } |
|---|
| 181 | $func{PARAMS} = \@params; |
|---|
| 182 | |
|---|
| 183 | # The only case this is needed is bsettop_uninit (no return code, no parameters) |
|---|
| 184 | # and this is a special exception. But I'm leaving it in for completeness. |
|---|
| 185 | if ($#params == -1 && $func{RETTYPE} eq "void") { |
|---|
| 186 | $func{NOSTRUCT} = 1; |
|---|
| 187 | } |
|---|
| 188 | |
|---|
| 189 | # Return a reference to the func hash |
|---|
| 190 | return \%func; |
|---|
| 191 | } |
|---|
| 192 | |
|---|
| 193 | # this is the main function of the module |
|---|
| 194 | # it takes an array of functions as input |
|---|
| 195 | # and returns an array of function data structures |
|---|
| 196 | sub parse_funcs |
|---|
| 197 | { |
|---|
| 198 | my $func; |
|---|
| 199 | my @funcrefs; |
|---|
| 200 | for $func (@_) { |
|---|
| 201 | my $funcref = parse_func $func; |
|---|
| 202 | |
|---|
| 203 | # The following functions are handled as special cases. |
|---|
| 204 | # Don't autogenerate any code. |
|---|
| 205 | if ($funcref->{FUNCNAME} eq "bsettop_init" || |
|---|
| 206 | $funcref->{FUNCNAME} eq "bsettop_get_init_settings" || |
|---|
| 207 | $funcref->{FUNCNAME} eq "bsettop_set_init_settings" || |
|---|
| 208 | $funcref->{FUNCNAME} eq "bsettop_uninit") |
|---|
| 209 | { |
|---|
| 210 | next; |
|---|
| 211 | } |
|---|
| 212 | |
|---|
| 213 | push @funcrefs, $funcref; |
|---|
| 214 | |
|---|
| 215 | #&print_api($funcref); |
|---|
| 216 | } |
|---|
| 217 | @funcrefs; |
|---|
| 218 | } |
|---|
| 219 | |
|---|
| 220 | # |
|---|
| 221 | # debug printout |
|---|
| 222 | # |
|---|
| 223 | sub print_api |
|---|
| 224 | { |
|---|
| 225 | my $func; |
|---|
| 226 | for $func (@_) { |
|---|
| 227 | my $params = $func->{PARAMS}; |
|---|
| 228 | my $param; |
|---|
| 229 | print "Function: $func->{RETTYPE} $func->{FUNCNAME}\n"; |
|---|
| 230 | for $param (@$params) { |
|---|
| 231 | print " Param: $param->{TYPE} $param->{NAME}\n"; |
|---|
| 232 | print " isref: $param->{ISREF}\n"; |
|---|
| 233 | print " inparam: $param->{INPARAM}\n"; |
|---|
| 234 | print " basetype: $param->{BASETYPE}\n"; |
|---|
| 235 | print " arraylen: $param->{ARRAYLENGTH}\n"; |
|---|
| 236 | } |
|---|
| 237 | } |
|---|
| 238 | } |
|---|
| 239 | |
|---|
| 240 | 1; |
|---|