+sub dotperllibdir () {
+ my $dir;
+
+ for my $dir (@INC) {
+ if ($dir =~ m/\.perl-lib$/) {
+ return $dir;
+ }
+ }
+ die "no appropriate dotperllib dir in @INC";
+}
+
+sub sourcebasedir () {
+ return dotperllibdir().'/..';
+}
+
+sub datadir () {
+ my $edir= $ENV{'YARRG_DATA_DIR'};
+ return $edir if defined $edir;
+ my $dir= dotperllibdir();
+ if (stat "$dir/DATA") {
+ return "$dir/DATA";
+ } elsif ($!==&ENOENT) {
+ return "$dir";
+ } else {
+ die "stat $dir/DATA $!";
+ }
+ return '.';
+}
+
+my @ocean_list;
+
+sub ocean_list () {
+ my $datadir= datadir();
+ if (!@ocean_list) {
+ my $fn= "$datadir/source-info.txt";
+ my $f= new IO::File $fn or die "$fn $!";
+ my @r;
+ while (<$f>) {
+ next unless m/^ocean\s+(\S.*\S)\s*$/;
+ push @r, $1;
+ }
+ $f->error and die $!;
+ close $fn;
+ @ocean_list= @r;
+ }
+ return @ocean_list;
+}
+
+sub dbw_connect ($) {
+ my ($ocean) = @_;
+ die "unknown ocean $ocean ?"
+ unless grep { $_ eq $ocean } ocean_list();
+ return dbr_connect(datadir(), $ocean);
+}
+
+sub to_json_shim ($) {
+ my ($obj) = @_;
+ # In JSON.pm 2.x, jsonToObj prints a warning to stderr which
+ # our callers don't like at all.
+ if ($JSON::VERSION >= 2.0) {
+ return to_json($obj);
+ } else {
+ return objToJson($obj);