9

Consider the following Pascal program:

    1  1 PROGRAM MAIN(OUTPUT); VAR F:TEXT; I:INTEGER;
    2  2 BEGIN
    3  2    REWRITE(F);
    4  3    FOR I := 10 TO 30 DO BEGIN
    5  3       WRITELN(   I, ’:’, ’ABCDEFGHIJ’ : I);
    6  3       WRITELN(F, I, ’:’, ’ABCDEFGHIJ’ : I);
    7  2    END;
    8  2    RESET(F);
    9  2    WRITELN(’--------------------’);
   10  3    WHILE NOT EOF(F) DO BEGIN
   11  3       WRITE(F^);
   12  3       GET(F)
   13  3    END
   14  0 END.

The program writes a staircase of ABCDEFGHIJ to the standard output and to a local temporary file, then writes a separator line and copies the local file character by character to the standard output. The expectation is that there will be two copies of the staircase of ABCDEFGHIJ; however, the result on the BESM-6 is

        10:ABCDEFGHIJ
        11: ABCDEFGHIJ
        12:  ABCDEFGHIJ
        13:   ABCDEFGHIJ
        14:    ABCDEFGHIJ
        15:     ABCDEFGHIJ
        16:      ABCDEFGHIJ
        17:       ABCDEFGHIJ
        18:        ABCDEFGHIJ
        19:         ABCDEFGHIJ
        20:          ABCDEFGHIJ
        21:           ABCDEFGHIJ
        22:            ABCDEFGHIJ
        23:             ABCDEFGHIJ
        24:              ABCDEFGHIJ
        25:               ABCDEFGHIJ
        26:                ABCDEFGHIJ
        27:                 ABCDEFGHIJ
        28:                  ABCDEFGHIJ
        29:                   ABCDEFGHIJ
        30:                    ABCDEFGHIJ
--------------------
        10:ABCDEFGHIJ
   15:     ABCDEFGHIJ
    ABCDEFGHIJ
             ABCDEFGHIJ
 CDEFGHIJ
 HIJ

To put it mildly, only the first line is correct, the rest is garbage.

To achieve the expected result, it is necessary to write

   11  3       IF EOLN(F) THEN WRITELN ELSE WRITE(F^);

Or, given that the internal character encoding is almost ASCII, IF F^ = CHR(10) THEN ... also works.

In Programming in Pascal By Nell B. Dale, 1997 (search for eoln, there are only 5 occurrences), it is unclear if explicitly writing an eoln character to the standard output is guaranteed to be functionally equivalent to writeln on all platforms.

Theoretically, even on MS-DOS the internal files, including files of type text, could be treated as binary, and writeln to these files would write just chr(10); the standard output would be treated as text, and writeln to it would write chr(13), chr(10); and for efficiency, there would be no checking for chr(10) appearing in the items being output; thus resulting in an incorrect text file if an equivalent program is run.

Would that be a conforming behavior?

A related issue: when reading from the standard input ("punched cards"), eoln(input) becomes true after 80 of get(input), but at that moment input^ is a space character rather than the line feed. If that is conforming, then the first question would thus be answered in the positive as well.

7
  • 6
    AFAIK, the Pascal standard says nothing about end-of-line encoding in output vs. files, so if the OS chooses to handle this differently, that it's an OS issue, and not a Pascal issue. And if you need to use EOLN to make it compatible, then you need to use EOLN.
    – dirkt
    Commented May 2, 2021 at 8:23
  • @dirkt In the past, the standards were not written with as much rigor regarding the unspecified and/or undefined behavior as they are now. While I would expect as much, if there is a Pascal manual which mentioned that caveat, it would be nice to see.
    – Leo B.
    Commented May 2, 2021 at 8:31
  • Are you running this on windows or linux or some other OS? Which compiler are you using
    – cup
    Commented May 2, 2021 at 8:42
  • 1
    @cup It is a batch-mode OS for a Soviet mainframe BESM-6. The Pascal compiler, as much as I can tell, is close to the original CDC compiler. It ran in the programming environment with a character encoding which was very close to ASCII/ISO.
    – Leo B.
    Commented May 2, 2021 at 9:03
  • 1
    @texdr.aft Syntactic nesting levels.
    – Leo B.
    Commented May 2, 2021 at 21:30

1 Answer 1

13

The ISO 7185 Pascal standard, section 6.4.3.5 "File-types", says (my emphasis):

There shall be a file-type that is denoted by the required structured-type-identifier text. The structure of the type denoted by text shall define an additional sequence-type whose values shall be designated lines. A line shall be a sequence cs ~S(end-of-line), where cs is a sequence of components possessing the char-type, and end-of-line shall represent a special component-value. Any assertion in clause 6 that the end-of-line value is attributed to a variable other than a component of a sequence shall be construed as an assertion that the variable has attributed to it the char-type value space. If l is a line, then no component of l other than l.last shall be an end-of-line. There shall be an implementation-defined subset of the set of char-type values, designated characters prohibited from textfiles; the effect of causing a character in that subset to be attributed to a component of either t.L or t.R for any textfile t shall be implementation-dependent.

A line-sequence, ls, shall be either the empty sequence or the sequence l ~ ls' where l is a line and ls' is a line-sequence.

Every value t of the type denoted by text shall satisfy the following two rules:

a) If t.M = Inspection, then t.L ~ t.R shall be a line-sequence.

b) If t.M = Generation, then t.L ~ t.R shall be ls ~cs, where ls is a line-sequence and cs is a sequence of components possessing the char-type.

NOTE -- 5 In rule b), cs may be considered, especially if it is non-empty, to be a partial line that is being generated. Such a partial line cannot occur during inspection of a fi le. Also, cs does not correspond to t.R, since t.R is the empty sequence if t.M = Generation.

A variable that possesses the type denoted by the required type-identifier text shall be designated a textfile.

So the standard specifically says that end-of-line sequences are implementation dependent, and it doesn't disallow this to differ between standard output, and a file.

It was also always considered good practice in Pascal to never rely on any particular end-of-line encoding, and use eoln/readln/writeln instead. That way, programs would work on different Pascal systems.

So following that practice would also allow for difference between end-of-line representations in different files. And given what kind of OS Pascal was developed first for, I wouldn't be surprised if there are other OS where encoding differs depending on what kind of device the file is on (for example, devices differed by the number of bits a word on the device had).

Finally, "manuals" for Pascal don't matter. The language specification was written by the inventor of Pascal, Niklaus Wirth, and was later turned into the ISO standard quoted. That said, implementations often choose to deviate from that standard, to the displeasure of Wirth, in particular with respect to files and other OS specifics. So "is it allowed Pascal behaviour?" and "does some manual mention this?" are very very different things. Manuals mention many things that are not "allowed" Pascal behaviours.

8
  • 2
    Interesting: the standard introduces a fine distinction between text and file of char; the manuals I've seen say that they are synonyms.
    – Leo B.
    Commented May 2, 2021 at 8:56
  • 3
    With the distinction being that text has a concept of line endings while file of char does not. (If I was reading it correctly) Commented May 2, 2021 at 11:24
  • 1
    It's too few characters to permit an edit, but Niklaus Wirth's name is spelt like that (not Nikolaus)
    – abligh
    Commented May 2, 2021 at 16:39
  • 1
    @AlexHajnal A word with the bit pattern 000...00001010, which is actually not a properly formatted integer in that programming system (the latter must have an "integer exponent" in the upper bits).
    – Leo B.
    Commented May 2, 2021 at 18:03
  • 4
    Don't forget there are OSs where file formats don't correspond to the Pascal (or Unix/MSDOS) model at all. For example a file with fixed length records on OS/360 has no separator characters at all. a Pascal implementation would still have to support EOLN etc (and also pad short lines to the correct length with some character, throw an error attempting to write a line longer than the record length, etc...).
    – alephzero
    Commented May 2, 2021 at 18:34

You must log in to answer this question.

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