10

One of the notable contributions in FORTRAN 77 was the CHARACTER data type, which made character processing quite usable.

As I understand it, FORTRAN 66 (sometimes called FORTRAN IV, but they're not identical) relied on Hollerith codes to work with characters, and these were mapped into machine words, which then had to be decomposed (using shifts and masks) to work with.

But it's not clear to me how FORTRAN 66 worked with reading and writing the data in and out. I've heard anecdotes about working with or modifying FORMAT statements, but I've never seen an example.

I'm curious if anyone has any examples of character work with FORTRAN 66.

4
  • You might wish to refer to Fortran techniques with special reference to non-numerical applications (1972) which is an introduction to text searching/indexing in FORTRAN. This was before CHARACTER types were available in the language.
    – scruss
    Apr 7, 2023 at 19:29
  • That's a really cool book, thanks @scruss! Apr 8, 2023 at 15:47
  • You're welcome! The author was attempting to do what we'd now call corpus linguistics or natural language processing on an ICL 1900 in Fortran. Some of the other techniques documented such as avoiding subroutines and handling (pseudo-)recursion were clearly necessary at the time, but look utterly horrid now
    – scruss
    Apr 8, 2023 at 18:24
  • 1
    Indeed. The "Open Coding" bit gave me nascent glimpses of the Intercals "COMEFROM". Apr 9, 2023 at 15:01

3 Answers 3

11

Individual characters could be read into integer variables (or elements of integer arrays) using the format specifier A1, manipulated at will, then printed using the A1 format specifier.

For example (using the BESM-6 clone of the CDC 1604 FORTRAN compiler),

                PROGRAM MAIN
                INTEGER STR(80)
                READ 10,STR
            10  FORMAT(80A1)
       2        PRINT 11,STR
            11  FORMAT(’ READ: ’, 80A1)
       3        DO 2 I = 1,80
       4        IF (STR(81-I).NE.1H )
       5       -                      GOTO 3
       6     2  CONTINUE
       7     3  I=81-I
       8        PRINT 12,I
            12  FORMAT(’ STRING LENGTH = ’, I3)
       9        DO 4 J=1,I
      10        K=STR(J)
      11        STR(J)=STR(81-J)
      12     4  STR(81-J)=K
      13        I=81-I
      14        PRINT 13,(STR(J),J=I,80)
            13  FORMAT(’ REVERSED: ’, 80A1)
                END
           *EXECUTE
 READ:  HELLO, WORLD!
 STRING LENGTH =  14
 REVERSED: !DLROW ,OLLEH

Also there were operators ENCODE and DECODE, said to be non-standard in FORTRAN 77 but provided for compatibility with older versions of FORTRAN.

They are somewhat analogous in functionality to the C library functions snprintf and sscanf, allowing to perform formatted I/O to/from packed character strings. For example, generating a format string on the fly and printing something using it could look like

                PROGRAM MAIN
                INTEGER STR(80),FMT(20)
                READ 10,STR
            10  FORMAT(80A1)
       2        ENCODE (80, 11, FMT) STR
            11  FORMAT (2H(’,20A1,5H’,I6))
       3        PRINT FMT,123456
                END
           *EXECUTE
ARBITRARY PREFIX    123456

Here the input stream contained the line ARBITRARY PREFIX which was read into an "unpacked character" array, then interpolated into an array containing "packed characters" using the ENCODE statement to form a valid format string, then the newly formed packed character string was used as the format to print an integer.

13
  • 1
    Very interesting! Though I'd be surprised if much code was written to do character/string manipulation in FORTRAN, except as part of interpreters, written in FORTRAN, for some easier-to-use string language. (IIRC there were other special purpose languages with interpreters written in (early) FORTRAN but I can't find any references now ...)
    – davidbak
    Aug 22, 2022 at 2:54
  • 13
    Programming languages are like hammers. If all you have is FORTRAN, then the problem will be fortranified :))
    – Raffzahn
    Aug 22, 2022 at 10:05
  • 3
    @Raffzahn --- Or the language, if you have something else. After all, the determined Real Programmer can write FORTRAN programs in any language. Aug 22, 2022 at 17:04
  • 2
    @Raffzahn 50+ years ago FORTRAN was like Pytnon today: there was a library for everything, and for some purposes, using it was orders of magnitude less efficient than a more appropriate tool.
    – Leo B.
    Aug 22, 2022 at 17:36
  • 1
    @Raffzahn I intended it as an amusing parallel. :)
    – Leo B.
    Aug 22, 2022 at 18:47
6

With respect to this:

I've heard anecdotes about working with or modifying FORMAT statements, but I've never seen an example.

The FORTRAN IV language for IBM 7090/7094 IBSYS version 13 supported this.

Under 'H-conversion' the manual says:

On input, n characters are extracted from the input record and replace the n characters included with the source program FORMAT specification.

Thus, you code 6HFOOBAR in your FORMAT statement. If you use that in a READ, FOOBAR gets overwritten; a subsequent WRITE referencing the same format will print the new characters.

Reference: 7090 FORTRAN IV manual at Bitsavers; see page 17. This is a slightly earlier edition than my paper manual, but the H-conversion details are the saeme.

I imagine this is useful only for captions and headings, since there's no processing, just read in and write out.

The same behaviour existed in the FORTRAN II language; see page 47. And even before that, in the 1956 FORTRAN system for the IBM 704, see page 28.

(KDF9 Algol, of approximately the same vintage, used to have a 'copytext' library function that directly copied string data from input to output, for similar reasons).

6
  • 1
    That works in the BESM-6/CDC 1604 FORTRAN as well, I've just verified it. Reading the line ABCDEFGHIJ 12345 using the format (10HXXXXXXXXXX,I6), modifying the integer variable just read, and using the same format label to output it back would print ABCDEFGHIJ 98765.
    – Leo B.
    Aug 22, 2022 at 23:17
  • Yea, this really intrigued me, the idea of reading "into" the format statement. It's hard to imagine how this was done in the real world, and for what applications. Trying to visualize someone running, say, a simple inventory report using this technique. Aug 23, 2022 at 14:39
  • How about a heading that's to be printed at the top of every page, specific to a single execution of the "report program"? It's probably easier to read it into the "header format" than to mess with reading it (via A-conversion) into an array variable to be used when printing the header. It smells a bit like self-modifying code though...
    – dave
    Aug 23, 2022 at 20:22
  • Sure, but that's seems a pretty narrow example for what I assume must have been a fairly common, and idiomatic technique. Just thinking of the extra hoops the runtime must have to run through to facilitate stomping on the format string during the read in the first place. I don't think this was happenstance, someone asked for this and thought it was a pretty good idea so they designed it in to the language and runtime. Aug 24, 2022 at 1:56
  • @WillHartung - It doesn't seem like too many hoops to me - I'd imagine it being much like A-conversion, except for the specifics of hthe destination address. And maybe it just falls out of having H-conversion on output. It was in FORTRAN pretty much from the beginning; see my recent edits for references. So someone apparently found it useful.
    – dave
    Aug 24, 2022 at 2:29
5

In FORTRAN 66, you could store up to the word size in characters. For instance, on a 24-bit machine with 6-bit characters

      INTEGER C1(80), C2(40), C4(20)
      READ(10,11) (C1(II), II=1, 80)
11    FORMAT(80A1)
      READ(10,12) (C2(II), II=1, 40)
12    FORMAT(40A2)
      READ(10,13) (C3(II), II=1, 20)
13    FORMAT(20A4)

These could then be manipulated in chunks of 1, 2 or 4. The only problem is splitting them up or having wildcards. Simple like-for-like comparisons could be done just using .EQ.

On some implementations, this is not restricted to just integers: double precision could also be used. This had the advantage of storing more characters, which was useful if you had names mixed in with values. They could be printed like

      DIMENSION VAL(5)
      DOUBLE PRECISION VAL
      ...
      WRITE(11,14) (VAL(II), II = 1, 5)
14    FORMAT(1X, A8, 4D9.2)

The only problem is that if this was used for calculations, your arrays all began at 2.

On CDCs, with their 60 bit words, 10 6-bit characters could be stored in each integer. The problem was that the integers were only 48 bits so if a word, full of alphanumerics was printed as an integer, you'd get an overflow error.

3
  • That last paragraph - on CDC machines - made a weird answer even weirder...
    – davidbak
    Aug 22, 2022 at 20:22
  • Took me a while to figure out why I couldn't print the 60-bit integer.
    – cup
    Aug 23, 2022 at 6:53
  • if a word, full of alphanumerics was printed as an integer, you'd get an overflow error That's weird. A respectable implementation ought to diagnose the error condition more precisely ("attempting to print word contents in octal/hex as an integer"), or to handle it gracefully, printing some distinct characters instead of the integer value.
    – Leo B.
    Aug 23, 2022 at 7:48

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .