-- Match.mesa
-- modified by McCreight, September 8, 1980 4:30 PM
-- written by McCreight, May 30, 1980 6:08 PM
-- edited by Brotz, November 19, 1981 9:59 AM

DIRECTORY
MatchDefs USING [];

Match: PROGRAM
EXPORTS MatchDefs =

BEGIN


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

patternAnchor ← 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] = ’* =>
{patternAnchor ← patternPos ← patternPos + 1; nameAnchor ← namePos};
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 * yet.
patternPos ← patternAnchor;
namePos ← nameAnchor ← nameAnchor + 1;
END;
ENDLOOP;

IF namePos >= name.length OR patternAnchor >= pattern.length THEN
RETURN[TRUE]; -- name finished or pattern ends with * --
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; -- of IsMatch --


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


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


END. -- of Match --