implement TclLib; include "sys.m"; sys: Sys;include "draw.m";include "tk.m";include "bufio.m"; bufmod : Bufio;Iobuf : import bufmod; include "string.m"; str : String; include "tcl.m";include "tcllib.m"; include "utils.m"; utils : Tcl_Utils; error : int; DEF,DEC,INT : con iota;valid_commands:= array[] of { "concat" , "join" , "lindex" , "linsert" , "list" , "llength" , "lrange" , "lreplace" , "lsearch" , "lsort" , "split"}; about() : array of string { return valid_commands;} exec(tcl : ref Tcl_Core->TclData,argv : array of string) : (int,string) { if (tcl.context==nil); str = load String String->PATH; sys = load Sys Sys->PATH; utils = load Tcl_Utils Tcl_Utils->PATH; if (str==nil || utils==nil) return (1,"Can't load modules\n"); case argv[0] { "concat" => return (error,do_concat(argv,0)); "join" => return (error,do_join(argv)); "lindex" => return (error,do_lindex(argv)); "linsert" => return (error,do_linsert(argv)); "list" => return (error,do_concat(argv,1)); "llength" => return (error,do_llength(argv)); "lrange" => return (error,do_lrange(argv)); "lreplace" => return (error,do_lreplace(argv)); "lsearch" => return (error,do_lsearch(argv)); "lsort" => return (error,do_lsort(argv)); "split" => return (error,do_split(argv)); } return (1,nil);} spaces(s : string) : int{ if (s==nil) return 1; for(i:=0;i<len s;i++) if (s[i]==' ' || s[i]=='\t') return 1; return 0;} sort(a: array of string, key: int): array of string { m: int; n := len a; for(m = n; m > 1; ) { if(m < 5) m = 1; else m = (5*m-1)/11; for(i := n-m-1; i >= 0; i--) { tmp := a[i]; for(j := i+m; j <= n-1 && greater(tmp, a[j], key); j += m) a[j-m] = a[j]; a[j-m] = tmp; } } return a;} greater(x, y: string, sortkey: int): int { case (sortkey) { DEF => return(x > y); DEC => return(x < y); INT => return(int x > int y); } return 0;} # from here on are the commands in alphabetical order... # turns an array into a string with spaces between the elements.# in braces is non-zero, the elements will be enclosed in braces.do_concat(argv : array of string, braces : int) : string { retval :string; retval=nil; for(i:=1;i<len argv;i++){ flag:=0; if (spaces(argv[i])) flag=1; if (braces && flag) retval[len retval]='{'; retval += argv[i]; if (braces && flag) retval[len retval]='}'; retval[len retval]=' '; } if (retval!=nil) retval=retval[0:len retval-1]; return retval;} do_join(argv : array of string) : string { retval : string; if (len argv ==1 || len argv >3) return notify(1,"join list ?joinString?"); if (len argv == 2) return argv[1]; if (argv[1]==nil) return nil; arr := utils->break_it(argv[1]); for (i:=0;i<len arr;i++){ retval+=arr[i]; if (i!=len arr -1) retval+=argv[2]; } return retval;} do_lindex(argv : array of string) : string { if (len argv != 3) return notify(1,"lindex list index"); (num,rest):=str->toint(argv[2],10); if (rest!=nil) return notify(2,argv[2]); arr:=utils->break_it(argv[1]); if (num>=len arr) return nil; return arr[num];} do_linsert(argv : array of string) : string { if (len argv < 4){ return notify(1, "linsert list index element ?element ...?"); } (num,rest):=str->toint(argv[2],10); if (rest!=nil) return notify(2,argv[2]); arr:=utils->break_it(argv[1]); narr := array[len arr + len argv - 2] of string; narr[0]="do_concat"; if (num==0){ narr[1:]=argv[3:]; narr[len argv -2:]=arr[0:]; }else if (num>= len arr){ narr[1:]=arr[0:]; narr[len arr+1:]=argv[3:]; }else{ narr[1:]=arr[0:num]; narr[num+1:]=argv[3:]; narr[num+len argv -2:]=arr[num:]; } return do_concat(narr,1);} do_llength(argv : array of string) : string { if (len argv !=2){ return notify(1,"llength list"); } arr:=utils->break_it(argv[1]); return string len arr;} do_lrange(argv :array of string) : string { beg,end : int; rest : string; if (len argv != 4) return notify(1,"lrange list first last"); (beg,rest)=str->toint(argv[2],10); if (rest!=nil) return notify(2,argv[2]); (end,rest)=str->toint(argv[3],10); if (rest!=nil) return notify(2,argv[3]); if (beg <0) beg=0; if (end < 0) return nil; if (beg > end) return nil; arr:=utils->break_it(argv[1]); if (beg>len arr) return nil; narr:=array[end-beg+2] of string; narr[0]="do_concat"; narr[1:]=arr[beg:end+1]; return do_concat(narr,1);} do_lreplace(argv : array of string) : string { beg,end : int; rest : string; if (len argv < 3) return notify(1,"lreplace list "+ "first last ?element element ...?"); arr:=utils->break_it(argv[1]); (beg,rest)=str->toint(argv[2],10); if (rest!=nil) return notify(2,argv[2]); (end,rest)=str->toint(argv[3],10); if (rest!=nil) return notify(2,argv[3]); if (beg <0) beg=0; if (end < 0) return nil; if (beg > end) return notify(0, "first index must not be greater than second"); if (beg>len arr) return notify(1, "list doesn't contain element "+string beg); narr:=array[len arr-(end-beg+1)+len argv - 3] of string; narr[1:]=arr[0:beg]; narr[beg+1:]=argv[4:]; narr[beg+1+len argv-4:]=arr[end+1:]; narr[0]="do_concat"; return do_concat(narr,1);} do_lsearch(argv : array of string) : string { if (len argv!=3) return notify(1,"lsearch ?mode? list pattern"); arr:=utils->break_it(argv[1]); for(i:=0;i<len arr;i++) if (arr[i]==argv[2]) return string i; return "-1";} do_lsort(argv : array of string) : string { lis : array of string; key : int; key=DEF; if (len argv == 1) return notify(1,"lsort ?-ascii? ?-integer? ?-real?"+ " ?-increasing? ?-decreasing?"+ " ?-command string? list"); for(i:=1;i<len argv;i++) if (argv[i][0]=='-') case argv[i]{ "-decreasing" => key = DEC; * => if (len argv != i+1) return notify(0,sys->sprint( "bad switch \"%s\": must be"+ " -ascii, -integer, -real, "+ "-increasing -decreasing, or"+ " -command" ,argv[i])); } lis=utils->break_it(argv[len argv-1]); arr:=sort(lis,key); narr:= array[len arr+1] of string; narr[0]="list"; narr[1:]=arr[0:]; return do_concat(narr,1);} do_split(argv : array of string) : string { arr := array[20] of string; narr : array of string; if (len argv ==1 || len argv>3) return notify(1,"split string ?splitChars?"); if (len argv == 2) return argv[1]; s:=argv[1]; if (s==nil) return nil; if (argv[2]==nil){ arr=array[len s+1] of string; for(i:=0;i<len s;i++) arr[i+1][len arr[i+1]]=s[i]; arr[0]="do_concat"; return do_concat(arr,1); } i:=1; while(s!=nil){ (piece,rest):=str->splitl(s,argv[2]); arr[i]=piece; if (len rest>1) s=rest[1:]; if (len rest==1) s=nil; i++; if (i==len arr){ narr=array[i+10] of string; narr[0:]=arr[0:]; arr=array[i+10] of string; arr=narr; } } narr = array[i] of string; arr[0]="do_concat"; narr = arr[0:i+1]; return do_concat(narr,1);} notify(num : int,s : string) : string { error=1; case num{ 1 => return sys->sprint( "wrong # args: should be \"%s\"",s); 2 => return sys->sprint( "expected integer but got \"%s\"",s); * => return s; }}
implement TclLib;
include "sys.m";
sys: Sys;
include "draw.m";
include "tk.m";
include "bufio.m";
bufmod : Bufio;
Iobuf : import bufmod;
include "string.m";
str : String;
include "tcl.m";
include "tcllib.m";
include "utils.m";
utils : Tcl_Utils;
error : int;
DEF,DEC,INT : con iota;
valid_commands:= array[] of {
"concat" ,
"join" ,
"lindex" ,
"linsert" ,
"list" ,
"llength" ,
"lrange" ,
"lreplace" ,
"lsearch" ,
"lsort" ,
"split"
};
about() : array of string {
return valid_commands;
}
exec(tcl : ref Tcl_Core->TclData,argv : array of string) : (int,string) {
if (tcl.context==nil);
str = load String String->PATH;
sys = load Sys Sys->PATH;
utils = load Tcl_Utils Tcl_Utils->PATH;
if (str==nil || utils==nil)
return (1,"Can't load modules\n");
case argv[0] {
"concat" =>
return (error,do_concat(argv,0));
"join" =>
return (error,do_join(argv));
"lindex" =>
return (error,do_lindex(argv));
"linsert" =>
return (error,do_linsert(argv));
"list" =>
return (error,do_concat(argv,1));
"llength" =>
return (error,do_llength(argv));
"lrange" =>
return (error,do_lrange(argv));
"lreplace" =>
return (error,do_lreplace(argv));
"lsearch" =>
return (error,do_lsearch(argv));
"lsort" =>
return (error,do_lsort(argv));
"split" =>
return (error,do_split(argv));
}
return (1,nil);
}
spaces(s : string) : int{
if (s==nil) return 1;
for(i:=0;i<len s;i++)
if (s[i]==' ' || s[i]=='\t') return 1;
return 0;
}
sort(a: array of string, key: int): array of string {
m: int;
n := len a;
for(m = n; m > 1; ) {
if(m < 5)
m = 1;
else
m = (5*m-1)/11;
for(i := n-m-1; i >= 0; i--) {
tmp := a[i];
for(j := i+m; j <= n-1 && greater(tmp, a[j], key); j += m)
a[j-m] = a[j];
a[j-m] = tmp;
}
}
return a;
}
greater(x, y: string, sortkey: int): int {
case (sortkey) {
DEF => return(x > y);
DEC => return(x < y);
INT => return(int x > int y);
}
return 0;
}
# from here on are the commands in alphabetical order...
# turns an array into a string with spaces between the elements.
# in braces is non-zero, the elements will be enclosed in braces.
do_concat(argv : array of string, braces : int) : string {
retval :string;
retval=nil;
for(i:=1;i<len argv;i++){
flag:=0;
if (spaces(argv[i])) flag=1;
if (braces && flag) retval[len retval]='{';
retval += argv[i];
if (braces && flag) retval[len retval]='}';
retval[len retval]=' ';
}
if (retval!=nil)
retval=retval[0:len retval-1];
return retval;
}
do_join(argv : array of string) : string {
retval : string;
if (len argv ==1 || len argv >3)
return notify(1,"join list ?joinString?");
if (len argv == 2)
return argv[1];
if (argv[1]==nil) return nil;
arr := utils->break_it(argv[1]);
for (i:=0;i<len arr;i++){
retval+=arr[i];
if (i!=len arr -1)
retval+=argv[2];
}
return retval;
}
do_lindex(argv : array of string) : string {
if (len argv != 3)
return notify(1,"lindex list index");
(num,rest):=str->toint(argv[2],10);
if (rest!=nil)
return notify(2,argv[2]);
arr:=utils->break_it(argv[1]);
if (num>=len arr)
return nil;
return arr[num];
}
do_linsert(argv : array of string) : string {
if (len argv < 4){
return notify(1,
"linsert list index element ?element ...?");
}
(num,rest):=str->toint(argv[2],10);
if (rest!=nil)
return notify(2,argv[2]);
arr:=utils->break_it(argv[1]);
narr := array[len arr + len argv - 2] of string;
narr[0]="do_concat";
if (num==0){
narr[1:]=argv[3:];
narr[len argv -2:]=arr[0:];
}else if (num>= len arr){
narr[1:]=arr[0:];
narr[len arr+1:]=argv[3:];
}else{
narr[1:]=arr[0:num];
narr[num+1:]=argv[3:];
narr[num+len argv -2:]=arr[num:];
}
return do_concat(narr,1);
}
do_llength(argv : array of string) : string {
if (len argv !=2){
return notify(1,"llength list");
}
arr:=utils->break_it(argv[1]);
return string len arr;
}
do_lrange(argv :array of string) : string {
beg,end : int;
rest : string;
if (len argv != 4)
return notify(1,"lrange list first last");
(beg,rest)=str->toint(argv[2],10);
if (rest!=nil)
return notify(2,argv[2]);
(end,rest)=str->toint(argv[3],10);
if (rest!=nil)
return notify(2,argv[3]);
if (beg <0) beg=0;
if (end < 0) return nil;
if (beg > end) return nil;
arr:=utils->break_it(argv[1]);
if (beg>len arr) return nil;
narr:=array[end-beg+2] of string;
narr[0]="do_concat";
narr[1:]=arr[beg:end+1];
return do_concat(narr,1);
}
do_lreplace(argv : array of string) : string {
beg,end : int;
rest : string;
if (len argv < 3)
return notify(1,"lreplace list "+
"first last ?element element ...?");
arr:=utils->break_it(argv[1]);
(beg,rest)=str->toint(argv[2],10);
if (rest!=nil)
return notify(2,argv[2]);
(end,rest)=str->toint(argv[3],10);
if (rest!=nil)
return notify(2,argv[3]);
if (beg <0) beg=0;
if (end < 0) return nil;
if (beg > end)
return notify(0,
"first index must not be greater than second");
if (beg>len arr)
return notify(1,
"list doesn't contain element "+string beg);
narr:=array[len arr-(end-beg+1)+len argv - 3] of string;
narr[1:]=arr[0:beg];
narr[beg+1:]=argv[4:];
narr[beg+1+len argv-4:]=arr[end+1:];
narr[0]="do_concat";
return do_concat(narr,1);
}
do_lsearch(argv : array of string) : string {
if (len argv!=3)
return notify(1,"lsearch ?mode? list pattern");
arr:=utils->break_it(argv[1]);
for(i:=0;i<len arr;i++)
if (arr[i]==argv[2])
return string i;
return "-1";
}
do_lsort(argv : array of string) : string {
lis : array of string;
key : int;
key=DEF;
if (len argv == 1)
return notify(1,"lsort ?-ascii? ?-integer? ?-real?"+
" ?-increasing? ?-decreasing?"+
" ?-command string? list");
for(i:=1;i<len argv;i++)
if (argv[i][0]=='-')
case argv[i]{
"-decreasing" =>
key = DEC;
* =>
if (len argv != i+1)
return notify(0,sys->sprint(
"bad switch \"%s\": must be"+
" -ascii, -integer, -real, "+
"-increasing -decreasing, or"+
" -command" ,argv[i]));
}
lis=utils->break_it(argv[len argv-1]);
arr:=sort(lis,key);
narr:= array[len arr+1] of string;
narr[0]="list";
narr[1:]=arr[0:];
return do_concat(narr,1);
}
do_split(argv : array of string) : string {
arr := array[20] of string;
narr : array of string;
if (len argv ==1 || len argv>3)
return notify(1,"split string ?splitChars?");
if (len argv == 2)
return argv[1];
s:=argv[1];
if (s==nil) return nil;
if (argv[2]==nil){
arr=array[len s+1] of string;
for(i:=0;i<len s;i++)
arr[i+1][len arr[i+1]]=s[i];
arr[0]="do_concat";
return do_concat(arr,1);
}
i:=1;
while(s!=nil){
(piece,rest):=str->splitl(s,argv[2]);
arr[i]=piece;
if (len rest>1)
s=rest[1:];
if (len rest==1)
s=nil;
i++;
if (i==len arr){
narr=array[i+10] of string;
narr[0:]=arr[0:];
arr=array[i+10] of string;
arr=narr;
}
}
narr = array[i] of string;
arr[0]="do_concat";
narr = arr[0:i+1];
return do_concat(narr,1);
}
notify(num : int,s : string) : string {
error=1;
case num{
1 =>
return sys->sprint(
"wrong # args: should be \"%s\"",s);
2 =>
return sys->sprint(
"expected integer but got \"%s\"",s);
* =>
return s;
}
}