home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / CPM / LANGUAGS / MODULA2 / STRLIB.MOD < prev    next >
Text File  |  2000-06-30  |  16KB  |  446 lines

  1. (************************************************************************)
  2. (*       Requires MRI Modula2                                           *)
  3. (*       From JOURNAL OF PASCAL, ADA AND MODULA2                        *)
  4. (*                                                                      *)
  5. (*        Strlib:                                                       *)
  6. (*               Library module to handle strings.  Included is         *)
  7. (*               terminal I/O, string length, assignment, conc-         *)
  8. (*               atention, insertion, deletion, alteration and          *)
  9. (*               the ability to select portions of a string.            *)
  10. (*                                                                      *)
  11. (*       Verson :                                                       *)
  12. (*               1.0 ; November 16, 83 ;   Namir C. Shammas             *)
  13. (*               1.1 ; November 21, 84 ;   Walter Maner                 *)
  14. (*                                                                      *)
  15. (************************************************************************)
  16.  
  17.  
  18. IMPLEMENTATION MODULE Strlib;
  19.  
  20. FROM Terminal IMPORT WriteString,WriteLn,Write,Read;
  21. FROM InOut IMPORT ReadCard,WriteCard;
  22.  
  23. PROCEDURE Len(Str : ARRAY OF CHAR):CARDINAL;
  24.  
  25. (* Returns the length of the string *)
  26.  
  27. VAR  i : CARDINAL;
  28.  Found : BOOLEAN;
  29. BEGIN
  30.     i := 0; Found :=FALSE;
  31.  
  32. (* Scan the string until the eos is found *)
  33.  
  34.     WHILE (NOT Found) AND (i <= HIGH(Str)) DO
  35.         IF Str[i] = eos THEN Found := TRUE 
  36.                         ELSE INC(i)
  37.         END;
  38.     END;
  39.     RETURN i
  40. END Len;
  41.  
  42. PROCEDURE StringIs (VAR Str1 : ARRAY OF CHAR; Str2 : ARRAY OF CHAR);
  43.  
  44. (* Procedure will assign string Str2 to string Str1 *)
  45.  
  46. VAR 
  47.    i,long1,long2 : CARDINAL;
  48. BEGIN
  49.  
  50. (* Obtain the length of both strings Str1 & Str2 *)
  51.     long1 := Len(Str1);
  52.     long2 := Len(Str2);
  53.  
  54. (* If string Str2 if too long pick up only the portion that will *)
  55. (* fit  in string Str1.                                          *)
  56.     IF long2 > (HIGH(Str1)+1) THEN long2 := HIGH(Str1)+1 END;
  57.     FOR i := 0 TO (long2-1) DO
  58.         Str1[i] := Str2[i]
  59.     END;
  60.  
  61. (* Put the eos if string Str1 is not full to capacity *)
  62.     IF HIGH(Str1) # (long2-1) THEN Str1[long2] := eos END;
  63. END StringIs;
  64.  
  65. PROCEDURE ShowString(Str : ARRAY OF CHAR );
  66.  
  67. (* Procedure to display a string on the console *)
  68.  
  69. VAR i,long : CARDINAL;
  70. BEGIN
  71.     long := Len(Str);
  72.     FOR i := 0 TO (long-1) DO
  73.         Write(Str[i]);
  74.     END;
  75. END ShowString;
  76.  
  77. PROCEDURE StringAdd (VAR Str1 : ARRAY OF CHAR; Str2 : ARRAY OF CHAR );
  78.  
  79. (* Procedure to concatenate two strings such that,                 *)
  80. (*                     Str1 = Str1 + Str2                          *)
  81. (*                                                                 *)
  82. (*-----------------------------------------------------------------*)
  83. (*  Error Handling : If Str2 will be concatenated to strign Str1   *)
  84. (*  in as much "free space" is availble.                           *)
  85. (*-----------------------------------------------------------------*)
  86.  
  87.  
  88. VAR 
  89.     i,long1,long2, hi : CARDINAL;
  90. BEGIN
  91.  
  92. (* Obtain the length of the strings  *)
  93.     hi := HIGH(Str1);
  94.     long1 := Len(Str1);
  95.     long2 := Len(Str2);
  96.  
  97. (* If string Str2 if too long pick up only the portion that will *)
  98. (* fit  in string Str1.                                          *)  
  99.     IF (long1+long2-1) > hi THEN long2 := hi - long1 + 1 END;
  100.         FOR i := 0 TO (long2-1) DO
  101.             Str1[i+long1] := Str2[i]
  102.         END;
  103.  
  104. (* Put the eos if string Str1 is not full to capacity *)
  105.         IF hi # (long1+long2-1) THEN Str1[long1+long2] := eos END;
  106. END StringAdd;
  107.  
  108. PROCEDURE StringDelete(VAR Str : ARRAY OF CHAR ; First,Last : CARDINAL);
  109.  
  110. (* Procedure to delete a portion of a string by specifying the first *)
  111. (* and last character by position.                                   *)
  112. (*                                                                   *)
  113. (*-------------------------------------------------------------------*)
  114. (*  Error Handling :                                                 *)
  115. (*                                                                   *)
  116. (*  (1) If Fisrt is greater than the string length, string Str will  *)
  117. (*      remain intact.                                               *)
  118. (*  (2) If Last is graeter than the string length, string Str will   *)
  119. (*      end at position Last.                                        *)
  120. (*-------------------------------------------------------------------*)
  121.  
  122.  
  123. VAR i,long : CARDINAL;
  124. BEGIN
  125.     long := Len(Str);
  126.  
  127. (* If the first character is greater than the string length ignore   *)
  128. (* the Procedure altogether.                                         *)
  129.  
  130.     IF First < long THEN
  131.  
  132.  
  133.        IF Last >= long (* Check if the last character *)
  134.                        (* position is within limits.  *)
  135.               THEN
  136.         Str[First] := eos
  137.  
  138.               ELSE (* Delete up to the last character *)
  139.                 FOR i := Last TO (long-1) DO
  140.             Str[First+i-Last-1] := Str[i]
  141.         END;
  142.  
  143.         (* Put the eos if string Str1 *)
  144.         Str[long+First-Last-1] := eos
  145.        END;
  146.     END;
  147. END StringDelete;    
  148.  
  149. PROCEDURE StringPos(Str1,Str2 : ARRAY OF CHAR ; Start : CARDINAL):CARDINAL;
  150.  
  151. (* Returns the position where the sub-string Str2 occurs within string *)
  152. (* starting at positon 'Start' Str1.                                   *)
  153. (*                                                                     *)
  154. (*---------------------------------------------------------------------*)
  155. (*  Error Handling :                                                   *)
  156. (*  (1) If Str2 is bigger than Str1 to begin with, then there can be   *)
  157. (*      no matching of Str2 in Str1.                                   *)
  158. (*  (2) If Start is greater than the length of Str1 then return zero   *)
  159. (*      as a result.                                                   *)
  160. (*---------------------------------------------------------------------*)
  161.  
  162.  
  163. VAR 
  164.     long1,long2,ptr1,ptr2,last : CARDINAL;
  165.     Found : BOOLEAN;
  166.     
  167. BEGIN
  168.  
  169. (* Initialize and obtain string lengths *)
  170.     IF Start = 0 THEN Start := 1 END;
  171.     ptr1 := Start-1; ptr2 :=0; last := ptr1;
  172.     Found := FALSE;
  173.     long1 := Len(Str1);
  174.     long2 := Len(Str2);
  175. (* Peform the function if the sub-string is indeed the smaller *)
  176.     IF (long1 >= long2) AND (Start <= (long1-1)) THEN
  177.         REPEAT    
  178.             IF Str1[ptr1] = Str2[ptr2]
  179.                 THEN
  180.                     IF ptr2 = 0 THEN last := ptr1 END;
  181.                     IF ptr2 = long2-1 
  182.                           THEN 
  183.                         Found := TRUE
  184.                           ELSE        
  185.                         INC(ptr2)
  186.                     END;    
  187.                 ELSE
  188.                     IF ptr2 > 0 THEN ptr1 := last; ptr2 := 0 END;
  189.             END;
  190.             INC(ptr1)
  191.         UNTIL (Found = TRUE) OR (ptr1 >= long1-1);
  192.     END; 
  193. (* Return zero if there was no match.                          *)
  194.     IF NOT Found THEN ptr1 := 0 
  195.              ELSE DEC(ptr1,long2-1)
  196.     END;
  197.     RETURN ptr1        
  198. END StringPos;
  199.  
  200. PROCEDURE StringLeft(VAR Str1 : ARRAY OF CHAR ;
  201.                          Str2 : ARRAY OF CHAR; Count : CARDINAL);
  202.  
  203. (* Procedure will return the 'Count' leftmost characters of string *)
  204. (* Str2 and save the result in string Str1.                        *)
  205. (*                                                                 *)
  206. (*-----------------------------------------------------------------*)
  207. (*  Error Handling :                                               *)
  208. (* (1) If Count = 0 then reassugn Count as 1.                      *)
  209. (* (2) If Count is greater than the string length then adjust it   *)
  210. (*     to equal the latter.                                        *)
  211. (*-----------------------------------------------------------------*)
  212.  
  213. VAR long : CARDINAL;
  214.  
  215. BEGIN
  216.  
  217.     StringIs(Str1,Str2);
  218.     long := Len(Str1) - 1;
  219.     IF Count = 1 THEN Count := 1 END;
  220.     IF Count > long THEN Count := long END;
  221.     IF Count <> long THEN
  222.           Str1[Count] := eos
  223.     END;
  224. END StringLeft;
  225.  
  226. PROCEDURE StringRight(VAR Str1 : ARRAY OF CHAR ;
  227.                           Str2 : ARRAY OF CHAR;  Count : CARDINAL);
  228.  
  229. (* Procedure will return the 'Count' rightmost characters of string *)
  230. (* Str2 and save the result in string Str1.                         *)
  231. (*                                                                  *)
  232. (*------------------------------------------------------------------*)
  233. (*  Error Handling : If Count is zero or greater than the string    *)
  234. (*  length then string Str1 will be an exact copy of Str2.          *)
  235. (*------------------------------------------------------------------*)
  236.  
  237. VAR i,long ,used: CARDINAL;
  238. BEGIN
  239.  
  240. (* Copy string Str2 into string Str1 and obtain its length.         *)
  241.     StringIs(Str1,Str2);
  242.     long := Len(Str1);
  243.     IF (Count <= long) AND (Count # 0) THEN 
  244.  
  245. (* Obtain the first character position to relocate string Str1.     *)
  246.         used := long - Count;
  247.         FOR i := 0 TO (Count-1) DO
  248.             Str1[i] := Str1[used+i]
  249.         END;
  250.         Str1[Count] := eos
  251.     END;
  252. END StringRight;
  253.  
  254. PROCEDURE StringMid(VAR Str1 : ARRAY OF CHAR ;
  255.                         Str2 : ARRAY OF CHAR;  Start, Count : CARDINAL);
  256.  
  257. (* Procedure will copy the portion of string Str2 from the character   *)
  258. (* position 'Start' and for 'Count' characters into string Str1.       *)
  259. (*                                                                     *)
  260. (*---------------------------------------------------------------------*)
  261. (*  Error Handling : If the sum of Start and Count is greater than the *)
  262. (*  string length then the resulting string Str1 will be identical to  *)
  263. (*  string Str2.                                                       *)
  264. (*---------------------------------------------------------------------*)
  265.  
  266. VAR i,long : CARDINAL;
  267. BEGIN
  268.     StringIs(Str1,Str2);
  269.     IF Start > 0 THEN DEC(Start) END;
  270.     long := Len(Str1);
  271.     IF (Start + Count) <= long THEN 
  272.         FOR i := Start TO (Start+Count-1) DO
  273.             Str1[i-Start] := Str1[i]
  274.         END;
  275.         IF HIGH(Str1) # Count THEN Str1[Count] := eos END;
  276.     END;
  277. END StringMid;
  278.  
  279. PROCEDURE StringRemove(VAR Str1 : ARRAY OF CHAR; Str2 : ARRAY OF CHAR);
  280.  
  281. (* Procedure to remove all occurences of sub-string Str2 from Str1. *)
  282.  
  283. VAR 
  284.     i,long1,long2,ptr,position,move,high : CARDINAL;
  285.  
  286. BEGIN
  287.     high := HIGH(Str1);
  288.     long1 := Len(Str1);
  289.     long2 := Len(Str2);
  290.     ptr := 1;
  291.     REPEAT 
  292.         position := StringPos(Str1,Str2,ptr);
  293.         IF position # 0 THEN (* Shift characters to overwrite Str2 *)
  294.             ptr := position - 1;
  295.             FOR i := (ptr+long2) TO (long1-1) DO
  296.                 Str1[i-long2] := Str1[i]
  297.             END;
  298.             DEC(long1,long2);
  299.             Str1[long1] := eos;
  300.         END;
  301.     UNTIL position = 0; (* Cannot find any more sub-strings *)
  302. END StringRemove;
  303.  
  304. PROCEDURE StringInsert(VAR Str1 : ARRAY OF CHAR; Str2 : ARRAY OF CHAR; 
  305.                           Start : CARDINAL);
  306.  
  307. (* Procedure will insert string Str2 in Str1 at the character *)
  308. (* position 'Start' of string Str1.                           *)
  309. (*                                                            *)
  310. (*------------------------------------------------------------*)
  311. (*  Error Handling : If there no room for string Str2 to be   *)
  312. (*  inserted entirely string Str1 will remain intact.         *)
  313. (*------------------------------------------------------------*)
  314.  
  315. VAR
  316.    i,long1,long2 : CARDINAL;
  317. BEGIN
  318.         DEC(Start);
  319.         long1 := Len(Str1);
  320.         long2 := Len(Str2);
  321.         IF (long1+long2-1) <= HIGH(Str1) THEN 
  322.  
  323. (* Relocate portions of Str1 to make way for string Str2.      *)
  324.                 FOR i := (long1-1) TO Start BY -1 DO
  325.                         Str1[i+long2] := Str1[i]
  326.                 END;
  327.  
  328. (* Copy string Str2 into the reserved loaction of string Str1. *)
  329.                 FOR i := Start TO (Start+long2-1) DO
  330.                         Str1[i] := Str2[i-Start]
  331.                 END;
  332.                 INC(long1,long2);
  333.                 IF (long1-1) < HIGH(Str1) THEN Str1[long1] := eos END;
  334.         END;                
  335. END StringInsert;
  336.  
  337. PROCEDURE StringReplace(VAR Str1 : ARRAY OF CHAR; Str2,Str3 : ARRAY OF CHAR);
  338.  
  339. (* Procedure will replace all occurences of sub-string Str2, in string *)
  340. (* Str1, by sub-string Str3.                                           *)
  341.  
  342. VAR 
  343.     i,long1,long2,long3,ptr,pos,Stringhigh : CARDINAL;
  344. BEGIN
  345.     long1 := Len(Str1);
  346.     long2 := Len(Str2);
  347.     long3 := Len(Str3);
  348.     ptr := 1;
  349.     Stringhigh := HIGH(Str1)+1;
  350.     REPEAT
  351.         pos := StringPos(Str1,Str2,ptr);
  352.         IF pos # 0 THEN
  353.             ptr := pos;
  354.             StringDelete(Str1,ptr,(ptr+long2-1));
  355.             StringInsert(Str1,Str3,ptr);
  356.             long1 := long1 - long2 + long3;
  357.             IF long1 = Stringhigh THEN pos :=0
  358.                                   ELSE Str1[long1] := eos
  359.             END;
  360.         END;
  361.     UNTIL pos = 0;
  362. END StringReplace;
  363.  
  364. PROCEDURE StringChange(VAR Str1 : ARRAY OF CHAR; Str2,Str3 : ARRAY OF CHAR;
  365.                            Start,Repeat:CARDINAL);
  366.  
  367. (* Procedure will replace sub-string Str2 with Str3 in string Str1 *)
  368. (* start at character position 'Start' and for 'Repeat' times.     *)
  369.  
  370. VAR 
  371.     i,long1,long2,long3,ptr,pos,Stringhigh : CARDINAL;
  372. BEGIN
  373.     long1 := Len(Str1);
  374.     long2 := Len(Str2);
  375.     long3 := Len(Str3);
  376.     ptr := Start;
  377.     Stringhigh := HIGH(Str1)+1;
  378.     REPEAT
  379.         pos := StringPos(Str1,Str2,ptr);
  380.         IF pos # 0 THEN
  381.             ptr := pos;
  382.             StringDelete(Str1,ptr,(ptr+long2-1));
  383.             StringInsert(Str1,Str3,ptr);
  384.             long1 := long1 - long2 + long3;
  385.             IF long1 = Stringhigh THEN pos :=0
  386.                                   ELSE Str1[long1] := eos
  387.             END;
  388.         DEC(Repeat);
  389.         END;
  390.     UNTIL pos*Repeat = 0;
  391. END StringChange;
  392.  
  393. PROCEDURE StringAlter(VAR Str1 : ARRAY OF CHAR; Str2 : ARRAY OF CHAR; 
  394.                                 Start : CARDINAL);
  395.  
  396. (* Procedure will overwrite string Str1 with sub-string Str2 starting *)
  397. (* at position 'Start'.                                               *)
  398. (*                                                                    *)
  399. (*--------------------------------------------------------------------*)
  400. (*  Error Handling : If there is no room for string Str2 to fit in    *)
  401. (*  its entirey string Str1 will remain intact.                       *)
  402. (*--------------------------------------------------------------------*)
  403.  
  404. VAR
  405.     i,long,ptr : CARDINAL;
  406. BEGIN
  407.     DEC(Start);
  408.     long := Len(Str2);
  409.     IF (Start+long-1) <= HIGH(Str1) THEN 
  410.         FOR i := Start TO (Start+long-1) DO
  411.             Str1[i] := Str2[i-Start]
  412.         END;
  413.     END;
  414. END StringAlter;
  415.  
  416. PROCEDURE InputString (VAR Str : ARRAY OF CHAR);
  417.  
  418. (* Read string from the keyboard.                                    *)
  419.  
  420. VAR 
  421.     i,high : CARDINAL;
  422.     ch : CHAR;
  423. BEGIN
  424.     high := HIGH(Str);
  425.     i := 0;
  426.     REPEAT
  427.         Read(ch);
  428.         Write(ch);
  429.         IF ch # CHAR(177C)
  430.                 THEN 
  431.                     Str[i] := ch;
  432.                     INC(i)
  433.                 ELSE
  434.                     Write(' ');
  435.                     Write(ch);
  436.                     IF i > 0 THEN DEC(i) END;
  437.         END;
  438.     UNTIL (ch = CHAR(36C)) OR (i > high);
  439.     IF i <= high THEN 
  440.            DEC(i);
  441.            Str[i] := eos
  442.     END;
  443. END InputString;
  444.  
  445. END Strlib.
  446.