1implement TclLib; 2 3include "sys.m"; 4 sys: Sys; 5include "draw.m"; 6include "tk.m"; 7include "bufio.m"; 8 bufmod : Bufio; 9Iobuf : import bufmod; 10 11include "string.m"; 12 str : String; 13include "tcl.m"; 14include "tcllib.m"; 15 16error : int; 17started : int; 18valid_commands:=array[] of {"format","string"}; 19 20about() : array of string{ 21 return valid_commands; 22} 23 24init(){ 25 started=1; 26 sys=load Sys Sys->PATH; 27} 28 29exec(tcl : ref Tcl_Core->TclData,argv : array of string) : (int,string) { 30 if (tcl.context==nil); 31 if (!started) init(); 32 error=0; 33 str=load String String->PATH; 34 if (str==nil) 35 return(1,"String module not loaded."); 36 if (len argv==1 && argv[0]=="string") 37 return (error, 38 notify(1,"string option arg ?arg ...?")); 39 case argv[0]{ 40 "format" => 41 return (error,do_format(argv)); 42 "string" => 43 return (error,do_string(argv)); 44 } 45 return (1,nil); 46} 47 48 49do_string(argv : array of string) : string{ 50 case argv[1]{ 51 "compare" => 52 if (len argv == 4){ 53 i:= - (argv[2]<argv[3])+ (argv[2]>argv[3]); 54 return string i; 55 } 56 return notify(1, 57 "string compare string1 string2"); 58 "first" => 59 return nil; 60 "last" => 61 return nil; 62 "index" => 63 if (len argv == 4){ 64 if (len argv[2] > int argv[3]) 65 return argv[2][int argv[3]:int argv[3]+1]; 66 return nil; 67 } 68 return notify(1, 69 "string index string charIndex"); 70 "length" => 71 if (len argv==3) 72 return string len argv[2]; 73 return notify(1,"string length string"); 74 "match" => 75 return nil; 76 "range" => 77 if (len argv==5){ 78 end :int; 79 if (argv[4]=="end") 80 end=len argv[2]; 81 else 82 end=int argv[4]; 83 if (end>len argv[2]) end=len argv[2]; 84 beg:=int argv[3]; 85 if (beg<0) beg=0; 86 if (beg>end) 87 return nil; 88 return argv[2][int argv[3]:end]; 89 } 90 return notify(1, 91 "string range string first last"); 92 "tolower" => 93 if (len argv==3) 94 return str->tolower(argv[2]); 95 return notify(1,"string tolower string"); 96 "toupper" => 97 if (len argv==3) 98 return str->tolower(argv[2]); 99 return notify(1,"string tolower string"); 100 "trim" => 101 return nil; 102 "trimleft" => 103 return nil; 104 "trimright" => 105 return nil; 106 "wordend" => 107 return nil; 108 "wordstart" => 109 return nil; 110 } 111 return nil; 112} 113 114do_format(argv : array of string) : string { 115 retval,num1,num2,rest,curfm : string; 116 i,j : int; 117 if (len argv==1) 118 return notify(1, 119 "format formatString ?arg arg ...?"); 120 j=2; 121 i1:=-1; 122 i2:=-1; 123 (retval,rest)=str->splitl(argv[1],"%"); 124 do { 125 (curfm,rest)=str->splitl(rest[1:],"%"); 126 i=0; 127 num1=""; 128 num2=""; 129 if (curfm[i]=='-'){ 130 num1[len num1]=curfm[i]; 131 i++; 132 } 133 while(curfm[i]>='0' && curfm[i]<='9'){ 134 num1[len num1]=curfm[i]; 135 i++; 136 } 137 if (num1!="") 138 (i1,nil) = str->toint(num1,10); 139 if (curfm[i]=='.'){ 140 i++; 141 while(curfm[i]>='0' && curfm[i]<='9'){ 142 num2[len num2]=curfm[i]; 143 i++; 144 } 145 (i2,nil) = str->toint(num2,10); 146 } else { 147 i2=i1; 148 i1=-1; 149 } 150 case curfm[i] { 151 's' => 152 retval+=print_string(i1,i2,argv[j]); 153 'd' => 154 retval+=print_int(i1,i2,argv[j]); 155 'f' => 156 retval+=print_float(i1,i2,argv[j]); 157 'x' => 158 retval+=print_hex(i1,i2,argv[j]); 159 } 160 j++; 161 } while (rest!=nil && j<len argv); 162 return retval; 163} 164 165notify(num : int,s : string) : string { 166 error=1; 167 case num{ 168 1 => 169 return sys->sprint( 170 "wrong # args: should be \"%s\"",s); 171 * => 172 return s; 173 } 174} 175 176print_string(i1,i2 : int, s : string) : string { 177 retval : string; 178 if (i1==-1 && i2==-1) 179 retval=sys->sprint("%s",s); 180 if (i1==-1 && i2!=-1) 181 retval=sys->sprint("%*s",i1,s); 182 if (i1!=-1 && i2!=-1) 183 retval=sys->sprint("%*.*s",i1,i2,s); 184 if (i1!=-1 && i2==-1) 185 retval=sys->sprint("%.*s",i2,s); 186 return retval; 187} 188 189print_int(i1,i2 : int, s : string) : string { 190 retval,ret2 : string; 191 n : int; 192 (num,nil):=str->toint(s,10); 193 width:=1; 194 i:=num; 195 while((i/=10)!= 0) width++; 196 if (i2 !=-1 && width<i2) width=i2; 197 for(i=0;i<width;i++) 198 retval[len retval]='0'; 199 while(width!=0){ 200 retval[width-1]=num%10+'0'; 201 num/=10; 202 width--; 203 } 204 if (i1 !=-1 && i1>i){ 205 for(n=0;n<i1-i;n++) 206 ret2[len ret2]=' '; 207 ret2+=retval; 208 retval=ret2; 209 } 210 return retval; 211} 212 213 214print_float(i1,i2 : int, s : string) : string { 215 r:= real s; 216 retval:=sys->sprint("%*.*f",i1,i2,r); 217 return retval; 218} 219 220print_hex(i1,i2 : int, s : string) : string { 221 retval,ret2 : string; 222 n : int; 223 (num,nil):=str->toint(s,10); 224 width:=1; 225 i:=num; 226 while((i/=16)!= 0) width++; 227 if (i2 !=-1 && width<i2) width=i2; 228 for(i=0;i<width;i++) 229 retval[len retval]='0'; 230 while(width!=0){ 231 n=num%16; 232 if (n>=0 && n<=9) 233 retval[width-1]=n+'0'; 234 else 235 retval[width-1]=n+'a'-10; 236 num/=16; 237 width--; 238 } 239 if (i1 !=-1 && i1>i){ 240 for(n=0;n<i1-i;n++) 241 ret2[len ret2]=' '; 242 ret2+=retval; 243 retval=ret2; 244 } 245 return retval; 246} 247