1*37da2899SCharles.Forsythimplement TclLib; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "sys.m"; 4*37da2899SCharles.Forsyth sys: Sys; 5*37da2899SCharles.Forsythinclude "draw.m"; 6*37da2899SCharles.Forsythinclude "tk.m"; 7*37da2899SCharles.Forsythinclude "bufio.m"; 8*37da2899SCharles.Forsyth bufmod : Bufio; 9*37da2899SCharles.ForsythIobuf : import bufmod; 10*37da2899SCharles.Forsyth 11*37da2899SCharles.Forsythinclude "string.m"; 12*37da2899SCharles.Forsyth str : String; 13*37da2899SCharles.Forsyth 14*37da2899SCharles.Forsythinclude "tcl.m"; 15*37da2899SCharles.Forsythinclude "tcllib.m"; 16*37da2899SCharles.Forsyth 17*37da2899SCharles.Forsythinclude "utils.m"; 18*37da2899SCharles.Forsyth utils : Tcl_Utils; 19*37da2899SCharles.Forsyth 20*37da2899SCharles.Forsyth 21*37da2899SCharles.Forsytherror : int; 22*37da2899SCharles.Forsyth 23*37da2899SCharles.ForsythDEF,DEC,INT : con iota; 24*37da2899SCharles.Forsythvalid_commands:= array[] of { 25*37da2899SCharles.Forsyth "concat" , 26*37da2899SCharles.Forsyth "join" , 27*37da2899SCharles.Forsyth "lindex" , 28*37da2899SCharles.Forsyth "linsert" , 29*37da2899SCharles.Forsyth "list" , 30*37da2899SCharles.Forsyth "llength" , 31*37da2899SCharles.Forsyth "lrange" , 32*37da2899SCharles.Forsyth "lreplace" , 33*37da2899SCharles.Forsyth "lsearch" , 34*37da2899SCharles.Forsyth "lsort" , 35*37da2899SCharles.Forsyth "split" 36*37da2899SCharles.Forsyth}; 37*37da2899SCharles.Forsyth 38*37da2899SCharles.Forsythabout() : array of string { 39*37da2899SCharles.Forsyth return valid_commands; 40*37da2899SCharles.Forsyth} 41*37da2899SCharles.Forsyth 42*37da2899SCharles.Forsythexec(tcl : ref Tcl_Core->TclData,argv : array of string) : (int,string) { 43*37da2899SCharles.Forsyth if (tcl.context==nil); 44*37da2899SCharles.Forsyth str = load String String->PATH; 45*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 46*37da2899SCharles.Forsyth utils = load Tcl_Utils Tcl_Utils->PATH; 47*37da2899SCharles.Forsyth if (str==nil || utils==nil) 48*37da2899SCharles.Forsyth return (1,"Can't load modules\n"); 49*37da2899SCharles.Forsyth case argv[0] { 50*37da2899SCharles.Forsyth "concat" => 51*37da2899SCharles.Forsyth return (error,do_concat(argv,0)); 52*37da2899SCharles.Forsyth "join" => 53*37da2899SCharles.Forsyth return (error,do_join(argv)); 54*37da2899SCharles.Forsyth "lindex" => 55*37da2899SCharles.Forsyth return (error,do_lindex(argv)); 56*37da2899SCharles.Forsyth "linsert" => 57*37da2899SCharles.Forsyth return (error,do_linsert(argv)); 58*37da2899SCharles.Forsyth "list" => 59*37da2899SCharles.Forsyth return (error,do_concat(argv,1)); 60*37da2899SCharles.Forsyth "llength" => 61*37da2899SCharles.Forsyth return (error,do_llength(argv)); 62*37da2899SCharles.Forsyth "lrange" => 63*37da2899SCharles.Forsyth return (error,do_lrange(argv)); 64*37da2899SCharles.Forsyth "lreplace" => 65*37da2899SCharles.Forsyth return (error,do_lreplace(argv)); 66*37da2899SCharles.Forsyth "lsearch" => 67*37da2899SCharles.Forsyth return (error,do_lsearch(argv)); 68*37da2899SCharles.Forsyth "lsort" => 69*37da2899SCharles.Forsyth return (error,do_lsort(argv)); 70*37da2899SCharles.Forsyth "split" => 71*37da2899SCharles.Forsyth return (error,do_split(argv)); 72*37da2899SCharles.Forsyth } 73*37da2899SCharles.Forsyth return (1,nil); 74*37da2899SCharles.Forsyth} 75*37da2899SCharles.Forsyth 76*37da2899SCharles.Forsythspaces(s : string) : int{ 77*37da2899SCharles.Forsyth if (s==nil) return 1; 78*37da2899SCharles.Forsyth for(i:=0;i<len s;i++) 79*37da2899SCharles.Forsyth if (s[i]==' ' || s[i]=='\t') return 1; 80*37da2899SCharles.Forsyth return 0; 81*37da2899SCharles.Forsyth} 82*37da2899SCharles.Forsyth 83*37da2899SCharles.Forsyth 84*37da2899SCharles.Forsythsort(a: array of string, key: int): array of string { 85*37da2899SCharles.Forsyth m: int; 86*37da2899SCharles.Forsyth n := len a; 87*37da2899SCharles.Forsyth for(m = n; m > 1; ) { 88*37da2899SCharles.Forsyth if(m < 5) 89*37da2899SCharles.Forsyth m = 1; 90*37da2899SCharles.Forsyth else 91*37da2899SCharles.Forsyth m = (5*m-1)/11; 92*37da2899SCharles.Forsyth for(i := n-m-1; i >= 0; i--) { 93*37da2899SCharles.Forsyth tmp := a[i]; 94*37da2899SCharles.Forsyth for(j := i+m; j <= n-1 && greater(tmp, a[j], key); j += m) 95*37da2899SCharles.Forsyth a[j-m] = a[j]; 96*37da2899SCharles.Forsyth a[j-m] = tmp; 97*37da2899SCharles.Forsyth } 98*37da2899SCharles.Forsyth } 99*37da2899SCharles.Forsyth return a; 100*37da2899SCharles.Forsyth} 101*37da2899SCharles.Forsyth 102*37da2899SCharles.Forsythgreater(x, y: string, sortkey: int): int { 103*37da2899SCharles.Forsyth case (sortkey) { 104*37da2899SCharles.Forsyth DEF => return(x > y); 105*37da2899SCharles.Forsyth DEC => return(x < y); 106*37da2899SCharles.Forsyth INT => return(int x > int y); 107*37da2899SCharles.Forsyth } 108*37da2899SCharles.Forsyth return 0; 109*37da2899SCharles.Forsyth} 110*37da2899SCharles.Forsyth 111*37da2899SCharles.Forsyth# from here on are the commands in alphabetical order... 112*37da2899SCharles.Forsyth 113*37da2899SCharles.Forsyth# turns an array into a string with spaces between the elements. 114*37da2899SCharles.Forsyth# in braces is non-zero, the elements will be enclosed in braces. 115*37da2899SCharles.Forsythdo_concat(argv : array of string, braces : int) : string { 116*37da2899SCharles.Forsyth retval :string; 117*37da2899SCharles.Forsyth retval=nil; 118*37da2899SCharles.Forsyth for(i:=1;i<len argv;i++){ 119*37da2899SCharles.Forsyth flag:=0; 120*37da2899SCharles.Forsyth if (spaces(argv[i])) flag=1; 121*37da2899SCharles.Forsyth if (braces && flag) retval[len retval]='{'; 122*37da2899SCharles.Forsyth retval += argv[i]; 123*37da2899SCharles.Forsyth if (braces && flag) retval[len retval]='}'; 124*37da2899SCharles.Forsyth retval[len retval]=' '; 125*37da2899SCharles.Forsyth } 126*37da2899SCharles.Forsyth if (retval!=nil) 127*37da2899SCharles.Forsyth retval=retval[0:len retval-1]; 128*37da2899SCharles.Forsyth return retval; 129*37da2899SCharles.Forsyth} 130*37da2899SCharles.Forsyth 131*37da2899SCharles.Forsythdo_join(argv : array of string) : string { 132*37da2899SCharles.Forsyth retval : string; 133*37da2899SCharles.Forsyth if (len argv ==1 || len argv >3) 134*37da2899SCharles.Forsyth return notify(1,"join list ?joinString?"); 135*37da2899SCharles.Forsyth if (len argv == 2) 136*37da2899SCharles.Forsyth return argv[1]; 137*37da2899SCharles.Forsyth if (argv[1]==nil) return nil; 138*37da2899SCharles.Forsyth arr := utils->break_it(argv[1]); 139*37da2899SCharles.Forsyth for (i:=0;i<len arr;i++){ 140*37da2899SCharles.Forsyth retval+=arr[i]; 141*37da2899SCharles.Forsyth if (i!=len arr -1) 142*37da2899SCharles.Forsyth retval+=argv[2]; 143*37da2899SCharles.Forsyth } 144*37da2899SCharles.Forsyth return retval; 145*37da2899SCharles.Forsyth} 146*37da2899SCharles.Forsyth 147*37da2899SCharles.Forsythdo_lindex(argv : array of string) : string { 148*37da2899SCharles.Forsyth if (len argv != 3) 149*37da2899SCharles.Forsyth return notify(1,"lindex list index"); 150*37da2899SCharles.Forsyth (num,rest):=str->toint(argv[2],10); 151*37da2899SCharles.Forsyth if (rest!=nil) 152*37da2899SCharles.Forsyth return notify(2,argv[2]); 153*37da2899SCharles.Forsyth arr:=utils->break_it(argv[1]); 154*37da2899SCharles.Forsyth if (num>=len arr) 155*37da2899SCharles.Forsyth return nil; 156*37da2899SCharles.Forsyth return arr[num]; 157*37da2899SCharles.Forsyth} 158*37da2899SCharles.Forsyth 159*37da2899SCharles.Forsythdo_linsert(argv : array of string) : string { 160*37da2899SCharles.Forsyth if (len argv < 4){ 161*37da2899SCharles.Forsyth return notify(1, 162*37da2899SCharles.Forsyth "linsert list index element ?element ...?"); 163*37da2899SCharles.Forsyth } 164*37da2899SCharles.Forsyth (num,rest):=str->toint(argv[2],10); 165*37da2899SCharles.Forsyth if (rest!=nil) 166*37da2899SCharles.Forsyth return notify(2,argv[2]); 167*37da2899SCharles.Forsyth arr:=utils->break_it(argv[1]); 168*37da2899SCharles.Forsyth narr := array[len arr + len argv - 2] of string; 169*37da2899SCharles.Forsyth narr[0]="do_concat"; 170*37da2899SCharles.Forsyth if (num==0){ 171*37da2899SCharles.Forsyth narr[1:]=argv[3:]; 172*37da2899SCharles.Forsyth narr[len argv -2:]=arr[0:]; 173*37da2899SCharles.Forsyth }else if (num>= len arr){ 174*37da2899SCharles.Forsyth narr[1:]=arr[0:]; 175*37da2899SCharles.Forsyth narr[len arr+1:]=argv[3:]; 176*37da2899SCharles.Forsyth }else{ 177*37da2899SCharles.Forsyth narr[1:]=arr[0:num]; 178*37da2899SCharles.Forsyth narr[num+1:]=argv[3:]; 179*37da2899SCharles.Forsyth narr[num+len argv -2:]=arr[num:]; 180*37da2899SCharles.Forsyth } 181*37da2899SCharles.Forsyth return do_concat(narr,1); 182*37da2899SCharles.Forsyth} 183*37da2899SCharles.Forsyth 184*37da2899SCharles.Forsythdo_llength(argv : array of string) : string { 185*37da2899SCharles.Forsyth if (len argv !=2){ 186*37da2899SCharles.Forsyth return notify(1,"llength list"); 187*37da2899SCharles.Forsyth } 188*37da2899SCharles.Forsyth arr:=utils->break_it(argv[1]); 189*37da2899SCharles.Forsyth return string len arr; 190*37da2899SCharles.Forsyth} 191*37da2899SCharles.Forsyth 192*37da2899SCharles.Forsythdo_lrange(argv :array of string) : string { 193*37da2899SCharles.Forsyth beg,end : int; 194*37da2899SCharles.Forsyth rest : string; 195*37da2899SCharles.Forsyth if (len argv != 4) 196*37da2899SCharles.Forsyth return notify(1,"lrange list first last"); 197*37da2899SCharles.Forsyth (beg,rest)=str->toint(argv[2],10); 198*37da2899SCharles.Forsyth if (rest!=nil) 199*37da2899SCharles.Forsyth return notify(2,argv[2]); 200*37da2899SCharles.Forsyth (end,rest)=str->toint(argv[3],10); 201*37da2899SCharles.Forsyth if (rest!=nil) 202*37da2899SCharles.Forsyth return notify(2,argv[3]); 203*37da2899SCharles.Forsyth if (beg <0) beg=0; 204*37da2899SCharles.Forsyth if (end < 0) return nil; 205*37da2899SCharles.Forsyth if (beg > end) return nil; 206*37da2899SCharles.Forsyth arr:=utils->break_it(argv[1]); 207*37da2899SCharles.Forsyth if (beg>len arr) return nil; 208*37da2899SCharles.Forsyth narr:=array[end-beg+2] of string; 209*37da2899SCharles.Forsyth narr[0]="do_concat"; 210*37da2899SCharles.Forsyth narr[1:]=arr[beg:end+1]; 211*37da2899SCharles.Forsyth return do_concat(narr,1); 212*37da2899SCharles.Forsyth} 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsythdo_lreplace(argv : array of string) : string { 215*37da2899SCharles.Forsyth beg,end : int; 216*37da2899SCharles.Forsyth rest : string; 217*37da2899SCharles.Forsyth if (len argv < 3) 218*37da2899SCharles.Forsyth return notify(1,"lreplace list "+ 219*37da2899SCharles.Forsyth "first last ?element element ...?"); 220*37da2899SCharles.Forsyth arr:=utils->break_it(argv[1]); 221*37da2899SCharles.Forsyth (beg,rest)=str->toint(argv[2],10); 222*37da2899SCharles.Forsyth if (rest!=nil) 223*37da2899SCharles.Forsyth return notify(2,argv[2]); 224*37da2899SCharles.Forsyth (end,rest)=str->toint(argv[3],10); 225*37da2899SCharles.Forsyth if (rest!=nil) 226*37da2899SCharles.Forsyth return notify(2,argv[3]); 227*37da2899SCharles.Forsyth if (beg <0) beg=0; 228*37da2899SCharles.Forsyth if (end < 0) return nil; 229*37da2899SCharles.Forsyth if (beg > end) 230*37da2899SCharles.Forsyth return notify(0, 231*37da2899SCharles.Forsyth "first index must not be greater than second"); 232*37da2899SCharles.Forsyth if (beg>len arr) 233*37da2899SCharles.Forsyth return notify(1, 234*37da2899SCharles.Forsyth "list doesn't contain element "+string beg); 235*37da2899SCharles.Forsyth narr:=array[len arr-(end-beg+1)+len argv - 3] of string; 236*37da2899SCharles.Forsyth narr[1:]=arr[0:beg]; 237*37da2899SCharles.Forsyth narr[beg+1:]=argv[4:]; 238*37da2899SCharles.Forsyth narr[beg+1+len argv-4:]=arr[end+1:]; 239*37da2899SCharles.Forsyth narr[0]="do_concat"; 240*37da2899SCharles.Forsyth return do_concat(narr,1); 241*37da2899SCharles.Forsyth} 242*37da2899SCharles.Forsyth 243*37da2899SCharles.Forsythdo_lsearch(argv : array of string) : string { 244*37da2899SCharles.Forsyth if (len argv!=3) 245*37da2899SCharles.Forsyth return notify(1,"lsearch ?mode? list pattern"); 246*37da2899SCharles.Forsyth arr:=utils->break_it(argv[1]); 247*37da2899SCharles.Forsyth for(i:=0;i<len arr;i++) 248*37da2899SCharles.Forsyth if (arr[i]==argv[2]) 249*37da2899SCharles.Forsyth return string i; 250*37da2899SCharles.Forsyth return "-1"; 251*37da2899SCharles.Forsyth} 252*37da2899SCharles.Forsyth 253*37da2899SCharles.Forsythdo_lsort(argv : array of string) : string { 254*37da2899SCharles.Forsyth lis : array of string; 255*37da2899SCharles.Forsyth key : int; 256*37da2899SCharles.Forsyth key=DEF; 257*37da2899SCharles.Forsyth if (len argv == 1) 258*37da2899SCharles.Forsyth return notify(1,"lsort ?-ascii? ?-integer? ?-real?"+ 259*37da2899SCharles.Forsyth " ?-increasing? ?-decreasing?"+ 260*37da2899SCharles.Forsyth " ?-command string? list"); 261*37da2899SCharles.Forsyth for(i:=1;i<len argv;i++) 262*37da2899SCharles.Forsyth if (argv[i][0]=='-') 263*37da2899SCharles.Forsyth case argv[i]{ 264*37da2899SCharles.Forsyth "-decreasing" => 265*37da2899SCharles.Forsyth key = DEC; 266*37da2899SCharles.Forsyth * => 267*37da2899SCharles.Forsyth if (len argv != i+1) 268*37da2899SCharles.Forsyth return notify(0,sys->sprint( 269*37da2899SCharles.Forsyth "bad switch \"%s\": must be"+ 270*37da2899SCharles.Forsyth " -ascii, -integer, -real, "+ 271*37da2899SCharles.Forsyth "-increasing -decreasing, or"+ 272*37da2899SCharles.Forsyth " -command" ,argv[i])); 273*37da2899SCharles.Forsyth } 274*37da2899SCharles.Forsyth lis=utils->break_it(argv[len argv-1]); 275*37da2899SCharles.Forsyth arr:=sort(lis,key); 276*37da2899SCharles.Forsyth narr:= array[len arr+1] of string; 277*37da2899SCharles.Forsyth narr[0]="list"; 278*37da2899SCharles.Forsyth narr[1:]=arr[0:]; 279*37da2899SCharles.Forsyth return do_concat(narr,1); 280*37da2899SCharles.Forsyth} 281*37da2899SCharles.Forsyth 282*37da2899SCharles.Forsyth 283*37da2899SCharles.Forsyth 284*37da2899SCharles.Forsythdo_split(argv : array of string) : string { 285*37da2899SCharles.Forsyth arr := array[20] of string; 286*37da2899SCharles.Forsyth narr : array of string; 287*37da2899SCharles.Forsyth if (len argv ==1 || len argv>3) 288*37da2899SCharles.Forsyth return notify(1,"split string ?splitChars?"); 289*37da2899SCharles.Forsyth if (len argv == 2) 290*37da2899SCharles.Forsyth return argv[1]; 291*37da2899SCharles.Forsyth s:=argv[1]; 292*37da2899SCharles.Forsyth if (s==nil) return nil; 293*37da2899SCharles.Forsyth if (argv[2]==nil){ 294*37da2899SCharles.Forsyth arr=array[len s+1] of string; 295*37da2899SCharles.Forsyth for(i:=0;i<len s;i++) 296*37da2899SCharles.Forsyth arr[i+1][len arr[i+1]]=s[i]; 297*37da2899SCharles.Forsyth arr[0]="do_concat"; 298*37da2899SCharles.Forsyth return do_concat(arr,1); 299*37da2899SCharles.Forsyth } 300*37da2899SCharles.Forsyth i:=1; 301*37da2899SCharles.Forsyth while(s!=nil){ 302*37da2899SCharles.Forsyth (piece,rest):=str->splitl(s,argv[2]); 303*37da2899SCharles.Forsyth arr[i]=piece; 304*37da2899SCharles.Forsyth if (len rest>1) 305*37da2899SCharles.Forsyth s=rest[1:]; 306*37da2899SCharles.Forsyth if (len rest==1) 307*37da2899SCharles.Forsyth s=nil; 308*37da2899SCharles.Forsyth i++; 309*37da2899SCharles.Forsyth if (i==len arr){ 310*37da2899SCharles.Forsyth narr=array[i+10] of string; 311*37da2899SCharles.Forsyth narr[0:]=arr[0:]; 312*37da2899SCharles.Forsyth arr=array[i+10] of string; 313*37da2899SCharles.Forsyth arr=narr; 314*37da2899SCharles.Forsyth } 315*37da2899SCharles.Forsyth } 316*37da2899SCharles.Forsyth narr = array[i] of string; 317*37da2899SCharles.Forsyth arr[0]="do_concat"; 318*37da2899SCharles.Forsyth narr = arr[0:i+1]; 319*37da2899SCharles.Forsyth return do_concat(narr,1); 320*37da2899SCharles.Forsyth} 321*37da2899SCharles.Forsyth 322*37da2899SCharles.Forsythnotify(num : int,s : string) : string { 323*37da2899SCharles.Forsyth error=1; 324*37da2899SCharles.Forsyth case num{ 325*37da2899SCharles.Forsyth 1 => 326*37da2899SCharles.Forsyth return sys->sprint( 327*37da2899SCharles.Forsyth "wrong # args: should be \"%s\"",s); 328*37da2899SCharles.Forsyth 2 => 329*37da2899SCharles.Forsyth return sys->sprint( 330*37da2899SCharles.Forsyth "expected integer but got \"%s\"",s); 331*37da2899SCharles.Forsyth * => 332*37da2899SCharles.Forsyth return s; 333*37da2899SCharles.Forsyth } 334*37da2899SCharles.Forsyth} 335*37da2899SCharles.Forsyth 336