THE RATFOR LIBRARY -- PRESENTED AT DECUS FALL SYMPOSIUM, 1980 STEPHEN M. LAZARUS FORD AEROSPACE AND COMMUNICATIONS CORPORATION MAIL STOP X-90 3939 FABIAN WAY PALO ALTO, CALIFORNIA 94303 (415) 494-7400 X6291 UIC [307,25] OF THE RSX TAPE WILL CONTAIN THE RATFOR LIBRARY, A COPY OF THESE TRANSPARENCIES, THE EXAMPLES PRESENTED, AND WHATEVER ELSE ENDS UP THERE. WHY A RATFOR LIBRARY EXTEND THE LANGUAGE INTERFACE TO THE OPERATING SYSTEM HANDLE I/O PROVIDE PORTABILITY LANGUAGE EXTENSION 1. USE FUNCTIONS NEW LANGUAGE VERBS FUNCTIONS CAN BE ARGUEMENTS OF LOGICAL EXPRESSIONS TOP DOWN PROGRAMMING ENCOURAGED 2. PROVIDE FACILITIES NOT HANDLED WELL BY THE LANGUAGE E.G. STRING PROCESSING IS PAINFUL IN FORTRAN. 3. EXAMPLE -- OUTPUT ALL WONDERFUL LINES FROM A FILE DEFINE (WONDERFUL,1) DEFINE (IS,==) WHILE ( GETL(INPUT,MAXLINE,STDIN) ~= EOF ) IF ( INPUT(LINE) IS WONDERFUL ) CALL PUTL( LINE,STDOUT ) STRING MANIPULATION ROUTINES EQUAL -- COMPARE TWO STRINGS FOR EQUALITY LENGTH -- GET LENGTH OF STRING SCOPY -- COPY A STRING TYPE -- IDENTIFY IF CHAR IS NUMERIC OR ALPHABETIC CTOI -- CHARACTER TO INTEGER CONVERSION CHEXTI -- CHARACTER TO EXTENDED INTEGER CONVERSION ITOC -- INTEGER TO CHARACTER CONVERSION INDEX -- LOCATE A CHARACTER IN A STRING BRAKE -- ELIMINATE NON SPECIFIED CHARACTERS FROM A STRING SPAN -- REMOVE SPECIFIED CHARACTERS FROM A STRING MATCH -- MATCH A STRING AMATCH -- PERFORM AN ANCHORED MATCH ON A STRING ANY -- FIND ANY OF A LIST OF CHARACTERS IN A STRING NOTANY -- FIND ANY CHARACTERS NOT IN LIST IN A STRING SHIFT -- LEFT SHIFT A STRING RPLACE -- REPLACE ALL OCCURANCES OF A CHARACTER IN A STRING TRIM -- REMOVE TRAILING BLANNKS AND TABS APPEND -- APPEND A STRING TO ANOTHER REMOVE -- REMOVE A SUBSTRING INSERT -- INSERT A STRING INTO ANOTHER LPAD -- LEFT PAD A STRING WITH BLANKS RPAD -- RIGHT PAD A STRING WITH BLANKS ALIGN -- ALIGN A STRING IN A SPECIFIED FIELD ALLDIG -- IDENTIFY IF STRING IS ALL DIGITS CLOWER -- COVERT CHARACTER TO LOWER CASE CUPPER -- CONVERT CHARACTER TO UPPER CASE FOLD -- FOLD A STRING TO LOWER CASE UPPER -- CONVERT A STRING TO UPPER CASE ADDSET -- ADD A CHARACTER TO AN ARRAY GETWRD -- GET NEXT WORD FROM A STRING SKIPBL -- SKIP BLANKS AND TABS SUBFOR -- SUBSTITUTED ONE STRING FOR ANOTHER WITHIN A STRING I/O ROUTINES GETL -- GET AN INPUT LINE PUTL -- PUT A LINE ONTO OUTPUT GETC -- GET A CHARACTER FROM INPUT PUTC -- PUT A CHARACTER ONTO OUTPUT PUTDEC -- PUT A DECIMAL STRING ONTO OUTPUT MCR LINE ROUTINES NXTMCR -- READ NEXT MCR COMMAND LINE NXTFIL -- READ NEXT FILE NAME FROM COMMND LINE SETOTL -- PROCESS COMMAND LINE OF OUTLET PROGRAM ( 1 OUTPUT FILE) SETFLT -- PROCESS COMMAND LINE OF FILTER PROGRAM (1 INPUT FILE, 1 OUTPUT FILE) GETARG -- GET COMMAND LINE ARGUEMENT MCRERR -- REPORT ERROR CANT -- INDICATE THAT A FILE CAN'T BE OPENED KILFER -- KILL CERTAIN FILE ERROR REPORTS TEMPATE FILE TO PROCESS COMMAND LINES -- MCRLINE.RAT #******************* DEFINITIONS TO BE SUPPLIED ************************* # DEFINE (PROMPT= ) # 3 CHARACTER PROMPT STRING (E.G. "PMP") DEFINE (INPUTEXT= ) # DEFAULT EXTENSION FOR INPUT FILE (E.G. ".IN") DEFINE (OUTPUTEXT= ) # DEFAULT EXTENSION FOR OUTPUT FILE (E.G. ".OUT") DEFINE (PROGNAME= ) # NAME OF YOUR PROGRAM TO BE CALLED AS A SUBROUTINE # (E.G. SUBROU) # #******************* END OF DEFINITIONS TO BE SUPPLIED ****************** # INCLUDE DEFN/NL # STANDARD DEFINITIONS # INTEGER SETFLT # WHILE( SETFLT(STDLUNTI, PROMPT,INPUTEXT,OUTPUTEXT,STDLUNIND) == YES) CALL PROGNAME CALL EXIT END EXAMPLE PROGRAM -- COMMAND FILE GENERATOR PROBLEM: WISH TO RUN A LIST OF FILES THROUGH A UTILITY. SOLUTION: 1. USE PIP OR SRD TO OBTAIN A LISTING OF FILES WANTED. -----> 2. USE THIS FILE NAME LIST TO GENERATE A COMMAND FILE. 3. RUN THE UTILITY USING THE COMMAND FILE. PROGRAM "CMD" PERFORMS STEP #2. DESIGN OF CMD PROGRAM OPEN INPUT AND OUTPUT FILES AS GIVEN IN THE COMMAND LINE DETERMINE PROCESSING OPTIONS FROM THE COMMAND LINE READ TEMPLATE COMMAND LINE FROM THE COMMAND LINE REPEAT { EXTRACT VALID FILE NAME FROM INPUT FILE (IGNORE EXTRANEOUS GARBAGE PRODUCE BY PIP OR SRD) TAKE ENTIRE NAME, NAME MINUS VERSION NUMBER, OR NAME MINUS EXTENSION AS SPECIFIED BY PROCESSING OPTION SUBSTITUTE NAME IN TEMPLATE COMMAND LINE OUTPUT THE COMMAND LINE } UNTIL END OF INPUT FILE IS REACHED USE OF CMD PROGRAM TO COMPILE ALL FORTRAN FILES IN DIRECTORY PIP DIREC.LST = *.FTN CMD COMPILE.CMD = DIREC.LST/NOEXTENSION/COMMAND:?,?=? F4P @COMPILE.CMD #COMMND Generate Command File from Directory # # DEFINE (PROMPT="CMD" ) # 3 CHARACTER PROMPT STRING (E.G. "PMP") DEFINE (INPUTEXT=".LST" ) # DEFAULT EXTENSION FOR INPUT FILE (E.G. ".IN") DEFINE (OUTPUTEXT=".CMD" ) # DEFAULT EXTENSION FOR OUTPUT FILE (E.G. ".OUT") DEFINE (PROGNAME=COMMND ) # NAME OF YOUR PROGRAM TO BE CALLED AS A SUBROUTINE # (E.G. SUBROU) # INCLUDE DEFN/NL # STANDARD DEFINITIONS # INTEGER SETFLT # WHILE( SETFLT(STDLUNTI, PROMPT,INPUTEXT,OUTPUTEXT,STDLUNIND) == YES) CALL PROGNAME CALL EXIT END # SUBROUTINE COMMND # DEFINE(ENTIRELINE=0) DEFINE(ENTIRENAME=1) DEFINE(NOVERSION=2) DEFINE(NOEXTENSION=3) DEFINE (FUNNYCOMMA=-20) DEFINE (FUNNYEQUAL=-21) DEFINE (FUNNYSLASH=-22) # CHARACTER FILNAM(20), # INPUT FILE NAME CMD(MAXLINE), # COMMAND WITH SUBSTITUTIONS TEMCOM(MAXLINE) # TEMPLATE COMMAND INTEGER GETNAM, # FUNCTION TO GET NEXT FILE NAME FROM INPUT SUBFOR, # SUBSTITUTION FUNCTION APPEND, # RATLIB APPEND FUNCTION MODE # CONTROL MODE ( ENTIRENAME | NOEXTENSION | # NOVERSION) # CALL INIT(MODE,TEMCOM) # GET MODE AND TEMPLATE FROM COMMAND LINE IF ( TEMCOM(1) == EOS) { # PROMPT FOR COMMAND LINE IF NOT GIVEN CALL PUTL(" TYPE COMMAND LINE, '?' IS REPLACED BY FILE NAME",STDLUNTI) CALL GETL(TEMCOM,MAXLINE,STDLUNTI) } WHILE( GETNAM(MODE,FILNAM)~=EOF){ # GET THE NEXT NAME CMD(1)=EOS JUNK = APPEND (CMD,TEMCOM,1) JUNK = SUBFOR(CMD,"?",FILNAM) # DO THE SUBS CALL PUTL( CMD, STDLUNOUT) } RETURN END # SUBROUTINE INIT(MODE,TEMCOM) # DEFINE(SWITCHLENGTH=80) # # ************** DECLARATIONS REMOVED ********************* # MODE = ENTIRENAME # INITIALIZE MODE TEMCOM(1) = EOS # AND EMPTY COMMAND STRING # FOR ( NUMSWI = 1; GETARG(NUMSWI,WRKSWI,SWITCHLENGTH)~=EOF; INCREMENT(NUMSWI) ){ NEGATE = NO # INITIALIZE TO NO NEGATION IF ( WRKSWI(1) == '-'){ # SWITCH NEGATED BY "-" ? NEGATE = YES JUNK = SHIFT(WRKSWI,1) # SHIFT OUT NEGATION } IF ( WRKSWI(1)=='N' & WRKSWI(2)=='O'){ # SWITCH NEGATED BY "NO" ? NEGATE = YES JUNK = SHIFT(WRKSWI,2) # SHIFT OUT NEGATION } # FIRST LETTER WILL IDENTIFY THE SWITCH IF( WRKSWI(1) == "V") # NO VERSION SWITCH MODE = NOVERSION ELSE IF ( WRKSWI(1) == "E") # NO EXTENSION SWITCH MODE = NOEXTENSION ELSE IF ( WRKSWI(1) == "L") # ENTIRE LINE SWITCH MODE = ENTIRELINE ELSE IF ( WRKSWI(1) == "C"){ # COMMAND TEMPLATE LOC = INDEX(WRKSWI,":") + 1 # FIND THE COLIN IF ( LOC >> 1) CALL SCOPY(WRKSWI,LOC,TEMCOM,1,SWITCHLENGTH)# AND COPY ARG FOR( I = 1; TEMCOM(I) ~= EOS; INCREMENT(I) ) # CHANGE FUNNYCOMMA IF ( TEMCOM(I)==FUNNYCOMMA) # TO COMMA TEMCOM(I) = ',' ELSE IF ( TEMCOM(I)==FUNNYEQUAL) # AND FUNNY EQUAL TEMCOM(I) = '=' # TO EQUAL ELSE IF ( TEMCOM(I)==FUNNYSLASH) # AND FUNNYSLASH TEMCOM(I)= '/' # TO SLASH } ELSE # BAD SWITCH CALL MCRERR(STDLUNTI,PROMPT,'BAD SWITCH, IGNORED') } END # #GETNAM Get next file name # INTEGER FUNCTION GETNAM(MODE,FILNAM) # # ************** DECLARATIONS REMOVED ********************* # REPEAT{ # LOOP UNTIL PROPER LINE IS FOUND LEN = GETL(BUF, 80, STDLUNIN) IF ( LEN==EOF){ FILNAM(1)=EOS RETURN(EOF) } FOR ( I=1; BUF(I)~= EOS; INCREMENT(I) ){ # REMOVE NON-PRINTING CHARS IF ( BUF(I) >= BLANK & BUF(I) <= "~") # PRINTING CHARACTER? NEXT # YES, DO NOTHING ELSE { JUNK = SHIFT(BUF(I),1) # NO, SHIFT IT OUT DECREMENT(I) } } IF ( MODE==ENTIRELINE) # DONE SEARCH IF ACCEPTING ENTIRE LINE BREAK IF ( INDEX(BUF,";") ~= 0) # SEARCH FOR SEMICOLIN IN FILE NAME BREAK } IF ( MODE == NOVERSION) BRKCHR = ";" # BREAK OFF NAME BEFORE VERSION NUMBER ELSE IF ( MODE == NOEXTENSION) BRKCHR = "." # BREAK OFF NAME BEFORE EXTENSION ELSE IF ( MODE == ENTIRENAME | MODE == ENTIRELINE) BRKCHR = EOS IF ( BRKCHR ~= EOS) { PLACE = INDEX(BUF,BRKCHR) # TRUNCATE THE FILE NAME AT BRKCHR BUF(PLACE) = EOS } JUNK = SUBFOR(BUF,' ',EOS) # REMOVE ALL BLANKS FILNAM(1)=EOS # ZERO THE FILENAME LEN = APPEND(FILNAM, BUF, 1) # APPEND THE STRING TO FILE NAME RETURN(LEN) END