Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 18 Dec 2009 11:22:06 +0000
From:      Nick Barnes <Nick.Barnes@pobox.com>
To:        Giorgos Keramidas <keramida@ceid.upatras.gr>
Cc:        Anton Shterenlikht <mexas@bristol.ac.uk>, freebsd-questions@freebsd.org
Subject:   Re: editing a binary file 
Message-ID:  <11404.1261135326@thrush.ravenbrook.com>
In-Reply-To: <87d42cve53.fsf@kobe.laptop>  from Giorgos Keramidas <keramida@ceid.upatras.gr>  of "Fri, 18 Dec 2009 11:13:12 %2B0200"

next in thread | previous in thread | raw e-mail | index | archive | help
If your Fortran file has the same word size and enddian-ness as your
C, this simple program convert.c will strip all the record length
fields.  I just knocked it up now, no warranty, etc, but it works for
me.  Use as a pipe:

$ ls
convert.c       test.f
$ gcc -Wall -Werror -ansi -pedantic convert.c -o convert
$ gfortran44 test.f -o test
$ ./test
$ ls -l test-output
-rw-r--r--  1 nb  nb  2460 Dec 18 11:17 test-output
$ ./convert < test-output > test-converted
$ ls -l test-converted
-rw-r--r--  1 nb  nb  2420 Dec 18 11:18 test-converted
$

The code does a fair amount of checking; if you get one of the error
messages, let us know.  The most obvious unchecked problem is a short
read, which will complain about mismatched lengths.

If your Fortran has different word sizes or enddian-ness (e.g. most of
the Fortran output files I use on the Clear Climate Code project
<http://clearclimatecode.org/>; are generated on big-endian machines),
you will need to add code to tweak the 'size' value after reading it,
and when checking the record-end marker.

Nick B

/* convert.c: remove record length fields from Fortran output file. */
/* Nick Barnes, Ravenbrook Limited, 2009-12-18 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>

int main(void)
{
        long size;
        char *buf;
        ssize_t bytes;
        assert(sizeof(size) == 4);
        while(bytes = read(0, (void*)&size, sizeof(size))) {
                if (bytes < 0) {
                        fprintf(stderr, "read() returned %ld\n", bytes);
                        exit(1);
                }
                if (size <= 0) {
                        fprintf(stderr, "Read bad record length %ld\n", size);
                        exit(1);
                }
                buf = (char*)malloc(size + sizeof(size));
                if (!buf) {
                        fprintf(stderr, "Couldn't allocate buffer of %ld bytes\n",
                                size + sizeof(size));
                        exit(1);
                }
                bytes = read(0, buf, size + sizeof(size));
                if (bytes <= 0) {
                        fprintf(stderr, "read() returned %ld\n", bytes);
                        exit(1);
                }
                if ((*(long*)(buf+size)) != size) {
                        fprintf(stderr, "Mismatched record lengths: %ld, %ld\n",
                                size, *(long*)(buf+size));
                        exit(1);
                }
                write(1, buf, size);
                free(buf);
        }
        return 0;
}






Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?11404.1261135326>