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";
}