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: slouken@water.ca.gov (Sam Lantinga) Subject: s2func.pl (Convert structures to network data and back) Message-ID: Sender: news@sunnyboy.water.ca.gov 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 () { 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$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"; } .