Unified · Split
| @@ -1,3 +1,12 @@ | ||
| 1 | +20070217 | |
| 2 | + repair /appl/lib/libc.b and /appl/lib/libc0.b strncmp implementations (used only by c2l output) [inferno-os issue 9] | |
| 3 | +20070216 | |
| 4 | + add /module/lists.m, /appl/lib/lists.b, and lists(2) | |
| 5 | +20070209 | |
| 6 | + remove debugging -d option to exportfs call in emu/Plan9/devsrv9.c(!) | |
| 7 | +20070206 | |
| 8 | + /appl/svc/auth.sh: replace exit by raise | |
| 9 | + /man/2/styxservers: document replychan and replydirect | |
| 1 | 10 | 20070201 |
| 2 | 11 | update US timezone files to save energy |
| 3 | 12 | 20070131 |
| @@ -113,9 +113,16 @@ strncmp(s1: string, s2: string, n: int): int · 112 unmodified lines | ||
| 113 | 113 | { |
| 114 | 114 | l1 := len s1; |
| 115 | 115 | l2 := len s2; |
| 116 | − for(i := 0; i < l1 && i < l2 && i < n; i++) | |
| 116 | + m := n; | |
| 117 | + if(m > l1) | |
| 118 | + m = l1; | |
| 119 | + if(m > l2) | |
| 120 | + m = l2; | |
| 121 | + for(i := 0; i < m; i++) | |
| 117 | 122 | if(s1[i] != s2[i]) |
| 118 | − return s1[i]-int s2[i]; | |
| 123 | + return s1[i]-s2[i]; | |
| 124 | + if(i == n) | |
| 125 | + return 0; | |
| 119 | 126 | return l1-l2; |
| 120 | 127 | } |
| 121 | 128 | |
| @@ -170,12 +170,20 @@ strcmp(s1: array of byte, s2: array of byte): int · 169 unmodified lines | ||
| 170 | 170 | |
| 171 | 171 | strncmp(s1: array of byte, s2: array of byte, n: int): int |
| 172 | 172 | { |
| 173 | − l1 := strlen(s1); | |
| 174 | − l2 := strlen(s2); | |
| 175 | − for(i := 0; i < l1 && i < l2 && i < n; i++) | |
| 176 | − if(s1[i] != s2[i]) | |
| 177 | − return int s1[i]-int s2[i]; | |
| 178 | − return l1-l2; | |
| 173 | + i1 := i2 := 0; | |
| 174 | + while(n > 0){ | |
| 175 | + c1 := int s1[i1++]; | |
| 176 | + c2 := int s2[i2++]; | |
| 177 | + n--; | |
| 178 | + if(c1 != c2){ | |
| 179 | + if(c1 > c2) | |
| 180 | + return 1; | |
| 181 | + return -1; | |
| 182 | + } | |
| 183 | + if(c1 == 0) | |
| 184 | + break; | |
| 185 | + } | |
| 186 | + return 0; | |
| 179 | 187 | } |
| 180 | 188 | |
| 181 | 189 | strchr(s: array of byte, n: int): array of byte |
| @@ -0,0 +1,131 @@ | ||
| 1 | +implement Lists; | |
| 2 | + | |
| 3 | +include "lists.m"; | |
| 4 | + | |
| 5 | +# these will be more useful when p is a closure | |
| 6 | +allsat[T](p: ref fn(x: T): int, l: list of T): int | |
| 7 | +{ | |
| 8 | + for(; l != nil; l = tl l) | |
| 9 | + if(!p(hd l)) | |
| 10 | + return 0; | |
| 11 | + return 1; | |
| 12 | +} | |
| 13 | + | |
| 14 | +anysat[T](p: ref fn(x: T): int, l: list of T): int | |
| 15 | +{ | |
| 16 | + for(; l != nil; l = tl l) | |
| 17 | + if(p(hd l)) | |
| 18 | + return 1; | |
| 19 | + return 0; | |
| 20 | +} | |
| 21 | + | |
| 22 | +map[T](f: ref fn(x: T): T, l: list of T): list of T | |
| 23 | +{ | |
| 24 | + if(l == nil) | |
| 25 | + return nil; | |
| 26 | + return f(hd l) :: map(f, tl l); | |
| 27 | +} | |
| 28 | + | |
| 29 | +filter[T](p: ref fn(x: T): int, l: list of T): list of T | |
| 30 | +{ | |
| 31 | + if(l == nil) | |
| 32 | + return nil; | |
| 33 | + if(p(hd l)) | |
| 34 | + return hd l :: filter(p, tl l); | |
| 35 | + return filter(p, tl l); | |
| 36 | +} | |
| 37 | + | |
| 38 | +partition[T](p: ref fn(x: T): int, l: list of T): (list of T, list of T) | |
| 39 | +{ | |
| 40 | + l1: list of T; | |
| 41 | + l2: list of T; | |
| 42 | + for(; l != nil; l = tl l) | |
| 43 | + if(p(hd l)) | |
| 44 | + l1 = hd l :: l1; | |
| 45 | + else | |
| 46 | + l2 = hd l :: l2; | |
| 47 | + return (reverse(l1), reverse(l2)); | |
| 48 | +} | |
| 49 | + | |
| 50 | +append[T](l: list of T, x: T): list of T | |
| 51 | +{ | |
| 52 | + # could use the reversing loops instead if this is ever a bottleneck | |
| 53 | + if(l == nil) | |
| 54 | + return x :: nil; | |
| 55 | + return hd l :: append(tl l, x); | |
| 56 | +} | |
| 57 | + | |
| 58 | +concat[T](l: list of T, l2: list of T): list of T | |
| 59 | +{ | |
| 60 | + if(l2 == nil) | |
| 61 | + return l; | |
| 62 | + for(l = reverse(l); l2 != nil; l2 = tl l2) | |
| 63 | + l = hd l2 :: l; | |
| 64 | + return reverse(l); | |
| 65 | +} | |
| 66 | + | |
| 67 | +combine[T](l: list of T, l2: list of T): list of T | |
| 68 | +{ | |
| 69 | + for(; l != nil; l = tl l) | |
| 70 | + l2 = hd l :: l2; | |
| 71 | + return l2; | |
| 72 | +} | |
| 73 | + | |
| 74 | +reverse[T](l: list of T): list of T | |
| 75 | +{ | |
| 76 | + rl: list of T; | |
| 77 | + for(; l != nil; l = tl l) | |
| 78 | + rl = hd l :: rl; | |
| 79 | + return rl; | |
| 80 | +} | |
| 81 | + | |
| 82 | +last[T](l: list of T): T | |
| 83 | +{ | |
| 84 | + # l must not be nil | |
| 85 | + while(tl l != nil) | |
| 86 | + l = tl l; | |
| 87 | + return hd l; | |
| 88 | +} | |
| 89 | + | |
| 90 | +# delete the first instance of x in l | |
| 91 | +delete[T](x: T, l: list of T): list of T | |
| 92 | + for { T => eq: fn(a, b: T): int; } | |
| 93 | +{ | |
| 94 | + o: list of T; | |
| 95 | + for(; l != nil; l = tl l) | |
| 96 | + if(T.eq(x, hd l)){ | |
| 97 | + l = tl l; | |
| 98 | + for(; o != nil; o = tl o) | |
| 99 | + l = hd o :: l; | |
| 100 | + break; | |
| 101 | + } | |
| 102 | + return l; | |
| 103 | +} | |
| 104 | + | |
| 105 | +pair[T1, T2](l1: list of T1, l2: list of T2): list of (T1, T2) | |
| 106 | +{ | |
| 107 | + if(l1 == nil && l2 == nil) | |
| 108 | + return nil; | |
| 109 | + return (hd l1, hd l2) :: pair(tl l1, tl l2); | |
| 110 | +} | |
| 111 | + | |
| 112 | +unpair[T1, T2](l: list of (T1, T2)): (list of T1, list of T2) | |
| 113 | +{ | |
| 114 | + l1: list of T1; | |
| 115 | + l2: list of T2; | |
| 116 | + for(; l != nil; l = tl l){ | |
| 117 | + (v1, v2) := hd l; | |
| 118 | + l1 = v1 :: l1; | |
| 119 | + l2 = v2 :: l2; | |
| 120 | + } | |
| 121 | + return (reverse(l1), reverse(l2)); | |
| 122 | +} | |
| 123 | + | |
| 124 | +ismember[T](x: T, l: list of T): int | |
| 125 | + for { T => eq: fn(a, b: T): int; } | |
| 126 | +{ | |
| 127 | + for(; l != nil; l = tl l) | |
| 128 | + if(T.eq(x, hd l)) | |
| 129 | + return 1; | |
| 130 | + return 0; | |
| 131 | +} | |
Binary file not shown.
Binary file not shown.
Binary file not shown.
| @@ -1 +1 @@ | ||
| 1 | −#define VERSION "Fourth Edition (20070213)" | |
| 1 | +#define VERSION "Fourth Edition (20070217)" | |
| @@ -0,0 +1,185 @@ | ||
| 1 | +.TH LISTS 2 | |
| 2 | +.SH NAME | |
| 3 | +lists: allsat, anysat, append, combine, concat, delete, filter, ismember, last, map, pair, partition, rev, unpair\- list operations | |
| 4 | +.SH SYNOPSIS | |
| 5 | +.EX | |
| 6 | +include "lists.m" | |
| 7 | +lists := load Lists Lists->PATH; | |
| 8 | + | |
| 9 | +append: fn[T](l: list of T, x: T): list of T; | |
| 10 | +combine: fn[T](l1: list of T, l2: list of T): list of T; | |
| 11 | +concat: fn[T](l1: list of T, l2: list of T): list of T; | |
| 12 | +delete: fn[T](x: T, l: list of T): list of T | |
| 13 | + for { T => eq: fn(a, b: T): int; }; | |
| 14 | +ismember: fn[T](x: T, l: list of T): int | |
| 15 | + for { T => eq: fn(a, b: T): int; }; | |
| 16 | +last: fn[T](l: list of T): T; | |
| 17 | +pair: fn[T1, T2](l1: list of T1, l2: list of T2): | |
| 18 | + list of (T1, T2); | |
| 19 | +reverse: fn[T](l: list of T): list of T; | |
| 20 | +unpair: fn[T1, T2](l: list of (T1, T2)): | |
| 21 | + (list of T1, list of T2); | |
| 22 | + | |
| 23 | +allsat: fn[T](p: ref fn(x: T): int, l: list of T): int; | |
| 24 | +anysat: fn[T](p: ref fn(x: T): int, l: list of T): int; | |
| 25 | +filter: fn[T](p: ref fn(x: T): int, l: list of T): list of T; | |
| 26 | +map: fn[T](f: ref fn(x: T): T, l: list of T): list of T; | |
| 27 | +partition: fn[T](p: ref fn(x: T): int, l: list of T): | |
| 28 | + (list of T, list of T); | |
| 29 | +.EE | |
| 30 | +.SH DESCRIPTION | |
| 31 | +The module provides operations on lists of type | |
| 32 | +.IR T , | |
| 33 | +which may be any reference type, or | |
| 34 | +.BR string . | |
| 35 | +Reference types are | |
| 36 | +.BR array , | |
| 37 | +.BR chan , | |
| 38 | +.BR list , | |
| 39 | +.BR module , | |
| 40 | +and | |
| 41 | +.BI ref "adt". | |
| 42 | +None of the operations change their parameter lists: they always return a new list. | |
| 43 | +.PP | |
| 44 | +First, there is a group of common list operations. | |
| 45 | +.PP | |
| 46 | +.B Append | |
| 47 | +returns a new list with the elements of | |
| 48 | +.I l | |
| 49 | +followed by the element | |
| 50 | +.IR x . | |
| 51 | +.PP | |
| 52 | +.B Combine | |
| 53 | +returns a new list that has the elements of both | |
| 54 | +.I l1 | |
| 55 | +and | |
| 56 | +.I l2 | |
| 57 | +in no defined order. | |
| 58 | +.PP | |
| 59 | +.B Concat | |
| 60 | +returns a new list that has the elements of | |
| 61 | +.I l1 | |
| 62 | +followed by the elements of | |
| 63 | +.IR l2 . | |
| 64 | +.PP | |
| 65 | +.B Delete | |
| 66 | +returns a new list in which the first element of | |
| 67 | +.I l | |
| 68 | +that is equal to | |
| 69 | +.I x | |
| 70 | +has been removed (all others remain). | |
| 71 | +.I X | |
| 72 | +must be an adt reference type | |
| 73 | +.I T | |
| 74 | +with an operation | |
| 75 | +.IB T .eq | |
| 76 | +that returns true (non-zero) if two values of type | |
| 77 | +.I T | |
| 78 | +are considered equal. | |
| 79 | +.PP | |
| 80 | +.B Ismember | |
| 81 | +returns 1 if | |
| 82 | +there is an element of | |
| 83 | +.I l | |
| 84 | +that is equal to | |
| 85 | +.IR x . | |
| 86 | +.PP | |
| 87 | +.B Last | |
| 88 | +returns the value of the element at the end of list | |
| 89 | +.IR l . | |
| 90 | +A run-time error occurs if | |
| 91 | +.I l | |
| 92 | +is nil. | |
| 93 | +.PP | |
| 94 | +.B Pair | |
| 95 | +takes two lists | |
| 96 | +.I l1 | |
| 97 | +and | |
| 98 | +.IR l2 , | |
| 99 | +and returns a new list of tuples | |
| 100 | +.BI ( v1,\ v2 ) | |
| 101 | +in which each element of | |
| 102 | +.I l1 | |
| 103 | +has been paired with the corresponding element of | |
| 104 | +.IR l2 . | |
| 105 | +A run-time error occurs if the lists are not equal in length. | |
| 106 | +.PP | |
| 107 | +.B Reverse | |
| 108 | +returns a new list containing the elements of | |
| 109 | +.I l | |
| 110 | +in reverse order. | |
| 111 | +.PP | |
| 112 | +.B Unpair | |
| 113 | +takes a list of tuples | |
| 114 | +.BI ( v1,\ v2 ) | |
| 115 | +and returns a tuple of lists | |
| 116 | +.BI ( l1,\ l2 ) | |
| 117 | +where | |
| 118 | +.I l1 | |
| 119 | +contains the first element of each tuple, and | |
| 120 | +.I l2 | |
| 121 | +contains the second element of each tuple. | |
| 122 | +.PP | |
| 123 | +A second group of operations applies a function | |
| 124 | +.I f | |
| 125 | +or a Boolean predicate | |
| 126 | +.I p | |
| 127 | +to each element of a list | |
| 128 | +.IR l , | |
| 129 | +returning a transformed list or a Boolean value. | |
| 130 | +A predicate | |
| 131 | +.I p | |
| 132 | +must return non-zero if its parameter value satisfies its condition, and must return zero if it does not. | |
| 133 | +.PP | |
| 134 | +.B Allsat | |
| 135 | +returns 1 if all elements of | |
| 136 | +.I l | |
| 137 | +satisfy | |
| 138 | +.IR p , | |
| 139 | +and returns 0 otherwise. | |
| 140 | +.PP | |
| 141 | +.B Anyset | |
| 142 | +returns 1 if any element of | |
| 143 | +.I l | |
| 144 | +satisfies | |
| 145 | +.IR p , | |
| 146 | +and returns 0 otherwise. | |
| 147 | +.PP | |
| 148 | +.B Filter | |
| 149 | +returns a new list containing only the elements of | |
| 150 | +.I l | |
| 151 | +that satisfy | |
| 152 | +.IR p . | |
| 153 | +.PP | |
| 154 | +.B Map | |
| 155 | +returns a new list in which each element of | |
| 156 | +.I l | |
| 157 | +has been transformed by | |
| 158 | +.I f | |
| 159 | +(ie, if | |
| 160 | +.I l | |
| 161 | +is | |
| 162 | +.IB e0 :: e1 :: ... | |
| 163 | +then the result is | |
| 164 | +.IB f(e0) :: f(e1) :: ... ). | |
| 165 | +.PP | |
| 166 | +.B Partition | |
| 167 | +returns a tuple of lists | |
| 168 | +.BI ( l1,\ l2 ) | |
| 169 | +of lists where | |
| 170 | +.I l1 | |
| 171 | +contains all elements of | |
| 172 | +.I l | |
| 173 | +that satisfy | |
| 174 | +.I p | |
| 175 | +and | |
| 176 | +.I l2 | |
| 177 | +contains all elements of | |
| 178 | +.I l | |
| 179 | +that do not satisfy | |
| 180 | +.IR p . | |
| 181 | +.SH SOURCE | |
| 182 | +.B /appl/lib/lists.b | |
| 183 | +.SH BUGS | |
| 184 | +The current implementation of polymorphism is limited to reference types and strings, | |
| 185 | +which in turn limits use of this module. | |
| @@ -0,0 +1,24 @@ | ||
| 1 | +Lists: module | |
| 2 | +{ | |
| 3 | + map: fn[T](f: ref fn(x: T): T, l: list of T): list of T; | |
| 4 | + allsat: fn[T](p: ref fn(x: T): int, l: list of T): int; | |
| 5 | + anysat: fn[T](p: ref fn(x: T): int, l: list of T): int; | |
| 6 | + filter: fn[T](p: ref fn(x: T): int, l: list of T): list of T; | |
| 7 | + partition: fn[T](p: ref fn(x: T): int, l: list of T): (list of T, list of T); | |
| 8 | + | |
| 9 | + append: fn[T](l: list of T, x: T): list of T; | |
| 10 | + concat: fn[T](l: list of T, l2: list of T): list of T; | |
| 11 | + combine: fn[T](l: list of T, l2: list of T): list of T; | |
| 12 | + reverse: fn[T](l: list of T): list of T; | |
| 13 | + last: fn[T](l: list of T): T; | |
| 14 | + delete: fn[T](x: T, l: list of T): list of T | |
| 15 | + for { T => eq: fn(a, b: T): int; }; | |
| 16 | + pair: fn[T1, T2](l1: list of T1, l2: list of T2): list of (T1, T2); | |
| 17 | + unpair: fn[T1, T2](l: list of (T1, T2)): (list of T1, list of T2); | |
| 18 | + ismember: fn[T](x: T, l: list of T): int | |
| 19 | + for { T => eq: fn(a, b: T): int; }; | |
| 20 | +}; | |
| 21 | + | |
| 22 | +#sort? | |
| 23 | +#join | |
| 24 | +#split | |