Index: trunk/Ohana/src/libautocode/generate
===================================================================
--- trunk/Ohana/src/libautocode/generate	(revision 4020)
+++ trunk/Ohana/src/libautocode/generate	(revision 4023)
@@ -38,5 +38,6 @@
 
 	# there are used internally (not just a replacement)
-	if ($key eq "TYPE") { $TYPE = $value; }
+	if ($key eq "TYPE")   { $TYPE = $value;   }
+	if ($key eq "SIZE")   { $SIZE = $value;   }
 	if ($key eq "STRUCT") { $STRUCT = $value; }
 
@@ -53,6 +54,7 @@
 	}
     }
-    if ($TYPE eq "BINTABLE") { &count_bintablesize; }
-    if ($TYPE eq "TABLE") { &count_tablesize; }
+    if ($TYPE eq "BINTABLE") { $Nexpect = &count_bintablesize; }
+    if ($TYPE eq "TABLE")    { $Nexpect = &count_tablesize;    }
+    if ($Nexpect != $SIZE) { die "size mismatch: $Nexpect vs $SIZE\n"; }
 }
 
@@ -95,33 +97,63 @@
 	if ($mode[$i] eq "SUBSTRUCT") { next; }
 
-	# need to handle all structures like: float poly[5][4]
-	# add [\d\.] to match ascii-type formats
-	($type, $length) = $format[$i] =~ m|^(\w+)\[(\d+)\]|;
-	if (!$type && !$length) { $type = $format[$i]; }
-
-	if ($type eq "char") {
-	    if ($length == 0) { 
-		$pt1 = sprintf "A";
-	    } else {
-		$pt1 = sprintf "%dA", $length;
-	    }
-	}
-
-	if ($type eq "byte")   { $pt1 = "B"; }
-	if ($type eq "short")  { $pt1 = "I"; }
-	if ($type eq "int")    { $pt1 = "J"; }
-	if ($type eq "e_time") { $pt1 = "J"; }
-	if ($type eq "float")  { $pt1 = "E"; }
-	if ($type eq "double") { $pt1 = "D"; }
-
-	if ($type eq "rawshort") { $pt1 = "I"; }
+	($type, $Np) = &get_type_array ($format[$i]);
+	
+	# rawshort is a short without byteswapping
+
+	$pt1 = 0;
+	if ($type eq "char")          { $pt1 = "A"; }
+	if ($type eq "byte")   	      { $pt1 = "B"; }
+	if ($type eq "unsigned char") { $pt1 = "B"; }
+	if ($type eq "rawshort")      { $pt1 = "I"; }
+	if ($type eq "short")  	      { $pt1 = "I"; }
+	if ($type eq "unsigned short"){ $pt1 = "I"; }
+	if ($type eq "int")    	      { $pt1 = "J"; }
+	if ($type eq "unsigned int")  { $pt1 = "J"; }
+	if ($type eq "e_time") 	      { $pt1 = "J"; }
+	if ($type eq "float")  	      { $pt1 = "E"; }
+	if ($type eq "double") 	      { $pt1 = "D"; }
+	if (!$pt1) { die "unknown type $type"; }
+
+	if ($Np == 1) {
+	    $pt2 = $pt1;
+	} else {
+	    $pt2 = sprintf "%d%s", $Np, $pt1;
+	}
 
 	printf FILE "  fits_define_bintable_column (header, ";
-	printf FILE "\"%s\",   ", $pt1;
-	printf FILE "\"%s\",   ", $field[$i];
-	printf FILE "\"%s\", ",   $comment[$i];
-	printf FILE "\"%s\", 1.0, 0.0);\n", $unit[$i];
-    }
-
+	printf FILE "%-8s",               "\"$pt2\", ";
+	printf FILE "%-20s",              "\"$field[$i]\", ";
+	printf FILE "%-35s",              "\"$comment[$i]\", ";
+	printf FILE "%-20s 1.0, 0.0);\n", "\"$unit[$i]\", ";
+    }
+
+}
+
+sub get_type_array {
+    
+    my ($format) = $_[0];
+    my ($type);
+    my ($Np, $N1, $N2, $N3);
+
+    $type = $N1 = $N2 = $N3 = $Np = 0;
+    if (!$type) {
+	($type, $N1, $N2, $N3) = $format =~ m|^(.w+)\[(\d+)\]\[(\d+)\]\[(\d+)\]|;
+	$Np = $N1*$N2*$N3;
+    }
+    if (!$type) {
+	($type, $N1, $N2)      = $format =~ m|^(.+)\[(\d+)\]\[(\d+)\]|;
+	$Np = $N1*$N2;
+    } 
+    if (!$type) {
+	($type, $N1)           = $format =~ m|^(.+)\[(\d+)\]|;
+	$Np = $N1;
+    }
+    if (!$type) { 
+	$type                  = $format; 
+	$Np = 1;
+    }
+    # print "type: $type, Np: $Np\n";
+    if ($Np == 0) { die "syntax error in format/array\n"; }
+    return ($type, $Np);
 }
 
@@ -131,23 +163,30 @@
 	# skip SUBSTRUCT type of entries:
 	if ($mode[$i] eq "SUBSTRUCT") { next; }
+
+	($type, $N1, $N2)      = $format[$i] =~ m|^(\w+)\[(\d+)\]\[(\d+)\]|;
+	if ($N2) { die "ASCII table cannot have multi-valued column"; }
 
 	($type, $length) = $format[$i] =~ m|^(\w+)\[([\d\.]+)\]|;
 	if (!$type && !$length) { die "format must be specified for ASCII table"; }
 
-	if ($type eq "char")   { $pt1 = sprintf "A%s", $length; }
-	if ($type eq "byte")   { $pt1 = sprintf "I%s", $length; }
-	if ($type eq "short")  { $pt1 = sprintf "I%s", $length; }
-	if ($type eq "int")    { $pt1 = sprintf "I%s", $length; }
-	if ($type eq "e_time") { $pt1 = sprintf "I%s", $length; }
-	if ($type eq "float")  { $pt1 = sprintf "F%s", $length; }
-	if ($type eq "double") { $pt1 = sprintf "F%s", $length; }
-
-	if ($type eq "rawshort")  { $pt1 = sprintf "I%s", $length; }
+	$pt1 = 0;
+	if ($type eq "char")   	      { $pt1 = sprintf "A%s", $length; }
+	if ($type eq "byte")   	      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "unsigned char") { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "rawshort")      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "short")  	      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "unsigned short"){ $pt1 = sprintf "I%s", $length; }
+	if ($type eq "int")    	      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "unsigned int")  { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "e_time") 	      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "float")  	      { $pt1 = sprintf "F%s", $length; }
+	if ($type eq "double") 	      { $pt1 = sprintf "F%s", $length; }
+	if (!$pt1) { die "unknown type $type"; }
 
 	printf FILE "  fits_define_table_column (header, ";
-	printf FILE "\"%s\", ",   $pt1;
-	printf FILE "\"%s\", ",   $field[$i];
-	printf FILE "\"%s\", ",   $comment[$i];
-	printf FILE "\"%s\");\n", $unit[$i];
+	printf FILE "%-8s",      "\"$pt1\", ";
+	printf FILE "%-20s",     "\"$field[$i]\", ";
+	printf FILE "%-35s",     "\"$comment[$i]\", ";
+	printf FILE "%-20s);\n", "\"$unit[$i]\"";
     }
 
@@ -160,9 +199,11 @@
 	if ($mode[$i] eq "SUBFIELD") { next; }
 
-	($type, $length) = $format[$i] =~ m|^(\w+)\[([\d\.]+)\]|;
-	if (!$type && !$length) { $type = $format[$i]; }
-
-	if (($type eq "char") && ($length != 0)) { 
-	    $pt2 = sprintf "%s[%d];", $element[$i], $length;
+	# here we only want to match the pattern [1][2][3]..[N]
+	($type, $array) = $format[$i] =~ m|^(\w+)(\[.*\])|;
+	# print "type: $type, array: $array\n";
+	if (!$type && !$array) { $type = $format[$i]; }
+
+	if ($array && (($TYPE eq "BINTABLE") || ($type eq "char"))) {
+	    $pt2 = sprintf "%s%s;", $element[$i], $array;
 	} else {
 	    $pt2 = sprintf "%s;", $element[$i];
@@ -179,5 +220,11 @@
 }
 
+# this does not work with ASCII tables, 
+# but should not be needed for ASCII tables!
 sub write_byteswaps {
+    if ($TYPE eq "TABLE") {
+	printf FILE "/*** no byteswaps for ASCII tables ***/\n";
+	return;
+    }
     $N = 0;
     for ($i = 0; $i < @field; $i++) {
@@ -185,47 +232,26 @@
 	if ($mode[$i] eq "SUBSTRUCT") { next; }
 
-	($type, $length) = $format[$i] =~ m|^(\w+)\[([\d\.]+)\]|;
-	if (!$type && !$length) { $type = $format[$i]; }
-
-	if ($type eq "char") {
-	    if ($length == 0) { 
-		$N ++;
-	    } else {
-		$N += $length;
-	    }
-	    next;   # skip byte swap command
-	}
-	if ($type eq "byte")  {
-	    $N ++;
-	    next;
-	}
-	# this is a patch for old photreg tables: provide a fix for the tables
+	($type, $Np) = &get_type_array ($format[$i]);
+
+	# rawshort is a patch for old photreg tables: provide a fix for the tables
 	# some photreg tables were not byteswapped for certain columns
-	if ($type eq "rawshort")  {
-	    $N +=2;
-	    next;
-	}
-	if ($type eq "short")  {
-	    $T = "BYTE";
-	    $n = 2;
-	}
-	if ($type eq "int")    {
-	    $T = "WORD";
-	    $n = 4;
-	}
-	if ($type eq "e_time")    {
-	    $T = "WORD";
-	    $n = 4;
-	}
-	if ($type eq "float")  {
-	    $T = "WORD";
-	    $n = 4;
-	}
-	if ($type eq "double") { 
-	    $T = "DBLE";
-	    $n = 8;
-	}
-	printf FILE "    SWAP_%s (%d); // %s\n", $T, $N, $field[$i];
-	$N += $n;
+
+	$n = 0;
+	if ($type eq "char") 	      { $N +=   $Np; next; }
+	if ($type eq "byte") 	      { $N +=   $Np; next; }
+	if ($type eq "unsigned char") { $N +=   $Np; next; }
+	if ($type eq "rawshort")      { $N += 2*$Np; next; }
+	if ($type eq "short")  	      { $T = "BYTE"; $n = 2; }
+	if ($type eq "unsigned short"){ $T = "BYTE"; $n = 2; }
+	if ($type eq "int")    	      { $T = "WORD"; $n = 4; }
+	if ($type eq "unsigned int")  { $T = "WORD"; $n = 4; }
+	if ($type eq "e_time") 	      { $T = "WORD"; $n = 4; }
+	if ($type eq "float")  	      { $T = "WORD"; $n = 4; }
+	if ($type eq "double") 	      { $T = "DBLE"; $n = 8; }
+	if (!$n) { die "unknown type $type"; }
+	for ($j = 0; $j < $Np; $j++) {
+	    printf FILE "    SWAP_%s (%d); // %s\n", $T, $N, $field[$i];
+	    $N += $n;
+	}
     }
 }
@@ -239,25 +265,19 @@
 
 	# add [\d\.] to match ascii-type formats
-	($type, $length) = $format[$i] =~ m|^(\w+)\[(\d+)\]|;
-	if (!$type && !$length) { 
-	    $type = $format[$i]; 
-	    $length = 0;
-	}
-
-	if ($type eq "char") {
-	    if ($length) {
-		$Nbytes += $length;
-	    } else {
-		$Nbytes ++;
-	    }
-	}
-	if ($type eq "byte")   { $Nbytes += 1; }
-	if ($type eq "short")  { $Nbytes += 2; }
-	if ($type eq "int")    { $Nbytes += 4; }
-	if ($type eq "e_time") { $Nbytes += 4; }
-	if ($type eq "float")  { $Nbytes += 4; }
-	if ($type eq "double") { $Nbytes += 8; }
-
-	if ($type eq "rawshort")  { $Nbytes += 2; }
+	($type, $Np) = &get_type_array ($format[$i]);
+
+	$valid = 0;
+	if ($type eq "char")   	       { $Nbytes += 1*$Np; $valid = 1; }
+	if ($type eq "byte")   	       { $Nbytes += 1*$Np; $valid = 1; }
+	if ($type eq "unsigned char")  { $Nbytes += 1*$Np; $valid = 1; }
+	if ($type eq "rawshort")       { $Nbytes += 2*$Np; $valid = 1; }
+	if ($type eq "short")  	       { $Nbytes += 2*$Np; $valid = 1; }
+	if ($type eq "unsigned short") { $Nbytes += 2*$Np; $valid = 1; }
+	if ($type eq "int")    	       { $Nbytes += 4*$Np; $valid = 1; }
+	if ($type eq "unsigned int")   { $Nbytes += 4*$Np; $valid = 1; }
+	if ($type eq "e_time") 	       { $Nbytes += 4*$Np; $valid = 1; }
+	if ($type eq "float")  	       { $Nbytes += 4*$Np; $valid = 1; }
+	if ($type eq "double") 	       { $Nbytes += 8*$Np; $valid = 1; }
+	if (!$valid) { die "unknown type $type"; }
     }
     return ($Nbytes);
@@ -271,5 +291,7 @@
 	if ($mode[$i] eq "SUBSTRUCT") { next; }
 
-	($length) = $format[$i] =~ m|^\w+\[([\d\.]+)\]|;
+	($fpt) = $format[$i] =~ m|^\w+\[([\d\.]+)\]|;
+	$length = int($fpt);
+	# print "$format[$i], $length, $fpt\n";
 	if ($length == 0) { die "ASCII table format requires field size"; }
 	$Nbytes += $length;
@@ -302,6 +324,6 @@
     my ($i);
     for ($i = 0; $i < @key; $i++) {
+	# if ($VERBOSE) { print "$key[$i]  -- $value[$i]\n"; }
 	if ($line =~ m|\$$key[$i]|) {
-#	    print "$key[$i]  -- $value[$i]\n";
 	    if ($value[$i] eq "") { die "missing value for required key $key[$i]\n"; }
 	    $line =~ s|\$$key[$i]|$value[$i]|g;
