1# 2# Expression evaluation. 3# 4 5# 6# Filename pattern matching. 7# 8glob(e: ref Env, s: string): (string, list of string) 9{ 10 if (filepat == nil) { 11 filepat = load Filepat Filepat->PATH; 12 if (filepat == nil) 13 e.couldnot("load", Filepat->PATH); 14 } 15 l := filepat->expand(s); 16 if (l != nil) 17 return (nil, l); 18 return (s, nil); 19} 20 21# 22# RE pattern matching. 23# 24match(s1, s2: string): int 25{ 26 (re, nil) := regex->compile(s2, 0); 27 return regex->execute(re, s1) != nil; 28} 29 30# 31# RE match of two lists. Two non-singleton lists never match. 32# 33match2(e: ref Env, s1: string, l1: list of string, s2: string, l2: list of string): int 34{ 35 if (regex == nil) { 36 regex = load Regex Regex->PATH; 37 if (regex == nil) 38 e.couldnot("load", Regex->PATH); 39 } 40 if (s1 != nil) { 41 if (s2 != nil) 42 return match(s1, s2); 43 while (l2 != nil) { 44 if (match(s1, hd l2)) 45 return 1; 46 l2 = tl l2; 47 } 48 } else if (l1 != nil) { 49 if (s2 == nil) 50 return 0; 51 while (l1 != nil) { 52 if (match(hd l1, s2)) 53 return 1; 54 l1 = tl l1; 55 } 56 } else if (s2 != nil) 57 return match(nil, s2); 58 else if (l2 != nil) { 59 while (l2 != nil) { 60 if (match(nil, hd l2)) 61 return 1; 62 l2 = tl l2; 63 } 64 } else 65 return 1; 66 return 0; 67} 68 69# 70# Test list equality. Same length and identical members. 71# 72eqlist(l1, l2: list of string): int 73{ 74 while (l1 != nil && l2 != nil) { 75 if (hd l1 != hd l2) 76 return 0; 77 l1 = tl l1; 78 l2 = tl l2; 79 } 80 return l1 == nil && l2 == nil; 81} 82 83# 84# Equality operator. 85# 86Cmd.evaleq(c: self ref Cmd, e: ref Env): int 87{ 88 (s1, l1, nil) := c.left.eeval2(e); 89 (s2, l2, nil) := c.right.eeval2(e); 90 if (s1 != nil) 91 return s1 == s2; 92 if (l1 != nil) 93 return eqlist(l1, l2); 94 return s2 == nil && l2 == nil; 95} 96 97# 98# Match operator. 99# 100Cmd.evalmatch(c: self ref Cmd, e: ref Env): int 101{ 102 (s1, l1, nil) := c.left.eeval2(e); 103 (s2, l2, nil) := c.right.eeval2(e); 104 return match2(e, s1, l1, s2, l2); 105} 106 107# 108# Catenation operator. 109# 110Item.caret(i: self ref Item, e: ref Env): (string, list of string, int) 111{ 112 (s1, l1, x1) := i.left.ieval2(e); 113 (s2, l2, x2) := i.right.ieval2(e); 114 return caret(s1, l1, x1, s2, l2, x2); 115} 116 117# 118# Caret of lists. A singleton distributes. Otherwise pairwise, padded with nils. 119# 120caret(s1: string, l1: list of string, x1: int, s2: string, l2: list of string, x2: int): (string, list of string, int) 121{ 122 l: list of string; 123 if (s1 != nil) { 124 if (s2 != nil) 125 return (s1 + s2, nil, x1 | x2); 126 if (l2 == nil) 127 return (s1, nil, x1); 128 while (l2 != nil) { 129 l = (s1 + hd l2) :: l; 130 l2 = tl l2; 131 } 132 } else if (s2 != nil) { 133 if (l1 == nil) 134 return (s2, nil, x2); 135 while (l1 != nil) { 136 l = (hd l1 + s2) :: l; 137 l1 = tl l1; 138 } 139 } else if (l1 != nil) { 140 if (l2 == nil) 141 return (nil, l1, 0); 142 while (l1 != nil || l2 != nil) { 143 if (l1 != nil) { 144 s1 = hd l1; 145 l1 = tl l1; 146 } else 147 s1 = nil; 148 if (l2 != nil) { 149 s2 = hd l2; 150 l2 = tl l2; 151 } else 152 s2 = nil; 153 l = (s1 + s2) :: l; 154 } 155 } else if (l2 != nil) 156 return (nil, l2, 0); 157 return (nil, revstrs(l), 0); 158} 159