














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
