137da2899SCharles.Forsythimplement String; 2*a584e848SCharles.Forsyth 337da2899SCharles.Forsythinclude "string.m"; 437da2899SCharles.Forsyth 537da2899SCharles.Forsythsplitl(s: string, cl: string): (string, string) 637da2899SCharles.Forsyth{ 737da2899SCharles.Forsyth n := len s; 837da2899SCharles.Forsyth for(j := 0; j < n; j++) { 937da2899SCharles.Forsyth if(in(s[j], cl)) 1037da2899SCharles.Forsyth return (s[0:j], s[j:n]); 1137da2899SCharles.Forsyth } 1237da2899SCharles.Forsyth return (s,""); 1337da2899SCharles.Forsyth} 1437da2899SCharles.Forsyth 1537da2899SCharles.Forsythsplitr(s: string, cl: string): (string, string) 1637da2899SCharles.Forsyth{ 1737da2899SCharles.Forsyth n := len s; 1837da2899SCharles.Forsyth for(j := n-1; j >= 0; j--) { 1937da2899SCharles.Forsyth if(in(s[j], cl)) 2037da2899SCharles.Forsyth return (s[0:j+1], s[j+1:n]); 2137da2899SCharles.Forsyth } 2237da2899SCharles.Forsyth return ("",s); 2337da2899SCharles.Forsyth} 2437da2899SCharles.Forsyth 2537da2899SCharles.Forsythdrop(s: string, cl: string): string 2637da2899SCharles.Forsyth{ 2737da2899SCharles.Forsyth n := len s; 2837da2899SCharles.Forsyth for(j := 0; j < n; j++) { 2937da2899SCharles.Forsyth if(!in(s[j], cl)) 3037da2899SCharles.Forsyth return (s[j:n]); 3137da2899SCharles.Forsyth } 3237da2899SCharles.Forsyth return ""; 3337da2899SCharles.Forsyth} 3437da2899SCharles.Forsyth 3537da2899SCharles.Forsythtake(s: string, cl: string): string 3637da2899SCharles.Forsyth{ 3737da2899SCharles.Forsyth n := len s; 3837da2899SCharles.Forsyth for(j := 0; j < n; j++) { 3937da2899SCharles.Forsyth if(!in(s[j], cl)) 4037da2899SCharles.Forsyth return (s[0:j]); 4137da2899SCharles.Forsyth } 4237da2899SCharles.Forsyth return s; 4337da2899SCharles.Forsyth} 4437da2899SCharles.Forsyth 4537da2899SCharles.Forsythin(c: int, s: string): int 4637da2899SCharles.Forsyth{ 4737da2899SCharles.Forsyth n := len s; 4837da2899SCharles.Forsyth if(n == 0) 4937da2899SCharles.Forsyth return 0; 5037da2899SCharles.Forsyth ans := 0; 5137da2899SCharles.Forsyth negate := 0; 5237da2899SCharles.Forsyth if(s[0] == '^') { 5337da2899SCharles.Forsyth negate = 1; 5437da2899SCharles.Forsyth s = s[1:]; 5537da2899SCharles.Forsyth n--; 5637da2899SCharles.Forsyth } 5737da2899SCharles.Forsyth for(i := 0; i < n; i++) { 5837da2899SCharles.Forsyth if(s[i] == '-' && i > 0 && i < n-1) { 5937da2899SCharles.Forsyth if(c >= s[i-1] && c <= s[i+1]) { 6037da2899SCharles.Forsyth ans = 1; 6137da2899SCharles.Forsyth break; 6237da2899SCharles.Forsyth } 6337da2899SCharles.Forsyth i++; 6437da2899SCharles.Forsyth } 6537da2899SCharles.Forsyth else 6637da2899SCharles.Forsyth if(c == s[i]) { 6737da2899SCharles.Forsyth ans = 1; 6837da2899SCharles.Forsyth break; 6937da2899SCharles.Forsyth } 7037da2899SCharles.Forsyth } 7137da2899SCharles.Forsyth if(negate) 7237da2899SCharles.Forsyth ans = !ans; 7337da2899SCharles.Forsyth return ans; 7437da2899SCharles.Forsyth} 7537da2899SCharles.Forsyth 7637da2899SCharles.Forsythsplitstrl(s: string, t: string): (string, string) 7737da2899SCharles.Forsyth{ 7837da2899SCharles.Forsyth n := len s; 7937da2899SCharles.Forsyth nt := len t; 8037da2899SCharles.Forsyth if(nt == 0) 8137da2899SCharles.Forsyth return ("", s); 8237da2899SCharles.Forsyth c0 := t[0]; 8337da2899SCharles.Forsyth mainloop: 8437da2899SCharles.Forsyth for(j := 0; j <= n-nt; j++) { 8537da2899SCharles.Forsyth if(s[j] == c0) { 8637da2899SCharles.Forsyth for(k := 1; k < nt; k++) 8737da2899SCharles.Forsyth if(s[j+k] != t[k]) 8837da2899SCharles.Forsyth continue mainloop; 8937da2899SCharles.Forsyth return(s[0:j], s[j:n]); 9037da2899SCharles.Forsyth } 9137da2899SCharles.Forsyth } 9237da2899SCharles.Forsyth return (s,""); 9337da2899SCharles.Forsyth} 9437da2899SCharles.Forsyth 9537da2899SCharles.Forsythsplitstrr(s: string, t: string): (string, string) 9637da2899SCharles.Forsyth{ 9737da2899SCharles.Forsyth n := len s; 9837da2899SCharles.Forsyth nt := len t; 9937da2899SCharles.Forsyth if(nt == 0) 10037da2899SCharles.Forsyth return (s, ""); 10137da2899SCharles.Forsyth c0 := t[0]; 10237da2899SCharles.Forsyth mainloop: 10337da2899SCharles.Forsyth for(j := n-nt; j >= 0; j--) { 10437da2899SCharles.Forsyth if(s[j] == c0) { 10537da2899SCharles.Forsyth for(k := 1; k < nt; k++) 10637da2899SCharles.Forsyth if(s[j+k] != t[k]) 10737da2899SCharles.Forsyth continue mainloop; 10837da2899SCharles.Forsyth return(s[0:j+nt], s[j+nt:n]); 10937da2899SCharles.Forsyth } 11037da2899SCharles.Forsyth } 11137da2899SCharles.Forsyth return ("",s); 11237da2899SCharles.Forsyth} 11337da2899SCharles.Forsyth 11437da2899SCharles.Forsythprefix(pre: string, s: string): int 11537da2899SCharles.Forsyth{ 116*a584e848SCharles.Forsyth if(len s < len pre) 11737da2899SCharles.Forsyth return 0; 118*a584e848SCharles.Forsyth for(k := 0; k < len pre; k++) 11937da2899SCharles.Forsyth if(pre[k] != s[k]) 12037da2899SCharles.Forsyth return 0; 12137da2899SCharles.Forsyth return 1; 12237da2899SCharles.Forsyth} 12337da2899SCharles.Forsyth 12437da2899SCharles.Forsythtolower(s: string): string 12537da2899SCharles.Forsyth{ 126*a584e848SCharles.Forsyth for(i := 0; i < len s; i++) { 127*a584e848SCharles.Forsyth c := s[i]; 128*a584e848SCharles.Forsyth if(c >= 'A' && c <= 'Z') 129*a584e848SCharles.Forsyth s[i] += 'a' - 'A'; 13037da2899SCharles.Forsyth } 131*a584e848SCharles.Forsyth return s; 13237da2899SCharles.Forsyth} 13337da2899SCharles.Forsyth 13437da2899SCharles.Forsythtoupper(s: string): string 13537da2899SCharles.Forsyth{ 136*a584e848SCharles.Forsyth for(i := 0; i < len s; i++) { 137*a584e848SCharles.Forsyth c := s[i]; 138*a584e848SCharles.Forsyth if(c >= 'a' && c <= 'z') 139*a584e848SCharles.Forsyth s[i] += 'A' - 'a'; 14037da2899SCharles.Forsyth } 141*a584e848SCharles.Forsyth return s; 14237da2899SCharles.Forsyth} 14337da2899SCharles.Forsyth 144*a584e848SCharles.Forsythstartnum(s: string, base: int): (int, int, int) 14537da2899SCharles.Forsyth{ 146*a584e848SCharles.Forsyth if(s == nil || base != 0 && (base < 2 || base > 36)) 147*a584e848SCharles.Forsyth return (0, 0, 0); 14837da2899SCharles.Forsyth 14937da2899SCharles.Forsyth # skip possible leading white space 150*a584e848SCharles.Forsyth c := ' '; 15137da2899SCharles.Forsyth for (i := 0; i < len s; i++) { 15237da2899SCharles.Forsyth c = s[i]; 15337da2899SCharles.Forsyth if(c != ' ' && c != '\t' && c != '\n') 15437da2899SCharles.Forsyth break; 15537da2899SCharles.Forsyth } 15637da2899SCharles.Forsyth 157*a584e848SCharles.Forsyth # optional sign 15837da2899SCharles.Forsyth neg := 0; 15937da2899SCharles.Forsyth if(c == '-' || c == '+') { 16037da2899SCharles.Forsyth if(c == '-') 16137da2899SCharles.Forsyth neg = 1; 16237da2899SCharles.Forsyth i++; 16337da2899SCharles.Forsyth } 16437da2899SCharles.Forsyth 16537da2899SCharles.Forsyth if(base == 0) { 16637da2899SCharles.Forsyth # parse possible leading base designator 16737da2899SCharles.Forsyth start := i; 16837da2899SCharles.Forsyth base = -1; 16937da2899SCharles.Forsyth for (; i < start+3 && i < len s; i++) { 17037da2899SCharles.Forsyth c = s[i]; 17137da2899SCharles.Forsyth if (c == 'r' && i > start) { 17237da2899SCharles.Forsyth base = int s[start:i]; 17337da2899SCharles.Forsyth i++; 17437da2899SCharles.Forsyth break; 17537da2899SCharles.Forsyth } else if (c < '0' || c > '9') 17637da2899SCharles.Forsyth break; 17737da2899SCharles.Forsyth } 17837da2899SCharles.Forsyth if (base == -1) { 17937da2899SCharles.Forsyth i = start; 18037da2899SCharles.Forsyth base = 10; 18137da2899SCharles.Forsyth } else if (base == 0 || base > 36) 182*a584e848SCharles.Forsyth return (0, 0, i); 183*a584e848SCharles.Forsyth } 184*a584e848SCharles.Forsyth if(i >= len s) 185*a584e848SCharles.Forsyth return (0, 0, 0); 186*a584e848SCharles.Forsyth 187*a584e848SCharles.Forsyth return (base, neg, i); 18837da2899SCharles.Forsyth} 18937da2899SCharles.Forsyth 190*a584e848SCharles.Forsythtobig(s: string, base: int): (big, string) 191*a584e848SCharles.Forsyth{ 192*a584e848SCharles.Forsyth neg, i: int; 193*a584e848SCharles.Forsyth 194*a584e848SCharles.Forsyth (base, neg, i) = startnum(s, base); 195*a584e848SCharles.Forsyth if(base == 0) 196*a584e848SCharles.Forsyth return (big 0, s); 197*a584e848SCharles.Forsyth 19837da2899SCharles.Forsyth # parse number itself. 199*a584e848SCharles.Forsyth # probably this should check for overflow, and max out, as limbo op does? 20037da2899SCharles.Forsyth start := i; 20137da2899SCharles.Forsyth n := big 0; 20237da2899SCharles.Forsyth for (; i < len s; i++) { 203*a584e848SCharles.Forsyth if((d := digit(s[i], base)) < 0) 20437da2899SCharles.Forsyth break; 205*a584e848SCharles.Forsyth n = n*big base + big d; 20637da2899SCharles.Forsyth } 20737da2899SCharles.Forsyth if (i == start) 20837da2899SCharles.Forsyth return (big 0, s); 20937da2899SCharles.Forsyth if (neg) 21037da2899SCharles.Forsyth return (-n, s[i:]); 21137da2899SCharles.Forsyth return (n, s[i:]); 21237da2899SCharles.Forsyth} 21337da2899SCharles.Forsyth 21437da2899SCharles.Forsythtoint(s: string, base: int): (int, string) 21537da2899SCharles.Forsyth{ 216*a584e848SCharles.Forsyth neg, i: int; 217*a584e848SCharles.Forsyth 218*a584e848SCharles.Forsyth (base, neg, i) = startnum(s, base); 219*a584e848SCharles.Forsyth if(base == 0) 22037da2899SCharles.Forsyth return (0, s); 22137da2899SCharles.Forsyth 22237da2899SCharles.Forsyth # parse number itself. 223*a584e848SCharles.Forsyth # probably this should check for overflow, and max out, as limbo op does? 22437da2899SCharles.Forsyth start := i; 22537da2899SCharles.Forsyth n := 0; 22637da2899SCharles.Forsyth for (; i < len s; i++){ 227*a584e848SCharles.Forsyth if((d := digit(s[i], base)) < 0) 22837da2899SCharles.Forsyth break; 229*a584e848SCharles.Forsyth n = n*base + d; 23037da2899SCharles.Forsyth } 23137da2899SCharles.Forsyth if (i == start) 23237da2899SCharles.Forsyth return (0, s); 23337da2899SCharles.Forsyth if (neg) 23437da2899SCharles.Forsyth return (-n, s[i:]); 23537da2899SCharles.Forsyth return (n, s[i:]); 23637da2899SCharles.Forsyth} 23737da2899SCharles.Forsyth 238*a584e848SCharles.Forsythdigit(c: int, base: int): int 239*a584e848SCharles.Forsyth{ 240*a584e848SCharles.Forsyth if ('0' <= c && c <= '0' + base - 1) 241*a584e848SCharles.Forsyth return c-'0'; 242*a584e848SCharles.Forsyth else if ('a' <= c && c < 'a' + base - 10) 243*a584e848SCharles.Forsyth return (c - 'a' + 10); 244*a584e848SCharles.Forsyth else if ('A' <= c && c < 'A' + base - 10) 245*a584e848SCharles.Forsyth return (c - 'A' + 10); 246*a584e848SCharles.Forsyth else 247*a584e848SCharles.Forsyth return -1; 248*a584e848SCharles.Forsyth} 249*a584e848SCharles.Forsyth 250*a584e848SCharles.Forsythrpow(x: real, n: int): real 251*a584e848SCharles.Forsyth{ 252*a584e848SCharles.Forsyth inv := 0; 253*a584e848SCharles.Forsyth if(n < 0){ 254*a584e848SCharles.Forsyth n = -n; 255*a584e848SCharles.Forsyth inv = 1; 256*a584e848SCharles.Forsyth } 257*a584e848SCharles.Forsyth r := 1.0; 258*a584e848SCharles.Forsyth for(;;){ 259*a584e848SCharles.Forsyth if(n&1) 260*a584e848SCharles.Forsyth r *= x; 261*a584e848SCharles.Forsyth if((n >>= 1) == 0) 262*a584e848SCharles.Forsyth break; 263*a584e848SCharles.Forsyth x *= x; 264*a584e848SCharles.Forsyth } 265*a584e848SCharles.Forsyth if(inv) 266*a584e848SCharles.Forsyth r = 1.0/r; 267*a584e848SCharles.Forsyth return r; 268*a584e848SCharles.Forsyth} 269*a584e848SCharles.Forsyth 270*a584e848SCharles.Forsythmatch(p: string, s: string, i: int): int 271*a584e848SCharles.Forsyth{ 272*a584e848SCharles.Forsyth if(i+len p > len s) 273*a584e848SCharles.Forsyth return 0; 274*a584e848SCharles.Forsyth for(j := 0; j < len p; j++){ 275*a584e848SCharles.Forsyth c := s[i++]; 276*a584e848SCharles.Forsyth if(c >= 'A' && c <= 'Z') 277*a584e848SCharles.Forsyth c += 'a'-'A'; 278*a584e848SCharles.Forsyth if(p[j] != c) 279*a584e848SCharles.Forsyth return 0; 280*a584e848SCharles.Forsyth } 281*a584e848SCharles.Forsyth return 1; 282*a584e848SCharles.Forsyth} 283*a584e848SCharles.Forsyth 284*a584e848SCharles.Forsythtoreal(s: string, base: int): (real, string) 285*a584e848SCharles.Forsyth{ 286*a584e848SCharles.Forsyth neg, i: int; 287*a584e848SCharles.Forsyth 288*a584e848SCharles.Forsyth (base, neg, i) = startnum(s, base); 289*a584e848SCharles.Forsyth if(base == 0) 290*a584e848SCharles.Forsyth return (0.0, s); 291*a584e848SCharles.Forsyth 292*a584e848SCharles.Forsyth c := s[i]; 293*a584e848SCharles.Forsyth if((c == 'i' || c == 'I') && match("infinity", s, i)) 294*a584e848SCharles.Forsyth return (real s, s[i+8:]); 295*a584e848SCharles.Forsyth if((c == 'n' || c == 'N') && match("nan", s, i)) 296*a584e848SCharles.Forsyth return (real s, s[i+3:]); 297*a584e848SCharles.Forsyth 298*a584e848SCharles.Forsyth if(digit(c, base) < 0) 299*a584e848SCharles.Forsyth return (0.0, s); 300*a584e848SCharles.Forsyth 301*a584e848SCharles.Forsyth num := 0.0; 302*a584e848SCharles.Forsyth for(; i < len s && (d := digit(s[i], base)) >= 0; i++) 303*a584e848SCharles.Forsyth num = num*real base + real d; 304*a584e848SCharles.Forsyth dig := 0; # digits in fraction 305*a584e848SCharles.Forsyth if(i < len s && s[i] == '.'){ 306*a584e848SCharles.Forsyth i++; 307*a584e848SCharles.Forsyth for(; i < len s && (d = digit(s[i], base)) >= 0; i++){ 308*a584e848SCharles.Forsyth num = num*real base + real d; 309*a584e848SCharles.Forsyth dig++; 310*a584e848SCharles.Forsyth } 311*a584e848SCharles.Forsyth } 312*a584e848SCharles.Forsyth exp := 0; 313*a584e848SCharles.Forsyth eneg := 0; 314*a584e848SCharles.Forsyth if(i < len s && ((c = s[i]) == 'e' || c == 'E')){ 315*a584e848SCharles.Forsyth start := i; # might still be badly formed 316*a584e848SCharles.Forsyth i++; 317*a584e848SCharles.Forsyth if(i < len s && ((c = s[i]) == '-' || c == '+')){ 318*a584e848SCharles.Forsyth i++; 319*a584e848SCharles.Forsyth if(c == '-'){ 320*a584e848SCharles.Forsyth dig = -dig; 321*a584e848SCharles.Forsyth eneg = 1; 322*a584e848SCharles.Forsyth } 323*a584e848SCharles.Forsyth } 324*a584e848SCharles.Forsyth if(i < len s && s[i] >= '0' && s[i] <= '9'){ # exponents are always decimal 325*a584e848SCharles.Forsyth for(; i < len s && (d = digit(s[i], 10)) >= 0; i++) 326*a584e848SCharles.Forsyth exp = exp*base + d; 327*a584e848SCharles.Forsyth }else 328*a584e848SCharles.Forsyth i = start; 329*a584e848SCharles.Forsyth } 330*a584e848SCharles.Forsyth if(base == 10) 331*a584e848SCharles.Forsyth return (real s[0: i], s[i:]); # conversion can be more accurate 332*a584e848SCharles.Forsyth exp -= dig; 333*a584e848SCharles.Forsyth if(exp < 0){ 334*a584e848SCharles.Forsyth exp = -exp; 335*a584e848SCharles.Forsyth eneg = !eneg; 336*a584e848SCharles.Forsyth } 337*a584e848SCharles.Forsyth if(exp < 0 || exp > 19999) 338*a584e848SCharles.Forsyth exp = 19999; # huge but otherwise arbitrary limit 339*a584e848SCharles.Forsyth dem := rpow(real base, exp); 340*a584e848SCharles.Forsyth if(eneg) 341*a584e848SCharles.Forsyth num /= dem; 342*a584e848SCharles.Forsyth else 343*a584e848SCharles.Forsyth num *= dem; 344*a584e848SCharles.Forsyth if(neg) 345*a584e848SCharles.Forsyth return (-num,s[i:]); 346*a584e848SCharles.Forsyth return (num, s[i:]); 347*a584e848SCharles.Forsyth} 348*a584e848SCharles.Forsyth 34937da2899SCharles.Forsythappend(s: string, l: list of string): list of string 35037da2899SCharles.Forsyth{ 35137da2899SCharles.Forsyth t: list of string; 35237da2899SCharles.Forsyth 35337da2899SCharles.Forsyth # Reverse l, prepend s, and reverse result. 35437da2899SCharles.Forsyth while (l != nil) { 35537da2899SCharles.Forsyth t = hd l :: t; 35637da2899SCharles.Forsyth l = tl l; 35737da2899SCharles.Forsyth } 35837da2899SCharles.Forsyth t = s :: t; 35937da2899SCharles.Forsyth do { 36037da2899SCharles.Forsyth l = hd t :: l; 36137da2899SCharles.Forsyth t = tl t; 36237da2899SCharles.Forsyth } while (t != nil); 36337da2899SCharles.Forsyth return l; 36437da2899SCharles.Forsyth} 36537da2899SCharles.Forsyth 36637da2899SCharles.Forsythquoted(argv: list of string): string 36737da2899SCharles.Forsyth{ 36837da2899SCharles.Forsyth return quotedc(argv, nil); 36937da2899SCharles.Forsyth} 37037da2899SCharles.Forsyth 37137da2899SCharles.Forsythquotedc(argv: list of string, cl: string): string 37237da2899SCharles.Forsyth{ 37337da2899SCharles.Forsyth s := ""; 37437da2899SCharles.Forsyth while(argv != nil){ 37537da2899SCharles.Forsyth arg := hd argv; 37637da2899SCharles.Forsyth for(i := 0; i < len arg; i++){ 37737da2899SCharles.Forsyth c := arg[i]; 37837da2899SCharles.Forsyth if(c == ' ' || c == '\t' || c == '\n' || c == '\'' || in(c, cl)) 37937da2899SCharles.Forsyth break; 38037da2899SCharles.Forsyth } 38137da2899SCharles.Forsyth if(i < len arg || arg == nil){ 38237da2899SCharles.Forsyth s += "'" + arg[0:i]; 38337da2899SCharles.Forsyth for(; i < len arg; i++){ 38437da2899SCharles.Forsyth if (arg[i] == '\'') 38537da2899SCharles.Forsyth s[len s] = '\''; 38637da2899SCharles.Forsyth s[len s] = arg[i]; 38737da2899SCharles.Forsyth } 38837da2899SCharles.Forsyth s[len s] = '\''; 38937da2899SCharles.Forsyth }else 39037da2899SCharles.Forsyth s += arg; 39137da2899SCharles.Forsyth if(tl argv != nil) 39237da2899SCharles.Forsyth s[len s] = ' '; 39337da2899SCharles.Forsyth argv = tl argv; 39437da2899SCharles.Forsyth } 39537da2899SCharles.Forsyth return s; 39637da2899SCharles.Forsyth} 39737da2899SCharles.Forsyth 39837da2899SCharles.Forsythunquoted(s: string): list of string 39937da2899SCharles.Forsyth{ 40037da2899SCharles.Forsyth args: list of string; 40137da2899SCharles.Forsyth word: string; 40237da2899SCharles.Forsyth inquote := 0; 40337da2899SCharles.Forsyth for(j := len s; j > 0;){ 40437da2899SCharles.Forsyth c := s[j-1]; 40537da2899SCharles.Forsyth if(c == ' ' || c == '\t' || c == '\n'){ 40637da2899SCharles.Forsyth j--; 40737da2899SCharles.Forsyth continue; 40837da2899SCharles.Forsyth } 40937da2899SCharles.Forsyth for(i := j-1; i >= 0 && ((c = s[i]) != ' ' && c != '\t' && c != '\n' || inquote); i--){ # collect word 41037da2899SCharles.Forsyth if(c == '\''){ 41137da2899SCharles.Forsyth word = s[i+1:j] + word; 41237da2899SCharles.Forsyth j = i; 41337da2899SCharles.Forsyth if(!inquote || i == 0 || s[i-1] != '\'') 41437da2899SCharles.Forsyth inquote = !inquote; 41537da2899SCharles.Forsyth else 41637da2899SCharles.Forsyth i--; 41737da2899SCharles.Forsyth } 41837da2899SCharles.Forsyth } 41937da2899SCharles.Forsyth args = (s[i+1:j]+word) :: args; 42037da2899SCharles.Forsyth word = nil; 42137da2899SCharles.Forsyth j = i; 42237da2899SCharles.Forsyth } 42337da2899SCharles.Forsyth # if quotes were unbalanced, balance them and try again. 42437da2899SCharles.Forsyth if(inquote) 42537da2899SCharles.Forsyth return unquoted(s + "'"); 42637da2899SCharles.Forsyth return args; 42737da2899SCharles.Forsyth} 428