Xref: feenix.metronet.com alt.sources:2088
Newsgroups: alt.sources
Path: feenix.metronet.com!news.utdallas.edu!convex!convex!cs.utexas.edu!math.ohio-state.edu!magnus.acs.ohio-state.edu!usenet.ins.cwru.edu!agate!news.ucdavis.edu!sunnyboy.water.ca.gov!news
From:
[email protected] (Sam Lantinga)
Subject: s2func.pl (Convert structures to network data and back)
Message-ID: <
[email protected]>
Sender:
[email protected]
Organization: Calif. Dept. of Water Resources
Date: Sun, 17 Oct 1993 06:16:45 GMT
Lines: 225
Finally!! I got a program to write routines that will convert
binary structure definitions into a portable data representation and
re-convert them.. similar to htons() and ntohs() for structures!
This perl script takes a skeleton structure definition and
writes routines to convert it in and out of "network data representation".
It hasn't been thoroughly tested, but it has (and will) help me
write cross-platform networking code much faster.
Yay! :)
-Sam.
s2func.pl ---------------------------------------------------------
#!/site/bin/perl
#
# Sam Lantinga 10/17/93
#
# This is a perl script to take a structure definition and create
# structure -> network buffer / network buffer -> structure
# C functions.
#
# This script has not been completely tested, so use at your own risk.
#
# Each of the functions take the following form:
#
# structname2buf(structptr, bufptr, buflen)
# buf2structname(structptr, bufptr, buflen)
#
# and return the length of the filled buffer. They return -1 if
# the buffer was to small to contain the named structure.
#
# The structure definitions given to this script must be fairly
# simple. They must not contain any structures within them, must
# not contain pointers, and must take the form:
#
# struct structname {
# data element; /* Optional comment */
# data element; /* Optional comment */
# };
#
# The only data types allowed are: arrays of chars, shorts, ints
# and longs. All other data types are not recognized.
#
#################################################################
#
# Example code showing how these routines might be used.
#
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Server Side:
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# struct first_packet first;
#
# if ( (len=read(network_fd, buf, 4096)) <= 0 )
# return;
#
# if ( (len=buf2first_packet(&first, buf, len)) < 0 )
# return;
#
# fprintf(stderr, "Name: %s\n", first.name);
# fprintf(stderr, "Passwd: %s\n", first.passwd);
# fprintf(stderr, "Request: %d\n", first.request);
# fprintf(stderr, "Port: %d\n", first.lport);
# fprintf(stderr, "Pathname: %s\n", first.path);
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Client Side:
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# struct first_packet first;
#
# strcpy(first.name, "Myname");
# strcpy(first.passwd, "Open Sesame");
# first.request=1;
# first.lport=0;
# strcpy(first.path, "/tmp/tempfile");
#
#
# if ( (len=first_packet2buf(&first, buf, 4096)) < 0 ) {
# perror("first2buf() error");
# exit(3);
# }
# if ( sendto(network_fd, buf, len, 0, &serv_addr, sizeof(serv_addr)) < 0 ) {
# perror("sendto() error");
# exit(2);
# }
#
#################################################################
while (<STDIN>) {
chop;
if ( ! $_ ) {
next;
}
if ( /struct/ ) {
if ( $in_struct ) {
print STDERR "Structures within structures are not allowed.\n";
exit(1);
} else {
$in_struct=1;
($struct, $structname, $brace)=split(' ');
next;
}
} elsif ( ! $in_struct ) {
next;
}
if ( /\}/ ) { # Print out the conversion routines.
print "
int ${structname}2buf(structure, buf, len)
struct $structname *structure;
char *buf;
int len;
{
char ";
foreach $name (split(' ', $varlist)) {
$type=$variables{$name};
if ( $type eq "short" || $type eq "int" || $type eq "long" ) {
print "$name[12], ";
}
}
print "*ptr;
int i=0;
";
foreach $name (split(' ', $varlist)) {
$type=$variables{$name};
if ( $type eq "short" || $type eq "int" ) {
print "
sprintf($name, \"%d\", structure->$name);\n";
} elsif ( $type eq "long" ) {
print "
sprintf($name, \"%l\", structure->$name);\n";
}
}
foreach $name (split(' ', $varlist)) {
$type=$variables{$name};
if ( $type eq "short" || $type eq "int" || $type eq "long" ) {
$varname=$name;
} else {
$varname="structure->$name";
}
print "
for ( ptr=$varname; (*ptr && i<len); ++i, *(buf++)=(*(ptr++)) );
if ( *ptr == '\\0' ) {
*(buf++)='\\0';
++i;
} else
return(-1);
";
}
print "
return(i);
}
int buf2$structname(structure, buf, len)
struct $structname *structure;
char *buf;
int len;
{
int i=0;
char *ptr=buf;
";
foreach $name (split(' ', $varlist)) {
print "
for ( ; (*ptr && i<len); ++i, ++ptr );
if ( *ptr == '\\0' ) {
";
$type=$variables{$name};
if ( $type eq "short" || $type eq "int" ) {
print " structure->$name=atoi(buf);";
} elsif ( $type eq "long" ) {
print " structure->$name=atol(buf);";
} else {
print " strcpy(structure->$name, buf);";
}
print "
buf=(++ptr);
++i;
} else
return(-1);
";
}
print "
return(i);
}
";
undef %variables;
undef $varlist;
$in_struct=0;
next;
}
if ( ! /\;/ ) {
print STDERR "Expecting a semicolon: $_\n";
exit(1);
} else {
($_, $null)=split(/;/);
}
if ( /unsigned/ ) {
($unsigned, $type, $name)=split(' ');
} else {
($type, $name)=split(' ');
}
if ( $name =~ /\[.*\]/ ) {
($name, $array)=split(/\[/, $name);
if ( $type ne "char" ) {
print STDERR "$type is not an allowed array data type.\n";
exit(1);
}
} else if ( $type eq "char" ) {
print STDERR "You may not use the single char data type.\n";
exit(1);
}
if ( $name =~ /\*/ ) {
print STDERR "Structures containing pointers are not allowed.\n";
exit(1);
}
$variables{$name}=$type;
$varlist="$varlist $name";
}