📄 genperl.pl
字号:
#!/usr/bin/perl# script to translate th cryptlib C interface into a Perl header interface module# Copyright (C) 2007 Alvaro Livraghi###### G E N P E R L . P L Version 0.1 (last changes 2007-06-0)# --------------------------------------------------------------------# Based upon GenVB.pl by Wolfgang Gothier## PERL script for translation of the cryptlib header file# into a Perl header file used by Perl interface package # for Cryptlib (PerlCryptLib.pm).## This script does the translation of C-statements into# Perl code. (But only as much as is needed in # cryptlib.h, -NOT- usable as general translation utility)## --------------------------------------------------------------------## SYNTAX:# perl GenPerl.pl <cryptlib.h> <PerlCryptLib.ph>## cryptlib.h ........ (optional) Pathname of crytlib header file# default is "cryptlib.h"# PerlCryptLib.ph ... (optional) Pathname of PerlCrytLib header file# default is "PerlCryptLib.ph"## creates the Perl interface file with same basic name # and extension ".ph" in the same directory as the source file# default is "PerlCryptLib.ph"######use strict;use warnings;use File::stat;use File::Basename;my $inFileName = shift @ARGV || 'cryptlib.h'; # default filename is "cryptlib.h"my %DEFINED = ( 1, 1, # ifdef 1 is to be included "USE_VENDOR_ALGOS", 0 ); # set to 1 to include #IFDEF USE_VENDOR_ALGOSmy $Startline = qr{^#define C_INOUT}; # ignore all lines before this onemy ($inFileBase, $inPath, $inExt) = fileparse($inFileName, qr{\.[^.]*$});die("\"usage: $0 cryptlib.h\"\nParameter must be a C header file\nStop") unless ($inExt =~ m/^\.h$/i) && -r $inFileName;my $outFileName = shift @ARGV || $inPath.'PerlCryptLib.ph'; # default filename is "PerlCryptLib.ph"my ($outFileBase, $outPath, $outExt) = fileparse($outFileName, qr{\.[^.]*$});my ($Infile, $Outfile) = ($inPath.$inFileBase.'.h', $outPath.$outFileBase.$outExt);my $cryptlib_version;open(INFILE, "<$Infile") or die "Open error on $Infile: $!";open (OUTFILE, ">$Outfile") or die "Open error on $Outfile: $!";print "Transforming \"$Infile\" into \"$Outfile\"\n";my $Default = select(OUTFILE);# Ignore all input lines before (and including) $Startlinewhile (<INFILE>) { $cryptlib_version = $_ if m{#define\s+CRYPTLIB_VERSION\s+}; last if m/$Startline/;}# array to contain the preprocessed input lines:my @source;push @source, PERLHeader($Infile);push @source, $cryptlib_version if $cryptlib_version;my $INACTIVE = 0;my $LEVEL = 0;my $COMMENT = 0;# handle conditionals, include conditional code only if definition agrees with %DEFINEDwhile (<INFILE>) { # remove tabs 1 while s/\t/' ' x (length($&)*4 - length($`)%4)/e; if (/^\s*#if(\s|def\s)(\w+)/) { $LEVEL += 1; $INACTIVE += 1 unless $DEFINED{$2}; next; } if (/^\s*#if\s\(/) { #if (anyexpression) assumed always false $LEVEL += 1; $INACTIVE += 1; next; } if (/^\s*#ifndef\s(\w+)/) { $LEVEL += 1; $INACTIVE += 1 if $DEFINED{$1}; next; } if (/^\s*#(else|elif)\b/) { $INACTIVE = 1-$INACTIVE; next; } if (/^\s*\#endif\b/) { $LEVEL -= 1; $INACTIVE = 0; next; } # translate comments if (/\/\*(.*)\*\/\s*$/) { if ($1 !~ m(\*/)) { s!/\*(.*)\*/\s*$!#$1\n! } } if ($COMMENT) { $_ = "#".$_ unless s/^ /#/; $COMMENT = 0 if s/\*\/\s*$/\n/; s/\*\*$/***/; } $COMMENT = 1 if s/^(\s*)\/\*\*(.*)$/#**$1$2/; $COMMENT = 1 if s/^(\s*)\/\*(.*)$/#$1 $2/; push @source, $_ unless $INACTIVE;}# preprocessing finished, translation to PERL code followsmy $Warn="";while ($_ = shift @source) { # ignore special C++ handling if (/#ifdef\s+__cplusplus/) { $_ = shift @source while (!(/#endif/)); $_ = shift @source; } # continued lines if (s/\\$//) { $_ .= shift @source; redo if @source; } # incomplete typedef / enum lines if (/^\s*(typedef\s+enum|typedef\s+struct|enum)\s*\{[^}]*$/) { $_ .= shift @source; redo if @source; } # incomplete procedure calls if (/^\s*C_RET\s+\w+\s*\([^)]*$/) { $_ .= shift @source; redo if @source; } # lines are complete now, do the translation # hex values #s{0x([0-9a-fA-F]+)}{&H$1}g; # constant definitions #s/^\s*#define\s+(\w+)\s+(\w+|[+\-0-9]+|&H[0-9a-fA-F]+)/ Public Const $1 As Long = $2/; s/^\s*#define\s+(\w+)\s+(\w+|[+\-0-9]+|&H[0-9a-fA-F]+)/\tsub $1 { $2 }/; # typedef struct if (s!^(\s*)typedef\s+struct\s*{([^}]*)}\s*(\w+)\s*;!&typelist(split(/;/,$2))!e) { $_ = "sub $3\n{\n\t{\n$_\t}\n}\n"; } # typedef enum ( with intermediate constant definitions ) if (s!^\s*typedef\s+enum\s*{([^}]+=\s*\d+\b[^}]+)}\s*(\w+);!&enumt(split(/\n/,$1))!e) { $_ = "##### BEGIN ENUM $2 $_##### END ENUM $2\n"; } # typedef enum if (s!^\s*typedef\s+enum\s*{([^}]+)}\s*(\w+);!&enumt(split(/\n/,$1))!e) { $_ = "##### BEGIN ENUM $2\n$_##### END ENUM $2\n"; } # "simple" typedef s/^\s*typedef\s+(\w+)\s+(\w+);/sub $2 { 0 }/; # "simple" enum s!^\s*enum\s*{([^}]+)}\s*;!&enums(split(/,/,$1))!e; # translate function declarations without params if ( s/(\bC_RET\s*\w+\s*\(\s*[^)]+\s*\)\s*;)/#$1/ ) { s/\n/\n#/g; } # C-macro definitions are ignored if (s/\s*#define\s+(.*)/$1/) { s/\n/\n#/g; s/\s+$//; $_ = "# C-macro not translated to Perl code but implemented apart: \n# #define $_\n"; } # translation is done, output lines now print "$_" if @source;}print PERLFooter();select($Default);exit;# subroutine definitions follow:sub PERLHeader { my $Infile = shift; my $fstat = stat($Infile) if (-f $Infile && -r $Infile) or die "$Infile not readable"; my $infile_size = $fstat->size; my $infile_time = localtime($fstat->mtime); my $filename = basename($Infile); my $now = (localtime())[5]+1900;return <<ENDOFHEADER;# *****************************************************************************# * *# * cryptlib External API Interface *# * Copyright Peter Gutmann 1997-$now *# * *# * adapted for Perl Version 5.x by Alvaro Livraghi *# *****************************************************************************### ----------------------------------------------------------------------------## This file has been created automatically by a perl script from the file:## "$filename" dated $infile_time, filesize = $infile_size.## Please check twice that the file matches the version of $filename# in your cryptlib source! If this is not the right version, try to download an# update from CPAN web site. If the filesize or file creation date do not match,# then please do not complain about problems.## Published by Alvaro Livraghi, # mailto: perlcryptlib\@gmail.com if you find errors in this file.## -----------------------------------------------------------------------------#ENDOFHEADER}sub PERLFooter {return <<ENDFOOTER;## *****************************************************************************# * *# * End of Perl Functions *# * *# *****************************************************************************#1; ##### End-of perl header file!ENDFOOTER}# subroutine to handle simple enum elementssub enums { my $Index = 0; # startvalue = 0 for enum entries my $_S; foreach (@_) { chomp; s/^\s+//; # delete leading whitespace if (m/(\w+)\s*=\s*(\d+).*$/) { # new value is being set, $index must be updated $_S .= " sub $1 { $2 }\n"; eval($Index = $2+1); } else { $_S .= " sub $_ { ".$Index++." }\n"; } } return $_S;}# subroutine to handle typedef enum ( with intermediate constant definitions )sub enumt { my $LINES = ""; my $parval; my $lastValue = 0; foreach $parval (@_) { my ($val, $rem, $name, $value); $parval =~ s/^\s*(.*?)\s*$/$1/; ($val, $rem) = split('#', $parval, 2); $val = '' unless $val; $val =~ s/^\s*(.*?)\s*$/$1/; $rem = '' unless $rem; $rem =~ s/^\s*(.*?)\s*$/$1/; if ( $val ne '' ) { ($name, $value) = split('=', $val, 2); $name = '' unless $name; $name =~ s/^\s*(.*?)[\s\,]*$/$1/; $value = '' unless $value; $value =~ s/^\s*(.*?)[\s\,]*$/$1/; if ( $value eq '' || $value =~ /^\d/ ) { $value = $lastValue unless $value; $lastValue = $value + 1; } } if ( $name ) { foreach my $curname (split(',', $name)) { $curname =~ s/^\s*(.*?)\s*$/$1/; $LINES .= ($curname ? "\tsub $curname { $value }" : '') . ($rem ? "\t# $rem" : '') . "\n"; } } else { $LINES .= ($rem ? "\t# $rem" : '') . "\n"; } } return $LINES;}# handle the lines of a "typedef struct { ... } structname"sub typelist { my $tmp = ""; my $first = 0; foreach my $par (@_) { while ($par =~ s/^(\s*)\#(.+)\n(.*)/$3/) { # embedded comments $tmp .= "\t# $2\n"; } if ($par =~ s/^(\s*)(.*)\s(\w+)\s*\[\s*(\w+)\s*\]\s*$//) { # index conversion $tmp .= $1 . (!$first++ ? ' ' : ',') . "$3 => ' ' x $4"; } elsif ($par =~ s/^(\s*)(.*)\s(\w+)\s*$//) { # normal conversion $tmp .= $1 . (!$first++ ? ' ' : ',') . "$3 => 0"; } else {$tmp .= $par} # leave it alone } return $tmp;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -