From 7292390de5903b96e1f9798fbd8ae8a4ec65b85c Mon Sep 17 00:00:00 2001 From: Martin Ebourne Date: Sat, 4 Mar 2006 01:38:13 +0000 Subject: This is part 2 of a patch from James O'Gorman. This just renames all of the files that configure now substitutes - no changes to any of the files. --- lib/common/makeexception.pl | 277 ----------- lib/common/makeexception.pl.in | 277 +++++++++++ lib/raidfile/raidfile-config | 97 ---- lib/raidfile/raidfile-config.in | 97 ++++ lib/server/makeprotocol.pl | 997 ---------------------------------------- lib/server/makeprotocol.pl.in | 997 ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 1371 insertions(+), 1371 deletions(-) delete mode 100755 lib/common/makeexception.pl create mode 100755 lib/common/makeexception.pl.in delete mode 100755 lib/raidfile/raidfile-config create mode 100755 lib/raidfile/raidfile-config.in delete mode 100755 lib/server/makeprotocol.pl create mode 100755 lib/server/makeprotocol.pl.in (limited to 'lib') diff --git a/lib/common/makeexception.pl b/lib/common/makeexception.pl deleted file mode 100755 index 1564b75b..00000000 --- a/lib/common/makeexception.pl +++ /dev/null @@ -1,277 +0,0 @@ -#!@PERL@ - -# global exception list file -my $global_list = '../../ExceptionCodes.txt'; - - -my @exception; -my @exception_desc; -my $class; -my $class_number; - -# read the description! - -open EXCEPTION_DESC,$ARGV[0] or die "Can't open $ARGV[0]"; - -while() -{ - chomp; s/\A\s+//; s/#.+\Z//; s/\s+\Z//; s/\s+/ /g; - next unless m/\S/; - - if(m/\AEXCEPTION\s+(.+)\s+(\d+)\Z/) - { - $class = $1; - $class_number = $2; - } - else - { - my ($name,$number,$description) = split /\s+/,$_,3; - if($name eq '' || $number =~ m/\D/) - { - die "Bad line '$_'"; - } - if($exception[$number] ne '') - { - die "Duplicate exception number $number"; - } - $exception[$number] = $name; - $exception_desc[$number] = $description; - } -} - -die "Exception class and number not specified" unless $class ne '' && $class_number ne ''; - -close EXCEPTION_DESC; - -# write the code -print "Generating $class exception...\n"; - -open CPP,">autogen_${class}Exception.cpp" or die "Can't open cpp file for writing"; -open H,">autogen_${class}Exception.h" or die "Can't open h file for writing"; - -# write header file -my $guardname = uc 'AUTOGEN_'.$class.'EXCEPTION_H'; -print H <<__E; - -// Auto-generated file -- do not edit - -#ifndef $guardname -#define $guardname - -#include "BoxException.h" - -// -------------------------------------------------------------------------- -// -// Class -// Name: ${class}Exception -// Purpose: Exception -// Created: autogen -// -// -------------------------------------------------------------------------- -class ${class}Exception : public BoxException -{ -public: - ${class}Exception(unsigned int SubType) - : mSubType(SubType) - { - } - - ${class}Exception(const ${class}Exception &rToCopy) - : mSubType(rToCopy.mSubType) - { - } - - ~${class}Exception() throw () - { - } - - enum - { - ExceptionType = $class_number - }; - - enum - { -__E - -for(my $e = 0; $e <= $#exception; $e++) -{ - if($exception[$e] ne '') - { - print H "\t\t".$exception[$e].' = '.$e.(($e==$#exception)?'':',')."\n" - } -} - -print H <<__E; - }; - - virtual unsigned int GetType() const throw(); - virtual unsigned int GetSubType() const throw(); - virtual const char *what() const throw(); - -private: - unsigned int mSubType; -}; - -#endif // $guardname -__E - -# ----------------------------------------------------------------------------------------------------------- - -print CPP <<__E; - -// Auto-generated file -- do not edit - -#include "Box.h" -#include "autogen_${class}Exception.h" - -#include "MemLeakFindOn.h" - -#ifdef EXCEPTION_CODENAMES_EXTENDED - #ifdef EXCEPTION_CODENAMES_EXTENDED_WITH_DESCRIPTION -static const char *whats[] = { -__E - -my $last_seen = -1; -for(my $e = 0; $e <= $#exception; $e++) -{ - if($exception[$e] ne '') - { - for(my $s = $last_seen + 1; $s < $e; $s++) - { - print CPP "\t\"UNUSED\",\n" - } - my $ext = ($exception_desc[$e] ne '')?" ($exception_desc[$e])":''; - print CPP "\t\"${class} ".$exception[$e].$ext.'"'.(($e==$#exception)?'':',')."\n"; - $last_seen = $e; - } -} - -print CPP <<__E; -}; - #else -static const char *whats[] = { -__E - -$last_seen = -1; -for(my $e = 0; $e <= $#exception; $e++) -{ - if($exception[$e] ne '') - { - for(my $s = $last_seen + 1; $s < $e; $s++) - { - print CPP "\t\"UNUSED\",\n" - } - print CPP "\t\"${class} ".$exception[$e].'"'.(($e==$#exception)?'':',')."\n"; - $last_seen = $e; - } -} - -print CPP <<__E; -}; - #endif -#endif - -unsigned int ${class}Exception::GetType() const throw() -{ - return ${class}Exception::ExceptionType; -} - -unsigned int ${class}Exception::GetSubType() const throw() -{ - return mSubType; -} - -const char *${class}Exception::what() const throw() -{ -#ifdef EXCEPTION_CODENAMES_EXTENDED - if(mSubType < 0 || mSubType > (sizeof(whats) / sizeof(whats[0]))) - { - return "${class}"; - } - return whats[mSubType]; -#else - return "${class}"; -#endif -} - -__E - -close H; -close CPP; - -# update the global exception list -my $list_before; -my $list_after; -my $is_after = 0; -if(open CURRENT,$global_list) -{ - while() - { - next if m/\A#/; - - if(m/\AEXCEPTION TYPE (\w+) (\d+)/) - { - # check that the number isn't being reused - if($2 == $class_number && $1 ne $class) - { - die "Class number $class_number is being used by $class and $1 -- correct this.\n"; - } - if($2 > $class_number) - { - # This class comes after the current one (ensures numerical ordering) - $is_after = 1; - } - if($1 eq $class) - { - # skip this entry - while() - { - last if m/\AEND TYPE/; - } - $_ = ''; - } - } - - if($is_after) - { - $list_after .= $_; - } - else - { - $list_before .= $_; - } - } - - close CURRENT; -} - -open GLOBAL,">$global_list" or die "Can't open global exception code listing for writing"; - -print GLOBAL <<__E; -# -# automatically generated file, do not edit. -# -# This file lists all the exception codes used by the system. -# Use to look up more detailed descriptions of meanings of errors. -# -__E - -print GLOBAL $list_before; - -print GLOBAL "EXCEPTION TYPE $class $class_number\n"; -for(my $e = 0; $e <= $#exception; $e++) -{ - if($exception[$e] ne '') - { - my $ext = ($exception_desc[$e] ne '')?" - $exception_desc[$e]":''; - print GLOBAL "($class_number/$e) - ${class} ".$exception[$e].$ext."\n"; - } -} -print GLOBAL "END TYPE\n"; - -print GLOBAL $list_after; - -close GLOBAL; - - diff --git a/lib/common/makeexception.pl.in b/lib/common/makeexception.pl.in new file mode 100755 index 00000000..1564b75b --- /dev/null +++ b/lib/common/makeexception.pl.in @@ -0,0 +1,277 @@ +#!@PERL@ + +# global exception list file +my $global_list = '../../ExceptionCodes.txt'; + + +my @exception; +my @exception_desc; +my $class; +my $class_number; + +# read the description! + +open EXCEPTION_DESC,$ARGV[0] or die "Can't open $ARGV[0]"; + +while() +{ + chomp; s/\A\s+//; s/#.+\Z//; s/\s+\Z//; s/\s+/ /g; + next unless m/\S/; + + if(m/\AEXCEPTION\s+(.+)\s+(\d+)\Z/) + { + $class = $1; + $class_number = $2; + } + else + { + my ($name,$number,$description) = split /\s+/,$_,3; + if($name eq '' || $number =~ m/\D/) + { + die "Bad line '$_'"; + } + if($exception[$number] ne '') + { + die "Duplicate exception number $number"; + } + $exception[$number] = $name; + $exception_desc[$number] = $description; + } +} + +die "Exception class and number not specified" unless $class ne '' && $class_number ne ''; + +close EXCEPTION_DESC; + +# write the code +print "Generating $class exception...\n"; + +open CPP,">autogen_${class}Exception.cpp" or die "Can't open cpp file for writing"; +open H,">autogen_${class}Exception.h" or die "Can't open h file for writing"; + +# write header file +my $guardname = uc 'AUTOGEN_'.$class.'EXCEPTION_H'; +print H <<__E; + +// Auto-generated file -- do not edit + +#ifndef $guardname +#define $guardname + +#include "BoxException.h" + +// -------------------------------------------------------------------------- +// +// Class +// Name: ${class}Exception +// Purpose: Exception +// Created: autogen +// +// -------------------------------------------------------------------------- +class ${class}Exception : public BoxException +{ +public: + ${class}Exception(unsigned int SubType) + : mSubType(SubType) + { + } + + ${class}Exception(const ${class}Exception &rToCopy) + : mSubType(rToCopy.mSubType) + { + } + + ~${class}Exception() throw () + { + } + + enum + { + ExceptionType = $class_number + }; + + enum + { +__E + +for(my $e = 0; $e <= $#exception; $e++) +{ + if($exception[$e] ne '') + { + print H "\t\t".$exception[$e].' = '.$e.(($e==$#exception)?'':',')."\n" + } +} + +print H <<__E; + }; + + virtual unsigned int GetType() const throw(); + virtual unsigned int GetSubType() const throw(); + virtual const char *what() const throw(); + +private: + unsigned int mSubType; +}; + +#endif // $guardname +__E + +# ----------------------------------------------------------------------------------------------------------- + +print CPP <<__E; + +// Auto-generated file -- do not edit + +#include "Box.h" +#include "autogen_${class}Exception.h" + +#include "MemLeakFindOn.h" + +#ifdef EXCEPTION_CODENAMES_EXTENDED + #ifdef EXCEPTION_CODENAMES_EXTENDED_WITH_DESCRIPTION +static const char *whats[] = { +__E + +my $last_seen = -1; +for(my $e = 0; $e <= $#exception; $e++) +{ + if($exception[$e] ne '') + { + for(my $s = $last_seen + 1; $s < $e; $s++) + { + print CPP "\t\"UNUSED\",\n" + } + my $ext = ($exception_desc[$e] ne '')?" ($exception_desc[$e])":''; + print CPP "\t\"${class} ".$exception[$e].$ext.'"'.(($e==$#exception)?'':',')."\n"; + $last_seen = $e; + } +} + +print CPP <<__E; +}; + #else +static const char *whats[] = { +__E + +$last_seen = -1; +for(my $e = 0; $e <= $#exception; $e++) +{ + if($exception[$e] ne '') + { + for(my $s = $last_seen + 1; $s < $e; $s++) + { + print CPP "\t\"UNUSED\",\n" + } + print CPP "\t\"${class} ".$exception[$e].'"'.(($e==$#exception)?'':',')."\n"; + $last_seen = $e; + } +} + +print CPP <<__E; +}; + #endif +#endif + +unsigned int ${class}Exception::GetType() const throw() +{ + return ${class}Exception::ExceptionType; +} + +unsigned int ${class}Exception::GetSubType() const throw() +{ + return mSubType; +} + +const char *${class}Exception::what() const throw() +{ +#ifdef EXCEPTION_CODENAMES_EXTENDED + if(mSubType < 0 || mSubType > (sizeof(whats) / sizeof(whats[0]))) + { + return "${class}"; + } + return whats[mSubType]; +#else + return "${class}"; +#endif +} + +__E + +close H; +close CPP; + +# update the global exception list +my $list_before; +my $list_after; +my $is_after = 0; +if(open CURRENT,$global_list) +{ + while() + { + next if m/\A#/; + + if(m/\AEXCEPTION TYPE (\w+) (\d+)/) + { + # check that the number isn't being reused + if($2 == $class_number && $1 ne $class) + { + die "Class number $class_number is being used by $class and $1 -- correct this.\n"; + } + if($2 > $class_number) + { + # This class comes after the current one (ensures numerical ordering) + $is_after = 1; + } + if($1 eq $class) + { + # skip this entry + while() + { + last if m/\AEND TYPE/; + } + $_ = ''; + } + } + + if($is_after) + { + $list_after .= $_; + } + else + { + $list_before .= $_; + } + } + + close CURRENT; +} + +open GLOBAL,">$global_list" or die "Can't open global exception code listing for writing"; + +print GLOBAL <<__E; +# +# automatically generated file, do not edit. +# +# This file lists all the exception codes used by the system. +# Use to look up more detailed descriptions of meanings of errors. +# +__E + +print GLOBAL $list_before; + +print GLOBAL "EXCEPTION TYPE $class $class_number\n"; +for(my $e = 0; $e <= $#exception; $e++) +{ + if($exception[$e] ne '') + { + my $ext = ($exception_desc[$e] ne '')?" - $exception_desc[$e]":''; + print GLOBAL "($class_number/$e) - ${class} ".$exception[$e].$ext."\n"; + } +} +print GLOBAL "END TYPE\n"; + +print GLOBAL $list_after; + +close GLOBAL; + + diff --git a/lib/raidfile/raidfile-config b/lib/raidfile/raidfile-config deleted file mode 100755 index f1098adc..00000000 --- a/lib/raidfile/raidfile-config +++ /dev/null @@ -1,97 +0,0 @@ -#!@PERL@ -use strict; - -# should be running as root -if($> != 0) -{ - printf "\nWARNING: this should be run as root\n\n" -} - -# check and get command line parameters -if($#ARGV != 4 && $#ARGV != 2) -{ - print <<__E; - -Setup raidfile config utility. - -Bad command line parameters. -Usage: - raidfile-config config-dir block-size dir0 [dir1 dir2] - -config-dir usually /etc/box -block-size must be a power of two, and usually the block or fragment size of your filing system -dir0, dir1, dir2 are the directories used as the root of the raid file system - -If only one directory is specified, then userland RAID is disabled. Specifying three directories -enables it. - -__E - exit(1); -} - -my ($config_dir,$block_size,@dirs) = @ARGV; - -my $conf = $config_dir . '/raidfile.conf'; - -# check dirs are unique, and exist -my %d; -for(@dirs) -{ - die "$_ is used twice" if exists $d{$_}; - die "$_ is not a directory" unless -d $_; - die "$_ should be an absolute path" unless m/\A\//; - $d{$_} = 1; -} - -# check block size is OK -$block_size = int($block_size); -die "Bad block size" if $block_size <= 0; -my $c = 1; -while(1) -{ - last if $c == $block_size; - die "Block size $block_size is not a power of two" if $c > $block_size; - $c = $c * 2; -} - -# check that it doesn't already exist -if(-f $conf) -{ - die "$conf already exists. Delete and try again" -} - -# create directory -if(!-d $config_dir) -{ - print "Creating $config_dir...\n"; - mkdir $config_dir,0755 or die "Can't create $config_dir"; -} - -# adjust if userland RAID is disabled -if($#dirs == 0) -{ - $dirs[1] = $dirs[0]; - $dirs[2] = $dirs[0]; - print "WARNING: userland RAID is disabled.\n" -} - -# write the file -open CONFIG,">$conf" or die "Can't open $conf for writing"; - -print CONFIG <<__E; - -disc0 -{ - SetNumber = 0 - BlockSize = $block_size - Dir0 = $dirs[0] - Dir1 = $dirs[1] - Dir2 = $dirs[2] -} - -__E - -close CONFIG; - -print "Config file written.\n"; - diff --git a/lib/raidfile/raidfile-config.in b/lib/raidfile/raidfile-config.in new file mode 100755 index 00000000..f1098adc --- /dev/null +++ b/lib/raidfile/raidfile-config.in @@ -0,0 +1,97 @@ +#!@PERL@ +use strict; + +# should be running as root +if($> != 0) +{ + printf "\nWARNING: this should be run as root\n\n" +} + +# check and get command line parameters +if($#ARGV != 4 && $#ARGV != 2) +{ + print <<__E; + +Setup raidfile config utility. + +Bad command line parameters. +Usage: + raidfile-config config-dir block-size dir0 [dir1 dir2] + +config-dir usually /etc/box +block-size must be a power of two, and usually the block or fragment size of your filing system +dir0, dir1, dir2 are the directories used as the root of the raid file system + +If only one directory is specified, then userland RAID is disabled. Specifying three directories +enables it. + +__E + exit(1); +} + +my ($config_dir,$block_size,@dirs) = @ARGV; + +my $conf = $config_dir . '/raidfile.conf'; + +# check dirs are unique, and exist +my %d; +for(@dirs) +{ + die "$_ is used twice" if exists $d{$_}; + die "$_ is not a directory" unless -d $_; + die "$_ should be an absolute path" unless m/\A\//; + $d{$_} = 1; +} + +# check block size is OK +$block_size = int($block_size); +die "Bad block size" if $block_size <= 0; +my $c = 1; +while(1) +{ + last if $c == $block_size; + die "Block size $block_size is not a power of two" if $c > $block_size; + $c = $c * 2; +} + +# check that it doesn't already exist +if(-f $conf) +{ + die "$conf already exists. Delete and try again" +} + +# create directory +if(!-d $config_dir) +{ + print "Creating $config_dir...\n"; + mkdir $config_dir,0755 or die "Can't create $config_dir"; +} + +# adjust if userland RAID is disabled +if($#dirs == 0) +{ + $dirs[1] = $dirs[0]; + $dirs[2] = $dirs[0]; + print "WARNING: userland RAID is disabled.\n" +} + +# write the file +open CONFIG,">$conf" or die "Can't open $conf for writing"; + +print CONFIG <<__E; + +disc0 +{ + SetNumber = 0 + BlockSize = $block_size + Dir0 = $dirs[0] + Dir1 = $dirs[1] + Dir2 = $dirs[2] +} + +__E + +close CONFIG; + +print "Config file written.\n"; + diff --git a/lib/server/makeprotocol.pl b/lib/server/makeprotocol.pl deleted file mode 100755 index 3dce6118..00000000 --- a/lib/server/makeprotocol.pl +++ /dev/null @@ -1,997 +0,0 @@ -#!@PERL@ -use strict; - -# Make protocol C++ classes from a protocol description file - -# built in type info (values are is basic type, C++ typename) -# may get stuff added to it later if protocol uses extra types -my %translate_type_info = -( - 'int64' => [1, 'int64_t'], - 'int32' => [1, 'int32_t'], - 'int16' => [1, 'int16_t'], - 'int8' => [1, 'int8_t'], - 'bool' => [1, 'bool'], - 'string' => [0, 'std::string'] -); - -# built in instructions for logging various types -# may be added to -my %log_display_types = -( - 'int64' => ['0x%llx', 'VAR'], - 'int32' => ['0x%x', 'VAR'], - 'int16' => ['0x%x', 'VAR'], - 'int8' => ['0x%x', 'VAR'], - 'bool' => ['%s', '((VAR)?"true":"false")'], - 'string' => ['%s', 'VAR.c_str()'] -); - - - -my ($type, $file) = @ARGV; - -if($type ne 'Server' && $type ne 'Client') -{ - die "Neither Server or Client is specified on command line\n"; -} - -open IN, $file or die "Can't open input file $file\n"; - -print "Making $type protocol classes from $file...\n"; - -my @extra_header_files; - -my $implement_syslog = 0; -my $implement_filelog = 0; - -# read attributes -my %attr; -while() -{ - # get and clean line - my $l = $_; $l =~ s/#.*\Z//; $l =~ s/\A\s+//; $l =~ s/\s+\Z//; next unless $l =~ m/\S/; - - last if $l eq 'BEGIN_OBJECTS'; - - my ($k,$v) = split /\s+/,$l,2; - - if($k eq 'ClientType') - { - add_type($v) if $type eq 'Client'; - } - elsif($k eq 'ServerType') - { - add_type($v) if $type eq 'Server'; - } - elsif($k eq 'ImplementLog') - { - my ($log_if_type,$log_type) = split /\s+/,$v; - if($type eq $log_if_type) - { - if($log_type eq 'syslog') - { - $implement_syslog = 1; - } - elsif($log_type eq 'file') - { - $implement_filelog = 1; - } - else - { - printf("ERROR: Unknown log type for implementation: $log_type\n"); - exit(1); - } - } - } - elsif($k eq 'LogTypeToText') - { - my ($log_if_type,$type_name,$printf_format,$arg_template) = split /\s+/,$v; - if($type eq $log_if_type) - { - $log_display_types{$type_name} = [$printf_format,$arg_template] - } - } - else - { - $attr{$k} = $v; - } -} - -sub add_type -{ - my ($protocol_name, $cpp_name, $header_file) = split /\s+/,$_[0]; - - $translate_type_info{$protocol_name} = [0, $cpp_name]; - push @extra_header_files, $header_file; -} - -# check attributes -for(qw/Name ServerContextClass IdentString/) -{ - if(!exists $attr{$_}) - { - die "Attribute $_ is required, but not specified\n"; - } -} - -my $protocol_name = $attr{'Name'}; -my ($context_class, $context_class_inc) = split /\s+/,$attr{'ServerContextClass'}; -my $ident_string = $attr{'IdentString'}; - -my $current_cmd = ''; -my %cmd_contents; -my %cmd_attributes; -my %cmd_constants; -my %cmd_id; -my @cmd_list; - -# read in the command definitions -while() -{ - # get and clean line - my $l = $_; $l =~ s/#.*\Z//; $l =~ s/\s+\Z//; next unless $l =~ m/\S/; - - # definitions or new command thing? - if($l =~ m/\A\s+/) - { - die "No command defined yet" if $current_cmd eq ''; - - # definition of component - $l =~ s/\A\s+//; - - my ($type,$name,$value) = split /\s+/,$l; - if($type eq 'CONSTANT') - { - push @{$cmd_constants{$current_cmd}},"$name = $value" - } - else - { - push @{$cmd_contents{$current_cmd}},$type,$name; - } - } - else - { - # new command - my ($name,$id,@attributes) = split /\s+/,$l; - $cmd_attributes{$name} = [@attributes]; - $cmd_id{$name} = int($id); - $current_cmd = $name; - push @cmd_list,$name; - } -} - -close IN; - - - -# open files -my $h_filename = 'autogen_'.$protocol_name.'Protocol'.$type.'.h'; -open CPP,'>autogen_'.$protocol_name.'Protocol'.$type.'.cpp'; -open H,">$h_filename"; - -print CPP <<__E; - -// Auto-generated file -- do not edit - -#include "Box.h" -#include "$h_filename" -#include "IOStream.h" - -__E - -if($implement_syslog) -{ - print H < -#endif -EOF -} - - -my $guardname = uc 'AUTOGEN_'.$protocol_name.'Protocol'.$type.'_H'; -print H <<__E; - -// Auto-generated file -- do not edit - -#ifndef $guardname -#define $guardname - -#include "Protocol.h" -#include "ProtocolObject.h" -#include "ServerException.h" - -class IOStream; - -__E - -if($implement_filelog) -{ - print H qq~#include \n~; -} - -# extra headers -for(@extra_header_files) -{ - print H qq~#include "$_"\n~ -} -print H "\n"; - -if($type eq 'Server') -{ - # need utils file for the server - print H '#include "Utils.h"',"\n\n" -} - - -my $derive_objects_from = 'ProtocolObject'; -my $objects_extra_h = ''; -my $objects_extra_cpp = ''; -if($type eq 'Server') -{ - # define the context - print H "class $context_class;\n\n"; - print CPP "#include \"$context_class_inc\"\n\n"; - - # change class we derive the objects from - $derive_objects_from = $protocol_name.'ProtocolObject'; - - $objects_extra_h = <<__E; - virtual std::auto_ptr DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext); -__E - $objects_extra_cpp = <<__E; -std::auto_ptr ${derive_objects_from}::DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext) -{ - THROW_EXCEPTION(ConnectionException, Conn_Protocol_TriedToExecuteReplyCommand) -} -__E -} - -print CPP qq~#include "MemLeakFindOn.h"\n~; - -if($type eq 'Client' && ($implement_syslog || $implement_filelog)) -{ - # change class we derive the objects from - $derive_objects_from = $protocol_name.'ProtocolObjectCl'; -} -if($implement_syslog) -{ - $objects_extra_h .= <<__E; - virtual void LogSysLog(const char *Action) const = 0; -__E -} -if($implement_filelog) -{ - $objects_extra_h .= <<__E; - virtual void LogFile(const char *Action, FILE *file) const = 0; -__E -} - -if($derive_objects_from ne 'ProtocolObject') -{ - # output a definition for the protocol object derviced class - print H <<__E; -class ${protocol_name}ProtocolServer; - -class $derive_objects_from : public ProtocolObject -{ -public: - $derive_objects_from(); - virtual ~$derive_objects_from(); - $derive_objects_from(const $derive_objects_from &rToCopy); - -$objects_extra_h -}; -__E - - # and some cpp definitions - print CPP <<__E; -${derive_objects_from}::${derive_objects_from}() -{ -} -${derive_objects_from}::~${derive_objects_from}() -{ -} -${derive_objects_from}::${derive_objects_from}(const $derive_objects_from &rToCopy) -{ -} -$objects_extra_cpp -__E -} - - - -my $classname_base = $protocol_name.'Protocol'.$type; - -# output the classes -for my $cmd (@cmd_list) -{ - print H <<__E; -class $classname_base$cmd : public $derive_objects_from -{ -public: - $classname_base$cmd(); - $classname_base$cmd(const $classname_base$cmd &rToCopy); - ~$classname_base$cmd(); - int GetType() const; - enum - { - TypeID = $cmd_id{$cmd} - }; -__E - # constants - if(exists $cmd_constants{$cmd}) - { - print H "\tenum\n\t{\n\t\t"; - print H join(",\n\t\t",@{$cmd_constants{$cmd}}); - print H "\n\t};\n"; - } - # flags - if(obj_is_type($cmd,'EndsConversation')) - { - print H "\tbool IsConversationEnd() const;\n"; - } - if(obj_is_type($cmd,'IsError')) - { - print H "\tbool IsError(int &rTypeOut, int &rSubTypeOut) const;\n"; - } - if($type eq 'Server' && obj_is_type($cmd, 'Command')) - { - print H "\tstd::auto_ptr DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext); // IMPLEMENT THIS\n" - } - - # want to be able to read from streams? - my $read_from_streams = (obj_is_type($cmd,'Command') && $type eq 'Server') || (obj_is_type($cmd,'Reply') && $type eq 'Client'); - my $write_to_streams = (obj_is_type($cmd,'Command') && $type eq 'Client') || (obj_is_type($cmd,'Reply') && $type eq 'Server'); - - if($read_from_streams) - { - print H "\tvoid SetPropertiesFromStreamData(Protocol &rProtocol);\n"; - - # write Get functions - for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) - { - my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); - - print H "\t".translate_type_to_arg_type($ty)." Get$nm() {return m$nm;}\n"; - } - } - my $param_con_args = ''; - if($write_to_streams) - { - # extra constructor? - if($#{$cmd_contents{$cmd}} >= 0) - { - my @a; - for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) - { - my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); - - push @a,translate_type_to_arg_type($ty)." $nm"; - } - $param_con_args = join(', ',@a); - print H "\t$classname_base$cmd(".$param_con_args.");\n"; - } - print H "\tvoid WritePropertiesToStreamData(Protocol &rProtocol) const;\n"; - # set functions - for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) - { - my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); - - print H "\tvoid Set$nm(".translate_type_to_arg_type($ty)." $nm) {m$nm = $nm;}\n"; - } - } - - if($implement_syslog) - { - print H "\tvirtual void LogSysLog(const char *Action) const;\n"; - } - if($implement_filelog) - { - print H "\tvirtual void LogFile(const char *Action, FILE *file) const;\n"; - } - - - # write member variables and setup for cpp file - my @def_constructor_list; - my @copy_constructor_list; - my @param_constructor_list; - - print H "private:\n"; - for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) - { - my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); - - print H "\t".translate_type_to_member_type($ty)." m$nm;\n"; - - my ($basic,$typename) = translate_type($ty); - if($basic) - { - push @def_constructor_list, "m$nm(0)"; - } - push @copy_constructor_list, "m$nm(rToCopy.m$nm)"; - push @param_constructor_list, "m$nm($nm)"; - } - - # finish off - print H "};\n\n"; - - # now the cpp file... - my $def_con_vars = join(",\n\t ",@def_constructor_list); - $def_con_vars = "\n\t: ".$def_con_vars if $def_con_vars ne ''; - my $copy_con_vars = join(",\n\t ",@copy_constructor_list); - $copy_con_vars = "\n\t: ".$copy_con_vars if $copy_con_vars ne ''; - my $param_con_vars = join(",\n\t ",@param_constructor_list); - $param_con_vars = "\n\t: ".$param_con_vars if $param_con_vars ne ''; - - my $class = "$classname_base$cmd".'::'; - print CPP <<__E; -$class$classname_base$cmd()$def_con_vars -{ -} -$class$classname_base$cmd(const $classname_base$cmd &rToCopy)$copy_con_vars -{ -} -$class~$classname_base$cmd() -{ -} -int ${class}GetType() const -{ - return $cmd_id{$cmd}; -} -__E - if($read_from_streams) - { - print CPP "void ${class}SetPropertiesFromStreamData(Protocol &rProtocol)\n{\n"; - for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) - { - my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); - if($ty =~ m/\Avector/) - { - print CPP "\trProtocol.ReadVector(m$nm);\n"; - } - else - { - print CPP "\trProtocol.Read(m$nm);\n"; - } - } - print CPP "}\n"; - } - if($write_to_streams) - { - # implement extra constructor? - if($param_con_vars ne '') - { - print CPP "$class$classname_base$cmd($param_con_args)$param_con_vars\n{\n}\n"; - } - print CPP "void ${class}WritePropertiesToStreamData(Protocol &rProtocol) const\n{\n"; - for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) - { - my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); - if($ty =~ m/\Avector/) - { - print CPP "\trProtocol.WriteVector(m$nm);\n"; - } - else - { - print CPP "\trProtocol.Write(m$nm);\n"; - } - } - print CPP "}\n"; - } - if(obj_is_type($cmd,'EndsConversation')) - { - print CPP "bool ${class}IsConversationEnd() const\n{\n\treturn true;\n}\n"; - } - if(obj_is_type($cmd,'IsError')) - { - # get parameters - my ($mem_type,$mem_subtype) = split /,/,obj_get_type_params($cmd,'IsError'); - print CPP <<__E; -bool ${class}IsError(int &rTypeOut, int &rSubTypeOut) const -{ - rTypeOut = m$mem_type; - rSubTypeOut = m$mem_subtype; - return true; -} -__E - } - - if($implement_syslog) - { - my ($format,$args) = make_log_strings($cmd); - print CPP <<__E; -void ${class}LogSysLog(const char *Action) const -{ - ::syslog(LOG_INFO,"%s $format",Action$args); -} -__E - } - if($implement_filelog) - { - my ($format,$args) = make_log_strings($cmd); - print CPP <<__E; -void ${class}LogFile(const char *Action, FILE *File) const -{ - ::fprintf(File,"%s $format\\n",Action$args); - ::fflush(File); -} -__E - } -} - -# finally, the protocol object itself -print H <<__E; -class $classname_base : public Protocol -{ -public: - $classname_base(IOStream &rStream); - virtual ~$classname_base(); - - std::auto_ptr<$derive_objects_from> Receive(); - void Send(const ${derive_objects_from} &rObject); -__E -if($implement_syslog) -{ - print H "\tvoid SetLogToSysLog(bool Log = false) {mLogToSysLog = Log;}\n"; -} -if($implement_filelog) -{ - print H "\tvoid SetLogToFile(FILE *File = 0) {mLogToFile = File;}\n"; -} -if($type eq 'Server') -{ - # need to put in the conversation function - print H "\tvoid DoServer($context_class &rContext);\n\n"; - # and the send vector thing - print H "\tvoid SendStreamAfterCommand(IOStream *pStream);\n\n"; -} -if($type eq 'Client') -{ - # add plain object taking query functions - my $with_params; - for my $cmd (@cmd_list) - { - if(obj_is_type($cmd,'Command')) - { - my $has_stream = obj_is_type($cmd,'StreamWithCommand'); - my $argextra = $has_stream?', IOStream &rStream':''; - my $queryextra = $has_stream?', rStream':''; - my $reply = obj_get_type_params($cmd,'Command'); - print H "\tstd::auto_ptr<$classname_base$reply> Query(const $classname_base$cmd &rQuery$argextra);\n"; - my @a; - my @na; - for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) - { - my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); - push @a,translate_type_to_arg_type($ty)." $nm"; - push @na,"$nm"; - } - my $ar = join(', ',@a); - my $nar = join(', ',@na); - $nar = "($nar)" if $nar ne ''; - - $with_params .= "\tinline std::auto_ptr<$classname_base$reply> Query$cmd($ar$argextra)\n\t{\n"; - $with_params .= "\t\t$classname_base$cmd send$nar;\n"; - $with_params .= "\t\treturn Query(send$queryextra);\n"; - $with_params .= "\t}\n"; - } - } - # quick hack to correct bad argument lists for commands with zero paramters but with streams - $with_params =~ s/\(, /(/g; - print H "\n",$with_params,"\n"; -} -print H <<__E; -private: - $classname_base(const $classname_base &rToCopy); -__E -if($type eq 'Server') -{ - # need to put the streams to send vector - print H "\tstd::vector mStreamsToSend;\n\tvoid DeleteStreamsToSend();\n"; -} - -if($implement_filelog || $implement_syslog) -{ - print H <<__E; - virtual void InformStreamReceiving(u_int32_t Size); - virtual void InformStreamSending(u_int32_t Size); -__E -} - -if($implement_syslog) -{ - print H "private:\n\tbool mLogToSysLog;\n"; -} -if($implement_filelog) -{ - print H "private:\n\tFILE *mLogToFile;\n"; -} -print H <<__E; - -protected: - virtual std::auto_ptr MakeProtocolObject(int ObjType); - virtual const char *GetIdentString(); -}; - -__E - -my $construtor_extra = ''; -$construtor_extra .= ', mLogToSysLog(false)' if $implement_syslog; -$construtor_extra .= ', mLogToFile(0)' if $implement_filelog; - -my $destructor_extra = ($type eq 'Server')?"\n\tDeleteStreamsToSend();":''; - -my $prefix = $classname_base.'::'; -print CPP <<__E; -$prefix$classname_base(IOStream &rStream) - : Protocol(rStream)$construtor_extra -{ -} -$prefix~$classname_base() -{$destructor_extra -} -const char *${prefix}GetIdentString() -{ - return "$ident_string"; -} -std::auto_ptr ${prefix}MakeProtocolObject(int ObjType) -{ - switch(ObjType) - { -__E - -# do objects within this -for my $cmd (@cmd_list) -{ - print CPP <<__E; - case $cmd_id{$cmd}: - return std::auto_ptr(new $classname_base$cmd); - break; -__E -} - -print CPP <<__E; - default: - THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnknownCommandRecieved) - } -} -__E -# write receieve and send functions -print CPP <<__E; -std::auto_ptr<$derive_objects_from> ${prefix}Receive() -{ - std::auto_ptr<${derive_objects_from}> preply((${derive_objects_from}*)(Protocol::Receive().release())); - -__E - if($implement_syslog) - { - print CPP <<__E; - if(mLogToSysLog) - { - preply->LogSysLog("Receive"); - } -__E - } - if($implement_filelog) - { - print CPP <<__E; - if(mLogToFile != 0) - { - preply->LogFile("Receive", mLogToFile); - } -__E - } -print CPP <<__E; - - return preply; -} - -void ${prefix}Send(const ${derive_objects_from} &rObject) -{ -__E - if($implement_syslog) - { - print CPP <<__E; - if(mLogToSysLog) - { - rObject.LogSysLog("Send"); - } -__E - } - if($implement_filelog) - { - print CPP <<__E; - if(mLogToFile != 0) - { - rObject.LogFile("Send", mLogToFile); - } -__E - } - -print CPP <<__E; - Protocol::Send(rObject); -} - -__E -# write server function? -if($type eq 'Server') -{ - print CPP <<__E; -void ${prefix}DoServer($context_class &rContext) -{ - // Handshake with client - Handshake(); - - // Command processing loop - bool inProgress = true; - while(inProgress) - { - // Get an object from the conversation - std::auto_ptr<${derive_objects_from}> pobj(Receive()); - -__E - if($implement_syslog) - { - print CPP <<__E; - if(mLogToSysLog) - { - pobj->LogSysLog("Receive"); - } -__E - } - if($implement_filelog) - { - print CPP <<__E; - if(mLogToFile != 0) - { - pobj->LogFile("Receive", mLogToFile); - } -__E - } - print CPP <<__E; - - // Run the command - std::auto_ptr<${derive_objects_from}> preply((${derive_objects_from}*)(pobj->DoCommand(*this, rContext).release())); - -__E - if($implement_syslog) - { - print CPP <<__E; - if(mLogToSysLog) - { - preply->LogSysLog("Send"); - } -__E - } - if($implement_filelog) - { - print CPP <<__E; - if(mLogToFile != 0) - { - preply->LogFile("Send", mLogToFile); - } -__E - } - print CPP <<__E; - - // Send the reply - Send(*(preply.get())); - - // Send any streams - for(unsigned int s = 0; s < mStreamsToSend.size(); s++) - { - // Send the streams - SendStream(*mStreamsToSend[s]); - } - // Delete these streams - DeleteStreamsToSend(); - - // Does this end the conversation? - if(pobj->IsConversationEnd()) - { - inProgress = false; - } - } -} - -void ${prefix}SendStreamAfterCommand(IOStream *pStream) -{ - ASSERT(pStream != NULL); - mStreamsToSend.push_back(pStream); -} - -void ${prefix}DeleteStreamsToSend() -{ - for(std::vector::iterator i(mStreamsToSend.begin()); i != mStreamsToSend.end(); ++i) - { - delete (*i); - } - mStreamsToSend.clear(); -} - -__E -} - -# write logging functions? -if($implement_filelog || $implement_syslog) -{ - my ($fR,$fS); - - if($implement_syslog) - { - $fR .= qq~\tif(mLogToSysLog) { ::syslog(LOG_INFO, (Size==Protocol::ProtocolStream_SizeUncertain)?"Receiving stream, size uncertain":"Receiving stream, size %d", Size); }\n~; - $fS .= qq~\tif(mLogToSysLog) { ::syslog(LOG_INFO, (Size==Protocol::ProtocolStream_SizeUncertain)?"Sending stream, size uncertain":"Sending stream, size %d", Size); }\n~; - } - if($implement_filelog) - { - $fR .= qq~\tif(mLogToFile) { ::fprintf(mLogToFile, (Size==Protocol::ProtocolStream_SizeUncertain)?"Receiving stream, size uncertain":"Receiving stream, size %d\\n", Size); ::fflush(mLogToFile); }\n~; - $fS .= qq~\tif(mLogToFile) { ::fprintf(mLogToFile, (Size==Protocol::ProtocolStream_SizeUncertain)?"Sending stream, size uncertain":"Sending stream, size %d\\n", Size); ::fflush(mLogToFile); }\n~; - } - - print CPP <<__E; - -void ${prefix}InformStreamReceiving(u_int32_t Size) -{ -$fR} - -void ${prefix}InformStreamSending(u_int32_t Size) -{ -$fS} - -__E -} - - -# write client Query functions? -if($type eq 'Client') -{ - for my $cmd (@cmd_list) - { - if(obj_is_type($cmd,'Command')) - { - my $reply = obj_get_type_params($cmd,'Command'); - my $reply_id = $cmd_id{$reply}; - my $has_stream = obj_is_type($cmd,'StreamWithCommand'); - my $argextra = $has_stream?', IOStream &rStream':''; - my $send_stream_extra = ''; - if($has_stream) - { - $send_stream_extra = <<__E; - - // Send stream after the command - SendStream(rStream); -__E - } - print CPP <<__E; -std::auto_ptr<$classname_base$reply> ${classname_base}::Query(const $classname_base$cmd &rQuery$argextra) -{ - // Send query - Send(rQuery); - $send_stream_extra - // Wait for the reply - std::auto_ptr<${derive_objects_from}> preply(Receive().release()); - - if(preply->GetType() == $reply_id) - { - // Correct response - return std::auto_ptr<$classname_base$reply>(($classname_base$reply*)preply.release()); - } - else - { - // Set protocol error - int type, subType; - if(preply->IsError(type, subType)) - { - SetError(type, subType); - TRACE2("Protocol: Error received %d/%d\\n", type, subType); - } - else - { - SetError(Protocol::UnknownError, Protocol::UnknownError); - } - - // Throw an exception - THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnexpectedReply) - } -} -__E - } - } -} - - - -print H <<__E; -#endif // $guardname - -__E - -# close files -close H; -close CPP; - - -sub obj_is_type -{ - my ($c,$ty) = @_; - for(@{$cmd_attributes{$c}}) - { - return 1 if $_ =~ m/\A$ty/; - } - - return 0; -} - -sub obj_get_type_params -{ - my ($c,$ty) = @_; - for(@{$cmd_attributes{$c}}) - { - return $1 if $_ =~ m/\A$ty\((.+?)\)\Z/; - } - die "Can't find attribute $ty\n" -} - -# returns (is basic type, typename) -sub translate_type -{ - my $ty = $_[0]; - - if($ty =~ m/\Avector\<(.+?)\>\Z/) - { - my $v_type = $1; - my (undef,$v_ty) = translate_type($v_type); - return (0, 'std::vector<'.$v_ty.'>') - } - else - { - if(!exists $translate_type_info{$ty}) - { - die "Don't know about type name $ty\n"; - } - return @{$translate_type_info{$ty}} - } -} - -sub translate_type_to_arg_type -{ - my ($basic,$typename) = translate_type(@_); - return $basic?$typename:'const '.$typename.'&' -} - -sub translate_type_to_member_type -{ - my ($basic,$typename) = translate_type(@_); - return $typename -} - -sub make_log_strings -{ - my ($cmd) = @_; - - my @str; - my @arg; - for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) - { - my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); - - if(exists $log_display_types{$ty}) - { - # need to translate it - my ($format,$arg) = @{$log_display_types{$ty}}; - push @str,$format; - $arg =~ s/VAR/m$nm/g; - push @arg,$arg; - } - else - { - # is opaque - push @str,'OPAQUE'; - } - } - return ($cmd.'('.join(',',@str).')', join(',','',@arg)); -} - - diff --git a/lib/server/makeprotocol.pl.in b/lib/server/makeprotocol.pl.in new file mode 100755 index 00000000..3dce6118 --- /dev/null +++ b/lib/server/makeprotocol.pl.in @@ -0,0 +1,997 @@ +#!@PERL@ +use strict; + +# Make protocol C++ classes from a protocol description file + +# built in type info (values are is basic type, C++ typename) +# may get stuff added to it later if protocol uses extra types +my %translate_type_info = +( + 'int64' => [1, 'int64_t'], + 'int32' => [1, 'int32_t'], + 'int16' => [1, 'int16_t'], + 'int8' => [1, 'int8_t'], + 'bool' => [1, 'bool'], + 'string' => [0, 'std::string'] +); + +# built in instructions for logging various types +# may be added to +my %log_display_types = +( + 'int64' => ['0x%llx', 'VAR'], + 'int32' => ['0x%x', 'VAR'], + 'int16' => ['0x%x', 'VAR'], + 'int8' => ['0x%x', 'VAR'], + 'bool' => ['%s', '((VAR)?"true":"false")'], + 'string' => ['%s', 'VAR.c_str()'] +); + + + +my ($type, $file) = @ARGV; + +if($type ne 'Server' && $type ne 'Client') +{ + die "Neither Server or Client is specified on command line\n"; +} + +open IN, $file or die "Can't open input file $file\n"; + +print "Making $type protocol classes from $file...\n"; + +my @extra_header_files; + +my $implement_syslog = 0; +my $implement_filelog = 0; + +# read attributes +my %attr; +while() +{ + # get and clean line + my $l = $_; $l =~ s/#.*\Z//; $l =~ s/\A\s+//; $l =~ s/\s+\Z//; next unless $l =~ m/\S/; + + last if $l eq 'BEGIN_OBJECTS'; + + my ($k,$v) = split /\s+/,$l,2; + + if($k eq 'ClientType') + { + add_type($v) if $type eq 'Client'; + } + elsif($k eq 'ServerType') + { + add_type($v) if $type eq 'Server'; + } + elsif($k eq 'ImplementLog') + { + my ($log_if_type,$log_type) = split /\s+/,$v; + if($type eq $log_if_type) + { + if($log_type eq 'syslog') + { + $implement_syslog = 1; + } + elsif($log_type eq 'file') + { + $implement_filelog = 1; + } + else + { + printf("ERROR: Unknown log type for implementation: $log_type\n"); + exit(1); + } + } + } + elsif($k eq 'LogTypeToText') + { + my ($log_if_type,$type_name,$printf_format,$arg_template) = split /\s+/,$v; + if($type eq $log_if_type) + { + $log_display_types{$type_name} = [$printf_format,$arg_template] + } + } + else + { + $attr{$k} = $v; + } +} + +sub add_type +{ + my ($protocol_name, $cpp_name, $header_file) = split /\s+/,$_[0]; + + $translate_type_info{$protocol_name} = [0, $cpp_name]; + push @extra_header_files, $header_file; +} + +# check attributes +for(qw/Name ServerContextClass IdentString/) +{ + if(!exists $attr{$_}) + { + die "Attribute $_ is required, but not specified\n"; + } +} + +my $protocol_name = $attr{'Name'}; +my ($context_class, $context_class_inc) = split /\s+/,$attr{'ServerContextClass'}; +my $ident_string = $attr{'IdentString'}; + +my $current_cmd = ''; +my %cmd_contents; +my %cmd_attributes; +my %cmd_constants; +my %cmd_id; +my @cmd_list; + +# read in the command definitions +while() +{ + # get and clean line + my $l = $_; $l =~ s/#.*\Z//; $l =~ s/\s+\Z//; next unless $l =~ m/\S/; + + # definitions or new command thing? + if($l =~ m/\A\s+/) + { + die "No command defined yet" if $current_cmd eq ''; + + # definition of component + $l =~ s/\A\s+//; + + my ($type,$name,$value) = split /\s+/,$l; + if($type eq 'CONSTANT') + { + push @{$cmd_constants{$current_cmd}},"$name = $value" + } + else + { + push @{$cmd_contents{$current_cmd}},$type,$name; + } + } + else + { + # new command + my ($name,$id,@attributes) = split /\s+/,$l; + $cmd_attributes{$name} = [@attributes]; + $cmd_id{$name} = int($id); + $current_cmd = $name; + push @cmd_list,$name; + } +} + +close IN; + + + +# open files +my $h_filename = 'autogen_'.$protocol_name.'Protocol'.$type.'.h'; +open CPP,'>autogen_'.$protocol_name.'Protocol'.$type.'.cpp'; +open H,">$h_filename"; + +print CPP <<__E; + +// Auto-generated file -- do not edit + +#include "Box.h" +#include "$h_filename" +#include "IOStream.h" + +__E + +if($implement_syslog) +{ + print H < +#endif +EOF +} + + +my $guardname = uc 'AUTOGEN_'.$protocol_name.'Protocol'.$type.'_H'; +print H <<__E; + +// Auto-generated file -- do not edit + +#ifndef $guardname +#define $guardname + +#include "Protocol.h" +#include "ProtocolObject.h" +#include "ServerException.h" + +class IOStream; + +__E + +if($implement_filelog) +{ + print H qq~#include \n~; +} + +# extra headers +for(@extra_header_files) +{ + print H qq~#include "$_"\n~ +} +print H "\n"; + +if($type eq 'Server') +{ + # need utils file for the server + print H '#include "Utils.h"',"\n\n" +} + + +my $derive_objects_from = 'ProtocolObject'; +my $objects_extra_h = ''; +my $objects_extra_cpp = ''; +if($type eq 'Server') +{ + # define the context + print H "class $context_class;\n\n"; + print CPP "#include \"$context_class_inc\"\n\n"; + + # change class we derive the objects from + $derive_objects_from = $protocol_name.'ProtocolObject'; + + $objects_extra_h = <<__E; + virtual std::auto_ptr DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext); +__E + $objects_extra_cpp = <<__E; +std::auto_ptr ${derive_objects_from}::DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext) +{ + THROW_EXCEPTION(ConnectionException, Conn_Protocol_TriedToExecuteReplyCommand) +} +__E +} + +print CPP qq~#include "MemLeakFindOn.h"\n~; + +if($type eq 'Client' && ($implement_syslog || $implement_filelog)) +{ + # change class we derive the objects from + $derive_objects_from = $protocol_name.'ProtocolObjectCl'; +} +if($implement_syslog) +{ + $objects_extra_h .= <<__E; + virtual void LogSysLog(const char *Action) const = 0; +__E +} +if($implement_filelog) +{ + $objects_extra_h .= <<__E; + virtual void LogFile(const char *Action, FILE *file) const = 0; +__E +} + +if($derive_objects_from ne 'ProtocolObject') +{ + # output a definition for the protocol object derviced class + print H <<__E; +class ${protocol_name}ProtocolServer; + +class $derive_objects_from : public ProtocolObject +{ +public: + $derive_objects_from(); + virtual ~$derive_objects_from(); + $derive_objects_from(const $derive_objects_from &rToCopy); + +$objects_extra_h +}; +__E + + # and some cpp definitions + print CPP <<__E; +${derive_objects_from}::${derive_objects_from}() +{ +} +${derive_objects_from}::~${derive_objects_from}() +{ +} +${derive_objects_from}::${derive_objects_from}(const $derive_objects_from &rToCopy) +{ +} +$objects_extra_cpp +__E +} + + + +my $classname_base = $protocol_name.'Protocol'.$type; + +# output the classes +for my $cmd (@cmd_list) +{ + print H <<__E; +class $classname_base$cmd : public $derive_objects_from +{ +public: + $classname_base$cmd(); + $classname_base$cmd(const $classname_base$cmd &rToCopy); + ~$classname_base$cmd(); + int GetType() const; + enum + { + TypeID = $cmd_id{$cmd} + }; +__E + # constants + if(exists $cmd_constants{$cmd}) + { + print H "\tenum\n\t{\n\t\t"; + print H join(",\n\t\t",@{$cmd_constants{$cmd}}); + print H "\n\t};\n"; + } + # flags + if(obj_is_type($cmd,'EndsConversation')) + { + print H "\tbool IsConversationEnd() const;\n"; + } + if(obj_is_type($cmd,'IsError')) + { + print H "\tbool IsError(int &rTypeOut, int &rSubTypeOut) const;\n"; + } + if($type eq 'Server' && obj_is_type($cmd, 'Command')) + { + print H "\tstd::auto_ptr DoCommand(${protocol_name}ProtocolServer &rProtocol, $context_class &rContext); // IMPLEMENT THIS\n" + } + + # want to be able to read from streams? + my $read_from_streams = (obj_is_type($cmd,'Command') && $type eq 'Server') || (obj_is_type($cmd,'Reply') && $type eq 'Client'); + my $write_to_streams = (obj_is_type($cmd,'Command') && $type eq 'Client') || (obj_is_type($cmd,'Reply') && $type eq 'Server'); + + if($read_from_streams) + { + print H "\tvoid SetPropertiesFromStreamData(Protocol &rProtocol);\n"; + + # write Get functions + for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) + { + my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); + + print H "\t".translate_type_to_arg_type($ty)." Get$nm() {return m$nm;}\n"; + } + } + my $param_con_args = ''; + if($write_to_streams) + { + # extra constructor? + if($#{$cmd_contents{$cmd}} >= 0) + { + my @a; + for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) + { + my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); + + push @a,translate_type_to_arg_type($ty)." $nm"; + } + $param_con_args = join(', ',@a); + print H "\t$classname_base$cmd(".$param_con_args.");\n"; + } + print H "\tvoid WritePropertiesToStreamData(Protocol &rProtocol) const;\n"; + # set functions + for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) + { + my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); + + print H "\tvoid Set$nm(".translate_type_to_arg_type($ty)." $nm) {m$nm = $nm;}\n"; + } + } + + if($implement_syslog) + { + print H "\tvirtual void LogSysLog(const char *Action) const;\n"; + } + if($implement_filelog) + { + print H "\tvirtual void LogFile(const char *Action, FILE *file) const;\n"; + } + + + # write member variables and setup for cpp file + my @def_constructor_list; + my @copy_constructor_list; + my @param_constructor_list; + + print H "private:\n"; + for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) + { + my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); + + print H "\t".translate_type_to_member_type($ty)." m$nm;\n"; + + my ($basic,$typename) = translate_type($ty); + if($basic) + { + push @def_constructor_list, "m$nm(0)"; + } + push @copy_constructor_list, "m$nm(rToCopy.m$nm)"; + push @param_constructor_list, "m$nm($nm)"; + } + + # finish off + print H "};\n\n"; + + # now the cpp file... + my $def_con_vars = join(",\n\t ",@def_constructor_list); + $def_con_vars = "\n\t: ".$def_con_vars if $def_con_vars ne ''; + my $copy_con_vars = join(",\n\t ",@copy_constructor_list); + $copy_con_vars = "\n\t: ".$copy_con_vars if $copy_con_vars ne ''; + my $param_con_vars = join(",\n\t ",@param_constructor_list); + $param_con_vars = "\n\t: ".$param_con_vars if $param_con_vars ne ''; + + my $class = "$classname_base$cmd".'::'; + print CPP <<__E; +$class$classname_base$cmd()$def_con_vars +{ +} +$class$classname_base$cmd(const $classname_base$cmd &rToCopy)$copy_con_vars +{ +} +$class~$classname_base$cmd() +{ +} +int ${class}GetType() const +{ + return $cmd_id{$cmd}; +} +__E + if($read_from_streams) + { + print CPP "void ${class}SetPropertiesFromStreamData(Protocol &rProtocol)\n{\n"; + for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) + { + my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); + if($ty =~ m/\Avector/) + { + print CPP "\trProtocol.ReadVector(m$nm);\n"; + } + else + { + print CPP "\trProtocol.Read(m$nm);\n"; + } + } + print CPP "}\n"; + } + if($write_to_streams) + { + # implement extra constructor? + if($param_con_vars ne '') + { + print CPP "$class$classname_base$cmd($param_con_args)$param_con_vars\n{\n}\n"; + } + print CPP "void ${class}WritePropertiesToStreamData(Protocol &rProtocol) const\n{\n"; + for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) + { + my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); + if($ty =~ m/\Avector/) + { + print CPP "\trProtocol.WriteVector(m$nm);\n"; + } + else + { + print CPP "\trProtocol.Write(m$nm);\n"; + } + } + print CPP "}\n"; + } + if(obj_is_type($cmd,'EndsConversation')) + { + print CPP "bool ${class}IsConversationEnd() const\n{\n\treturn true;\n}\n"; + } + if(obj_is_type($cmd,'IsError')) + { + # get parameters + my ($mem_type,$mem_subtype) = split /,/,obj_get_type_params($cmd,'IsError'); + print CPP <<__E; +bool ${class}IsError(int &rTypeOut, int &rSubTypeOut) const +{ + rTypeOut = m$mem_type; + rSubTypeOut = m$mem_subtype; + return true; +} +__E + } + + if($implement_syslog) + { + my ($format,$args) = make_log_strings($cmd); + print CPP <<__E; +void ${class}LogSysLog(const char *Action) const +{ + ::syslog(LOG_INFO,"%s $format",Action$args); +} +__E + } + if($implement_filelog) + { + my ($format,$args) = make_log_strings($cmd); + print CPP <<__E; +void ${class}LogFile(const char *Action, FILE *File) const +{ + ::fprintf(File,"%s $format\\n",Action$args); + ::fflush(File); +} +__E + } +} + +# finally, the protocol object itself +print H <<__E; +class $classname_base : public Protocol +{ +public: + $classname_base(IOStream &rStream); + virtual ~$classname_base(); + + std::auto_ptr<$derive_objects_from> Receive(); + void Send(const ${derive_objects_from} &rObject); +__E +if($implement_syslog) +{ + print H "\tvoid SetLogToSysLog(bool Log = false) {mLogToSysLog = Log;}\n"; +} +if($implement_filelog) +{ + print H "\tvoid SetLogToFile(FILE *File = 0) {mLogToFile = File;}\n"; +} +if($type eq 'Server') +{ + # need to put in the conversation function + print H "\tvoid DoServer($context_class &rContext);\n\n"; + # and the send vector thing + print H "\tvoid SendStreamAfterCommand(IOStream *pStream);\n\n"; +} +if($type eq 'Client') +{ + # add plain object taking query functions + my $with_params; + for my $cmd (@cmd_list) + { + if(obj_is_type($cmd,'Command')) + { + my $has_stream = obj_is_type($cmd,'StreamWithCommand'); + my $argextra = $has_stream?', IOStream &rStream':''; + my $queryextra = $has_stream?', rStream':''; + my $reply = obj_get_type_params($cmd,'Command'); + print H "\tstd::auto_ptr<$classname_base$reply> Query(const $classname_base$cmd &rQuery$argextra);\n"; + my @a; + my @na; + for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) + { + my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); + push @a,translate_type_to_arg_type($ty)." $nm"; + push @na,"$nm"; + } + my $ar = join(', ',@a); + my $nar = join(', ',@na); + $nar = "($nar)" if $nar ne ''; + + $with_params .= "\tinline std::auto_ptr<$classname_base$reply> Query$cmd($ar$argextra)\n\t{\n"; + $with_params .= "\t\t$classname_base$cmd send$nar;\n"; + $with_params .= "\t\treturn Query(send$queryextra);\n"; + $with_params .= "\t}\n"; + } + } + # quick hack to correct bad argument lists for commands with zero paramters but with streams + $with_params =~ s/\(, /(/g; + print H "\n",$with_params,"\n"; +} +print H <<__E; +private: + $classname_base(const $classname_base &rToCopy); +__E +if($type eq 'Server') +{ + # need to put the streams to send vector + print H "\tstd::vector mStreamsToSend;\n\tvoid DeleteStreamsToSend();\n"; +} + +if($implement_filelog || $implement_syslog) +{ + print H <<__E; + virtual void InformStreamReceiving(u_int32_t Size); + virtual void InformStreamSending(u_int32_t Size); +__E +} + +if($implement_syslog) +{ + print H "private:\n\tbool mLogToSysLog;\n"; +} +if($implement_filelog) +{ + print H "private:\n\tFILE *mLogToFile;\n"; +} +print H <<__E; + +protected: + virtual std::auto_ptr MakeProtocolObject(int ObjType); + virtual const char *GetIdentString(); +}; + +__E + +my $construtor_extra = ''; +$construtor_extra .= ', mLogToSysLog(false)' if $implement_syslog; +$construtor_extra .= ', mLogToFile(0)' if $implement_filelog; + +my $destructor_extra = ($type eq 'Server')?"\n\tDeleteStreamsToSend();":''; + +my $prefix = $classname_base.'::'; +print CPP <<__E; +$prefix$classname_base(IOStream &rStream) + : Protocol(rStream)$construtor_extra +{ +} +$prefix~$classname_base() +{$destructor_extra +} +const char *${prefix}GetIdentString() +{ + return "$ident_string"; +} +std::auto_ptr ${prefix}MakeProtocolObject(int ObjType) +{ + switch(ObjType) + { +__E + +# do objects within this +for my $cmd (@cmd_list) +{ + print CPP <<__E; + case $cmd_id{$cmd}: + return std::auto_ptr(new $classname_base$cmd); + break; +__E +} + +print CPP <<__E; + default: + THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnknownCommandRecieved) + } +} +__E +# write receieve and send functions +print CPP <<__E; +std::auto_ptr<$derive_objects_from> ${prefix}Receive() +{ + std::auto_ptr<${derive_objects_from}> preply((${derive_objects_from}*)(Protocol::Receive().release())); + +__E + if($implement_syslog) + { + print CPP <<__E; + if(mLogToSysLog) + { + preply->LogSysLog("Receive"); + } +__E + } + if($implement_filelog) + { + print CPP <<__E; + if(mLogToFile != 0) + { + preply->LogFile("Receive", mLogToFile); + } +__E + } +print CPP <<__E; + + return preply; +} + +void ${prefix}Send(const ${derive_objects_from} &rObject) +{ +__E + if($implement_syslog) + { + print CPP <<__E; + if(mLogToSysLog) + { + rObject.LogSysLog("Send"); + } +__E + } + if($implement_filelog) + { + print CPP <<__E; + if(mLogToFile != 0) + { + rObject.LogFile("Send", mLogToFile); + } +__E + } + +print CPP <<__E; + Protocol::Send(rObject); +} + +__E +# write server function? +if($type eq 'Server') +{ + print CPP <<__E; +void ${prefix}DoServer($context_class &rContext) +{ + // Handshake with client + Handshake(); + + // Command processing loop + bool inProgress = true; + while(inProgress) + { + // Get an object from the conversation + std::auto_ptr<${derive_objects_from}> pobj(Receive()); + +__E + if($implement_syslog) + { + print CPP <<__E; + if(mLogToSysLog) + { + pobj->LogSysLog("Receive"); + } +__E + } + if($implement_filelog) + { + print CPP <<__E; + if(mLogToFile != 0) + { + pobj->LogFile("Receive", mLogToFile); + } +__E + } + print CPP <<__E; + + // Run the command + std::auto_ptr<${derive_objects_from}> preply((${derive_objects_from}*)(pobj->DoCommand(*this, rContext).release())); + +__E + if($implement_syslog) + { + print CPP <<__E; + if(mLogToSysLog) + { + preply->LogSysLog("Send"); + } +__E + } + if($implement_filelog) + { + print CPP <<__E; + if(mLogToFile != 0) + { + preply->LogFile("Send", mLogToFile); + } +__E + } + print CPP <<__E; + + // Send the reply + Send(*(preply.get())); + + // Send any streams + for(unsigned int s = 0; s < mStreamsToSend.size(); s++) + { + // Send the streams + SendStream(*mStreamsToSend[s]); + } + // Delete these streams + DeleteStreamsToSend(); + + // Does this end the conversation? + if(pobj->IsConversationEnd()) + { + inProgress = false; + } + } +} + +void ${prefix}SendStreamAfterCommand(IOStream *pStream) +{ + ASSERT(pStream != NULL); + mStreamsToSend.push_back(pStream); +} + +void ${prefix}DeleteStreamsToSend() +{ + for(std::vector::iterator i(mStreamsToSend.begin()); i != mStreamsToSend.end(); ++i) + { + delete (*i); + } + mStreamsToSend.clear(); +} + +__E +} + +# write logging functions? +if($implement_filelog || $implement_syslog) +{ + my ($fR,$fS); + + if($implement_syslog) + { + $fR .= qq~\tif(mLogToSysLog) { ::syslog(LOG_INFO, (Size==Protocol::ProtocolStream_SizeUncertain)?"Receiving stream, size uncertain":"Receiving stream, size %d", Size); }\n~; + $fS .= qq~\tif(mLogToSysLog) { ::syslog(LOG_INFO, (Size==Protocol::ProtocolStream_SizeUncertain)?"Sending stream, size uncertain":"Sending stream, size %d", Size); }\n~; + } + if($implement_filelog) + { + $fR .= qq~\tif(mLogToFile) { ::fprintf(mLogToFile, (Size==Protocol::ProtocolStream_SizeUncertain)?"Receiving stream, size uncertain":"Receiving stream, size %d\\n", Size); ::fflush(mLogToFile); }\n~; + $fS .= qq~\tif(mLogToFile) { ::fprintf(mLogToFile, (Size==Protocol::ProtocolStream_SizeUncertain)?"Sending stream, size uncertain":"Sending stream, size %d\\n", Size); ::fflush(mLogToFile); }\n~; + } + + print CPP <<__E; + +void ${prefix}InformStreamReceiving(u_int32_t Size) +{ +$fR} + +void ${prefix}InformStreamSending(u_int32_t Size) +{ +$fS} + +__E +} + + +# write client Query functions? +if($type eq 'Client') +{ + for my $cmd (@cmd_list) + { + if(obj_is_type($cmd,'Command')) + { + my $reply = obj_get_type_params($cmd,'Command'); + my $reply_id = $cmd_id{$reply}; + my $has_stream = obj_is_type($cmd,'StreamWithCommand'); + my $argextra = $has_stream?', IOStream &rStream':''; + my $send_stream_extra = ''; + if($has_stream) + { + $send_stream_extra = <<__E; + + // Send stream after the command + SendStream(rStream); +__E + } + print CPP <<__E; +std::auto_ptr<$classname_base$reply> ${classname_base}::Query(const $classname_base$cmd &rQuery$argextra) +{ + // Send query + Send(rQuery); + $send_stream_extra + // Wait for the reply + std::auto_ptr<${derive_objects_from}> preply(Receive().release()); + + if(preply->GetType() == $reply_id) + { + // Correct response + return std::auto_ptr<$classname_base$reply>(($classname_base$reply*)preply.release()); + } + else + { + // Set protocol error + int type, subType; + if(preply->IsError(type, subType)) + { + SetError(type, subType); + TRACE2("Protocol: Error received %d/%d\\n", type, subType); + } + else + { + SetError(Protocol::UnknownError, Protocol::UnknownError); + } + + // Throw an exception + THROW_EXCEPTION(ConnectionException, Conn_Protocol_UnexpectedReply) + } +} +__E + } + } +} + + + +print H <<__E; +#endif // $guardname + +__E + +# close files +close H; +close CPP; + + +sub obj_is_type +{ + my ($c,$ty) = @_; + for(@{$cmd_attributes{$c}}) + { + return 1 if $_ =~ m/\A$ty/; + } + + return 0; +} + +sub obj_get_type_params +{ + my ($c,$ty) = @_; + for(@{$cmd_attributes{$c}}) + { + return $1 if $_ =~ m/\A$ty\((.+?)\)\Z/; + } + die "Can't find attribute $ty\n" +} + +# returns (is basic type, typename) +sub translate_type +{ + my $ty = $_[0]; + + if($ty =~ m/\Avector\<(.+?)\>\Z/) + { + my $v_type = $1; + my (undef,$v_ty) = translate_type($v_type); + return (0, 'std::vector<'.$v_ty.'>') + } + else + { + if(!exists $translate_type_info{$ty}) + { + die "Don't know about type name $ty\n"; + } + return @{$translate_type_info{$ty}} + } +} + +sub translate_type_to_arg_type +{ + my ($basic,$typename) = translate_type(@_); + return $basic?$typename:'const '.$typename.'&' +} + +sub translate_type_to_member_type +{ + my ($basic,$typename) = translate_type(@_); + return $typename +} + +sub make_log_strings +{ + my ($cmd) = @_; + + my @str; + my @arg; + for(my $x = 0; $x < $#{$cmd_contents{$cmd}}; $x+=2) + { + my ($ty,$nm) = (${$cmd_contents{$cmd}}[$x], ${$cmd_contents{$cmd}}[$x+1]); + + if(exists $log_display_types{$ty}) + { + # need to translate it + my ($format,$arg) = @{$log_display_types{$ty}}; + push @str,$format; + $arg =~ s/VAR/m$nm/g; + push @arg,$arg; + } + else + { + # is opaque + push @str,'OPAQUE'; + } + } + return ($cmd.'('.join(',',@str).')', join(',','',@arg)); +} + + -- cgit v1.2.1