-- Match.mesa
-- modified by McCreight, September 8, 1980 4:30 PM
-- written by McCreight, May 30, 1980 6:08 PM
-- edited by Brotz, March 9, 1981 5:41 PM

DIRECTORY
MatchDefs: FROM "MatchDefs" USING [];

Match: PROGRAM IMPORTS -- nothing -- EXPORTS MatchDefs =
PUBLIC BEGIN

--

IsMatch: PROCEDURE[name,pattern:STRING] RETURNS [BOOLEAN] =
BEGIN -- does the name match the pattern?
patternPos,namePos,patternAnchor,nameAnchor:CARDINAL;

patternAnchor←0; nameAnchor←0; -- where name began matching non-* seg of pattern
patternPos←patternAnchor; namePos←nameAnchor; -- next compare position

DO -- loop for last ’* in pattern.
WHILE patternPos<pattern.length DO
SELECT TRUE FROM
(pattern[patternPos]=’*) =>
BEGIN
patternPos←patternPos+1; patternAnchor←patternPos;
nameAnchor←namePos;
END;

namePos>=name.length => RETURN[FALSE];

(pattern[patternPos]=’#) =>
BEGIN
IF patternPos#0 AND patternPos=patternAnchor
THEN -- first char(s) of * segment
{patternAnchor←patternAnchor+1; nameAnchor←namePos+1};
patternPos←patternPos+1; namePos←namePos+1;
END;

(pattern[patternPos]=’’) AND (patternPos<pattern.length-1) AND
(pattern[patternPos+1]=name[namePos]) => -- quoted character matches
{patternPos←patternPos+2; namePos←namePos+1};

pattern[patternPos]=name[namePos] => -- chars match
{patternPos←patternPos+1; namePos←namePos+1};

ENDCASE =>
BEGIN
IF patternAnchor=0 THEN RETURN[FALSE]; -- char mismatch, no pattern * thus far
patternPos←patternAnchor;
nameAnchor←nameAnchor+1; namePos←nameAnchor
END;
ENDLOOP;

IF namePos>=name.length OR
patternAnchor>=pattern.length THEN -- name finished or pattern ends with *
RETURN[TRUE];

WHILE namePos<name.length DO -- skip trailing .’s or !ddd in name
SELECT name[namePos] FROM
’. => NULL;
’! =>
BEGIN
namePos←namePos+1;
WHILE namePos<name.length DO
SELECT name[namePos] FROM
IN [’0..’9] => NULL;
ENDCASE => EXIT;
namePos←namePos+1;
ENDLOOP;
END;
ENDCASE => EXIT;
namePos←namePos+1;
REPEAT FINISHED => RETURN[TRUE]; -- Trailing stuff was harmless.
ENDLOOP;

IF patternAnchor = 0 THEN RETURN[FALSE]
ELSE {patternPos ← patternAnchor; namePos ← nameAnchor ← nameAnchor + 1};
ENDLOOP;

END; -- IsMatch

--

Capitalize: PROCEDURE[s,capS: STRING] =
BEGIN
c:CHARACTER; i:CARDINAL;
capS.length←s.length;
FOR i IN [0..s.length) DO
c←s[i];
IF c IN [’a..’z]
THEN capS[i]←c-40B
ELSE capS[i]←c;
ENDLOOP;
END;

--

UnCapitalize: PROCEDURE[s,unCapS: STRING] =
BEGIN
c:CHARACTER; i:CARDINAL;
unCapS.length←s.length;
FOR i IN [0..s.length) DO
c←s[i];
IF c IN [’A..’Z]
THEN unCapS[i]←c+40B
ELSE unCapS[i]←c;
ENDLOOP;
END;

-- Main Program
END.