#
Chapter 9

Ex 9.1

         PROGRAM ex9 1 CONTEXT VOID
         USE standard
         BEGIN
            FILE f;
            IF   open(f,
                      "textbook",
                      stand in channel)/=0
            THEN
               print("Cannot open textbook");
               exit(1)
            FI;

            STRING s;
            WHILE get(f,(s,newline));  UPB s /= 0
            DO
               print((s,newline))
            OD;

            close(f)
         END
         FINISH

Ex 9.2

         PROGRAM ex9 2 CONTEXT VOID
         USE standard
         BEGIN
            FILE f;

            IF   open(f,
                      "textbook",
                      stand in channel)/=0
            THEN
               print("Cannot open textbook");
               exit(1)
            FI;

            REAL r, sum:=0, INT n;  get(f,n);

            TO n DO get(f,r); sum+:=r OD;
            print(sum);  close(f)
         END
         FINISH

Ex 9.3

         PROGRAM ex9 3 CONTEXT VOID
         USE standard
         BEGIN
            FILE inf,outf;

            IF   open(inf,
                      "textbook",
                      stand in channel)/=0
            THEN
               print("cannot open textbook");
               exit(1)
            ELIF establish(outf,
                           "result",
                           stand out channel,
                           0,0,0)/=0
            THEN
               print("Cannot create result");
               exit(2)
            FI;

            REAL sum:=0, r, INT n;

            get(inf,n);
            TO n
            DO
               get(inf,r);  sum+:=r
            OD;
            put(outf,sum);
            close(inf);  close(outf)
         END
         FINISH

Ex 9.4
  Note that in this answer, you will have to find some means of obviating the a68toc bug for the `BY` construct.

         PROGRAM ex9 4 CONTEXT VOID
         USE standard
         BEGIN
            INT size = 10 000;
            [2:size]BOOL flags;

            FOR i
            FROM LWB flags TO UPB flags
            DO flags[i]:=TRUE OD;

            FOR i
            FROM LWB flags TO UPB flags
            DO
               IF flags[i]
               THEN
                  FOR k
                  FROM i+i BY --i TO UPB flags
                  DO
                     flags[k]:=FALSE
                  OD
               FI
            OD;

            #Now the file is needed#
            FILE f;
            IF   establish(f,
                           "primes",
                            stand out channel,
                            0,0,0)/=0
            THEN
               print("Cannot create primes");
               exit(1)
            FI;

            FOR i FROM LWB flags TO UPB flags
            DO
               IF flags[i]
               THEN put(f,(i,newline))
               FI
            OD;

            close(f)
         END
         FINISH

Ex 9.5
  Notice that the processing of a line is done entirely within the `WHILE` clause.

         PROGRAM ex9 5 CONTEXT VOID
         USE standard
         BEGIN
            FILE inf, outf;

            IF   open(inf,
                      "inbook",
                      stand in channel)/=0
            THEN
               print("Cannot open inbook");
               exit(1)
            ELIF establish(outf,
                           "outbook",
                           stand out channel,
                           0,0,0)/=0
            THEN
               print("Cannot create outbook");
               exit(2)
            FI;

            STRING line;

            WHILE
               get(inf,(line,newline));
               put(outf,(line,newline));
               IF UPB line = 0
               THEN FALSE
               ELSE line /= UPB line * blank
               FI
            DO SKIP OD;

            close(inf);  close(outf)
         END
         FINISH

Ex 9.6

         PROGRAM ex9 6 CONTEXT VOID
         USE transput
         BEGIN
            FILE inf, outf;

            IF   open(inf,
                      "lines",
                      stand in channel)/=0
            THEN
               print("Cannot open book lines");
               exit(1)
            ELIF establish(outf,
                           "words",
                           stand out channel,
                           0,0,0)/=0
            THEN
               print("Cannot create book words");
               exit(2)
            FI;

            []CHAR terminators=" *"+cr+lf;
            make term(inf,terminators);

            STRING word, CHAR ch:=blank;

            WHILE
               get(inf,word);
               IF ch/=blank
               THEN ch PLUSTO word
               FI;

               WHILE
                  get(inf,ch);
               CO String terminator,
                  but cr/lf ignored CO
                  ch = blank
               DO SKIP OD;  #Skip spaces#
               put(outf,(word,newline));
               ch /= "*"
            DO SKIP OD;

            close(inf);  close(outf)
         END
         FINISH

Ex 9.7
  If the `on logical file end` procedure yields
  `FALSE`, the standard prelude causes an error message to be displayed and the program itself exits with an equivalent error number. Here is the code for the program:-

         PROGRAM ex9 7 CONTEXT VOID
         USE standard
         IF FILE inf;
            STRING line;  INT n,sum:=0;
            open(inf,
                 "inbook",
                  stand in channel)/=0
         THEN
            print(("Cannot open inbook",
                   newline));
            exit(1)
         ELSE
            on logical file end(inf,
             (REF FILE f)BOOL:
               IF FILE ouf;
                  establish(ouf,
                            "outbook",
                            stand out channel,
                            0,0,0)/=0
               THEN
                  print(("Cannot establish ",
                         "outbook",newline));
                  exit(2); SKIP
               ELSE
                  put(ouf,(sum/n,newline));
                  close(ouf);  FALSE
               FI);

            FOR i
            DO
               get(inf,(line,newline));
               n:=i;  sum+:=UPB line
            OD
         FI
         FINISH

Ex 9.8
  In the following solution, note how `skip` `terminators` is called immediately after reading the first argument (the full path of the program):-

         PROGRAM ex9 8 CONTEXT VOID
         USE standard
         IF FILE arg, inf, ouf;
            STRING line, infn, oufn;
            INT n,sum:=0;

            open(arg,"",arg channel)/=0
         THEN
            put(stand error,
                ("Cannot access the ",
                 "program arguments",
                 newline));
              exit(1)
         ELIF
            on logical file end(arg,
             (REF FILE f)BOOL:
              (put(stand error,
                   ("Insufficient arguments",
                    newline));
               stop;  SKIP));
            get(arg,(LOC STRING,skip terminators,
                     infn,skip terminators,
                      oufn));
            open(inf,infn,stand in channel)/=0
         THEN
            print(("Cannot open ",infn,newline));
            exit(2)
         ELSE
            on logical file end(inf,
             (REF FILE f)BOOL:
              IF establish(ouf,
                           oufn,
                           stand out channel,
                           0,0,0)/=0
              THEN
                 print(("Cannot establish ",
                        oufn,
                        newline));
                 exit(3); SKIP
              ELSE
                 put(ouf,("Average=",sum/n,
                          newline));
                 close(ouf);
                 FALSE
              FI);

            FOR i
            DO
               get(inf,(line,newline));
               n:=i;  sum+:=UPB line
            OD
         FI
         FINISH

Ex 9.9
  Notice that the physical file end of the output file has also been covered:-

         PROGRAM ex9 9 CONTEXT VOID
         USE standard
         IF FILE arg, inf, ouf;
            STRING line, infn, oufn;
            open(arg,"",arg channel)/=0
         THEN
            put(stand error,
                ("Cannot access the arguments",
                 newline));
            exit(1)
         ELIF
            on logical file end(arg,
             (REF FILE f)BOOL:
              (put(stand error,
                   ("Insufficient arguments",
                    newline));  stop;  SKIP));
            get(arg,(LOC STRING,
                     skip terminators,
                     infn,skip terminators,
                     oufn));
            open(inf,infn,stand in channel)/=0
         THEN
            print(("Cannot open ",infn,newline));
            exit(2)
         ELIF
            establish(ouf,
                      oufn,
                      stand out channel,
                      0,0,0)/=0
         THEN
            print(("Cannot establish ",oufn,
                   newline));
                   exit(3)
         ELSE
            on logical file end(inf,
             (REF FILE f)BOOL:
              (close(ouf);  close(inf);
               stop;  SKIP));
            on physical file end(ouf,
             (REF FILE f)BOOL:
              (put(stand error,
                   ("Write error on ",idf(ouf),
                    newline));
               exit(4); SKIP));
            DO
               get(inf,(line,newline));
               FOR i FROM LWB line TO UPB line
               DO
                  REF CHAR li=line[i];
                  IF li=blank THEN li:="*" FI
               OD;
               put(ouf,(line,newline))
            OD
         FI
         FINISH

Ex 9.10

          PROGRAM ex9 10 CONTEXT VOID
          USE standard
          IF FILE env;
             open(env,"PATH",env channel)=0
          THEN
             on logical file end(env,
              (REF FILE e)BOOL: (stop; SKIP));
             make term(env,":"+nul ch);
             STRING s;
             DO
                get(env,s);
                IF UPB s >= LWB s
                THEN print((s,newline))
                FI;
                skip delimiters(env)
             OD;
             close(env)
          FI
          FINISH

Ex 9.11

         PROGRAM ex9 11 CONTEXT VOID
         USE standard
         IF FILE arg;
            open(arg,"",arg channel)/=0
         THEN
            put(stand error,
                ("Cannot access arguments",
                 newline));
            exit(1)
         ELSE
            on logical file end(arg,
             (REF FILE a)BOOL: (stop;  SKIP));
            get(arg,(LOC STRING,
                     LOC CHAR,
                     skip terminators));
            DO
               make term(arg,"/");
               STRING env name;
               CHAR terminator:=nul ch;
               get(arg,
                   (env name,
                    skip terminators,
                    terminator));
               IF FILE env;
                  open(env,
                       env name,
                       env channel)/=0
               THEN
                  print((env name," undefined",
                         newline))
               ELSE
                  make term(env,
                            terminator+nul ch);
                  STRING s;
                  on logical file end(
                     env,
                     (REF FILE f)BOOL:
                       (GOTO continue; SKIP));
                  DO
                     get(env,s);
                     IF UPB s >= LWB s
                     THEN print((s,newline))
                     FI;
                     skip terminators(env)
                  OD;
                  continue:
                  close(env)
               FI;
               make term(arg,blank);
               skip terminators(arg)
            OD
         FI
         FINISH

  Notice the addition of `nul ch` to cater for the lack of a specific terminator in the environment string.
Ex 9.12

          PROGRAM ex9 12 CONTEXT VOID
          USE standard
          IF FILE abc;
              open(abc,"ABC",env channel)/=0
          THEN
              print(("Environment string ABC",
                    "is undefined",newline));
              stop
          ELSE
              INT sum:=0, n;
              on logical file end(
               abc,
               (REF FILE f)BOOL:
                (close(f);
                 print(("Total=",sum,newline));
                 stop;  SKIP));
             DO
                get(abc,n);
                sum+:=n
             OD
          FI
          FINISH

Ex 9.13
  Notice how the size of the month denotation is used to ensure that the rainfall is aligned appropriately.

         PROGRAM ex9 13 CONTEXT VOID
         USE standard
         BEGIN
         []STRING months=
             ("January","February","March",
              "April","May","June","July",
              "August","September",
              "October","November",
              "December");

         []REAL rainfall=
             ( 6.54, 12.3,  10.1,  13.83,
               5.04, 9.15,  14.34, 16.38,
               13.84, 10.45, 8.49, 7.57);

         FOR m TO UPB months
         DO
            STRING mm=months[m];
            print((mm,(12-UPB mm)*blank,
                   fixed(rainfall[m],-5,2),
                   newline))
         OD
         END
         FINISH

Ex 9.14
  The difficult part is calculating which number to print at each position.

         PROGRAM ex9 14 CONTEXT VOID
         USE standard
         BEGIN
            print(("Table of square roots ",
                   "1 to 100",
                   newline,newline));

            FOR i TO 25
            DO
               FOR j TO 4
               DO
                  INT number = (j-1)*25+i;
                  print((whole(number,-6),
                         fixed(sqrt(number),
                               -8,4)))
               OD;
               print(newline)
            OD
         END
         FINISH

Ex 9.15

         PROGRAM ex9 15 CONTEXT VOID
         USE standard
         BEGIN
            REAL pi power:=1;
            print(("Table of powers of pi",
                   " 1 to 10",
                 newline,newline));

            FOR i TO 10
            DO
              pi power*:=pi;
              print((whole(i,-3),"  ",
                     float(pi power,
                           12,6,2),
                     newline))
            OD
         END
         FINISH

Ex 9.16
  To write this program, you need to know how many bytes Algol 68 uses to store an integer in a binary book. In the program below, that number is presumed to be identified by `int bin bytes`. You will need to write a short program to output a couple of integers to a binary book and then see how long it is (and you might find its contents of interest).

         PROGRAM ex9 16 CONTEXT VOID
         USE standard
         BEGIN
         FILE work;

         IF   establish(work,
                        "ex9 9 1.tmp",
                        stand back channel,
                        0,0,0)/=0
         THEN
            print("Cannot create workbook");
            exit(1)
         FI;

         FOR i TO 1000 DO put bin(work,i) OD;

         INT int bin bytes=?;
         CO Your value replaces ? CO

         FOR i FROM 17 BY --17 TO 1000
         DO
            set(work,0,0,(i-1)*int bin bytes);
            INT n;  get bin(work,n);
            print((n,newline))
         OD;

         close(work)
         END
         FINISH

Ex 9.17
  Reading the words should not present any problems to you. The only new bit is the output. However, for the sake of completeness, here is the whole program.

         PROGRAM ex9 17 CONTEXT VOID
         USE standard
         BEGIN
            FILE inf, out1, out2;

            IF open(inf,
                    "inbook",
                    stand in channel)/=0
            THEN
               print("Cannot open inbook");
               exit(1)
            ELIF establish(out1,
                           "outbook1",
                           stand out channel,
                           0,0,0)/=0
            THEN
               print("Cannot create outbook1");
               exit(2)
            ELIF establish(out2,
                           "outbook2",
                           stand out channel,
                           0,0,0)/=0
            THEN
               print("Cannot create outbook2");
               exit(3)
            FI;

            make term(inf, blank+cr+lf);

            STRING word; CHAR ch:=blank;

            on logical file end(inf,
             (REF FILE f)BOOL:
              (close(out1);
               close(out2);
               close(f);
               stop;  SKIP));

            DO
               get(inf,(word,
                        skip terminators));

               IF UPB word > 0
               THEN
                  put bin(out2,
                          (current pos(out1),
                           UPB word));
                  put bin(out1,word)
               FI
            OD
         END
         FINISH

Ex 9.18
  A useful wrinkle is to end your report with the words `END OF REPORT` so that your reader knows that there are no pages of the report which could have been lost. In a professionally written program, you would put a page number and the date of the report, but we have not yet covered how that can be done (see chapter 12).

         PROGRAM ex9 18 CONTEXT VOID
         USE standard
         IF []STRING
              months =
               ("January","February","March",
                "April","May","June",
                "July","August","September",
                "October","November","December");
            []REAL
              rainfall =
               ( 6.54, 12.30, 10.10, 13,83,
                 5.04,  9.15, 14.34, 16.38,
                13.84, 10.45, 8.49,   7.57);
            FILE prn;
            establish(prn,
                      "rainfall.out",
                      stand out channel,
                      0,0,0)/=0
         THEN
            put(stand error,
                ("Cannot establish rainfall.out",
                 newline));  stop
         ELSE
            put(prn,
                ("Rainfall figures in 1995",
                 newline,newline,
                 "Month",7*blank,
                 "Rainfall in mm",
                 newline));

            FOR m TO UPB months
            DO
              STRING mm = months[m];
              put(prn,
                  (mm,(12-UPB mm)*blank,
                   fixed(rainfall[m],-5,2),
                   newline))
            OD;
            put(prn,
                (newline,
                 "END OF REPORT",
                 newline));
            close(prn)
         END
         FINISH

Ex 9.19
  You will need to get the identification of the file from the argument line.

         PROGRAM ex9 19 CONTEXT VOID
         USE standard
         IF STRING in idf;  FILE arg, inf, prn;
            open(arg,"",arg channel)/=0
         THEN
            put(stand error,
                ("Cannot access arguments",
                 newline));
            exit(1)
         ELIF
            on logical file end(arg,
             (REF FILE f)BOOL:
              (put(stand error,
                   ("Usage: tt idf",
                    newline));
               stop;  SKIP));
            get(arg,(LOC STRING,skip terminators,
                     in idf));
            close(arg);
            open(inf,in idf,stand in channel)/=0
         THEN
             put(stand error,
                 ("Cannot open ",in idf,
                  newline));
            exit(2)
         ELIF
            establish(prn,"tt.out",
                      stand out channel,
                      0,0,0)/=0
         THEN
            put(stand error,
                ("Cannot establish tt.out",
                 newline));
            exit(3)
         ELSE
            STRING line;
            on logical file end(inf,
             (REF FILE f)BOOL:
              (close(f);  close(prn);
               stop;  SKIP));

            FOR i
            DO
               get(inf,(line,newline));
               put(prn,(whole(i,-6),": "));
               IF UPB line > 0
               THEN put(prn,line)
               FI;
               newline(prn)
            OD
         FI
         FINISH

Ex 9.20

         PROGRAM ex9 20 CONTEXT VOID
         USE standard
         BEGIN
            REAL r;

            WHILE read(r); r/=0.0
            DO
               print((float(r,-12,3,-2),newline))
            OD
         END
         FINISH

Ex 9.21
  This program is not all that difficult. Take it slowly, step by step. Although reading an employee record only appears once in the program, it is better to write it as a procedure so as not to obscure the main logic. Likewise, printing each line of the report is also declared as a procedure. Notice how the given solution checks for errors.

         PROGRAM ex9 21 CONTEXT VOID
         USE standard
         BEGIN
            FILE arg, emp, prn;
            STRING emp idf;
            INT week:=0;

            IF open(arg,"",arg channel)/=0
            THEN
              put(stand error,
                 ("Cannot access the arguments",
                  newline));
              exit(1)
            ELIF
              on logical file end(arg,
               (REF FILE f)BOOL:
               (put(stand error,
                   ("Usage: tt emp-book week-no",
                    newline));
                exit(2); SKIP));
              get(arg,
                 (LOC STRING,LOC CHAR,
                  emp idf,week));
              week < 1 OR week > 53
            THEN
               put(stand error,
                   ("Invalid week number",
                    newline));
               exit(3)
            ELIF open(emp,
                      emp idf,
                      stand in channel)/=0
            THEN
              put(stand error,
                 ("Cannot open ",emp idf,
                  newline));
              exit(4)
            ELIF
              establish(prn,
                        "report",
                        stand out channel,
                        0,0,0)/=0
            THEN
              put(stand error,
                 ("Cannot establish report",
                  newline));
              exit(5)
            FI;

            MODE
              EMPLOYEE=STRUCT(STRING name,
                              [2]STRING address,
                              STRING dept,
                                     ni code,
                                     tax code,
                              REAL basic,
                                   overtime,
                              [52]REAL
                                 net pay,tax);

            PROC get emp=(REF FILE f,
                          REF EMPLOYEE e)VOID:
            BEGIN
              [80]CHAR s;

              PROC get str=[]CHAR:
              (
                 INT len;  get bin(f,len);
                 [len]CHAR s;
                 get bin(f,s);
                 s
              ); \#get str\#

              IF (name OF e:=get str) /= ""
              THEN
                FOR i TO UPB address OF e
                DO
                  (address OF e)[i]:=get str
                OD;
                dept OF e:=get str;
                ni code OF e:=get str;
                tax code OF e:=get str;
                get bin(f,(basic OF e,
                           overtime OF e,
                           net pay OF e,
                           tax OF e))
              FI
            END #get emp#;

            PROC put emp=(REF FILE f,
                          REF EMPLOYEE e)VOID:
              put(f,(name OF e,
                     (40-UPB name OF e)*blank,
                      fixed((net pay OF e)[week],
                             -8,2),
                      newline));

            INT line:=60, page:=0;

            PROC heading = (REF FILE f)VOID:
            IF line = 60
            THEN line:=0; #reset the line count#
              put(f,
                  (newpage,
                   "Report of net pay for week ",
                   whole(week,0),
                   40*blank,"Page ",
                   whole(page+:=1,0),
                   newline,newline,
                   "Employee name",
                   28*blank,"Net pay",
                   newline,newline))
            FI #heading#;

            EMPLOYEE employee;
            REAL total pay:=0; INT n:=0;

            on logical file end(emp,
             (REF FILE f)BOOL:
              (put(prn,
                   ("Total net pay for ",
                    whole(n,0),
                    " employees =",
                    fixed(total pay,-11,2),
                    newline,
                    newline,
                    "End of report",newline));
              close(f);  close(prn);  stop;
              SKIP));

            DO
               heading(prn);
               get emp(emp,employee);

              IF name OF employee /= ""
              THEN
                 total pay+:=
                  (net pay OF employee)[week];
                 n+:=1;
                 #count of total employees#
                 put emp(prn,employee);
                 line+:=1
              FI
            OD
         END
         FINISH