#!/usr/bin/perl # ==================================================================== # The Vovida Software License, Version 1.0 # # Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in # the documentation and/or other materials provided with the # distribution. # # 3. The names "VOCAL", "Vovida Open Communication Application Library", # and "Vovida Open Communication Application Library (VOCAL)" must # not be used to endorse or promote products derived from this # software without prior written permission. For written # permission, please contact vocal\@vovida.org. # # 4. Products derived from this software may not be called "VOCAL", nor # may "VOCAL" appear in their name, without prior written # permission of Vovida Networks, Inc. # # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND # NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA # NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES # IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE # USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH # DAMAGE. # # ==================================================================== # # This software consists of voluntary contributions made by Vovida # Networks, Inc. and many individuals on behalf of Vovida Networks, # Inc. For more information on Vovida Networks, Inc., please see # . # $Id: cApiBuilder,v 1.11 2000/08/12 01:24:57 bogawa Exp $ use strict 'subs'; #use strict 'getopts.pl'; @functions = ( ); # main data structure that holds all info about all functions $doCode = 1; # flag to generate CXX file, otherwise do header file @inclues = {}; # holds allfiles to be included in generated output # parse the heasder information for $arg ( @ARGV ) { &debug(" arg=",$arg,"\n"); if ( $arg =~ /^-c/ ) { $doCode = 1; } if ( $arg =~ /^-h/ ) { $doCode = 0; } if ( $arg =~ /^-d/ ) { $debugCode = 1; } if ( $arg =~ /^-i/ ) { # an file to include $arg =~ s/^-i//; push @includes, $arg; } } #generate the file header info print < ) { # still need to deal with C style comments if ( s/^\#include/\#include/g > 0 ) { print $_ if $doCode; } else { chomp; $ignore = 1 if(/\/\/ API:ignore begin/) ; $ignore = 0 if(/\/\/ API:ignore end/) ; next if($ignore); s/:/ : /g; s/,/ , /g; s/\(/ \( /g; s/\)/ \) /g; s/\{/ \{ /g; s/\}/ \} /g; s/\;/ \; /g; s/\/\/.*$/ /g; s/\#.*$/ /g; s/^t/ /g; s/const/ /g; s/virtual/ /g; $data .= $_ . " "; } } # remvoe C Style comments $data =~ s/\/\*.*?\*\///gm; # tokenize the data @data = split( " " , $data ); $inClass = 0; $inPublic = 0; for( $i=0; $i < $#data; $i++ ) { if ( $data[$i] eq "class" ) { $className = $data[$i+1]; if ( $data[$i+2] ne ";" ) { while ( $data[$i] ne "{" ) { $i++; } $i++; $inClass = 1; $inPublic = 0; &debug("# in class " , $className , "\n"); } } if ( $data[$i] eq "}" ) { $inClass = 0; } if ( ($data[$i] eq "public") and $inClass ) { while ( $data[$i] ne ":" ) { $i++; } $i++; $inPublic = 1; &debug("# in public of " , $className , "\n"); } if ( ($data[$i] eq "private") or ($data[$i] eq "protected") ) { while ( $data[$i] ne ":" ) { $i++; } $i++; $inPublic = 0; } if ( ($data[$i] eq "(" ) and $inClass and $inPublic ) { #found a function $functionName = $data[$i-1]; if ( $functionName eq $className ) { $returnType = $className . "*"; $functionName = "constructor"; } elsif ( $functionName eq ( "~" . $className ) ) { $returnType = "void"; $functionName = "destructor"; } else { $staticFunction = ( $data[$i-3] eq "static"); $returnType = $data[$i-2]; $returnType = "int" if ($returnType eq ";"); $returnType = "int" if ($returnType eq ":"); $returnType = "int" if ($returnType eq "{"); } $i++; $rec = { }; $rec->{name} = $functionName; $rec->{isStatic} = $staticFunction; $rec->{class} = $className; $rec->{return} = $returnType; &debug("#func ",$returnType," ",$className,"::",$functionName,"\n"); $numParam = 0; # get the parameters PARAM: while ( 1 ) { last PARAM if ( $data[$i] eq ")" ); #for ( $t=$i; $t<$i+3; $t++) { print "data[",$t,"]=",$data[$t],"\n"; } $type = $data[$i]; $name = $data[$i+1]; $name =~ s/=.*//g; # kill default paramters &debug("# param ",$numParam," ",$type," ",$name,"\n"); $rec->{"paramName",$numParam} = $name; $rec->{"paramType",$numParam} = $type; $numParam++; $rec->{numParam} = $numParam; $i = $i+2; &debug("data is ",$data[$i],"\n"); last PARAM if ( $data[$i] eq ")" ); if ( $data[$i] eq "," ) { $i++; next PARAM; } print STDERR "VERY CONFUSED\n"; print "VERY CONFUSED\n"; for ( $j = $i-10; $j < $i+10; $j++ ) { print $data[$j]," "; } print "\n"; last PARAM; } push @functions, $rec; # eat rest of function INLINEFUNC: while ( ($data[$i] ne ";") ) { if (($data[$i] eq "{") ) { #Deal with inline function $i++; $depth = 1; while ( $depth > 0 ) { $depth++ if ($data[$i] eq "{"); $depth-- if ($data[$i] eq "}"); $i++; } last INLINEFUNC; } $i++; } } &debug($i,": ",$data[$i] , "\n"); } # print the functions if (0) { for $func ( @functions ) { print "static " if $func->{isStatic}; print $func->{return}," ", $func->{class},"::",$func->{name},"("; for( $t=0; $t < $func->{numParam}; $t++) { print "," if ( $t != 0 ); print $func->{"paramType",$t}," ",$func->{"paramName",$t}; } print ");\n"; } } %definedTypes = ( "void" => 1, "bool" => 1, "char" => 1, "int" => 1, "long" => 1, "float" => 1, "double" => 1, "string" => 1, "String" => 1, "RtpSeqNumber" => 1, "RtcpHeader" => 1, "RtcpReport" => 1, "RtcpSDESItem" => 1, "RtcpSDESType" => 1, "RtcpSender" => 1, "RtcpType" => 1, "RtpHeader" => 1, "RtpPayloadType" => 1, "RtpSource" => 1, "RtpTime" => 1, "RtpSrc" => 1, "u_int32_t" => 1 ); sub addType ( $ ) { my $type = shift; &debug("adding type ",$type," -> ",&mapTypeToC($type),"\n"); $_ = $type; s/&//g; s/\*//g; $_ = "builtin" if ( $definedTypes{$_} ); $type = $_; $types{$type} = $type unless ( $type eq "builtin" ); } sub mapTypeToC ( $ ) { $_ = shift; s/string&/char\*/g; s/string/char\*/g; s/&/\*/g; s/bool/int/g; my $type = $_; # try to fix template classes s/\<(\w*)\>/_Tmpl_$1_/; $type =~ s/\<(\w*)\>/_Tmpl_$1_/; s/Ptr$/\*/; s/\**//g; &debug("check defined for " , $_ , "\n"); if ( $definedTypes{$_} ) { &debug("is defined\n"); #$type .= "_isCDefined"; } else { &debug("is not defined\n"); $type =~ s/\*/Ptr/; # needs work for builtin types # $type .= "Ptr"; # needs work for builtin types } # try to fix template classes s/\<(\w*)\>/_Tmpl_$1_/; # s/^intPtr/int*/; # s/^longPtr/long*/; # s/^charPtr/char*/; # s/^shortPtr/short*/; # s/^floatPtr/float*/; # s/^doublePtr/double*/; # s/^voidPtr/void*/; $mapTypeToC = $type; } # compute all the type lookups for $func ( @functions ) { &addType( $func->{class} ); &addType( $func->{return} ); for( $t=0; $t < $func->{numParam}; $t++) { &addType( $func->{"paramType",$t} ); } } # generate the file if (1) { # print "\n#include \n\n" if $doCode; print "\n#include \n\n" if $doCode; for $include ( @includes ) { print "#include \"$include\" \n"; } print "\n#ifdef __cplusplus\nextern \"C\" \n{\n#endif\n"; print "\n\n"; print " \/\* This file uses the types : \n"; # build the type declarations for $type ( sort keys %types ) { $type =~ s/\<(\w*)\>/_Tmpl_$1_/; print "typedef void* ",$type,"Ptr;\n"; } print " */ \n "; print "\n\n"; print "/* these function return a string describibg any */ \n"; print "/* errors or NULL if there was no error */ \n\n"; # build the prototypes for $func ( @functions ) { if ( $func->{class} ne $prevClass ) { print "\n" ; $constructorCount=0; } $prevClass = $func->{class}; if ( $func->{name} eq "constructor" ) { if (1) { $constructorCount++; if ( $doCode ) { print "\n/// See ",$func->{class},"::",$func->{class},"\n"; } print "int "; print "\n" if $doCode; print $func->{class},"_create",$constructorCount; print "( ",&mapTypeToC($func->{class} . "*"),"* objPtr"; for( $t=0; $t < $func->{numParam}; $t++) { print ", ",&mapTypeToC($func->{"paramType",$t}); print " ",$func->{"paramName",$t}; } print ")"; print ";" unless $doCode; print "\n"; if ( $doCode ) { print "{\n"; print " int retValue=0;\n"; print " ",$func->{class},"* obj = NULL; \n"; print " try\n"; print " {\n"; print " "; print "obj = new ",$func->{class},"("; for( $t=0; $t < $func->{numParam}; $t++) { print "," if ( $t != 0 ); $type = $func->{"paramType",$t}; if ( $type eq "string" ) { print "string"; print "(",$func->{"paramName",$t},")"; } elsif ( $type eq "string&" ) { print "string"; print "(",$func->{"paramName",$t},")"; } elsif ( $type =~ /.*&$/ ) { # deal with a feverence type $type =~ s/&$//; print "*static_cast<",$type,"*>"; print "(",$func->{"paramName",$t},")"; } else { print "static_cast<",$type,">"; print "(",$func->{"paramName",$t},")"; } } print ")"; print ";\n"; print " assert(objPtr); \n"; print " *objPtr = static_cast<",&mapTypeToC($func->{class} . "*"),">(obj); \n"; print " }\n"; print " catch (...)\n"; print " {\n"; print " retValue=-1; \n"; print " }\n"; print " \n"; print " return retValue;\n"; print "}\n\n"; } } } elsif( $func->{name} eq "destructor" ) { if (1) { if ( $doCode ) { print "\n/// See ",$func->{class},"::~",$func->{class},"\n"; } print "void "; print "\n" if $doCode; print $func->{class},"_free"; print "( ",&mapTypeToC($func->{class} . "*")," objPtr"; print ")"; if ( $doCode ) { print "\n{\n"; print " assert(objPtr);\n"; print " ",$func->{class},"* obj = "; print "static_cast<",$func->{class},"*>(objPtr);\n"; print " delete obj;\n"; print "}\n"; } else { print ";\n"; } } } else { if (1) { if ( $doCode ) { print "\n/// See ",$func->{class},"::",$func->{name},"\n"; } print "int "; print "\n" if $doCode; # deal with overloaded function names $cName = $func->{class} . "_" . $func->{name}; $count = 1; while ( $usedName{$cName} ) { $count++; $cName = $func->{class} . "_" . $func->{name} . $count; } $usedName{$cName} = 1; print $cName; print "( "; # do the this pointer part print &mapTypeToC($func->{class} . "*")," objPtr" unless $func->{isStatic}; print ", " unless $func->{isStatic} or ( ($func->{numParam}==0) and (($func->{return} eq "void")) ); # do the parametes for( $t=0; $t < $func->{numParam}; $t++) { print ", " unless ( $t == 0 ); print &mapTypeToC($func->{"paramType",$t}); print " ",$func->{"paramName",$t}; } print ", " unless ($func->{return} eq "void")or($func->{numParam}==0); # do return value part if ( $func->{return} ne "void" ) { print &mapTypeToC($func->{return} . "*")," returnValue"; } # end the first line print ")"; print ";" unless $doCode; print "\n"; if ( $doCode ) { print "{\n"; print " int retValue=0;\n"; if ( !($func->{isStatic}) ) { print " ",$func->{class},"* obj = "; print "static_cast<",$func->{class},"*>(objPtr);\n"; } print " try\n"; print " {\n"; print " "; # deal with the return type here if ( $func->{return} ne "void" ) { print "*reinterpret_cast<",$func->{return},"*>(returnValue) = "; } if ( $func->{isStatic} ) { print "$func->{class}::"; } else { print "obj->"; } print $func->{name},"("; for( $t=0; $t < $func->{numParam}; $t++) { print "," if ( $t != 0 ); $type = $func->{"paramType",$t}; if ( $type eq "string" ) { print "string"; print "(",$func->{"paramName",$t},")"; } elsif ( $type eq "string&" ) { print "string"; print "(",$func->{"paramName",$t},")"; } elsif ( $type =~ /.*&$/ ) { # deal with a reference type $type =~ s/&$//; print "*static_cast<",$type,"*>"; print "(",$func->{"paramName",$t},")"; } else { print "static_cast<",$type,">"; print "(",$func->{"paramName",$t},")"; } } print ")"; print ";\n"; print " }\n"; print " catch (...)\n"; print " {\n"; print " retValue=-1; \n"; print " }\n"; print " \n"; print " return retValue;\n"; print "}\n\n"; } } } } print "\n#ifdef __cplusplus\n} /*close extern C*/ \n#endif\n"; } sub debug { if($debugCode) { print STDERR @_; } }