[Firebug-cvs] fireboard/tools/src/xlisten genc.pm,NONE,1.1 xpacket.c,1.3,1.4
Brought to you by:
doolin
From: David M. D. <do...@us...> - 2004-07-23 00:32:23
|
Update of /cvsroot/firebug/fireboard/tools/src/xlisten In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv1629 Modified Files: xpacket.c Added Files: genc.pm Log Message: perl script for autogenerating c code code from am types. --- NEW FILE: genc.pm --- # This file is part of the nesC compiler. # Copyright (C) 2002 Intel Corporation # # The attached "nesC" software is provided to you under the terms and # conditions of the GNU General Public License Version 2 as published by the # Free Software Foundation. # # nesC is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with nesC; see the file COPYING. If not, write to # the Free Software Foundation, 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA. true; sub gen() { my ($classname, @spec) = @_; require migdecode; &decode(@spec); &usage("no classname name specified") if !defined($java_classname); $java_extends = "net.tinyos.message.Message" if !defined($java_extends); # See if name has a package specifier if ($java_classname =~ /(.*)\.([^.]*)$/) { $package = $1; $java_classname = $2; } print "/**\n"; print " * This class is automatically generated by mig. DO NOT EDIT THIS FILE.\n"; print " * This code implements C interface to the '$java_classname'\n"; print " * message type.\n"; print " */\n\n"; print "#include <stdio.h>\n"; print "#include <stdlib.h>\n"; $I = " "; $smallskip = "\n\n"; $medskip = "\n\n\n\n"; $bigskip = "\n\n\n\n\n\n"; print "typedef struct _$java_classname $java_classname;\n\n"; print "typedef struct _XbowSensorboardPacket XbowSensorboardPacket;\n"; print "struct _XbowSensorboardPacket {\n"; print " unsigned char data[29];\n"; print "};\n"; print $medskip; print "struct _$java_classname {\n"; for (@fields) { ($field, $type, $bitlength, $offset, $amax, $abitsize, $aoffset) = @{$_}; ($ctype, $java_access, $arrayspec) = &cbasetype($type, $bitlength, 0); ## Gets an array of format specifiers useful in *print* functions ## in libc. the @format array can be passed push(@format, &formatstring($type, $bitlength, 0)); printf "$I$ctype $field;\n"; } print "};"; print $medskip; print "//Format string: @format\n"; print $medskip; ## In the code for the xlisten boards, the conversions are ## in the print statement. If the conversions were done ## before the print statement, then the conversion function ## becomes the only function needing to be stubbed. The ## runtime differences are neglible. print "/** User has to fill in any conversion code\n"; print " * necessary for processing.\n"; print " */\n"; print "$java_classname * convert(char * data) {\n"; print " // Just to keep gcc happy.\n"; print " return ($java_classname*)data;\n"; print "}\n"; print $medskip; ## Start printing output functions. print "/** Print the bytes of the packet. */\n"; print "void $java_classname\_print\_raw (XbowSensorboardPacket *packet) {\n\n"; print "$I$java_classname * userdata = ($java_classname*)packet->data;\n"; print "}\n\n"; print "/** Print typed output. */\n"; print "void $java_classname\_print\_cooked (XbowSensorboardPacket *packet) {\n\n"; print "$I$java_classname * userdata = ($java_classname*)packet->data;\n"; print "}\n\n"; print "/** Print cooked with tabs. */\n"; print "void $java_classname\_print\_tabbed (XbowSensorboardPacket *packet) {\n\n"; print "$I$java_classname * userdata = ($java_classname*)packet->data;\n"; print "}\n\n"; # print "package $package;\n\n" if $package; # print "public class $java_classname extends $java_extends {\n\n"; print "/** The default size of this message type in bytes. */\n"; print "static int DEFAULT_MESSAGE_SIZE = $size;\n\n"; print "/** The Active Message type associated with this message. */\n"; print "static int AM_TYPE = $amtype;\n\n"; print "/** If incomplete types are used, we need to provide a way\n"; print " * to manage memory.\n"; print " */\n"; print "$java_classname *\n"; print "$java_classname\_new() {\n"; print " $java_classname * userdata = ($java_classname*)malloc(sizeof($java_classname));\n"; print " memset((void*)userdata,0xda,sizeof($java_classname));\n"; print " return userdata;\n"; print "}\n"; print $medskip; print "void\n"; print "$java_classname\_delete($java_classname * userdata) {\n"; print " memset((void*)userdata,0xdd,sizeof($java_classname));\n"; print " free(userdata);\n"; print "}\n"; print $medskip; print "#if 0\n"; print "\n\n// All the rest is the old java stuff\n\n"; print " /** Create a new $java_classname of size $size. */\n"; print " public $java_classname() {\n"; print " super(DEFAULT_MESSAGE_SIZE);\n"; print " amTypeSet(AM_TYPE);\n"; print " }\n\n"; print " /** Create a new $java_classname of the given data_length. */\n"; print " public $java_classname(int data_length) {\n"; print " super(data_length);\n"; print " amTypeSet(AM_TYPE);\n"; print " }\n\n"; print " /**\n"; print " * Create a new $java_classname with the given data_length\n"; print " * and base offset.\n"; print " */\n"; print " public $java_classname(int data_length, int base_offset) {\n"; print " super(data_length, base_offset);\n"; print " amTypeSet(AM_TYPE);\n"; print " }\n\n"; print " /**\n"; print " * Create a new $java_classname using the given byte array\n"; print " * as backing store.\n"; print " */\n"; print " public $java_classname(byte[] data) {\n"; print " super(data);\n"; print " amTypeSet(AM_TYPE);\n"; print " }\n\n"; print " /**\n"; print " * Create a new $java_classname using the given byte array\n"; print " * as backing store, with the given base offset.\n"; print " */\n"; print " public $java_classname(byte[] data, int base_offset) {\n"; print " super(data, base_offset);\n"; print " amTypeSet(AM_TYPE);\n"; print " }\n\n"; print " /**\n"; print " * Create a new $java_classname using the given byte array\n"; print " * as backing store, with the given base offset and data length.\n"; print " */\n"; print " public $java_classname(byte[] data, int base_offset, int data_length) {\n"; print " super(data, base_offset, data_length);\n"; print " amTypeSet(AM_TYPE);\n"; print " }\n\n"; print " /**\n"; print " * Create a new $java_classname embedded in the given message\n"; print " * at the given base offset.\n"; print " */\n"; print " public $java_classname(net.tinyos.message.Message msg, int base_offset) {\n"; print " super(msg, base_offset, DEFAULT_MESSAGE_SIZE);\n"; print " amTypeSet(AM_TYPE);\n"; print " }\n\n"; print " /**\n"; print " * Create a new $java_classname embedded in the given message\n"; print " * at the given base offset and length.\n"; print " */\n"; print " public $java_classname(net.tinyos.message.Message msg, int base_offset, int data_length) {\n"; print " super(msg, base_offset, data_length);\n"; print " amTypeSet(AM_TYPE);\n"; print " }\n\n"; print " /**\n"; print " * Return a String representation of this message. Includes the\n"; print " * message type name and the non-indexed field values.\n"; print " */\n"; print " public String toString() {\n"; print " String s = \"Message <$java_classname> \\n\";\n"; for (@fields) { ($field, $type, $bitlength, $offset, $amax, $abitsize, $aoffset) = @{$_}; print " try {\n"; $javafield = $field; $javafield =~ s/\./_/g; if (!@$amax) { ($javatype, $java_access, $arrayspec) = &javabasetype($type, $bitlength, 0); if ($javatype eq "float") { print " s += \" [$field=\"+Float.toString(get_$javafield())+\"]\\n\";\n"; } else { print " s += \" [$field=0x\"+Long.toHexString(get_$javafield())+\"]\\n\";\n"; } } elsif (@$amax == 1 && $$amax[0] != 0) { ($javatype, $java_access, $arrayspec) = &javabasetype($type, $bitlength, @$amax); print " s += \" [$field=\";\n"; print " for (int i = 0; i < $$amax[0]; i++) {\n"; if ($javatype eq "float") { print " s += Float.toString(getElement_$javafield(i))+\" \";\n"; } else { if ($bitlength > 32) { print " s += \"0x\"+Long.toHexString(getElement_$javafield(i))+\" \";\n"; } elsif (bitlength > 16) { print " s += \"0x\"+Long.toHexString(getElement_$javafield(i) & 0xffffffff)+\" \";\n"; } elsif (bitlength > 8) { print " s += \"0x\"+Long.toHexString(getElement_$javafield(i) & 0xffff)+\" \";\n"; } else { print " s += \"0x\"+Long.toHexString(getElement_$javafield(i) & 0xff)+\" \";\n"; } } print " }\n"; print " s += \"]\\n\";\n"; } print " } catch (ArrayIndexOutOfBoundsException aioobe) { /* Skip field */ }\n"; } print " return s;\n"; print " }\n\n"; print " // Message-type-specific access methods appear below.\n\n"; for (@fields) { ($field, $type, $bitlength, $offset, $amax, $abitsize, $aoffset) = @{$_}; # Determine if array if (@$amax) { $isarray = 1; $arraydims = @$amax; $arraysize_bits = $$amax[0] * $$abitsize[0]; $index = 0; @args = map { $index++; "int index$index" } @{$amax}; $argspec = join(", ", @args); $index = 0; @passargs = map { $index++; "index$index" } @{$amax}; $passargs = join(", ", @passargs); } else { $isarray = 0; $arraydims = 0; $arraysize_bits = 0; $argspec = ""; $passargs = ""; } # Determine if signed if ($basetype eq "U") { $signed = 0; $signedstr = ", unsigned"; } elsif ($basetype eq "I") { $signed = 1; $signedstr = ", signed"; } elsif ($basetype eq "F" || $basetype eq "D" || $basetype eq "LD") { $signed = 1; $signstr = ""; } # Get field type and accessor $javafield = $field; $javafield =~ s/\./_/g; ($javatype, $java_access, $arrayspec) = &javabasetype($type, $bitlength, $arraydims); print " /////////////////////////////////////////////////////////\n"; print " // Accessor methods for field: $field\n"; if ($isarray) { print " // Field type: $javatype$arrayspec$signedstr\n"; print " // Offset (bits): $offset\n"; print " // Size of each element (bits): $bitlength\n"; } else { print " // Field type: $javatype$signedstr\n"; print " // Offset (bits): $offset\n"; print " // Size (bits): $bitlength\n"; } print " /////////////////////////////////////////////////////////\n\n"; ### isSigned if ($signed) { $strue = "true"; } else { $strue = "false"; } print " /**\n"; print " * Return whether the field '$field' is signed ($strue).\n"; print " */\n"; print " public static boolean isSigned_$javafield() {\n"; print " return $strue;\n"; print " }\n\n"; ### isArray if ($isarray) { $atrue = "true"; } else { $atrue = "false"; } print " /**\n"; print " * Return whether the field '$field' is an array ($atrue).\n"; print " */\n"; print " public static boolean isArray_$javafield() {\n"; print " return $atrue;\n"; print " }\n\n"; ### Offset print " /**\n"; print " * Return the offset (in bytes) of the field '$field'\n"; if ((int($offset) % 8) != 0) { print " * WARNING: This field is not byte-aligned (bit offset $offset).\n"; } print " */\n"; print " public static int offset_$javafield($argspec) {\n"; if ($isarray) { printoffset($base + $offset, $amax, $abitsize, $aoffset, 0); } else { print " return ($offset / 8);\n"; } print " }\n\n"; print " /**\n"; print " * Return the offset (in bits) of the field '$field'\n"; print " */\n"; print " public static int offsetBits_$javafield($argspec) {\n"; if ($isarray) { printoffset($base + $offset, $amax, $abitsize, $aoffset, 1); } else { print " return $offset;\n"; } print " }\n\n"; if (!$isarray) { ### For non-array fields ### Get print " /**\n"; print " * Return the value (as a $javatype) of the field '$field'\n"; print " */\n"; print " public $javatype get_$javafield() {\n"; print " return ($javatype)get$java_access(offsetBits_$javafield(), $bitlength);\n"; print " }\n\n"; ### Set print " /**\n"; print " * Set the value of the field '$field'\n"; print " */\n"; print " public void set_$javafield($javatype value) {\n"; print " set$java_access(offsetBits_$javafield(), $bitlength, value);\n"; print " }\n\n"; ### Size print " /**\n"; print " * Return the size, in bytes, of the field '$field'\n"; if ((int($bitlength) % 8) != 0) { print " * WARNING: This field is not an even-sized number of bytes ($bitlength bits).\n"; } print " */\n"; print " public static int size_$javafield() {\n"; if ((int($bitlength) % 8) != 0) { print " return ($bitlength / 8) + 1;\n"; } else { print " return ($bitlength / 8);\n"; } print " }\n\n"; print " /**\n"; print " * Return the size, in bits, of the field '$field'\n"; print " */\n"; print " public static int sizeBits_$javafield() {\n"; print " return $bitlength;\n"; print " }\n\n"; } else { ### For array fields ### Get print " /**\n"; print " * Return the entire array '$field' as a $javatype$arrayspec\n"; print " */\n"; print " public $javatype$arrayspec get_$javafield() {\n"; &printarrayget($javafield, $javatype, $arrayspec, $bitlength, $amax, $abitsize); print " }\n\n"; ### Set print " /**\n"; print " * Set the contents of the array '$field' from the given $javatype$arrayspec\n"; print " */\n"; print " public void set_$javafield($javatype$arrayspec value) {\n"; &printarrayset($javafield, $javatype, $arrayspec, $bitlength, $amax, $abitsize); print " }\n\n"; ### GetElement print " /**\n"; print " * Return an element (as a $javatype) of the array '$field'\n"; print " */\n"; print " public $javatype getElement_$javafield($argspec) {\n"; print " return ($javatype)get$java_access(offsetBits_$javafield($passargs), $bitlength);\n"; print " }\n\n"; ### SetElement print " /**\n"; print " * Set an element of the array '$field'\n"; print " */\n"; print " public void setElement_$javafield($argspec, $javatype value) {\n"; print " set$java_access(offsetBits_$javafield($passargs), $bitlength, value);\n"; print " }\n\n"; if ($arraysize_bits != 0) { ### Total size (when array size is known) print " /**\n"; print " * Return the total size, in bytes, of the array '$field'\n"; if ((int($arraysize_bits) % 8) != 0) { print " * WARNING: This array is not an even-sized number of bytes ($arraysize_bits bits).\n"; } print " */\n"; print " public static int totalSize_$javafield() {\n"; print " return ($arraysize_bits / 8);\n"; print " }\n\n"; print " /**\n"; print " * Return the total size, in bits, of the array '$field'\n"; print " */\n"; print " public static int totalSizeBits_$javafield() {\n"; print " return $arraysize_bits;\n"; print " }\n\n"; } ### Element size print " /**\n"; print " * Return the size, in bytes, of each element of the array '$field'\n"; if ((int($bitlength) % 8) != 0) { print " * WARNING: This field is not an even-sized number of bytes ($bitlength bits).\n"; } print " */\n"; print " public static int elementSize_$javafield() {\n"; print " return ($bitlength / 8);\n"; print " }\n\n"; print " /**\n"; print " * Return the size, in bits, of each element of the array '$field'\n"; print " */\n"; print " public static int elementSizeBits_$javafield() {\n"; print " return $bitlength;\n"; print " }\n\n"; ### Number of dimensions print " /**\n"; print " * Return the number of dimensions in the array '$field'\n"; print " */\n"; print " public static int numDimensions_$javafield() {\n"; print " return $arraydims;\n"; print " }\n\n"; ### Number of elements if ($arraydims == 1 && $$amax[0] != 0) { # For 1D arrays where the size of the array is known print " /**\n"; print " * Return the number of elements in the array '$field'\n"; print " */\n"; print " public static int numElements_$javafield() {\n"; print " return $$amax[0];\n"; print " }\n\n"; } print " /**\n"; print " * Return the number of elements in the array '$field'\n"; print " * for the given dimension.\n"; print " */\n"; print " public static int numElements_$javafield(int dimension) {\n"; print " int array_dims[] = { "; foreach $e (@$amax) { print "$e, "; } print " };\n"; print " if (dimension < 0 || dimension >= $arraydims) throw new ArrayIndexOutOfBoundsException();\n"; print " if (array_dims[dimension] == 0) throw new IllegalArgumentException(\"Array dimension \"+dimension+\" has unknown size\");\n"; print " return array_dims[dimension];\n"; print " }\n\n"; ### String conversions (for 1D arrays of 8-bit values) if ($arraydims == 1 && $bitlength == 8) { print " /**\n"; print " * Fill in the array '$field' with a String\n"; print " */\n"; print " public void setString_$javafield(String s) { \n"; if ($amax[0] != 0) { print " int len = Math.min(s.length(), $$amax[0]-1);\n"; } else { print " int len = s.length();\n"; } print " int i;\n"; print " for (i = 0; i < len; i++) {\n"; print " setElement_$javafield(i, ($javatype)s.charAt(i));\n"; print " }\n"; print " setElement_$javafield(i, ($javatype)0); //null terminate\n"; print " }\n\n"; print " /**\n"; print " * Read the array '$field' as a String\n"; print " */\n"; print " public String getString_$javafield() { \n"; if ($$amax[0] == 0) { print " char carr[] = new char[net.tinyos.message.Message.MAX_CONVERTED_STRING_LENGTH];\n"; } else { print " char carr[] = new char[Math.min(net.tinyos.message.Message.MAX_CONVERTED_STRING_LENGTH,$$amax[0])];\n"; } print " int i;\n"; print " for (i = 0; i < carr.length; i++) {\n"; print " if ((char)getElement_$javafield(i) == (char)0) break;\n"; print " carr[i] = (char)getElement_$javafield(i);\n"; print " }\n"; print " return new String(carr,0,i);\n"; print " }\n\n"; } } } print "}\n"; print "#endif\n"; } ## TODO Change all these back to the base types available in c, which are ## the same as in nesc. sub cbasetype() { my ($basetype, $bitlength, $arraydims) = @_; my $jtype, $acc; # Pick the java type whose range is closest to the corresponding C type if ($basetype eq "U") { $acc = "UIntElement"; if ($bitlength < 8) { $jtype = "byte"; } elsif ($bitlength < 16) { $jtype = "short"; } elsif ($bitlength < 32) { $jtype = "int"; } else { $jtype = "long"; } } elsif ($basetype eq "I") { $acc = "SIntElement"; if ($bitlength <= 8) { $jtype = "byte"; } elsif ($bitlength <= 16) { $jtype = "short"; } elsif ($bitlength <= 32) { $jtype = "int"; } else { $jtype = "long"; } } elsif ($basetype eq "F" || $basetype eq "D" || $basetype eq "LD") { $acc = "FloatElement"; $jtype = "float"; } if ($arraydims > 0) { # For array types $arrayspec = ""; for ($i = 0; $i < $arraydims; $i++) { $arrayspec = "[]" . $arrayspec; } } return ($jtype, $acc, $arrayspec); } ## TODO Get rid of all the superfluous code, ## or move the functionality into cbasetype. sub formatstring() { my ($basetype, $bitlength, $arraydims) = @_; my $jtype, $acc, $formatstring; # Pick the java type whose range is closest to the corresponding C type if ($basetype eq "U") { $acc = "UIntElement"; if ($bitlength < 8) { $jtype = "byte"; $formatstring = "c";} elsif ($bitlength < 16) { $jtype = "short"; $formatstring = "i";} elsif ($bitlength < 32) { $jtype = "int"; $formatstring = "i";} else { $jtype = "long"; $formatstring = "%i"} } elsif ($basetype eq "I") { $acc = "SIntElement"; if ($bitlength <= 8) { $jtype = "byte"; $formatstring = "c";} elsif ($bitlength <= 16) { $jtype = "short"; $formatstring = "i";} elsif ($bitlength <= 32) { $jtype = "int"; $formatstring = "i";} else { $jtype = "long"; } } elsif ($basetype eq "F" || $basetype eq "D" || $basetype eq "LD") { $acc = "FloatElement"; $jtype = "float"; $formatstring = "f"; } if ($arraydims > 0) { # For array types $arrayspec = ""; for ($i = 0; $i < $arraydims; $i++) { $arrayspec = "[]" . $arrayspec; } } #return ($jtype, $acc, $arrayspec, $formatstring); return ($formatstring); } sub javabasetype() { my ($basetype, $bitlength, $arraydims) = @_; my $jtype, $acc; # Pick the java type whose range is closest to the corresponding C type if ($basetype eq "U") { $acc = "UIntElement"; if ($bitlength < 8) { $jtype = "byte"; } elsif ($bitlength < 16) { $jtype = "short"; } elsif ($bitlength < 32) { $jtype = "int"; } else { $jtype = "long"; } } elsif ($basetype eq "I") { $acc = "SIntElement"; if ($bitlength <= 8) { $jtype = "byte"; } elsif ($bitlength <= 16) { $jtype = "short"; } elsif ($bitlength <= 32) { $jtype = "int"; } else { $jtype = "long"; } } elsif ($basetype eq "F" || $basetype eq "D" || $basetype eq "LD") { $acc = "FloatElement"; $jtype = "float"; } if ($arraydims > 0) { # For array types $arrayspec = ""; for ($i = 0; $i < $arraydims; $i++) { $arrayspec = "[]" . $arrayspec; } } return ($jtype, $acc, $arrayspec); } sub printoffset() { my ($offset, $max, $bitsize, $aoffset, $inbits) = @_; print " int offset = $offset;\n"; for ($i = 1; $i <= @$max; $i++) { # check index bounds. 0-sized arrays don't get an upper-bound check # (they represent variable size arrays. Normally they should only # occur as the first-dimension of the last element of the structure) if ($$max[$i - 1] != 0) { print " if (index$i < 0 || index$i >= $$max[$i - 1]) throw new ArrayIndexOutOfBoundsException();\n"; } else { print " if (index$i < 0) throw new ArrayIndexOutOfBoundsException();\n"; } print " offset += $$aoffset[$i - 1] + index$i * $$bitsize[$i - 1];\n"; } if ($inbits) { print " return offset;\n"; } else { print " return (offset / 8);\n"; } } sub printarrayget() { my ($javafield, $javatype, $arrayspec, $bitlength, $amax, $abitsize) = @_; # Check whether array has known size for ($i = 0; $i < @$amax; $i++) { if ($$amax[$i] == 0) { print " throw new IllegalArgumentException(\"Cannot get field as array - unknown size\");\n"; return; } } print " $javatype$arrayspec tmp = new $javatype"; for ($i = 0; $i < @$amax; $i++) { print "[$$amax[$i]]"; } print ";\n"; $indent = " "; for ($i = 0; $i < @$amax; $i++) { print " $indent for (int index$i = 0; index$i < numElements_$javafield($i); index$i++) {\n"; $indent = $indent . " "; } $indent = $indent . " "; print " $indent tmp"; for ($i = 0; $i < @$amax; $i++) { print "[index$i]"; } print " = getElement_$javafield("; for ($i = 0; $i < @$amax; $i++) { print "index$i"; if ($i != @$amax-1) { print ","; } } print ");\n"; $indent = substr($indent, 0, length($indent)-2); for ($i = 0; $i < @$amax; $i++) { $indent = substr($indent, 0, length($indent)-2); print " $indent }\n"; } print " return tmp;\n"; } sub printarrayset() { my ($javafield, $javatype, $arrayspec, $bitlength, $amax, $abitsize) = @_; $indent = " "; $val = ""; for ($i = 0; $i < @$amax; $i++) { print " $indent for (int index$i = 0; index$i < value$val.length; index$i++) {\n"; $val = $val . "[index$i]"; $indent = $indent . " "; } $indent = $indent . " "; print " $indent setElement_$javafield("; for ($i = 0; $i < @$amax; $i++) { print "index$i"; if ($i != @$amax-1) { print ","; } } print ", value"; for ($i = 0; $i < @$amax; $i++) { print "[index$i]"; } print ");\n"; $indent = substr($indent, 0, length($indent)-2); for ($i = 0; $i < @$amax; $i++) { $indent = substr($indent, 0, length($indent)-2); print " $indent }\n"; } } |