# STRING LIBRARY FILE=STRLIB.RAT ##PCN #47, 4 APR 79, ADD ALLDIG,FOLD,SHELL,INDEX,TYPE,UNFOLD # ##ALLDIG - I =ALLDIG(STR) ##FOLD - CALL FOLD (STR) ##INDEX - COL =INDEX (STR, CHAR) ##SCOMPR - I =SCOMPR(STR1, STR2) ##SCOMPX - I =SCOMPX(STR1, STR2, CHAR) ##SCOPY - LEN2=SCOPY (STR1, STR2, MAX, ERROR) ##SCTOI - NUM =SCTOI (STR, NCOL) ##SDECAT - CALL SDECAT(STR1, STR2, STR3, STR4) ##SEQL - I =SEQL (STR1, STR2) ##SFIND - COL =SFIND (STR, START, STOP, CHAR) ##SHELL - CALL SHELL (LASTP, NAMPTR, TABLE) ##SINDX - COL =SINDX (STR1, STR2) ##SINSRT - CALL SINSRT(STR1, STR2) ##SITOC - LEN =SITOC (NUM, STR, MAX) ##SJOIN - LEN2=SJOIN (STR1, STR2, MAX, ERROR) ##SLEN - LEN =SLEN (STR) ##SMIDV - LEN4=SMIDV (STR1, STR2, STR3, STR4, MAX, ERROR) ##SMOVE - I =SMOVE (STR1, FROM, TO, STR2, START) ##SNUMBR - NUM =SNUMBR(STR, START, STOP, NUM, NCOL) ##SPAD - CALL SPAD (STR, LEN) ##SPOSTV - LEN3=SPOSTV(STR1, STR2, STR3, MAX, ERROR) ##SPREFX - CALL SPREFX(STR1, STR2, STR3, STR4) ##SPREV - LEN3=SPREV (STR1, STR2, STR3, MAX, ERROR) ##SREPT - LEN2=SREPT (STR1, NUM, STR2, MAX, ERROR) ##SSAME - ICOL=SSAME (STR1, STR2, LORR) ##SSAMEX - ICOL=SSAMEX(STR1, STR2, LOOR) ##SSUFX - CALL SSUFX (STR1, STR2, STR3, STR4) ##SSWAP - LEN4=SSWAP (STR1, STR2, STR3, STR4, MAX, ERROR) ##STRGET - LEN =STRGET(LUN STR, MAX) ##STRPUT - ERR =STRPUT(LUN, STR) ##STRIM - LEN =STRIM (STR) ##TYPE - C =TYPE (CHAR) ##UNFOLD - CALL UNFOLD (STR) INCLUDE/NL DEFIN #PCN 47 # #GENERAL COMMENTS: ##ROUTINES THAT PRODUCE AN OUTPUT STRING GENERALY ALLOW A 'MAX' SIZE # FOR THE OUTPUT STRING TO BE SPECIFIED. THE OUTPUT IS CUT TO 'MAX' # CHARACTERS IF NECESSARY; IF IT IS,THE INTEGER 'ERROR' IS SET TO YES # (OTHERWISE TO NO) TO ALERT THAT TRUNCATION WAS NECESSARY. # ONE EXTRA ARRAY ELEMENT AT THE END OF THE STRING IS ALWAYS NECESSARY # (BEYOND MAX) FOR THE EOS. #SUBROUTINE CALLS SPECIFYING A SPECIFIC ARRAY ELEMENT (EG. STR(I)) CAUSE # ACTION TO BE TAKEN (AND RETURN VALUES AND MAX TO BE CALCULATED, IF # APPROPRIATE FROM THE SPECIFIED ELEMENT, NOT THE WHOLE STRING (FROM ELEMENT # 1) SINCE ONLY THE STRING STARTING AT THE SPECIFIED ELEMENT IS KNOWN # TO THE SUBROUTINE. EG J=SLEN(STRI)) SETS J TO THE NUMBER OF ELEMENTS # BETWEEN I AND EOS. # # ALLDIG - RETURN YES IF STR IS ALL DIGITS # INTEGER FUNCTION ALLDIG(STR) # CHARACTER STR(DUMMYSIZE), TYPE INTEGER I # ALLDIG = NO IF (STR(1) == EOS) RETURN DO I=1,HUGE [ IF (STR(I) == EOS) BREAK ELSE IF (TYPE(STR(I)) != DIGIT) RETURN ] ALLDIG = YES # RETURN END # # FOLD TO CONVERT TOKENS TO LOWER CASE #15MAY77 # SUBROUTINE FOLD(TOKEN) # CHARACTER TOKEN(DUMMYSIZE) INTEGER I # DO I=1,HUGE [ IF (TOKEN(I) == EOS) RETURN ELSE IF (TOKEN(I) >= BIGA & TOKEN(I) <= BIGZ) TOKEN(I)=TOKEN(I)+32 #ASCII ONLY!!! ] # RETURN END # # INDEX - FIND CHARACTER C IN STRING STR #15MAY77 # INTEGER FUNCTION INDEX(STR, C) # CHARACTER C, STR(DUMMYSIZE) # DO INDEX=1,HUGE [ IF (STR(INDEX) == EOS) BREAK ELSE IF (STR(INDEX) == C) RETURN ] INDEX = 0 # RETURN END # # SCOMM - USED BY SDECAT, SSUFX, SPREFX # SUBROUTINE SCOMM (I, STR1, STR3, STR4) # INTEGER I, SMOVE, J CHARACTER STR1(DUMMYSIZE), STR3(DUMMYSIZE), STR4(DUMMYSIZE) # J=SMOVE(STR1, 1, I-1, STR3, 1) #LEFT PART STR3(J+1)=EOS J=SMOVE(STR1, I, HUGE, STR4,1) #RIGHT PART STR4(J+1)=EOS # RETURN END # # SCOMPR - COMPARE TWO STRINGS ALPHABETICALY #RETURN 0 IF EQUAL #RETURN -1 IF STR1 IS CLOSER TO 'A' THEN STR2 #RETURN +1 IF STR1 IS CLOSER TO 'Z' THEN STR2 # INTEGER FUNCTION SCOMPR (STR1, STR2) # INTEGER I, J CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE) # J=1 FOR (I=1; STR1(I) == STR2(J); INCREMENT(I)) IF (STR1(I) == EOS) [ SCOMPR=0 RETURN #WITH A MATCH ALL THE WAY THRU ] ELSE INCREMENT (J) # IF (STR1(I) < STR2(J)) #ASCII ONLY!!! SCOMPR=-1 #STR1 IS HIGHER ELSE SCOMPR=+1 #STR1 IS LOWER # RETURN END # # SCOMPX - COMPARE 2 SPECIAL STRINGS ALPHABETICALLY #COMPAR THE SECTIONS OF 2 STRINGS BEFORE AND AFTER THE 'CHAR' SEPERATOR # INDEPENDENTLY. 0 IS RETURNED IF THE FIRST PART (UP TO 'CHAR')MATCHES # AND THE SECOND PART (FROM 'CHAR' TO EOS) MATCHES. # INTEGER FUNCTION SCOMPX (STR1, STR2, CHAR) # #RETURNS -1 IF STR1 IS HIGHER ALPHABETICALLY THEN STR2 #RETURNS 0 IF STR1 IS EQUAL TO STR2 #RETURNS +1 IF STR1 IS LOWER ALPHABETICALLY THEN STR2 # INTEGER I, J CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE), CHAR # J=1 FOR (I=1; STR1(I) != EOS & STR2(J) != EOS; INCREMENT(I)) [ IF (STR1(I) == CHAR) WHILE (STR2(J) != CHAR & STR2(J+1) != EOS) INCREMENT (J) #SLIDE ALONG 2 TO REGAIN SYNC ELSE IF (STR2(J) == CHAR) WHILE (STR1(I) != CHAR & STR1(I+1) != EOS) INCREMENT (I) ELSE IF (STR1(I) != STR2(J)) [ IF (STR1(I) < STR2(J)) #ASCII ONLY!!! SCOMPX=-1 ELSE SCOMPX=1 RETURN #NORMAL RETURN ] INCREMENT (J) #ELSE TRY NEXT CHAR. ] SCOMPX=0 #THEY MATCHED ALL THE WAY THRU # RETURN END # # SCOPY - COPY ONE STRING INTO ANOTHER STRING #COPYING STOPS WHEN THE END OF STR1 IS REACHED, OR WHEN # STR2 GETS TO BE 'MAX' CHAR. LONG (ERROR IS SET). # VALUE OF THE FUCTION IS RETURNED AS THE LENGTH OF STR2. # INTEGER FUNCTION SCOPY (STR1, STR2, MAX, ERROR) # INTEGER MAX, ERROR, I CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE) # SCOPY=0 ERROR=NO DO I=1,HUGE [ IF (STR1(I) == EOS) BREAK ELSE IF (SCOPY >= MAX) [ ERROR=YES BREAK ] ELSE [ INCREMENT (SCOPY) STR2(SCOPY)=STR1(I) #MOVE A CHARACTER ] ] # STR2(SCOPY+1)=EOS #MAKE OUTPUT A STRING # RETURN END # # SCTOI - CONVERT STRING AT IN(I) TO INTEGER, INCREMENT I #STARTING AT LOCATION 'I', LEADING BLANKS/TABS ARE SKIPPED; # THEN ALL DIGITS UP TO THE NEXT NON-DIGIT (INCLUDING BLANKS) # ARE CONVERTED TO A POSITIVE OR NEGATIVE INTEGER AND RETURNED # AS THE VALUE OF THE FUNCTION. 'I' IS INCREMENTED AND UPON RETURN # POINTS TO THE LOCATION OF THE FIRST NON-DIGIT. # INTEGER FUNCTION SCTOI(IN, I) # CHARACTER IN(DUMMYSIZE) INTEGER D, I, SFIND, PM STRING DIGITS "0123456789" # WHILE (IN(I) == BLANK \ IN(I) == TAB) #SKIP LEADING BLANKS INCREMENT (I) IF (IN(I) == MINUS) [ #ALLOW FOR NEGATIVE INTEGERS INCREMENT (I) PM=-1 ] ELSE PM=+1 # FOR (SCTOI = 0; IN(I) != EOS; INCREMENT (I)) [ D = SFIND (DIGITS, 1, 10, IN(I)) IF (D == 0) # NON-DIGIT STOPS SCAN BREAK SCTOI = 10 * SCTOI + D - 1 ] # IF (PM < 0) SCTOI=-SCTOI RETURN END # # SDECAT - BREAK A STRING INTO TWO SUBSTRINGS AT A CHARACTER #STR1 IS BROKEN INTO STR3 AND STR4 AT THE LEFTMOST OCCURRANCE (IN STR1) OF # ANY CHARACTER THAT IS ALSO ANYWHERE IN STR2. THE "BREAK CHARACTER" # GOES INTO STR4. # SUBROUTINE SDECAT (STR1, STR2, STR3, STR4) # INTEGER I, J, SSAME, SLEN CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE), STR3(DUMMYSIZE), STR4(DUMMYSIZE) # I=SSAME(STR1, STR2, +1) IF (I <= 0) #SEPERATOR WAS NOT THERE I=SLEN(STR1)+1 #SO IT ALL GOES INTO STR3 CALL SCOMM (I, STR1, STR3, STR4) #MOVE LEFT AND RIGHT PARTS # RETURN END # # SEQL - COMPARE STR1 TO STR2; RETURN YES IF EQUAL, #STR1 IS COMPARED CHARACTER BY CHARACTER TO STR2; IF THEY MATCH ALL THE WAY # THRU, THE FUNCTION VALUE IS RETURNED AS 'YES', IF NOT, AS 'NO'. # INTEGER FUNCTION SEQL(STR1, STR2) # CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE) INTEGER I # DO I=1,HUGE [ IF (STR1(I) != STR2(I)) BREAK ELSE IF (STR1(I) == EOS) [ SEQL = YES RETURN ] ] SEQL=NO # RETURN END # # SHELL - TO SORT DEFINE TABLE INTO ALPHABETICAL ORDER FOR RATFOR #SYKES 18 OCT 76,14MAR77 # SUBROUTINE SHELL (LASTP, NAMPTR, TABLE) # INTEGER GAP, I, IG, J, K, SCOMPR, N INTEGER LASTP, NAMPTR(DUMMYSIZE) CHARACTER TABLE(DUMMYSIZE) # FOR (GAP=LASTP/2; GAP > 0; GAP=GAP/2) FOR (J=GAP+1; J <= LASTP; INCREMENT(J)) FOR (I=J-GAP; I > 0; I=I-GAP) [ IG=I+GAP IF (SCOMPR(TABLE(NAMPTR(I)), TABLE(NAMPTR(IG))) <= 0) #PCN 47 BREAK N=NAMPTR(I) #ELSE SWAP POINTERS NAMPTR(I)=NAMPTR(IG) NAMPTR(IG)=N ] # RETURN END # # SINDX - FIND A STRING WITHIN ANOTHER STRING #FUNCTION VALUE IS RETURNED AS THE LOCATION WITHIN STR WHERE # PATN STARTS; OR AS 0, IF PATN DOES NOT OCCUR IN STR. # IF PATN IS NULL, IT IS CONSIDERED TO MATCH AT LOCATION 1. # INTEGER FUNCTION SINDX (STR, PATN) # INTEGER J, K CHARACTER STR(DUMMYSIZE), PATN(DUMMYSIZE) # FOR (SINDX=1; STR(SINDX) != EOS; INCREMENT(SINDX)) [ K=SINDX FOR (J=1; PATN(J) != EOS; INCREMENT(J)) IF (PATN(J) != STR(K)) BREAK ELSE INCREMENT (K) IF (PATN(J) == EOS) RETURN #THEY MATCHED AFTER ALL ELSE IF (STR(K) == EOS) BREAK #NO MATCH POSSIBLE ] #ELSE CONTINUE SINDX=0 #THEY DO NOT MATCH # RETURN END # # SFIND - FAST SEARCH OF A STRING FOR A CHARACTER #SEARCHES A STRING EITHER FROM LEFT TO RIGHT OR RIGHT TO LEFT, # DEPENDING ON THE RELATIVE VALUES OF START AND STOP, FOR A SPECIFIED # CHARACTER AND RETURNS AS THE FUNCTION VALUE THE COLUMN IN STR WHERE # THE FIRST MATCH IS FOUND; OR AS 0, IF NO CHARACTER IN STR MATCHES CHAR. # THIS IS NOT ANSII FORTRAN BECAUSE OF THE BACKWARD INCREMENT ON THE DO LOOP # BUT IN F4P IS SOMEWHAT FASTER THE STANDARD ROUTINES. # INTEGER FUNCTION SFIND (STR, START, STOP, CHAR) # INTEGER START, STOP, I CHARACTER STR(DUMMYSIZE), CHAR # IF (START > STOP) I=-1 ELSE I=+1 DO SFIND=START,STOP,I #RSX!!! NEGATIVE INCREMNT IF (STR(SFIND) == CHAR) RETURN #WITH THE LOCATION SFIND=0 #NOT THERE # RETURN END # # SINSRT - INSERT A STRING INTO ANOTHER STRING #COPY ALL OF STR1 INTO STR2; IF THIS OVERRUNS THE END OF STR2, # MAKE STR2 LONGER TO HOLD ALL OF STR1. # SUBROUTINE SINSRT (STR1, STR2) # INTEGER I, ENDS CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE) # ENDS=NO FOR (I=1; STR1(I) != EOS; INCREMENT(I)) [ IF (STR2(I) == EOS) ENDS=YES STR2(I)=STR1(I) ] IF (ENDS == YES) #IF WE OVERRAN THE END OF STR2 STR2(I)=EOS #IT IS NOW A LONGER STRING # RETURN END # # SITOC - CONVERT INTEGER INT TO CHAR STRING IN STR LEFT JUSTIFIED #CONVERT THE POSITIVE OR NEGATIVE INTEGER 'INT' TO A CHARACTER STRING # IN 'STR'. TRUNCATE THE STRING IF IT GOES BEYOND 'SIZE' CHARACTERS. # RETURN THE ACTUAL NUMBER OF CHARACTERS IN 'STR' AS THE VALUE OF THE FUNCTION. # INTEGER FUNCTION SITOC(INT, STR, SIZE) # INTEGER IABS, MOD INTEGER D, I, INT, INTVAL, J, K, SIZE CHARACTER STR(SIZE) STRING DIGITS "0123456789" # INTVAL = IABS(INT) STR(1) = EOS I = 1 REPEAT [ # GENERATE DIGITS INCREMENT (I) D = MOD(INTVAL, 10) STR(I) = DIGITS(D+1) INTVAL = INTVAL / 10 ] UNTIL (INTVAL == 0 \ I >= SIZE) IF (INT < 0 & I < SIZE) [ # THEN SIGN INCREMENT (I) STR(I) = MINUS ] SITOC = I - 1 FOR (J = 1; J < I; INCREMENT (J)) [ # THEN REVERSE K = STR(I) STR(I) = STR(J) STR(J) = K DECREMENT (I) ] # RETURN END # # SJOIN - CONCATINATE A STRING TO THE END OF ANOTHER STRING, #ADD STR2 TO THE END OF STR1 (IN STR1). MOVE ALL OF STR2 OR UNTIL # STR1 IS 'MAX' CHARS LONG (IN WHICH CASE, SET ERROR=YES) # RETURN THE VALUE OF THE FUNCTION AS THE NEW LENGTH OF STR1. # INTEGER FUNCTION SJOIN (STR1, STR2, MAX, ERROR) # INTEGER MAX, ERROR, I, SLEN, SCOPY CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE) # I=SLEN(STR1) #FIND WHERE TO START SJOIN=SCOPY(STR2, STR1(I+1), MAX-I, ERROR) + I # RETURN END # # SLEN - COMPUTE LENGTH OF STRING (NOT INCLUDING THE EOS) # INTEGER FUNCTION SLEN(STR) # CHARACTER STR(DUMMYSIZE) # DO SLEN=1,HUGE IF (STR(SLEN) == EOS) BREAK DECREMENT (SLEN) #WENT 1 TOO FAR # RETURN END # # SMIDV - SELECT THE MIDDLE OF A STRING #MOVE THE CHARACTERS IN STR1 THAT ARE BETWEEN STR2 AND STR3 (IN STR1) # INTO STR4. TRUNCATE STR4 TO 'MAX' CHARS (AND SET ERROR) IF NECESSARY. # THE VALUE OF THE FUNCTION IS RETURNED AS THE ACTUAL LENGTH OF STR4. # IF EITHER STR2 OR STR3 ARE NOT IN STR1, STR4 IS NULL. # INTEGER FUNCTION SMIDV (STR1, STR2, STR3, STR4, MAX, ERROR) # INTEGER MAX, ERROR INTEGER SLEN, SINDX, SMOVE, J, I CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE), STR3(DUMMYSIZE), STR4(DUMMYSIZE) # I=SINDX (STR1, STR2) #FIND STR2 IN STR1 IF (I > 0) [ I=I+SLEN(STR2) J=SINDX (STR1(I), STR3) #FIND STR3 IN STR1 TO THE RIGHT OF STR2 ] IF (I > 0 & J > 0) [ #BOTH STR2 & STR3 MUST BE THERE IF (J <= MAX) [ J=I+J-2 ERROR=NO ] ELSE [ ERROR=YES J=I+MAX-1 ] SMIDV=SMOVE(STR1, I, J, STR4, 1) STR4(SMIDV+1)=EOS ] ELSE [ ERROR=NO SMIDV=0 #IF BOTH STR2 AND STR3 WERE NOT IN STR1, STR4(1)=EOS #NO MIDDLE EXISTS TO BE PUT INTO STR4 ] # RETURN END # # SMOVE - MOVE CHARACTERS FROM ONE STRING TO ANOTHER #MOVE THE CHARACTERS IN STR1 BETWEEN 'FROM' & 'TO' (INCLUSIVE) # TO STR2, STARTING AT LOCATION 'START'. NO EOS IS PLACED AT THE # END OF THE MOVED CHARACTERS, SO THEY MUST NOT EXTEND STR2. # IF THE END OF STR1 IS REACHED BEFORE LOCATION 'TO', THE TRANSFER # IS ABORTED. THE VALUE OF THE FUNCTION IS RETURNED AS THE LAST # (RIGHTMOST) LOCATION IN STR2 MODIFIED. # INTEGER FUNCTION SMOVE (STR1, FROM, TO, STR2, START) # INTEGER FROM, TO, START, I CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE) # SMOVE=START-1 DO I=FROM, TO IF (STR1(I) == EOS) BREAK #EARLY TERMINATION FOR SHORT STR1 ELSE [ INCREMENT (SMOVE) STR2(SMOVE)=STR1(I) ] IF (SMOVE < START) SMOVE=0 #NOTHING WAS REALLY TRANSFERED # RETURN END # # SNUMBR - FUNCTION TO CONVERT A CHARACTER STRING TO AN INTEGER # #STARTING AT 'START', EXTRACT A INTEGER FROM 'STR' AND RETURN # IT AS THE VALUE OF THE FUNCTION AND AS 'NUM'; IGNORE BLANKS, BUT QUIT AT THE # FIRST NON-DIGIT/BLANK FOUND, BUT IN ANY CASE DO NOT GO PAST COL. 'STOP'. # RETURN IN 'NCOL' THE NUMBER OF THE NEXT COLUMN TO THE RIGHT IN 'STR'. # INTEGER FUNCTION SNUMBR (STR, START, STOP, NUM, NCOL) # INTEGER START, STOP, NUM, I, J, SCTOI, NCOL CHARACTER STR(DUMMYSIZE), TOK(7), TYPE # J=1 FOR (I=START; J <= 7 & I <= STOP; INCREMENT(I)) IF (STR(I) == BLANK) NEXT #SKIP LEADING AND IMBEDDED BLANKS ELSE IF (TYPE(STR(I)) != DIGIT & STR(I) != MINUS) BREAK #STOP AT FIRST NON-DIGIT ELSE [ TOK(J)=STR(I) INCREMENT (J) ] TOK(J)=EOS NCOL=I #NEXT COL IN STR AFTER THE FOUND NUMBER I=1 NUM=SCTOI (TOK, I) #CONVERT TO AN INTEGER SNUMBR=NUM # RETURN END # # SPAD - FILL A STRING UP TO A SPECIFIED LENGTH WITH BLANKS #PAD THE RIGHTHAND END OF STR WITH BLANKS OUT TO 'LEN'. # STR BECOMES A STRING OF LENGTH 'LEN'. # SUBROUTINE SPAD (STR, LEN) # INTEGER LEN, SLEN, I CHARACTER STR(DUMMYSIZE) # FOR (I=SLEN(STR)+1; I <= LEN; INCREMENT(I)) STR(I)=BLANK STR(LEN+1)=EOS #TRUNCATED IF STR IS LONGER THEN LEN TO START # RETURN END # # SPOSTV - SELECT THE RIGHT END OF A STRING #MOVE INTO STR3 ALL OF STR1 TO THE RIGHT OF THE END OF STR2(WITHIN STR1) # BUT TRUNCATE STR3 TO 'MAX' CHARS (AND SET ERROR) IF NECESSARY. # THE VALUE OF THE FUNCTION IS RETURNED AS THE ACUTAL NEW LENGTH OF STR3 # STR3 IS NULL IF STR2 IS NOT FOUND WITHIN STR1. # IF STR2 IS NULL, ALL OF STR1 GOES TO STR3. # INTEGER FUNCTION SPOSTV (STR1, STR2, STR3, MAX, ERROR) # INTEGER MAX, ERROR, I, SCOPY, SINDX, SLEN CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE), STR3(DUMMYSIZE) # I=SINDX (STR1, STR2) #FIND STR2 IN STR1 IF (I <= 0) [ #IF IT'S NOT THERE, STR3(1)=EOS #STR3 IS NULL BY DEFINITION ERROR=NO SPOSTV=0 ] ELSE [ I=I+SLEN(STR2) SPOSTV=SCOPY(STR1(I), STR3, MAX, ERROR) ] # RETURN END # # SPREFX - SEPERATE OUT A PREFIX #MOVE INTO STR3 THAT PART OF STR1 WHICH IS TO THE LEFT OF THE FIRST CHAR ALSO # FOUND (ANYWHERE) IN STR2. MOVE INTO STR4 THE REST OF STR1. STR3 AND STR4 ARE # NEW STRINGS. THE LEFTMOST OCCURRANCE IN STR1 OF ANY CHAR IN STR2 IS THE # "BREAK POINT". THE PIVOT CHARACTER GOES INTO STR4. # IF NONE IS FOUND IN STR2, ALL OF STR1 IS MOVED INTO STR4 AND STR3 IS NULL. # SUBROUTINE SPREFX (STR1, STR2, STR3, STR4) # INTEGER I, SSAME CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE), STR3(DUMMYSIZE), STR4(DUMMYSIZE) # I=SSAME (STR1, STR2, +1) #FIND CHAR. IN STR2 FROM LEFT IF (I <= 0) I=1 #NOT THERE, SO ALL GOES INTO STR4 CALL SCOMM (I, STR1, STR3, STR4) #MOVE LEFT AND RIGHT PARTS # RETURN END # # SPREV - SELECT THE LEFT END OF A STRING #MOVE THE PART OF STR1 BEFORE THE START OF STR2 INTO STR3. # TRUNCATE STR3 TO 'MAX' CHARS (AND SET ERROR) IF NECESSARY. # THE VALUE OF THE FUNCTION IS RETURNED AS THE LENGTH OF STR3. # STR3 IS NULL IF STR2 IS NOT FOUND WITHIN STR1. # IF STR2 IS NULL, ALL OF STR1 GOES TO STR3. # INTEGER FUNCTION SPREV (STR1, STR2, STR3, MAX, ERROR) # INTEGER MAX, ERROR, I, SINDX, SMOVE CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE), STR3(DUMMYSIZE) # I=SINDX (STR1, STR2) IF (I <= 0) [ #STR2 MUST BE THERE STR3(1)=EOS #OR STR3 IS NULL ERROR=NO SPREV=0 ] ELSE [ DECREMENT (I) IF (I <= MAX) ERROR=NO ELSE [ I=MAX #TRUNCATE LENGTH OF TRANSFER ERROR=YES ] SPREV=SMOVE (STR1, 1, I, STR3, 1) STR3(SPREV+1)=EOS ] # RETURN END # # SREPT - DUPLICATE A STRING INTO ANOTHER STRING #FILL STR2 WITH 'NUM' CONCATINATED COPIES OF STR1, BUT TRUNCATE # STR2 AT 'MAX' CHAR(AND SET ERROR) IF NECESSARY. # THE VALUE OF THE FUNCTION IS RETURNED AS THE ACUTAL NEW # LENGTH OF STR2. # INTEGER FUNCTION SREPT (STR1, NUM, STR2, MAX, ERROR) # INTEGER NUM, MAX, ERROR, SCOPY, I CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE) # SREPT=0 FOR (I=1; I <= NUM; INCREMENT(I)) [ SREPT=SCOPY (STR1, STR2(SREPT+1), MAX-SREPT, ERROR) + SREPT IF (ERROR == YES) BREAK ] # RETURN END # # SSAME - FIND FIRST CHARACTER IN STR1 ALSO IN STR2 #SCAN STR1 FROM LEFT TO RIGHT (IF LORR IS >0) OR FROM RIGHT TO LEFT # (IF LTOR IS <0) AND RETURN THE VALUE OF THE FUNCTION AS THE POSITION # IN STR1 WHERE THE FIRST CHARACTER IS FOUND THAT IS ALSO ANYWHERE IN STR2, # OR AS 0, IF NO CHARACTERS IN STR1 ARE FOUND IN STR2. # INTEGER FUNCTION SSAME (STR1, STR2, LORR) # INTEGER LORR, SLEN, I CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE) # IF (LORR > 0) SSAME=1 ELSE SSAME=SLEN(STR1) WHILE (SSAME > 0 & STR1(SSAME) != EOS) [ FOR (I=1; STR2(I) != EOS; INCREMENT(I)) IF (STR1(SSAME) == STR2(I)) RETURN #WITH POSITION IN STR1 OF 1ST MATCH IF (LORR > 0) INCREMENT (SSAME) ELSE DECREMENT (SSAME) ] SSAME=0 #NONE MATCHED # RETURN END # # SSAMEX - FIND FIRST CHARACTER IN STR1 NOT ALSO IN STR2 #SCAN STR1 FROM THE LEFT (IF LORR > 0) OR FROM THE RIGHT (IF LOOR <0) # AND RETURN THE VALUE OF THE FUNCTION AS THE LOCATION WITHIN STR1 OF # THE FIRST CHARACTER NOT FOUND (ANYWHERE) IN STR2 , OR AS 0, # IF EVERYTHING IN STR1 IS IN STR2. # INTEGER FUNCTION SSAMEX (STR1, STR2, LOOR) # INTEGER I, LOOR, SLEN CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE) # IF (LORR > 0) SSAMEX=1 ELSE SSAMEX=SLEN(STR1) WHILE (SSAMEX > 0 & STR1(SSAMEX) != EOS) [ FOR (I=1; STR2(I) != EOS; INCREMENT(I)) IF (STR1(SSAMEX) == STR2(I)) BREAK #FOUND THIS CHAR. IF (STR2(I) == EOS) #IT WAS NOT IN STR2 RETURN #SO RETURN WITH IT ELSE #CONTINUE IF (LORR > 0) INCREMENT (SSAMEX) ELSE DECREMENT (SSAMEX) ] SSAMEX=0 #EVERYTHING IN STR1 IS IN STR2 # RETURN END # # SSUFX - SEPERATE OUT A SUFFEX #MOVE CHARACTERS FROM STR1 INTO STR3 WHICH ARE TO THE RIGHT OF THE FIRST # OCCURANCE OF ANY CHARACTER FROM STR2 IN STR1, SCANNING RIGHT-TO-LEFT. # MOVE THE REMAINDER OF STR1 INTO STR4. FIRST CHARACTER IN STR1 TO MATCH # ANY CHARACTER IN STR2 IS THE "BREAK CHAR", AND IT GOES INTO STR4. # IF NONE IS FOUND IS STR2, ALL OF STR1 GOES INTO STR4 AND STR3 IS NULL. # SUBROUTINE SSUFX (STR1, STR2, STR3, STR4) # INTEGER I, SSAME, SLEN CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE), STR3(DUMMYSIZE), STR4(DUMMYSIZE) # I=SSAME (STR1, STR2, -1) #SEARCH FROM RIGHT IF (I <= 0) I=SLEN(STR1) #NO MATCH FOUND, STR3 IS NULL INCREMENT (I) # CALL SCOMM(I, STR1, STR4, STR3) #TRANSFER RIGHT & LEFT PARTS # RETURN END # # SSWAP - EXCHANGE PART OF A STRING FOR ANOTHER STRING #MOVE STR1 INTO STR4, EXCEPT THAT THE PART OF STR1 THAT MATCHES STR2 # IS REPLACED BY STR3. THE VALUE OF THE FUNCTION IS RETURNED AS THE # ACTUAL LENGTH OF STR4, OR AS 0, IF STR2 CANNOT BE FOUND. STR4 IS TRUNCATED # TO 'MAX' (AND ERROR IS SET) IF NECESSARY. # ONCE STR4 REACHES 'MAX' LENGTH, SJOIN WILL NOT ADD TO IT. # INTEGER FUNCTION SSWAP (STR1, STR2, STR3, STR4, MAX, ERROR) # INTEGER MAX, ERROR, SINDX, SJOIN, SMOVE, I, SLEN CHARACTER STR1(DUMMYSIZE), STR2(DUMMYSIZE), STR3(DUMMYSIZE), STR4(DUMMYSIZE) # I=SINDX(STR1, STR2) #FIND LOCATION OF STR2 IF (I <= 0) [ STR4(1)=EOS #STR2 WAS NOT THERE SO STR4 IS NULL ERROR=NO SSWAP=0 ] ELSE [ IF (I > MAX) [ # TOO LONG? ERROR=YES I=MAX+1 ] ELSE ERROR=NO SSWAP=SMOVE (STR1, 1, I-1, STR4, 1) #LEFT PART STR4(SSWAP+1)=EOS #MAKE A STRING SSWAP=SJOIN (STR4, STR3, MAX, ERROR) #REPLACEMENT PART I=I+SLEN(STR2) SSWAP=SJOIN(STR4, STR1(I), MAX, ERROR) #RIGHT PART ] # RETURN #WITH SSWAP = LENGTH OF STR4 END # # STRGET - READ A STRING FROM A SPECIFIED LUN # INTEGER FUNCTION STRGET (LUN, STR, MAX) # INTEGER LUN, MAX, N CHARACTER STR(MAX) # READ (LUN,1,END=100,ERR=101) STRGET, (STR(N),N=1,MAX) #RSX!!! 1 FORMAT (Q, 132A1) #RSX!!! STR(STRGET+1)=EOS RETURN # 100 STRGET=EOF STR(1)=EOS RETURN # 101 STRGET=BAD STR(1)=EOS RETURN # END # # STRPUT - WRITE A STRING TO A SPECIFIED LUN # INTEGER FUNCTION STRPUT (LUN, STR) # INTEGER LUN, I, N, SLEN, MIN0 CHARACTER STR(DUMMYSIZE) # I=MIN0 (132,SLEN(STR)) IF (I > 0) [ WRITE (LUN, 1, ERR=11, END=11) (STR(N),N=1,I) 1 FORMAT (1X, 132A1) ] ELSE WRITE (LUN, 1, ERR=11, END=11) #NULL STRPUT=YES RETURN # 11 STRPUT=BAD #ALL ERRORS RETURN END # # STRIM - REMOVE TRAILING BLANKS FROM THE RIGHT END OF A STRING #REMOVE ANY TRAILING BLANKS FROM THE RIGHT OF STR. THE VALUE OF THE # FUNCTION IS RETURNED AS THE NEW LENGTH OF STR. # INTEGER FUNCTION STRIM (STR) # INTEGER SLEN CHARACTER STR(DUMMYSIZE) # STRIM=SLEN(STR) WHILE (STRIM > 0 & STR(STRIM) == BLANK) DECREMENT (STRIM) STR(STRIM+1)=EOS # RETURN END # # TYPE - RETURN LETTER, DIGIT, OR CHARACTER TYPE # SYKES 14 OCT 76, FASTER VERSION # THIS ONE WORKS IF INTERNAL CHAR. SET IS ASCII # CHARFUNC FUNCTION TYPE FUNCSIZE (C) # CHARACTER C, TYPES(75) DATA TYPES/10*DIGIT,7*0,26*LETTER,6*0,26*LETTER/ # IF (C <= LETZ & C >= DIG0) TYPE=TYPES(C-47) ELSE TYPE=0 #NOT LETTER OR DIGIT IF (TYPE == 0) TYPE = C # RETURN END # # UNFOLD - CONVERT A STRING TO UPPER CASE #SYKES 15MAY77 # WORKS ONLY IF INTERNAL CHARACTER SET IS ASCII # SUBROUTINE UNFOLD (STR) # CHARACTER STR(DUMMYSIZE) INTEGER I # DO I=1,HUGE [ IF (STR(I) == EOS) RETURN ELSE IF (STR(I) >= LETA & STR(I) <= LETZ) STR(I)=STR(I)-32 ] # RETURN END