C COMMAND LINE PARSER FOR BUILD COMMAND C C WRITTEN BY: DAVID VILLENEUVE 1980 C NATIONAL RESEARCH COUNCIL C OTTAWA ONT K1A 0R6 C 613-993-9975 C C UPDATED TO RSX-11M V4.0 JULY 1983 C RSX-11M V4.1 C C THIS TASK PARSES A COMMAND LINE OF THE FORM: C C BUILD FILE=(F1,F2,...),LIB=(L1,L2,...),ASG=(A1,A2,...),... C C AND GENERATES A TASK BUILD COMMAND FILE AS DIRECTED C WHICH IS SUBMITTED TO EITHER TKB OR FTB. WHEN THE C TASK BUILDER EXITS, THE COMMAND FILE IS DELETED. C SEE THE EXTERNAL DOCUMENTATION ON THE FORMAT OF THE C COMMAND. C NOTE THAT PARTS OF THIS PROGRAM ARE IMPLEMENTATION-DEPENDENT, C IN PARTICULAR THE CODE IN SUBROUTINES BUILD1 AND BUILD2 C WHICH GENERATE THE TASK BUILD COMMAND FILES. THESE GENERATE C REFERENCES TO LIBRARIES WHICH DEPEND ON THE SYSTEM CONFIGURATION C AND THE DEFAULT FORTRAN. C SEE THE EXTERNAL RUNOFF DESCRIPTION FOR THE COMMAND SYNTAX. C C SUBROUTINE GETLIN RETRIEVES THE COMMAND LINE, LOOKS FOR A C SWITCH INDICATING A COMPILER IS TO RUN FIRST, AND DETERMINES C IF FORTRAN 77 IS TO BE USED BY THE PRESENCE OF A "77" SOMEWHERE C IN THE COMMAND NAME. C SUBROUTINE OPEN OPENS THE COMMAND FILE "BUILD.TMP", AND ALSO C DETERMINES IF THE UIC HAS A "USERLIB.OLB" TO LINK TO. C SUBROUTINE PARSE BREAKS THE COMMAND LINE UP INTO TOKENS, C WHICH ARE EITHER FILE NAMES, KEYWORDS OR DELIMITERS. C SUBROUTINE SECT SCANS THROUGH THE TOKENS AND MATCHES KEYWORDS C AND NAMES TO THE PERMISSIBLE KEYWORDS. THE PARAMETERS ARE C THEN NUMBERED FROM 1 TO N IN ISECT. C SUBROUTINE BUILD1 AND BUILD2 USE THE PARAMETERS TO GENERATE C THE TASK BUILD COMMAND FILE. THE LOGIC IN THESE SUBROUTINES C IS IMPLEMENTATION SPECIFIC. C SUBROUTINE CLOSEF CLOSES THE TASK BUILD FILE, AND OPTIONALLY C PRINTS IT. C SUBROUTINE TKB SPAWNS A FORTRAN COMPILER IF REQUESTED, THEN C SPAWNS THE TASK BUILDER TO BUILD THE TASK, THEN WAITS FOR IT C TO COMPLETE. C SUBROUTINE DELET DELETES THE COMMAND FILE, AND ALSO THE C OBJECT FILE IF THE COMPILER WAS RUN. C C DATA STRUCTURES USED: C LINE - ASCIZ STRING CONTAINS NAMES AND KEYWORDS FROM COMMAND LINE. C PTR - INDEX INTO LINE FOR BEGINNING OF EACH TOKEN. C ITYPE - CODE FOR TYPE OF TOKEN - NAME, DELIMITER TYPE. C ISECT - INDEX INTO PTR AND ITYPE FOR NUMBERED SECTION OF PARAMETERS. C COMPIL - ASCIZ STRING OF COMPILER TO RUN (OPTIONAL). C FTNNAM - ASCIZ STRING OF NAME OF TASK BEING BUILT. C C DEFINE THIS SYMBOL TO PRINT SOME INTERNAL TABLES C.DEFINE DEBUG C BYTE LINE(160), PTR(50), ITYPE(50), KEYWD(7,15) BYTE FTNNAM(40), COMPIL(32) INTEGER ISECT(15) CALL GETLIN (LINE, LLINE, IF77, COMPIL) IF (LINE(1) .EQ. '@') CALL INDIR1 (LINE, LLINE) IF (LINE(1) .EQ. '@') CALL INDIR2 (LINE, LLINE) CALL OPEN (LINE, LLINE, IULIB) CALL PARSE (LINE, LLINE, PTR, ITYPE, NNAMES) CALL SECT (LINE, PTR, ITYPE, ISECT, NNAMES, KEYWD) CALL BUILD1 (LINE, PTR, ITYPE, ISECT, NNAMES, KEYWD, 1 IULIB, IFTB, FTNNAM, IF77) CALL BUILD2 (LINE, PTR, ITYPE, ISECT, NNAMES, KEYWD, 1 IULIB, IFTB, FTNNAM, IF77) CALL CLOSEF (LINE, ISECT) CALL TKB (LINE, IFTB, COMPIL, FTNNAM, ISTAT) CALL DELET (COMPIL, FTNNAM, ISTAT) CALL EXIT END SUBROUTINE GETLIN (LINE, LLINE, IF77, COMPIL) C C GETS THE MCR COMMAND LINE, AND ANY CONTINUATION LINE. C SETS IF77 TO NONZERO IF FORTRAN 77 IS INDICATED IN COMMAND NAME. C SETS STRING COMPIL TO THE SWITCH VALUE AFTER THE COMMAND WHICH C INDICATES THE COMPILER TO USE BEFORE TASK BUILDING, E.G. BUI/FTN. C BYTE LINE(1), COMPIL(1) CALL GETMCR (LINE, LLINE) IF (LLINE .LE. 0) GO TO 20 !NO COMMAND LINE? LINE(LLINE+1) = 0 C C LOOK FOR SPACE FOLLOWING COMMAND NAME C CALL INDEXC (IBLANK, ' ', LINE) IF (IBLANK .LE. 0) IBLANK = LLINE+1 !NO BLANK FOLLOWING LINE(IBLANK) = 0 !MAKE STRING OF COMMAND C C LOOK FOR FORTRAN-77 SWITCH ANYWHERE IN COMMAND C CALL INDEXC (IF77, '77', LINE) C C SPLIT OFF STUFF AFTER SLASH INTO COMPIL FOR COMPILER NAME C CALL INDEXC (ISLASH, '/', LINE) COMPIL(1) = 0 IF (ISLASH .GT. 0) CALL SUBSTR (COMPIL, LINE, ISLASH+1, 32) C C SCAN FOR BEGINNING OF ARGUMENTS IN LINE C IFF (IBLANK .LT. LLINE) THEN { FOR J=IBLANK+1,LLINE IF (LINE(J) .NE. "40 .AND. LINE(J) .NE. "11) GO TO 40 } C C NO ARGUMENTS ON COMMAND LINE, MUST PROMPT FOR THEM C 20 WRITE (2,50) READ (2,60) LLINE, (LINE(J),J=1,132) GO TO 45 C C SHIFT ARGUMENT PART OF LINE TO LEFT, OVERWRITING COMMAND NAME C 40 LINE(LLINE+1) = 0 CALL STRING (LINE, LINE(J)) !SHIFT LINE LEFT LLINE = LLINE - J + 1 C C SEE IF HE HAS REQUESTED A CONTINUATION LINE C 45 IFF (LINE(LLINE) .EQ. "55) THEN { !CONTINUATION LINE WRITE (2,50) 50 FORMAT (' BUI>', $) READ (2,60) L, (LINE(J), J=LLINE, 160) 60 FORMAT (Q, 160A1) LLINE = LLINE + L - 1 } LINE(LLINE+1) = 0 RETURN END SUBROUTINE INDIR1 (LINE, LLINE) C C THIS DETERMINES IF AN INDIRECT FILE IS TO BE SEARCHED FOR THE C FULL BUILD COMMAND. THIS IS CAUSED BY A COMMAND LINE OF THE FORM C BUILD @filename C IF A FILENAME EXTENSION IS GIVEN, THAT FILE IS OPENED, OTHERWISE C IT WILL TRY EXTENSION .FTN AND .FTE. IT WILL THEN READ THE FIRST C 100 LINES OF THESE FILES, LOOKING FOR A LINE STARTING WITH C C--BUILD ... C THIS IS ASSUMED TO BE A VALID BUILD COMMAND WHICH IS THEN ACTED C ON BY THE REST OF THE PROGRAM IN THE USUAL WAY. C This subroutine is divided into two parts, the first to open C the indirect file, the second to look for the C--BUILD line. C BYTE LINE(160) IF (LINE(1) .NE. '@') RETURN CALL ERRSET (29, .TRUE., .TRUE., .TRUE., .FALSE., 31) !NO SUCH FILE CALL INDEXC (IDOT, '.', LINE) IF (IDOT .EQ. 0) CALL CONCAT (LINE, '.FTN') !TRY .FTN FIRST ITRY = 1 !FIRST TRY C C ATTEMPT TO OPEN INPUT FILE C CALL ASNLUN (1, 'SY', 0) !NEEDED TO OVERIDE INSTALLED ASN TO LB: REPEAT { OPEN (UNIT=1, NAME=LINE(2), TYPE='OLD', READONLY, ERR=100) RETURN !SUCCESSFUL C C PROBLEMS WITH OPEN ATTEMPT, TRY A DIFFERENT EXTENSION C 100 IFF (IDOT .EQ. 0 .AND. ITRY .EQ. 1) THEN { ITRY = ITRY+1 LINE(LLINE+1) = 0 CALL CONCAT (LINE, '.FTE') } ELSE { WRITE (2,%%) FORMAT (' BUI -- Failed to open indirect file') CALL EXIT } } END SUBROUTINE INDIR2 (LINE, LLINE) C C This is the second part of the INDIR routine. See INDIR1 for comments. C BYTE LINE(160) LOGICAL CMPLEF, LOG C C OPENED FILE OK - NOW SCAN FOR C--BUILD LINE C FOR J=1,100 { READ (1,%%, END=500) LLINE, LINE FORMAT (Q, 130A1, 30A1) LINE(LLINE+1) = 0 IF ( CMPLEF( LOG, 'C--BUILD', LINE ) ) GO TO 300 } GO TO 500 !NOT IN FIRST 100 LINES C C HAVE FOUND LINE WITH BUILD INSTRUCTION - SHIFT TO LEFT IN BUFFER C 300 WRITE (2,%%) (LINE(K), K=2,LLINE) !PRINT LINE FORMAT (1X, 132A1) FOR J=10,LLINE IF (LINE(J) .NE. "40 .AND. LINE(J) .NE. "11) GO TO 400 GO TO 500 !NOTHING AFTER BUILD 400 CALL STRING (LINE, LINE(J)) LLINE = LLINE - J + 1 CLOSE (UNIT=1) RETURN C C ERROR IN READING INDIRECT FILE C 500 WRITE (2,%%) FORMAT (' BUI -- Failed to find "C--BUILD" line in first 100', 1 ' lines of indirect file.') CALL EXIT END SUBROUTINE OPEN (LINE, LLINE, IULIB) C C OPENS THE COMMAND FILE FOR OUTPUT, SETS IULIB IF USERLIB.OLB EXISTS C BYTE LINE(1) C C SEE IF USER HAS A USERLIB C IULIB = 0 CALL ERRSET (29, .TRUE., .TRUE., .TRUE., .FALSE., 31) !NO SUCH FILE OPEN (UNIT=1, NAME='SY:USERLIB.OLB', TYPE='OLD', READONLY, ERR=100) READ (1,70, ERR = 80) 70 FORMAT (1X) IULIB = 1 !USERLIB EXISTS 80 CLOSE (UNIT=1) C C OPEN THE COMMAND FILE FOR OUTPUT C 100 OPEN (UNIT=1, NAME='SY:BUILD.TMP', TYPE='NEW', 1 CARRIAGECONTROL='LIST') RETURN END SUBROUTINE PARSE (LINE, LLINE, PTR, ITYPE, NNAMES) C C BREAKS LINE UP INTO A SEQUENCE OF ASCIZ STRINGS IN LINE, EACH INDEXED C BY PTR, AND OF TYPE ITYPE. TYPE 1 ENTRIES ARE NAMES, TYPE >2 ARE SINGLE C CHARACTER DELIMITERS. NNAMES IS SET TO THE NUMBER OF ENTRIES IN NAMES. C ALL NAMES MUST BEGIN WITH A LETTER OR A NUMBER, AND MAY CONTAIN ANY C CHARACTER EXCEPT: "()=," . C ITYPE FOR DELIMITERS IS SET AS FOLLOWS: C 0 => UNKNOWN TYPE C 1 => NAME C 2 => LEFT PARENTHESIS C 3 => RIGHT PARENTHESIS C 4 => EQUAL SIGN C 5 => COMMA C BYTE LINE(1), PTR(1), ITYPE(1) LOGICAL*1 UIC C C CONVERT THE LINE TO UPPER CASE C FOR J=1,LLINE IF (LINE(J) .GE. "141 .AND. LINE(J) .LE. "172) LINE(J) = LINE(J) - "40 NNAMES = 0 J1 = 1 REPEAT { C C FIND NEXT NON BLANK CHARACTER C IF (J1 .GT. LLINE) RETURN FOR J=J1, LLINE IF (LINE(J) .NE. "40 .AND. LINE(J) .NE. "11) GO TO 20 RETURN C C DECIDE IF DELIMITER OR NAME. C NAMES START WITH ALPHA, NUMBER, $ OR [. C 20 IFF (LINE(J) .EQ. "44 1 .OR. (LINE(J) .GE. "60 .AND. LINE(J) .LE. "71) 2 .OR. (LINE(J) .GE. "101 .AND. LINE(J) .LE. "133)) THEN { C C FOUND A NAME - LOOK FOR DELIMITER C J1 = J UIC = .FALSE. NNAMES = NNAMES + 1 PTR(NNAMES) = J1 ITYPE (NNAMES) = 1 FOR J=J1,LLINE { IF (LINE(J) .EQ. "51 .OR. LINE(J) .EQ. "75 1 .OR. LINE(J) .EQ. "50) GO TO 50 IF (LINE(J) .EQ. "133) UIC = .TRUE. IF (.NOT. UIC .AND. LINE(J) .EQ. "54) GO TO 50 IF (UIC .AND. LINE(J) .EQ. "135) UIC = .FALSE. } C C END OF A NAME - ELSE STMT WILL PUT ZERO BYTE AT END C 50 J1 = J } ELSE { C C DELIMITER CHARACTER C NNAMES = NNAMES + 1 PTR(NNAMES) = J ITYPE(NNAMES) = 0 !UNKNOWN TYPE IF (LINE(J) .EQ. "50) ITYPE(NNAMES) = 2 !( IF (LINE(J) .EQ. "51) ITYPE(NNAMES) = 3 !) IF (LINE(J) .EQ. "75) ITYPE(NNAMES) = 4 != IF (LINE(J) .EQ. "54) ITYPE(NNAMES) = 5 !, LINE(J) = 0 !CHANGE TO END OF STRING J1 = J+1 } } END SUBROUTINE SECT (LINE, PTR, ITYPE, ISECT, NNAMES, KEYWD) C C GOES THROUGH THE LIST OF TYPES GENERATED BY PARSE, AND SETS C THE ENTRIES OF ISECT TO THE INDEX INTO ITYPE AND PTR WHERE THE C CORRESPONDING SECTION BEGINS. THIS WILL EITHER BE A LEFT C PARENTHESIS, OR THE SINGLE NAME IN THE SECTION. IF ISECT(I) C IS ZERO, SECTION I IS MISSING C BYTE LINE(1), PTR(1), ITYPE(1), KEYWD(7,15) INTEGER ISECT(15) C C SET UP KEYWORD TABLE (SOMEDAY PUT IT INTO DATA STATEMENTS) C CALL STRING (KEYWD(1,1), 'FILE') CALL STRING (KEYWD(1,2), 'LIB') CALL STRING (KEYWD(1,3), 'MAP') CALL STRING (KEYWD(1,4), 'PRI') CALL STRING (KEYWD(1,5), 'ACTFIL') CALL STRING (KEYWD(1,6), 'MAXBUF') CALL STRING (KEYWD(1,7), 'FMTBUF') CALL STRING (KEYWD(1,8), 'COMMON') CALL STRING (KEYWD(1,9), 'LIBR') CALL STRING (KEYWD(1,10), 'CLSTR') CALL STRING (KEYWD(1,11), 'ASG') CALL STRING (KEYWD(1,12), 'UNITS') CALL STRING (KEYWD(1,13), 'TASK') CALL STRING (KEYWD(1,14), 'SIZE') CALL STRING (KEYWD(1,15), 'DEBUG') NKEYS = 15 N = 1 LASTSC = 0 C C SCAN THROUGH LIST FOR SECTIONS C REPEAT { IF (N .GT. NNAMES) RETURN IF (ITYPE(N) .EQ. 0 .OR. ITYPE(N) .GE. 3) GO TO 1000 IFF (N .LT. NNAMES .AND. ITYPE(N+1) .EQ. 4) THEN { C C ENTRY OF THE FORM "KEYWORD=" C IF (ITYPE(N) .NE. 1) GO TO 1000 FOR J=1,NKEYS { CALL COMPAR (ICOMP, LINE(PTR(N)), KEYWD(1,J)) IF (ICOMP .EQ. 0) GO TO 50 } C C NAME NOT FOUND IN KEYWORD LIST C K1 = PTR(N) K2 = K1 + LENGTH(LINE(K1)) - 1 WRITE (2,40) (LINE(K), K=K1,K2) 40 FORMAT (' BUILD -- Unknown keyword: ', 80A1) CALL EXIT C C NAME IS A KEYWORD, ENTER INTO ISECT C 50 N = N+2 !SKIP KEYWORD= IF (N .GT. NNAMES) RETURN LASTSC = J !FORCE LAST SECTION TO HERE ISECT(LASTSC) = N } ELSE { C C NO KEYWORD, SINGLE ENTRY C LASTSC = LASTSC + 1 !FOLLOWS PREVIOUS SECTION IFF (LASTSC .GT. NKEYS) THEN { WRITE (2,60) 60 FORMAT (' BUILD -- Too many arguments') CALL EXIT } ISECT(LASTSC) = N } C C NEXT ITEM SHOULD BE EITHER A NAME OR A LEFT PARENTHESIS C IF (ITYPE(N) .NE. 1 .AND. ITYPE(N) .NE. 2) GO TO 1000 C C SCAN THROUGH TO END OF THIS SECTION C IFF (ITYPE(N) .EQ. 2) THEN { !LOOK FOR RIGHT PARENTHESIS WHILE (ITYPE(N) .NE. 3) { N = N+1 IF (N .GT. NNAMES) RETURN } } N = N+1 !SKIP PARENTHESIS OR NAME IF (N .GE. NNAMES) RETURN IF (ITYPE(N) .NE. 5) GO TO 1000 !MUST BE COMMA N = N+1 !SKIP COMMA } C C ILLEGAL DELIMITER ERROR MESSAGE C 1000 WRITE (2,1010) LINE(PTR(N)) 1010 FORMAT (' BUILD -- Syntax error at character "', A1, '"') CALL EXIT END SUBROUTINE BUILD1 (LINE, PTR, ITYPE, ISECT, NNAMES, KEYWD, 1 IULIB, IFTB, FTNNAM, IF77) C C SCANS THROUGH THE SECTIONS INDEXED BY ISECT, AND CREATES THE TASK C BUILD COMMAND FILE AS REQUIRED, UP TO THE END OF THE LIBRARIES PART. C SETS IFTB TO NONZERO IF FAST TASK BUILDER MAY BE USED. C SETS FTNNAM TO THE NAME OF THE PROGRAM BEING BUILT. C IF IF77 IS NONZERO IT WILL USE THE F77 STYLE LIBRARIES, OTHER FOR. C BYTE LINE(1), PTR(1), ITYPE(1), KEYWD(7,15), FILE(32) BYTE FTNNAM(1), LINE2(80) INTEGER ISECT(15) LOGICAL*1 PAREN C C INPUT FILE SECTION C LASTSC = 1 N = ISECT(1) IFF (N .EQ. 0) THEN { WRITE (2,10) 10 FORMAT (' BUILD -- Input file name required') CALL EXIT } PAREN = .FALSE. IF (ITYPE(N) .EQ. 2) PAREN = .TRUE. IF (PAREN) N = N+1 IF (ITYPE(N) .NE. 1) GO TO 1000 CALL STRING (FILE, LINE(PTR(N))) !COPY FILENAME C C STRIP OFF ANY SWITCHES ON FILENAME C FOR J=1,LENGTH(FILE) IF (FILE(J) .EQ. "57) FILE(J) = 0 CALL STRING (FTNNAM, FILE) !SAVE FILENAME FOR FORTRAN CMD C C BUILD UP FIRST LINE: NAME/CP/FP=NAME C CALL STRING (LINE2, LINE(PTR(N))) CALL CONCAT (LINE2, '/CP/FP') IFF (ISECT(3) .NE. 0) THEN { !MAP REQUESTED CALL CONCAT (LINE2, "54) ! , CALL CONCAT (LINE2, FILE) ! FILENAME } CALL CONCAT (LINE2, "75) ! = CALL CONCAT (LINE2, FILE) ! FILENAME WRITE (1,20) (LINE2(J), J=1,LENGTH(LINE2))!OUTPUT FIRST TKB LINE 20 FORMAT (80A1) C C INSERT OTHER INPUT FILES C IFF (PAREN) THEN { N = N+1 WHILE (ITYPE(N) .EQ. 5) { N = N+1 !SKIP COMMA IF (ITYPE(N) .NE. 1) GO TO 1000 K1 = PTR(N) K2 = K1 + LENGTH(LINE(K1)) - 1 WRITE (1,20) (LINE(K), K=K1,K2) N = N+1 } } C C ENTER NAMES OF DEFAULT LIBRARIES AT TOP OF LIBRARY CHAIN C IF (IULIB .NE. 0) WRITE (1,30) 30 FORMAT ('USERLIB/LB') IF (IF77 .EQ. 0) WRITE (1,40) 40 FORMAT ('SF:[5,3]FTNLIB/LB') IF (IF77 .NE. 0) WRITE (1,45) 45 FORMAT ('SF:[5,3]FTNLIB77/LB') C C LIBRARY SECTION - TRANSLATE $ TO SYSTEM LIBRARY ACCOUNT SF:[5,3] C LASTSC = 2 N = ISECT(2) IFF (N .NE. 0) THEN { PAREN = .FALSE. IF (ITYPE(N) .EQ. 2) PAREN = .TRUE. IF (PAREN) N = N+1 REPEAT { IF (ITYPE(N) .NE. 1) GO TO 1000 LINE2(1) = 0 IFF (LINE(PTR(N)) .EQ. "44) THEN { !LIKE $NPLIB PTR(N) = PTR(N) + 1 CALL STRING (LINE2, 'SF:[5,3]') !UIC FOR $ } CALL CONCAT (LINE2, LINE(PTR(N))) CALL CONCAT (LINE2, '/LB') WRITE (1,20) (LINE2(J), J=1,LENGTH(LINE2)) N = N+2 } UNTIL (.NOT. PAREN .OR. ITYPE(N-1) .NE. 5) } C C INCLUDE FORTRAN OTS LIBRARY, UNLESS THIS IS INCLUDED IS SYSLIB C IF (IF77 .EQ. 0) WRITE (1,50) 50 FORMAT ('LB:[1,1]FOROTS/LB') IF (IF77 .NE. 0) WRITE (1,55) 55 FORMAT ('LB:[1,1]F4POTS/LB') C C END OF INPUT PART OF COMMAND FILE, NOW START OPTIONS PART C WRITE (1,60) 60 FORMAT ('/') RETURN C C ERROR HANDLER C 1000 WRITE (2,1010) (KEYWD(J,LASTSC), J=1,6) 1010 FORMAT (' BUILD -- Syntax error in ', 6A1, ' section') CALL EXIT END SUBROUTINE BUILD2 (LINE, PTR, ITYPE, ISECT, NNAMES, KEYWD, 1 IULIB, IFTB, FTNNAM, IF77) C C SCANS THROUGH THE SECTIONS INDEXED BY ISECT, AND CREATES THE TASK C BUILD COMMAND FILE OPTIONS SECTION. C SETS IFTB TO NONZERO IF FAST TASK BUILDER MAY BE USED. C IF IF77 IS NONZERO IT WILL USE THE F77 STYLE LIBRARIES, OTHER FOR. C BYTE LINE(1), PTR(1), ITYPE(1), KEYWD(7,15), FILE(80) BYTE FTNNAM(1) INTEGER ISECT(15) LOGICAL*1 PAREN C C INCLUDE DEFAULT RESIDENT LIBRARIES UNLESS LIBR= OR CLSTR=. C SIZE=0 (THE DEFAULT) LOADS 2 4K LIBRARIES, MAX SIZE = 24K. C SIZE=1 LOADS 2 4K LIBRARIES, CLUSTERED, MAX SIZE = 28K. C SIZE=2 DOES NOT LOAD ANY LIBRARIES, MAX SIZE = 32K. C C ALSO SET IFTB = 1 IF FAST TASK BUILDER MAY BE USED. C THE REGULAR TASK BUILDER MUST BE USED FOR CLSTR= OPTIONS, C BUT WE ALSO FORCE IT FOR SIZE=2 TO PUNISH THE GLUTTONS. C EXPLICITELY SAYING SIZE=0 WILL ALSO FORCE TKB; THIS IS C NECESSARY IF USING SOME NON-FTB OPTIONS, SUCH AS FORTRAN C VIRTUAL ARRAYS. NOTE THAT WE SUPPORT FORRES BUT NOT F4PRES. C IFTB = 1 !ASSUME FAST TASK BUILDER N = ISECT(14) !SIZE= OPTION IF (N .NE. 0) IFTB = 0 !SIZE OPTION GIVEN, USE TKB IFF (ISECT(9) .EQ. 0 .AND. ISECT(10) .EQ. 0) THEN { !NO CLSTR OR LIBR OPTIONS GIVEN IFF (N .EQ. 0 .OR. LINE(PTR(N)) .EQ. '0') THEN { !INCLUDE RESIDENT LIBRARY(S) IF (IF77 .EQ. 0) WRITE (1,65) 65 FORMAT ('LIBR=FORRES:RO') WRITE (1,70) 70 FORMAT ('LIBR=FCSRES:RO') } IFF (N .NE. 0 .AND. LINE(PTR(N)) .EQ. '1') THEN { !SIZE=1 CLUSTERED LIBRARIES IF (IF77 .EQ. 0) WRITE (1,75) 75 FORMAT ('CLSTR=FORRES,FCSRES:RO') IF (IF77 .NE. 0) WRITE (1,80) 80 FORMAT ('LIBR=FCSRES:RO') !NO CLSTR FOR F77 } } IF (ISECT(10) .NE. 0) IFTB = 0 !CLSTR= REQUIRES TKB C C ALL THE REST, RESIDENT LIBRARIES AND COMMON, ALL OPTIONS C FOR LASTSC = 4, 13 { N = ISECT(LASTSC) IFF (N .NE. 0) THEN { PAREN = .FALSE. IF (ITYPE(N) .EQ. 2) PAREN = .TRUE. IF (PAREN) N = N+1 REPEAT { IF (ITYPE(N) .NE. 1) GO TO 1000 CALL STRING (FILE, KEYWD(1,LASTSC)) CALL CONCAT (FILE, '=') CALL CONCAT (FILE, LINE(PTR(N))) WRITE (1,85) (FILE(J), J=1,LENGTH(FILE)) 85 FORMAT (80A1) N = N+2 } UNTIL (.NOT. PAREN .OR. ITYPE(N-1) .NE. 5) } } C C ALL FINISHED C WRITE (1,90) 90 FORMAT ('//') RETURN C C ERROR HANDLER C 1000 WRITE (2,1010) (KEYWD(J,LASTSC), J=1,6) 1010 FORMAT (' BUILD -- Syntax error in ', 6A1, ' section') CALL EXIT END SUBROUTINE CLOSEF (LINE, ISECT) C C CLOSES THE OUTPUT COMMAND FILE, AND PRINTS IT IF REQUESTED BY DEBUG=Y. C BYTE LINE(80) INTEGER ISECT(15) CLOSE (UNIT=1) IF (ISECT(15) .EQ. 0) RETURN OPEN (UNIT=1, NAME='SY:BUILD.TMP', TYPE='OLD', READONLY) FOR K=1,50 { READ (1,10,END=50) LLINE, LINE 10 FORMAT (Q, 80A1) WRITE (2,20) (LINE(J), J=1,LLINE) 20 FORMAT (1X, 80A1) } 50 CLOSE (UNIT=1) RETURN END SUBROUTINE TKB (LINE, IFTB, COMPIL, FTNNAM, ISTAT) C C THIS SPAWNS THE TASK BUILDER TO WORK ON THE COMMAND FILE BUILD.TMP. C DEPENDING ON THE VALUE OF IFTB, IT CHOOSES EITHER FTB OR TKB. C IT WAITS FOR COMPLETION OF THE TKB, AND SETS ISTAT TO ITS EXIT STATUS. C IF IFTB IS NONZERO, USE THE FAST TASKBUILDER, ELSE USE TKB. C IF COMPIL IS NONZERO, RUN THE FORTRAN COMPILER FIRST, USING THE C FILE NAME IN FTNNAM IN ASCIZ FORMAT. C INTEGER IOSTAT(8) BYTE LINE(1), COMPIL(1), FTNNAM(1), TEXT(40) DATA TASK /6RMCR.../ !TASK DISPATCHER C C OPTIONALLY RUN FORTRAN COMPILER FIRST. C IF FORTRAN EXITS WITH EXIT STATUS 2 OR WORSE, WE DON'T BOTHER TKBING. C IFF (COMPIL(1) .NE. 0) THEN { CALL STRING (TEXT, COMPIL) CALL CONCAT (TEXT, ' ') CALL CONCAT (TEXT, FTNNAM) CALL SPAWN (TASK,,, 1,, IOSTAT,, TEXT, LENGTH(TEXT),,, IDS) CALL STOPFR (1) !WAIT FOR TASK TO COMPLETE IF (IOSTAT(1) .GE. 2) GO TO 300 !FORTRAN ERRORS } C C SPAWN THE APPROPRIATE TASK BUILDER TASK C IFF (IFTB .NE. 0) THEN CALL SPAWN (TASK,,, 1,, IOSTAT,, 'FTB @BUILD.TMP', 14,,, IDS) ELSE CALL SPAWN (TASK,,, 1,, IOSTAT,, 'TKB @BUILD.TMP', 14,,, IDS) C C DON'T CHECK SUCCESS - CAN ALWAYS SPAWN TO MCR C C IF (IDS .LE. 0) WRITE (2,220) IDS C220 FORMAT (' BUI -- Failed to spawn TKB/FTB, IDS =', I5) CALL STOPFR (1) !WAIT FOR TASK TO COMPLETE C C SAVE TASK BUILDER'S EXIT STATUS C 300 ISTAT = IOSTAT(1) RETURN END SUBROUTINE DELET (COMPIL, FTNNAM, ISTAT) C C DELETE BUILD.TMP AND PERHAPS THE OBJECT FILE. C THEN EXIT WITH EXIT STATUS OF TASK BUILDER. C BYTE FTNNAM(1), COMPIL(1), TEXT(40) C C DELETE BUILD.TMP C OPEN (UNIT=1, NAME='SY:BUILD.TMP', TYPE='OLD') CLOSE (UNIT=1, DISPOSE='DELETE') C C DELETE OBJECT FILE IF FORTRAN WAS CALLED C IFF (COMPIL(1) .NE. 0) THEN { CALL STRING (TEXT, FTNNAM) CALL CONCAT (TEXT, '.OBJ') OPEN (UNIT=1, NAME=TEXT, TYPE='OLD') CLOSE (UNIT=1, DISPOSE='DELETE') } CALL EXST (ISTAT) !RETURN TKB'S EXIT STATUS END