#!/usr/bin/perl
#
# Reading in PacketCluster .DAT files, DX.DAT, OPERNAM.DAT and WWV.DAT 
# are supported. Also QSL.FUL files may be read with this tool and
# also general .FUL files.
#
# Last change:  DL6RAI Fri Jul 21 17:45:38 GMT 2000

require 'getopts.pl';
require 'ctime.pl';

$| = 1;
$db_name = "clx_db";
$home = (getpwnam('clx_us'))[7];
$file_out = 0;
$create_new = 0;
$column_out = 1;
$verbose = 0;
$cursor = 0;
$psql = "psql -d $db_name";
$max = 8000;		# Maximum length for text
$cols = 72;
$type = '';
$formats = 'dx|opernam|wwv|qsl|ful|vhf|iota';
$tab='';
$now = gmtime();

@lit_month = ('JAN','FEB','MAR','APR','MAY','JUN',
		 'JUL','AUG','SEP','OCT','NOV','DEC');

&Getopts('cfvp?t:r:k:');

if ( $#ARGV < 0 || ( $type eq "ful" && $#ARGV < 1) ) {
print <<NNNN;
Reads in AK1A PacketCluster *.DAT, QSL.FUL and general .FUL files

Usage: read_ak1a [-f] [-v] [-p] [-c] -t type [-r \"comment\"]
	[-k flags] <filename> [<tablename>]

    -f	write output to file postgres.input
    -v	be verbose
    -p	generate separate PSQL commands for each record (slow but secure)
    -c	create a new $tab table
    -t	type: specify data type {$formats}
    -r	comment: remarks/comment for Udt table
    -k	flags: read/write flags (+-, --, ++) for Udt table

NNNN

exit(1);
}

$filename = $ARGV[0];

if ( -r $filename ) {
	$size = (stat($filename))[7];
	$filedate =  &ctime((stat($filename))[9]);
	chop($filedate);
	$shorthand = $filename;
	$shorthand =~ s|^.*/||;
} elsif ( $filename eq "-" ) {
	$size = 0;
	$filedate = gmtime(); 
	chop($filedate);
	$shorthand = "STDIN";
} else {
	die "Cannot open $filename";
	exit(2);
}

if (length($opt_f) > 0) {
	$file_out = 1;
}

if (length($opt_v) > 0) {
	$verbose = 1;
	$psql = "psql -ed $db_name > /dev/tty ";
}

if (length($opt_p) > 0) {
	$column_out = 0;
}

if (length($opt_c) > 0) {
	$create_new = 1;
}

if (length($opt_t) > 0) {
	$type = $opt_t;
	$type =~ tr/A-Z/a-z/;
}

if (length($opt_k) > 0) {
	$flags = $opt_k;
} else {
	$flags = "+-";
}

if (length($opt_r) > 0) {
	$comment = $opt_r;
} else {
	$comment = "$shorthand database";
}

if ( $file_out == 1 ) {
        open(PG,"> postgres.input");
}
else {
        open(PG,"| $psql");
}

open(IN,"$filename")  || die "Could not open input file: >>$filename<<\n";

if ( $type eq "dx" ) {
	$tab = "dx_data";
	$rec_len = 86;
	$records = $size/$rec_len;
} elsif ( $type eq "opernam" ) {
	$tab = "us_data";
	$rec_len = 196;
	$records = $size/$rec_len;
} elsif ( $type eq "wwv" ) {
	$tab = "wwv_data";
	$rec_len = 90;
	$records = $size/$rec_len;
} elsif ( $type eq "qsl" ) {
	$tab = "qsl_mng";
	$records = `grep -c \'&&\' $filename`;
	chop $records;
	$records .= " (estimated)";
} elsif ( $type eq "ful" ) {
	$tablename = $ARGV[1];
	$tab = $tablename;
	if ($tab !~ /^Udt_*/i) { 
		$tab = "Udt_$tab";
	}
	$idx = "idx_" . $tab;
        $idx =~ s/udt_//i;
	$records = `grep -c \'&&\' $filename`;
	chop $records;
} elsif ( $type eq "vhf" ) {
	$tab = "Udt_vhf";
	$idx = "idx_vhf";
	$comment = "VHF database of VHF Group DL-West, updates pse to dl8ebw\@db0ndk";
	$records = "?";
} elsif ( $type eq "iota" ) {
	$tab = "Udt_iota";
	$idx = "idx_iota";
	$records = (split(' ',`wc -l $filename`))[0];
	$comment = "IOTA database, courtesy DL3KDV";
} else {
	die "format not one of $formats";
}

&init_pg;

printf "Reading $filename, $records records\n";

if    ( $type eq "dx" ) 	{ &read_dx; }

elsif ( $type eq "opernam" ) { 
	&read_oper; 
	&finish_pg;
	seek(IN,0,0); # reset to start of file
	$tab = "us_uhn";
	&init_pg;
	&read_uhn;
}

elsif ( $type eq "wwv" ) 	{ &read_wwv; }
elsif ( $type eq "qsl" ) 	{ &read_qsl; }
elsif ( $type eq "ful" ) 	{ &read_ful; }
elsif ( $type eq "vhf" ) 	{ &read_vhf; }
elsif ( $type eq "iota" ) 	{ &read_iota; }

close(IN);
&finish_pg;
close(PG);

sub status {

	$cursor = $cursor + length($cnt) + 1;
	if ( $cursor > $cols ) {
		print "\n";
		$cursor = 0;
	}
	printf("%d ",$cnt);

}

sub read_dx {

	while (read(IN,$data,$rec_len)) {

		($freq,$call,$date,$time,$cmt,$logger) = 
			unpack('A9x1A12x1A11x1A5x1A30x1A8',$data);

		if ($verbose == 1) {

			printf("dx='%s' f='%s' d='%s' t='%s' c='%s' l='%s'\n",
				$call,$freq,$date,$time,$cmt,$logger);

		}

		($day,$month,$year) = split('-',$date);

		next if (! &checkdate($time,$day,$month,$year));

		$d = sprintf("%s %02d %02d:%02d:00 %s GMT",
                	$month,$day,substr($time,0,2),
                	substr($time,2,2),$year);

		$freq += 0;		# add 0 so it sure is numeric

		$logger =~ s/\000.*$//;	# '\000' marks end of string
		$logger =~ tr/A-Z/a-z/;	# lower case 

		$call =~ tr /A-Z\\/a-z\//;	# lower case and '\' -> '/'

		$cmt =~ tr /-A-Za-z0-9&()\/\?\@\.\, //cd;

	        if ( $column_out == 1 ) {
			$qry = sprintf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
				$call,$cmt,$d,$logger,"\\N",$freq,"\\N","\\N");
        	}
	        else {
			$qry = sprintf("insert into %s \
				(dx_call,dx_freq,dx_dati,dx_misc,log_a) \
                		values('%s','%s','%s','%s','%s')\;",
		                $tab,$call,$freq,$d,$cmt,$logger);
        	}

		print PG "$qry\n";
		$cnt++;

		if ($cnt % 100 == 0) { &status(); }


	}
}

sub read_wwv {

	while (read(IN,$data,$rec_len)) {

		($date,$hour,$sf,$a,$k,$cmt,$logger) = 
			unpack('A11x2A2x1A3x2A3x2A2x6A39x3A9',$data);

		if ($verbose == 1) {

			printf("d='%s' h='%s' sf='%d' a='%d' k='%d' l='%s'\nc='%s'\n\n",
				$date,$hour,$sf,$a,$k,$logger,$cmt);

		}

		($day,$month,$year) = split('-',$date);

		next if (! &checkdate('0000Z',$day,$month,$year));

		next if ($sf !~ /[0-9]+/);	# this must be a number
		next if ($k !~ /[0-9]+/);	# must be an integer or empty
		next if ($a !~ /[0-9]+/);	# must be an integer or empty

		$d = sprintf("%s %02d %02d:18:00 %s GMT",
                	$month,$day,$hour,$year);

		$logger =~ s/\000.*$//;	# '\000' marks end of string
		$logger =~ tr/A-Z/a-z/;	# lower case 

		$cmt =~ tr/-A-Za-z0-9&()\/\?\@\.\, //cd;

	        if ( $column_out == 1 ) {
			$qry = sprintf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
				$d,$hour,$sf,$a,$k,$cmt,
				$logger,"\\N","\\N");
        	}
	        else {
			$qry = sprintf("insert into %s \
				(wwv_date,wwv_hour,wwv_sfi, \
				 wwv_a,wwv_k,wwv_fcast,log_a) \
                		values('%s','%s','%d','%d','%d','%s','%s')\;",
		                $tab,$d,$hour,$sf,$a,$k,$cmt,
				$logger,"\\N","\\N");
        	}

		print PG "$qry\n";
		$cnt++;

		if ($cnt % 100 == 0) { &status(); }


	}
}

sub read_oper {

	while (read(IN,$data,$rec_len)) {

		($call,$name,$last_seen,$date,$time,
			$lat_deg,$lat_min,$lat_sec,$ns,
			$lon_deg,$lon_min,$lon_sec,$ew,
			$qth,$homenode) = 
			unpack('x2A12x1A23SA11x1A5x3Cx1Cx1Cx1C1x1Cx1Cx1Cx1C1A80x1A9',$data);

		($day,$month,$year) = split('-',$date);

		next if (! &checkdate($time,$day,$month,$year));

		$d = sprintf("%s %02d %02d:%02d:00 %s GMT",
                	$month,$day,substr($time,0,2),
                	substr($time,2,2),$year);

		$call =~ tr/A-Z\\/a-z\//;	# lower case and '\' -> '/'

		if ( $lat_deg != 0 && $lon_deg != 0 ) {
			$location = sprintf("%02d %02d %1c %02d %02d %1c",
					$lat_deg,$lat_min,$ns,
					$lon_deg,$lon_min,$ew);
		} else {
			$location = "\\N";
		}

		if ($verbose == 1) {

			printf("c='%s' n='%s' last=%d d='%s' t='%s'\nlat = %d %d %d %c    lon = %d %d %d %c\nq='%s' h='%s'\n\n",
				$call,$name,$last_seen,$date,$time,
				$lat_deg,$lat_min,$lat_sec,$ns,
				$lon_deg,$lon_min,$lon_sec,$ew,
				$qth,$homenode);

		}

	        if ( $column_out == 1 ) {
			$qry = sprintf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
				$call,$name,$location,$qth,"\\N","\\N","\\N","\\N","\\N",$d,$d,"\\N","\\N","\\N","\\N");
        	}
	        else {
			$qry = sprintf("insert into %s \
				(us_call,us_name,us_loc,us_qth,f_login,l_login) \
                		values('%s','%s','%s','%s','%s','%s')\;",
		                $tab,$call,$name,$location,$qth,$d,$d);
        	}

		print PG "$qry\n";
		$cnt++;

		if ($cnt % 100 == 0) { &status(); }
	}
}

sub read_uhn {

	while (read(IN,$data,$rec_len)) {

		($call,$name,$last_seen,$date,$time,
			$lat_deg,$lat_min,$lat_sec,$ns,
			$lon_deg,$lon_min,$lon_sec,$ew,
			$qth,$homenodessid) = 
			unpack('x2A12x1A23SA11x1A5x3Cx1Cx1Cx1C1x1Cx1Cx1Cx1C1A80x1A9',$data);

		next if (! &checkdate($time,$day,$month,$year));

		$call =~ tr/A-Z\\/a-z\//;	# lower case and '\' -> '/'
		$call =~ tr/a-z0-9//cd;

		$homenodessid =~ s/\000.*$//;	# '\000' marks end of string
		$homenodessid =~ tr/A-Z/a-z/;	# lower case 
		if ($homenodessid =~ /-/) {
			($homenode,$ssid)=split(/-/,$homenodessid);
		} else {
			$homenode = $homenodessid;
			$ssid = 0;
		}
		$homenode =~ tr/a-z0-9//cd;

		if ($verbose == 1) {

			printf("c='%s' h='%s'\n\n",$call,$homenodessid);

		}

	        if ( $column_out == 1 ) {
			$qry = sprintf("%s\t%s\t%d\t%s\t%d\t%d",
				$call,$homenode,$ssid,$homenode,$ssid,0);
        	}
	        else {
			$qry = sprintf("insert into %s \
				(us_call,hb_call) \
                		values('%s','%s','%d','%s','%d','%d')\;",
		                $tab,$call,$homenode,$ssid,$homenode,$ssid,0);
        	}

		print PG "$qry\n";
		$cnt++;

		if ($cnt % 100 == 0) { &status(); }
	}
}

sub read_qsl {
# Importing QSL data into the qsl_mng table
# Tested with DB0SDX's sdx_qsl.ful of December 16, 1996 available from
# ftp://ftp.grossmann.com/pub/db.
#
# Problem sind noch die Klammerausdrcke mit Leerzeichen.
# Wie bringt man dem Split bei, da es so zerlegen soll:
# VP2E (CQWW-SSB 1995) VIA W5AJ:
# 1. VP2E
# 2. (CQWW-SSB 1995)
# 3. VIA
# 4. W5AJ


	sub print_qsl {
		if ( $mgr =~ /$key[\s:]+via[\s:]+/i ) {
			($dummy,$via,$mgr,@cmt) = split(/[\t\s]+/,$mgr);
		}
		elsif ( $mgr =~ /$key[\s:]+(.*)[\s:]via[\s:]+(.*)$/i ) {
			@cmt = $1;
			$mgr = $2;
			# ($dummy,$cmt[0],$via,$mgr) = split(/[\t\s]+/,$mgr);
		}
		elsif ( $mgr =~ /QSL[\s:]+via[\s:]+/i ) {
			($dummy,$via,$mgr,@cmt) = split(/[\t\s]+/,$mgr);
		}
		elsif ( $mgr =~ /$key[\s:]+QSL[\s:]+via[\s:]+/i ) {
			($dummy,$dummy,$via,$mgr,@cmt) = split(/[\t\s]+/,$mgr);
		}
		elsif ( $mgr =~ /^$key$/i ) {
			next;
		}
		else {
			($mgr,@cmt) = split(/\s+/,$mgr);
		}
		
		if ( $rmx =~ /UPDATED BY.*/i ) {
			$rmx =~ s/UPDATED BY //;
			$rmx =~ s/@ .* //;
			($src,$date,$time) = split(/[\t\s]+/,$rmx);
			$src =~ s/://;
			$src =~ tr/A-Z/a-z/;
			($day,$month,$year) = split('-',$date);
			goto DONE if (! &checkdate($time,$day,$month,$year));
		}
		
		$c = join(' ',@cmt);
		
		$d = sprintf("%s %02d %02d:%02d:00 %s GMT",
			$month,$day,substr($time,0,2),
			substr($time,2,2),$year);

		if ($src eq '' ||
			! &checkdate($time,$day,$month,$year)) { 
			$src = $shorthand; 
			$d = $filedate;
		}
		
		$key =~ tr/A-Z/a-z/;
		$mgr =~ tr/A-Z/a-z/;
		
		if ( $verbose == 1 ) {
			printf("%-3d q=%-13s m=%-8s a=%-12s d=%12s c=%s\n",
			$l,$key,$mgr,$src,$d,$c);
		}
	
		if ( $column_out == 1 ) {
			$qry = sprintf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s",
				$key,$mgr,$c,"5","\\N",$src,"\\N",$d);
		}
		else {
			$qry = sprintf("insert into %s (stn_call,stn_mng,    \
			a_comm,auth_i,inf_auth,add_time)                      \
			values('%s','%s','%s',5,'%s','%s')\;",
			$mng_tab,$key,$mgr,$c,$src,$d);
		}
		
		
		print PG "$qry\n";
		
		$cnt++;
		if ($cnt % 100 == 0) { &status(); }

DONE:		return;
	}

	while (<IN>) {
		if (/^[-\#]/) { next; }		# Kommentarzeilen und "-" weg
		if (/^[ \t]*$/) { next; }	# Leerzeilen weg
		if (/^.$/) { next; }		# einzelne Zeichen weg
		if (/^%%/) { next; }		# ungltige Eintrge
	
		tr/-A-Z0-9&()\/\?\@\.\, //cd;	# Alle ungltigen Zeichen weg
		tr/\n\r\'//d;			# \n und \r und ' weg
	
		s/\(/\\(/;			# Klammern schtzen
		s/\)/\\)/;
	
		if (/^&&/) {
			($key,$via,$src,$date,$time,$mgr,$rmx) = "";
	
			if ($l == 2) { 
				$key = shift(@v); $mgr = shift(@v); $rmx = "";
				&print_qsl
			}
		
			if ($l >= 3) {
				$key = $v[0];
				$rmx = $v[$l-1];
				for ($i=1;$i<$l-1;$i++) {
					$mgr=$v[$i];
					if (!($mgr =~ /UPDATED.*/ )) {
						&print_qsl
					}
				}
			}
	
			$l = 0;
			undef @v;
			undef @cmt;

		} else {
			push(@v,$_);
			$l++;
		}
	}
}

sub read_ful {
# Read a general .ful database table from Pavillion Software
# This subroutine finally replaces the clumsy pg_read program


	if ( $column_out == 1 ) {
		print PG "Clx_Udt_Info\t$comment\t$flags\t0\t0\t$now\tsystem\n";
	} else {
		printf PG ("insert into %s \
		(dt_key,dt_info,perm_fl,exec_fl,count_fl,ins_time,ins_call) \
		values('%s','%s','%s','%d','%d','%s','%s')\;\n",
		$tab,"Clx_Udt_Info",$comment,$flags,0,0,$now,"system");
	}

	undef(@v);
	$cnt = 0;
	while (<IN>) {

		tr/-A-Za-z0-9&()\/\?\@\.\, ://cd;# Alle ungltigen Zeichen weg
		tr/\n\r\'//d;			# \n und \r und ' weg
	
		if (/^&&/) {

			if ($v[0] =~ /^%%/) {	# ungltige Eintrge
				next; 
			}

			$key = lc shift @v;

			next if $key eq "";

			$data = join("\\\n",@v);
			$data = substr($data,0,$max);
			$data .= "\\\n";

			next if $data eq "";

			$d = sprintf("%s %02d %02d:%02d:00 %s GMT",
				$month,$day,substr($time,0,2),
				substr($time,2,2),$year);
		
			if ($src eq '' ||
				! &checkdate($time,$day,$month,$year)) { 
				$src = $shorthand; 
				$d = $filedate;
			}

	        	if ( $column_out == 1 ) {
				print PG "$key\t$data\t\\N\t\\N\t\\N\t$d\t$src\n";
			} else {
				printf PG ("insert into %s \
				(dt_key,dt_info,ins_time,ins_call) \
				values('%s','%s','%s','%s')\;\n",
				$tab,$key,$data,$d,$src);
			}

			undef(@v);
			$src = '';
			$d = '';

			$cnt++;
			if ($cnt % 10 == 0) { &status(); }

		} elsif ( /UPDATED BY.*/ ) {

			s/UPDATED BY //;
			s/@ .* //;
			($src,$date,$time) = split(/[\t\s]+/);
			$src =~ s/://;
			$src =~ tr/A-Z/a-z/;
			($day,$month,$year) = split('-',$date);

		} else {
			push(@v,$_);
			$l++;
		}
	}
}

sub read_vhf {

	$bs = 32; # 32 Bytes block size;
	$src = "VHF-DXG DL-West";
	
	@b = (	"Call:", "DXCC/WAE:", "QTH:", 
	        "ex-Calls:", "PBBS:", "Cluster:",
		"E-Mail:", "Name:", "Activity:", "Equipment:", "CW-Remarks:", 
		"SSB-Remarks:", "Last Updated:" );
	
	read(IN,$data,$bs);
	($valid,$year,$m,$day,$total,$hbytes,$rbytes) = 
		unpack('C1C1C1C1L1S1S1',$data);
	$fields = (($hbytes - ($bs+1) ) / $bs);

	$month = $lit_month[$m-1];
	if ( $year < 70 ) {
		$year += 2000;
	} else {
		$year += 1900;
	}
	$time = "00:00";
	$d = sprintf("%s %02d %02d:%02d:00 %s GMT",
		$month,$day,substr($time,0,2),
		substr($time,2,2),$year);
	
	$valid = ($valid & 0x7f); # mask the high bit, we don't need it
	if ($valid != 0x03) {
		print "File $filename is not a valid DBF file.\n";
		exit(1);
	}
	
	print  ("DBF Structure Information\n\n");
	printf ("   V-Byte:        %x\n",$valid);
	printf ("   Last Updated:  %02d %s %02d\n",$day,$month,$year);
	printf ("   Header length: %d bytes, %d fields\n",$hbytes,$fields);
	printf ("   Record length: %d bytes\n",$rbytes);
	printf ("   Total records: %d\n",$total);
	print  ("\n");
	
	$fmt = "a1"; # for a start (the 'valid' byte)
	foreach($i=0;$i<$fields;$i++) {
		read(IN,$data,$bs);
		($field_name,$field_type,$data_address,$field_length) = 
			unpack('A11a1L1C1',$data);
		printf ("%4d: Name: %-12s    Type: %1s    Length: %3d\n",
			$i,$field_name,$field_type,$field_length);
	
		if ( $field_type eq 'C' ) {
			$fmt .= sprintf("A%d",$field_length);
		}
	}
	
	print ("\n");
	
	# print STDERR "FMT: $fmt\n";
	
	seek(IN,$hbytes,0);
	
	# 
	# Position:
	# 0x0000   (0): Valid (' ','*') (1)
	# 0x0001   (1): Call           (20)
	# 0x0015  (21): DXCC/WAE       (10)
	# 0x001f  (31): QTH            (10)
	# 0x0029  (41): ex Calls       (50)
	# 0x005b  (91): PBBS           (20)
	# 0x006f (111): Cluster        (20)
	# 0x0083 (131): E-Mail         (50)
	# 0x00b5 (181): Name           (20)
	# 0x00c9 (201): Activity      (254)
	# 0x01c7 (455): Equipment     (254)
	# 0x02c5 (709): CW-Remarks     (20)
	# 0x02d9 (729): SSB-QRG        (10)
	# 0x02e3 (739): Last Updated    (8)
	# 
	
	for ($cnt=0;$cnt<$total;$cnt++) {
	
		read(IN,$data,$rbytes);
	
		($valid,@a) = unpack($fmt,$data);
		$a[2] = uc($a[2]); # QTH in upper case
	
		if ($valid eq ' ') {
			$key = lc($a[0]);
			$data = "";
			foreach ($i=0;$i<=$#a;$i++) {
				if ( $a[$i] ne "" ) {
                                        $a[$i] =~ tr/\n\r//d; # DL8EBW/AL7EB bug 6.11.99
					$data .= sprintf("%-14s %s\\\n",
						$b[$i],$a[$i]);
				}
			}
	
	        	if ( $column_out == 1 ) {
				print PG "$key\t$data\t\\N\t\\N\t\\N\t$d\t$src\n";
			} else {
				printf PG ("insert into %s \
				(dt_key,dt_info,ins_time,ins_call) \
				values('%s','%s','%s','%s')\;\n",
				$tab,$key,$data,$d,$src);
			}
	
			if (length($a[2]) == 6) {
				if (defined($call{$a[2]})) {
					$call{$a[2]} .= ", $a[0]";
				} else {
					$call{$a[2]} = "$a[0]";
				}
			}
	
		} else {
			print STDERR "Invalid record: $a[0]\n";
		}
	
		if ( $cnt % 1000 == 0) { &status(); }
	}

	if ( $column_out == 1 ) {
		print PG "Clx_Udt_Info\t$comment\t$flags\t0\t$cnt\t$now\tsystem\n";
	} else {
		printf PG ("insert into %s \
		(dt_key,dt_info,perm_fl,exec_fl,count_fl,ins_time,ins_call) \
		values('%s','%s','%s','%d','%d','%s','%s')\;\n",
		$tab,"Clx_Udt_Info",$comment,$flags,0,$cnt,$now,"system");
	}

	&status();
	print STDERR "\n";
	
	close(IN);
	
	foreach $i (keys %call) {
		$key = lc($i);
		$data = $call{$i} . "\\\n";
#		printf("%s\n%s\n&&\n",$i,$data);
        	if ( $column_out == 1 ) {
			print PG "$key\t$data\t\\N\t\\N\t\\N\t$d\t$src\n";
		} else {
			printf PG ("insert into %s \
			(dt_key,dt_info,ins_time,ins_call) \
			values('%s','%s','%s','%s')\;\n",
			$tab,$key,$call{$i},$d,$src);
		}
	}
}

sub read_iota {

# Read DL3KDV's IOTA ASCII database

	$src = "DL3KDV";

	if ( $column_out == 1 ) {
		print PG "Clx_Udt_Info\t$comment\t$flags\t0\t0\t$now\tsystem\n";
	} else {
		printf PG ("insert into %s \
		(dt_key,dt_info,perm_fl,exec_fl,count_fl,ins_time,ins_call) \
		values('%s','%s','%s','%d','%d','%s','%s')\;\n",
		$tab,"Clx_Udt_Info",$comment,$flags,0,0,$now,"system");
	}

	undef(@v);
	$cnt = 0;

	while (<IN>) {
		chop;
		s/, */,/g;
		s/\'/\\'/g;
		($id,$pfx_list,$name) = split(' ',$_,3);
		$e = sprintf("%-6s %-16s %s",$id,$pfx_list,$name);
		$list{$id} = $e . "\\n";
		foreach $i (split(/,/,$pfx_list)) {
			$list{$i} .= "$e\\n";
		}
		$cont = $id;
		$cont =~ s/-[0-9]+//;

		while(defined($list{"$cont" . "-x"})) {
			$cont .= "-x";
		}

		if ((length($list{$cont})+$width) > $max) {
			$list{$cont} .= "continue with $cont" . "-x\\n";
			$cont .= "-x";
		}
		$list{$cont} .= "$e\\n";
	}

	$d = $filedate;
	foreach $i (sort keys %list) {

		$key = lc $i;
		$data = $list{$i};

		next if ($data eq "" || $key eq "");

	       	if ( $column_out == 1 ) {
			print PG "$key\t$data\t\\N\t\\N\t\\N\t$d\t$src\n";
		} else {
			printf PG ("insert into %s \
			(dt_key,dt_info,ins_time,ins_call) \
			values('%s','%s','%s','%s')\;\n",
			$tab,$key,$data,$d,$src);
		}

		$cnt++;
		if ($cnt % 10 == 0) { &status(); }

	}
}

sub init_pg {

	$cnt = 0;

	if ( $create_new == 1 ) {
		print PG "DROP table $tab;\n";
		if ( $type eq "ful" || $type eq "vhf" || $type eq "iota" ) {
			$fmt = `cat $home/db/udt_tbl.tmpl`;
			$create = sprintf($fmt,$tab);
		} else {
			$create = `cat $home/db/$tab.cl`;
		}
		print PG "$create";
	}
	
	if ( $column_out == 1 ) {
	        print PG "COPY $tab FROM stdin\;\n";
	}
}

sub finish_pg {

	if ( $column_out == 1 ) {
		print PG "\\.\n";
	}

	if ( defined($idx) ) {
		print PG "create index $idx on $tab 
			using hash (dt_key varchar_ops);\n";
	}

	print "$cnt\n";
}

sub checkdate {

	my($time,$day,$month,$year) = @_;
	$rc = 1;

	$month =~ tr/a-z/A-Z/;
	if ($time !~ /[012][0-9][0-5][0-9]Z/) { $rc = 0; }
	if ($month !~ /[JFMASOND][AEOCUP][NBRYLGPTVC]/i) { $rc = 0; };
	if (! grep(/^$month$/,@lit_month)) { $rc = 0; };
	if ($year !~ /[12][0-9][0-9][0-9]/) { $rc = 0; };
	if ($day > 31) { $rc = 0; };
	if ($day < 1) { $rc = 0; };

	return $rc;
}
