*C; PROGRAM IFTRAN C IFTRAN Preprocessor C Revision V02-01 for PDP-11 RSX-11 FORTRAN C This revision by: C Bruce R. Mitchell C Department of Anesthesiology C The University of Wisconsin at Madison C From a Harris DATACRAFT IFTRAN supplied by: C Professor Donald L. Dietmeyer, Ph.D.E.E. C Department of Electrical and Computer Engineering C The University of Wisconsin at Madison C C Revision History: C 16-JAN-81 Error messages put in formats C 19-JAN-81 Character variables changed to type BYTE C 19-JAN-81 IFTCOM common rearranged C 20-JAN-81 Translation time checking inserted C 20-JAN-81 Command line parsing insertion begun C 20-JAN-81 Header information and common inserted C 26-JAN-81 All PUTGT, PUTCON calls changed to PUTFOR C 16-FEB-81 ENDFILE statement on output file removed C 16-FEB-81 Individual unclosed block error messages added C 17-FEB-81 Hooks added to decode FORMAT and DATA stmts C 01-APR-81 Invalid EXIT error messages expanded C 01-APR-81 Error messages moved to ERRORS subroutine C 24-APR-81 LISTNG changed to type LOGICAL*1 C 24-APR-81 Support added for stack level checking C 25-APR-81 Extended statement support added C 27-APR-81 Support added for line comment pass-through C 30-APR-81 Header, time information for each input routine IMPLICIT INTEGER (A - Z) BYTE MCRBUF, IHEAD, ITAIL, IHEAD2, LC, LCOMMA, BLANK, CHAR BYTE CMDLIN, DEFALT, FILNAM ; Local string varbs BYTE CONLBL, LABEL, LHEAD, LIST ; IFTCOM common string varbs BYTE DATBUF, TIMBUF ; HEADER common string varbs LOGICAL*1 LISTNG, PASCOM ; Listing, pass comments flags LOGICAL*1 COMFLG, EQUFLG, SWIFLG, CMDFIL ; Command parsing flags LOGICAL*1 PARFLG ; Command parsing flag REAL TYME, SECNDS ; Time handling variables COMMON /IFTCOM/ DONE, INFILE, IP, KIND, L, LNUM, LOUT, OUTFIL, + ERRCNT, LISTNG, PASCOM, CONLBL(6), LABEL(66), LHEAD(6), LIST(1320) COMMON /HEADER/ ISYS, PPN1, PPN2, DATBUF(9), TIMBUF(8) COMMON /EXTCOM/ SL, SL1, SL2, CML DIMENSION MCRBUF(80), TSKBUF(16), CMDLIN(6, 19), CMDLEN(6) DIMENSION CMDFIL(3), DEFALT(3, 4), FILNAM(19) DIMENSION IHEAD(9), ITAIL(9), IHEAD2(9) DIMENSION LAST(100), WSTACK(100), LSTACK(100), DOSTK(100), FORSTK(100) DATA CMDLIN(1,1), CMDLIN(1,2), CMDLIN(1,3) /'N', 'L', ':'/ DATA CMDLIN(2,1), CMDLIN(2,2), CMDLIN(2,3) /'N', 'L', ':'/ DATA CMDLEN /0, 0, 0, 0, 0, 0/ DATA DEFALT /'.', '.', '.', 'F', 'L', 'I', 'T', 'S', 'F', 'N', + 'T', 'T'/ DATA IHEAD /'I', 'F', '(', '.', 'N', 'O', 'T', '.', '('/ ; IF(.NOT.( DATA ITAIL /')', ')', ' ', 'G', 'O', ' ', 'T', 'O', ' '/ ; )) GO TO DATA IHEAD2 /'D', 'O', ' ', ' ', ' ', ' ', ' ', ' ', ' '/ ; DO DATA LC, LCOMMA, BLANK /'C', ',', ' '/ DATA COMFLG, EQUFLG, SWIFLG /.FALSE., .FALSE., .FALSE./ DATA PARFLG /.FALSE./ ; Not inside [] or () DATA CMDFIL /.FALSE., .FALSE., .FALSE./ 978 FORMAT (1H0, '*** TRANSLATION STATISTICS ***', /, 1H0, + ' Input file: ', 19A1) 979 FORMAT (1X, ' Output file: ', 19A1) 980 FORMAT (1X, ' Listing file: ', 19A1) 981 FORMAT (1X, ' Translation time: ', F6.2, ' seconds', /, 1H1) 984 FORMAT (' IFT - Unrecognized switch /', 2A1) 985 FORMAT (' IFT - Bad switch /', 6A1) 986 FORMAT (' IFT - Could not open input file ', 19A1) 987 FORMAT (' IFT - Could not open listing file ', 19A1) 988 FORMAT (' IFT - Could not open output file ', 19A1) 989 FORMAT (' IFT - Bad file name') 990 FORMAT (' IFT - No input file specified') 991 FORMAT (' IFT - Too many switches in command line') 992 FORMAT (' IFT - Fatal error in command line structure') 993 FORMAT (' IFT - Bad character ( ', A1, ' ) in column ', I2, + ' of command line.') 994 FORMAT (' IFT - Missing space after call, or empty command line.') 995 FORMAT (1X, ' Errors encountered: ', I3) 996 FORMAT (' IFT - ', I3, ' errors found - see listing.') 997 FORMAT (' UW IFTRAN V02.01') 998 FORMAT (' IFT - Unclosed [ or ( in file UIC specification') LISTNG = .TRUE. ; Listing default is ON PASCOM = .FALSE. ; Pass comments default is OFF SL = 72 ; Extended statement SL1 = 73 ; default SL2 = 74 ; is CML = 62 ; OFF DONE = 0 ; Not done yet INFILE = 3 ; Input file LUN OUTFIL = 1 ; Output file LUN LOUT = 2 ; Listing file LUN C Get task parameters and from that, system type and user PPNs CALL GETTSK (TSKBUF, TSKFLG) ; TSKFLG returns status PPN1 = IAND( ISHFT(TSKBUF(8), -8), 255) PPN2 = IAND(TSKBUF(8), 255) ISYS = TSKBUF(15) + 1 C Get invoking MCR command line for parse CALL GETMCR (MCRBUF, NMCR) ; NMCR = # chars in line J1 = 1 ; Search column WHILE (MCRBUF(J1) .NE. BLANK) ; Find 1st blank column J1 = J1 + 1 ; Increment search column IF (J1 .EQ. NMCR) ; Check void command line WRITE (5, 994) ; Tell him so CALL EXIT ; and quit END IF END WHILE C Push down line, strip space, check for invalid characters C (valid characters are A-Z 0-9 . , / : ; [ ] and ( ) on RSTS) J3 = 0 ; Number actual chars in line FOR J2 = J1, NMCR CHAR = MCRBUF(J2) ; Temporary for crunching IF (CHAR .NE. BLANK) ; Check if nonblank IF ((CHAR .NE. 40) .AND. (CHAR .NE. 41) .AND. (CHAR .NE. 44) + .AND. ((CHAR .LT. 46) .OR. (CHAR .GT. 59)) .AND. (CHAR .NE. 61) + .AND. ((CHAR .LT. 65) .OR. (CHAR .GT. 91)) .AND. (CHAR .NE. 93)) WRITE (5, 993) CHAR, J2 ; Flag bad character CALL EXIT ; and quit ELSE ; Good character J3 = J3 + 1 ; Increment pointer MCRBUF(J3) = MCRBUF(J2) ; Push down END IF END IF END FOR NMCR = J3 ; Replace number characters C Break out output, listing, input files and switches C CMDLIN stores file names and switches in rows 1-? C 1 - Output file 2 - Listing file 3 - Input file C 4 - Switch 1 5 - Switch 2 and so on J1 = 1 ; Row of CMDLIN J2 = 1 ; Column of CMDLIN FOR J3 = 1, NMCR CHAR = MCRBUF(J3) ; Temporary for crunching IF ((CHAR .EQ. 44) .AND. (.NOT.(PARFLG))) ; Comma & not in UIC? IF (COMFLG .OR. SWIFLG .OR. EQUFLG) ; No flags may precede WRITE (5, 992) ; Tell him so CALL EXIT ; and quit ELSE ; Valid COMFLG = .TRUE. ; Found a comma J1 = 2 ; Assume listing file next J2 = 1 ; Reset to first column END IF OR IF (CHAR .EQ. 61) ; Equal sign? IF (EQUFLG .OR. SWIFLG) ; Comma only valid precedent WRITE (5, 992) ; Tell him so CALL EXIT ; and quit ELSE ; Valid EQUFLG = .TRUE. ; Found an equal sign J1 = 3 ; Assume switches next J2 = 1 ; Reset to first column END IF OR IF (CHAR .EQ. 47) ; Slash? IF (.NOT. EQUFLG) ; Equals must precede WRITE (5, 992) ; Tell him so CALL EXIT ; and quit ELSE ; Valid SWIFLG = .TRUE. ; Found a slash J1 = J1 + 1 ; Assume more switches J2 = 1 ; Reset to first column END IF ELSE ; Part of a file name or switch IF ((CHAR .EQ. 40) .OR. (CHAR .EQ. 91)) PARFLG = .TRUE. ; ( or [ IF ((CHAR .EQ. 41) .OR. (CHAR .EQ. 93)) PARFLG = .FALSE. ; ) or ] IF ((CHAR .EQ. 46) .AND. (J1 .LT. 4)) ; Period in filespec? IF (CMDFIL(J1)) ; Found period already? WRITE (5, 989) ; Err out CALL EXIT ; and quit ELSE ; File extension follows CMDFIL(J1) = .TRUE. ; Found period END IF END IF IF (J1 .LT. 7) ; Too many switches? CMDLIN(J1, J2) = CHAR ; No, append to this one CMDLEN(J1) = J2 ; Length of each command J2 = J2 + 1 ; Increment column ELSE ; Yes, too many WRITE (5, 991) ; Tell him so CALL EXIT ; and quit END IF END IF END FOR IF (PARFLG) ; User forgot to close [ or ( WRITE (5, 998) ; Tell him so CALL EXIT ; and quit END IF NCMDS = J1 ; Number of commands IF (CMDLEN(3) .EQ. 0) ; What, no input file? WRITE (5, 990) ; Tell him so CALL EXIT ; and quit END IF C Check for output and listing files; if none, then default. Also C check for file extensions; if none, append the defaults. IF (CMDLEN(1) .EQ. 0) CMDLEN(1) = 3 ; Output defaults to NL: IF (CMDLEN(2) .EQ. 0) ; If no listing file CMDLEN(2) = 3 ; Listing defaults to NL: LISTNG = .FALSE. ; Turn off listing option END IF FOR J1 = 1, 3 IF (.NOT. CMDFIL(J1)) ; No extension given J2 = 1 J3 = CMDLEN(J1) + 1 DO ; Append default extension CMDLIN(J1, J3) = DEFALT(J1, J2) ; Stored in array DEFALT J2 = J2 + 1 J3 = J3 + 1 UNTIL (J2 .EQ. 5) CMDLEN(J1) = CMDLEN(J1) + 4 ; New length of filespec END IF END FOR C Assign logical unit numbers to files and open them for use. FOR J1 = 1, 3 ; 3 files to assign FOR J2 = 1, CMDLEN(J1) ; Copy filename into buffer FILNAM(J2) = CMDLIN(J1, J2) END FOR CALL ASSIGN (J1, FILNAM, CMDLEN(J1)) ; Do the assign END FOR OPEN (UNIT=1, TYPE='NEW', ERR=899, CARRIAGECONTROL = 'LIST') ; Output GO TO 898 ; Unless an error occurs 899 WRITE (5, 988) (CMDLIN(1, J1), J1=1,CMDLEN(1)) ; Tell user of problem CALL EXIT ; and give up 898 OPEN (UNIT=2, TYPE='NEW', ERR=897) ; Listing GO TO 896 ; Unless an error occurs 897 WRITE (5, 987) (CMDLIN(2, J1), J1=1,CMDLEN(2)) ; Tell user of problem CALL EXIT ; and give up 896 OPEN (UNIT=3, TYPE='OLD', ERR=895) ; Input GO TO 894 ; Unless an error occurs 895 WRITE (5, 986) (CMDLIN(3, J1), J1=1,CMDLEN(3)) ; Tell user of problem CALL EXIT ; and give up C Check for switches and set condition codes accordingly 894 IF (NCMDS .GT. 3) ; Are there any switches? FOR J1 = 4, NCMDS ; Loop for number of switches IF (CMDLEN(J1) .NE. 2) ; Is switch 2 chars long? WRITE (5, 985) (CMDLIN(J1, J2), J2=1,CMDLEN(J1)) ; Write error message CALL EXIT ; and give up END IF IF ((CMDLIN(J1,1) .EQ. 69) .AND. (CMDLIN(J1,2) .EQ. 88)) ; EX? SL = 80 ; Reset the EXTCOM variables for GETFOR SL1 = 81 SL2 = 82 CML = 70 OR IF ((CMDLIN(J1,1) .EQ. 80) .AND. (CMDLIN(J1,2) .EQ. 67)) ; PC? PASCOM = .TRUE. OR IF ((CMDLIN(J1,1) .EQ. 73) .AND. (CMDLIN(J1,2) .EQ. 68)) ; ID? WRITE (5, 997) ; Self-identify program/version ELSE ; Unrecognized switch WRITE (5, 984) CMDLIN(J1,1), CMDLIN(J1,2) ; Write error message CALL EXIT ; and give up END IF END FOR END IF C Here begins the original IFTRAN code DO ; Until EOF mark CONLBL(5) = BLANK CONLBL(6) = BLANK LNUM = 0 ; Listing line number LBL = 32000 ; Line numbers start at 32000 NDSTK = 0 ; # stmts on DO stack (?) NSTACK = 0 ; # stmts on IF stack (?) NWSTAK = 0 ; # stmts on WHILE stack (?) NFSTK = 0 ; # stmts on FOR stack (?) ERRCNT = 0 ; # of errors encountered LP = 1 LAST(LP) = 0 ; Last IFTRAN stmt type CALL DATE (DATBUF) ; Get current date CALL TIME (TIMBUF) ; Get current time TYME = SECNDS(0.0) ; Begin xlate time check CALL PAGEBK (61) ; Eject page and print header DO ;Until EOF mark IF (NFSTK .GT. 90) CALL ERRORS (31) ; FOR stack warning IF (NWSTAK .GT. 90) CALL ERRORS (32) ; WHILE stack warning IF (NSTACK .GT. 90) CALL ERRORS (33) ; IF stack warning IF (NDSTK .GT. 90) CALL ERRORS (34) ; DO stack warning CALL GETFOR ; Get and find type of input line IF (KIND .LE. 2) ; Then FORTRAN statement CALL PUTFOR (7, L, 1) C ****************************************************************** C * * C * IF () * C * * C ****************************************************************** OR IF (KIND .EQ. 3) NSTACK = NSTACK + 1 LBL = LBL - 5 LSTACK(NSTACK) = -1 * LBL NSTACK = NSTACK + 1 LBL = LBL - 5 LSTACK(NSTACK) = LBL GO TO 30 C ****************************************************************** C * * C * OR IF () * C * * C ****************************************************************** OR IF (KIND .EQ. 4) IF ((LAST(LP) .NE. 3) .AND. (LAST(LP) .NE. 4)) ; Last IF or OR IF? CALL ERRORS (1) ; If not, write error message ELSE LSTACK(NSTACK - 1) = IABS(LSTACK(NSTACK - 1)) CALL PUTFOR (DUMMY, LSTACK(NSTACK - 1), 2) CALL PUTFOR (LSTACK(NSTACK), DUMMY, 3) LBL = LBL - 5 LSTACK(NSTACK) = LBL GO TO 31 END IF C ****************************************************************** C * * C * ELSE * C * * C ****************************************************************** OR IF (KIND .EQ. 5) IF ((LAST(LP) .NE. 3) .AND. (LAST(LP) .NE. 4)) ; Last IF or OR IF? CALL ERRORS (1) ; If not, write error message ELSE LSTACK(NSTACK - 1) = IABS(LSTACK(NSTACK - 1)) CALL PUTFOR (DUMMY, LSTACK(NSTACK - 1), 2) CALL PUTFOR (LSTACK(NSTACK), DUMMY, 3) LSTACK(NSTACK) = -1 * LSTACK(NSTACK) LAST(LP) = KIND IF (LABEL(5) .NE. BLANK) CALL PUTFOR (0, DUMMY, 3) END IF C ****************************************************************** C * * C * END IF * C * * C ****************************************************************** OR IF (KIND .EQ. 6) IF ((LAST(LP) .GE. 3) .AND. (LAST(LP) .LE. 5)) ; Last IF, OR IF, ELSE? IF (LABEL(5) .NE. BLANK) CALL PUTFOR (0, DUMMY, 3) CALL PUTFOR (LSTACK(NSTACK), DUMMY, 3) CALL PUTFOR (LSTACK(NSTACK - 1), DUMMY, 3) NSTACK = NSTACK - 2 GO TO 50 ELSE ; Invalid END IF statement CALL ERRORS (12, LAST(LP)) ; Warn the user END IF C ****************************************************************** C * * C * WHILE () * C * * C ****************************************************************** OR IF (KIND .EQ. 7) NWSTAK = NWSTAK + 1 LBL = LBL - 5 WSTACK(NWSTAK) = LBL CALL PUTFOR (LBL, DUMMY, 3) NWSTAK = NWSTAK + 1 LBL = LBL - 5 WSTACK(NWSTAK) = LBL 30 LP = LP + 1 31 LAST(LP) = KIND IP = IP - 8 CALL COPY (8, IHEAD(1), LHEAD(IP)) CALL COPY (8, ITAIL(2), LIST(L + 1)) CALL INTALP (LBL, LIST(L + 9)) L = L + 13 CALL PUTFOR (IP, L, 1) C ****************************************************************** C * * C * END WHILE * C * * C ****************************************************************** OR IF (KIND .EQ. 8) IF (LAST(LP) .EQ. 7) ; Last WHILE? IF (LABEL(5) .NE. BLANK) CALL PUTFOR (0, DUMMY, 3) CALL PUTFOR (DUMMY, WSTACK(NWSTAK - 1), 2) CALL PUTFOR (WSTACK(NWSTAK), DUMMY, 3) NWSTAK = NWSTAK - 2 GO TO 50 ELSE ; Invalid END WHILE statement CALL ERRORS (13, LAST(LP)) ; Warn the user END IF C ****************************************************************** C * * C * END * C * * C ****************************************************************** OR IF (KIND .EQ. 9) CALL PUTFOR (7, L, 1) IF (NSTACK .NE. 0) CALL ERRORS (3) ; Flag unclosed IF block IF (NWSTAK .NE. 0) CALL ERRORS (5) ; Flag unclosed WHILE block IF (NDSTK .NE. 0) CALL ERRORS (4) ; Flag unclosed DO block IF (NFSTK .NE. 0) CALL ERRORS (6) ; Flag unclosed FOR block C Dump compilation statistics at end of each routine TYME = SECNDS(TYME) WRITE (LOUT, 978) (CMDLIN(3, I), I=1,CMDLEN(3)) ; Show input file WRITE (LOUT, 979) (CMDLIN(1, I), I=1,CMDLEN(1)) ; Show output file WRITE (LOUT, 980) (CMDLIN(2, I), I=1,CMDLEN(2)) ; Show listing file WRITE (LOUT, 995) ERRCNT ; Show error count WRITE (LOUT, 981) TYME ; Show translation time C If errors encountered and not listing, warn user on terminal IF ((ERRCNT .NE. 0) .AND. (.NOT.(LISTNG))) WRITE (5, 996) ERRCNT EXIT DO C ****************************************************************** C * * C * EXIT IF [IF ()] * C * * C ****************************************************************** OR IF (KIND .EQ. 10) IF (NSTACK .NE. 0) ; If preceding IF IF (L .EQ. (IP - 6)) L = L - 1 ; If unconditional EXIT IF CALL COPY (7, ITAIL(3), LIST(L + 1)) LSTACK(NSTACK - 1) = IABS(LSTACK(NSTACK - 1)) CALL INTALP (LSTACK(NSTACK - 1), LIST(L + 8)) L = L + 12 CALL PUTFOR (IP + 1, L, 1) ELSE ; No preceding IF CALL ERRORS (10) ; Write error message END IF ; NSTACK .NE. 0 C ****************************************************************** C * * C * EXIT WHILE [IF ()] * C * * C ****************************************************************** OR IF (KIND .EQ. 11) IF (NWSTAK .NE. 0) ; If preceding WHILE IF (L .EQ. (IP - 6)) L = L - 1 ; Unconditional EXIT WHILE CALL COPY (7, ITAIL(3), LIST(L + 1)) CALL INTALP (WSTACK(NWSTAK), LIST(L + 8)) L = L + 12 CALL PUTFOR (IP + 1, L, 1) ELSE ; No preceding WHILE CALL ERRORS (9) ; Write error message END IF C ****************************************************************** C * * C * DO FOR * C * * C ****************************************************************** OR IF (KIND .EQ. 12) NDSTK = NDSTK + 1 LBL = LBL - 5 DOSTK(NDSTK) = -1 * LBL NDSTK = NDSTK + 1 LBL = LBL - 5 DOSTK(NDSTK) = LBL IF (LABEL(5) .NE. BLANK) CALL PUTFOR (0, DUMMY, 3) CALL PUTFOR (LBL, DUMMY, 3) LP = LP + 1 LAST(LP) = KIND C ****************************************************************** C * * C * UNTIL () * C * * C ****************************************************************** OR IF (KIND .EQ. 13) IF (LAST(LP) .EQ. 12) ; Last DO? IP = IP - 8 CALL COPY (8, IHEAD(1), LHEAD(IP)) CALL COPY (8, ITAIL(2), LIST(L + 1)) CALL INTALP (DOSTK(NDSTK), LIST(L + 9)) L = L + 13 CALL PUTFOR (IP, L, 1) NDSTK = NDSTK - 1 CALL PUTFOR (DOSTK(NDSTK), DUMMY, 3) NDSTK = NDSTK - 1 50 LP = LP - 1 IF (LP .LT. 1) LP = 1 ELSE ; Invalid UNTIL statement CALL ERRORS (14, LAST(LP)) ; Warn the user END IF C ****************************************************************** C * * C * EXIT DO [IF ()] * C * * C ****************************************************************** OR IF (KIND .EQ. 14) IF (NDSTK .LE. 0) ; If no preceding DO CALL ERRORS (8) ; Write error message ELSE ; Preceding DO IF (L .EQ. (IP - 6)) L = L - 1 CALL COPY (7, ITAIL(3), LIST(L + 1)) DOSTK(NDSTK - 1) = IABS(DOSTK(NDSTK - 1)) CALL INTALP (DOSTK(NDSTK - 1), LIST(L + 8)) L = L + 12 CALL PUTFOR (IP + 1, L, 1) END IF C ****************************************************************** C * * C * FOR Var = Lim1, Lim2 [, Inc] * C * * C ****************************************************************** OR IF (KIND .EQ. 15) NFSTK = NFSTK + 1 LBL = LBL - 5 FORSTK(NFSTK) = -1 * LBL NFSTK = NFSTK + 1 LBL = LBL - 5 FORSTK(NFSTK) = LBL LP = LP + 1 LAST(LP) = KIND IP = IP - 8 CALL COPY (9, IHEAD2, LHEAD(IP)) CALL INTALP(LBL, LHEAD(IP + 3)) CALL PUTFOR (IP, L, 1) C ****************************************************************** C * * C * END FOR * C * * C ****************************************************************** OR IF (KIND .EQ. 16) IF (LAST(LP) .EQ. 15) ; Last FOR? IF (LABEL(5) .NE. BLANK) CALL PUTFOR (0, DUMMY, 3) LABEL(5) = BLANK END IF CALL PUTFOR (FORSTK(NFSTK), DUMMY, 3) CALL PUTFOR (0, DUMMY, 3) CALL PUTFOR (FORSTK(NFSTK - 1), DUMMY, 3) NFSTK = NFSTK - 2 GO TO 50 ELSE ; Invalid END FOR statement CALL ERRORS (15, LAST(LP)) END IF C ****************************************************************** C * * C * EXIT FOR [IF ()] * C * * C ****************************************************************** OR IF (KIND .EQ. 17) IF (NFSTK .NE. 0) ; If preceding FOR IF (L .EQ. (IP - 6)) L = L - 1 CALL COPY (7, ITAIL(3), LIST(L + 1)) FORSTK(NFSTK - 1) = IABS(FORSTK(NFSTK - 1)) CALL INTALP (FORSTK(NFSTK - 1), LIST(L + 8)) L = L + 12 CALL PUTFOR (IP + 1, L, 1) ELSE ; No FOR preceding CALL ERRORS (7) ; Write error message END IF ; NFSTK .NE. 0 END IF ; KIND .EQ. 1 UNTIL (DONE .EQ. 1) UNTIL (DONE .EQ. 1) CALL EXIT ; So no STOP message appears END