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 "bufio.m"; 7*37da2899SCharles.Forsyth bufmod : Bufio; 8*37da2899SCharles.ForsythIobuf : import bufmod; 9*37da2899SCharles.Forsyth 10*37da2899SCharles.Forsythinclude "string.m"; 11*37da2899SCharles.Forsyth str : String; 12*37da2899SCharles.Forsyth 13*37da2899SCharles.Forsythinclude "tk.m"; 14*37da2899SCharles.Forsyth 15*37da2899SCharles.Forsythinclude "tcl.m"; 16*37da2899SCharles.Forsyth 17*37da2899SCharles.Forsythinclude "tcllib.m"; 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsytherror : int; 20*37da2899SCharles.Forsythstarted : int; 21*37da2899SCharles.Forsythtclmod : ref Tcl_Core->TclData; 22*37da2899SCharles.Forsyth 23*37da2899SCharles.Forsythname2fid : array of (ref Iobuf,string,int); 24*37da2899SCharles.Forsyth 25*37da2899SCharles.Forsythvalid_commands := array[] of { 26*37da2899SCharles.Forsyth "close", 27*37da2899SCharles.Forsyth "eof" , 28*37da2899SCharles.Forsyth "file", 29*37da2899SCharles.Forsyth "flush", 30*37da2899SCharles.Forsyth "gets" , 31*37da2899SCharles.Forsyth "open", 32*37da2899SCharles.Forsyth "puts", 33*37da2899SCharles.Forsyth "read" , 34*37da2899SCharles.Forsyth "seek" , 35*37da2899SCharles.Forsyth "tell" 36*37da2899SCharles.Forsyth}; 37*37da2899SCharles.Forsyth 38*37da2899SCharles.Forsythinit() : string { 39*37da2899SCharles.Forsyth started=1; 40*37da2899SCharles.Forsyth str = load String String->PATH; 41*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 42*37da2899SCharles.Forsyth bufmod = load Bufio Bufio->PATH; 43*37da2899SCharles.Forsyth if (str==nil || bufmod==nil) 44*37da2899SCharles.Forsyth return "Can't initialise IO package."; 45*37da2899SCharles.Forsyth name2fid = array[100] of (ref Iobuf,string,int); 46*37da2899SCharles.Forsyth stdout := bufmod->fopen(sys->fildes(1),bufmod->OWRITE); 47*37da2899SCharles.Forsyth if (stdout==nil) 48*37da2899SCharles.Forsyth return "cannot open stdout for writing.\n"; 49*37da2899SCharles.Forsyth name2fid[0]=(nil,"stdin",0); 50*37da2899SCharles.Forsyth name2fid[1]=(stdout,"stdout",0); 51*37da2899SCharles.Forsyth return nil; 52*37da2899SCharles.Forsyth} 53*37da2899SCharles.Forsyth 54*37da2899SCharles.Forsythabout() : array of string{ 55*37da2899SCharles.Forsyth return valid_commands; 56*37da2899SCharles.Forsyth} 57*37da2899SCharles.Forsyth 58*37da2899SCharles.Forsythexec(tcl : ref Tcl_Core->TclData,argv : array of string) : (int,string) { 59*37da2899SCharles.Forsyth tclmod=tcl; 60*37da2899SCharles.Forsyth msg :string; 61*37da2899SCharles.Forsyth if (!started) init(); 62*37da2899SCharles.Forsyth error=0; 63*37da2899SCharles.Forsyth case argv[0] { 64*37da2899SCharles.Forsyth "close" => 65*37da2899SCharles.Forsyth msg = do_close(argv); 66*37da2899SCharles.Forsyth return (error,msg); 67*37da2899SCharles.Forsyth "eof" => 68*37da2899SCharles.Forsyth msg = do_eof(argv); 69*37da2899SCharles.Forsyth return (error,msg); 70*37da2899SCharles.Forsyth "file" => 71*37da2899SCharles.Forsyth msg = do_nothing(argv); 72*37da2899SCharles.Forsyth return (error,msg); 73*37da2899SCharles.Forsyth "flush" => 74*37da2899SCharles.Forsyth msg = do_nothing(argv); 75*37da2899SCharles.Forsyth return (error,msg); 76*37da2899SCharles.Forsyth "gets" => 77*37da2899SCharles.Forsyth msg = do_gets(argv); 78*37da2899SCharles.Forsyth return (error,msg); 79*37da2899SCharles.Forsyth "open" => 80*37da2899SCharles.Forsyth msg = do_open(argv); 81*37da2899SCharles.Forsyth return (error,msg); 82*37da2899SCharles.Forsyth "puts" => 83*37da2899SCharles.Forsyth msg = do_puts(argv); 84*37da2899SCharles.Forsyth return (error,msg); 85*37da2899SCharles.Forsyth "read" => 86*37da2899SCharles.Forsyth msg = do_read(argv); 87*37da2899SCharles.Forsyth return (error,msg); 88*37da2899SCharles.Forsyth "seek" => 89*37da2899SCharles.Forsyth msg = do_seek(argv); 90*37da2899SCharles.Forsyth return (error,msg); 91*37da2899SCharles.Forsyth "tell" => 92*37da2899SCharles.Forsyth msg = do_nothing(argv); 93*37da2899SCharles.Forsyth return (error,msg); 94*37da2899SCharles.Forsyth } 95*37da2899SCharles.Forsyth return (1,nil); 96*37da2899SCharles.Forsyth} 97*37da2899SCharles.Forsyth 98*37da2899SCharles.Forsythdo_nothing(argv : array of string) : string { 99*37da2899SCharles.Forsyth if (len argv==0); 100*37da2899SCharles.Forsyth return nil; 101*37da2899SCharles.Forsyth} 102*37da2899SCharles.Forsyth 103*37da2899SCharles.Forsythdo_close(argv : array of string) : string { 104*37da2899SCharles.Forsyth iob : ref Iobuf; 105*37da2899SCharles.Forsyth name : string; 106*37da2899SCharles.Forsyth j : int; 107*37da2899SCharles.Forsyth iob=nil; 108*37da2899SCharles.Forsyth if (len argv!=2) 109*37da2899SCharles.Forsyth return notify(1,"close fileId"); 110*37da2899SCharles.Forsyth for(i:=0;i<len name2fid;i++){ 111*37da2899SCharles.Forsyth (iob,name,j)=name2fid[i]; 112*37da2899SCharles.Forsyth if (name==argv[1]) 113*37da2899SCharles.Forsyth break; 114*37da2899SCharles.Forsyth } 115*37da2899SCharles.Forsyth if (iob==nil) 116*37da2899SCharles.Forsyth return notify(0,sys->sprint("bad file identifier \"%s\"", 117*37da2899SCharles.Forsyth argv[1])); 118*37da2899SCharles.Forsyth iob.flush(); 119*37da2899SCharles.Forsyth iob.close(); 120*37da2899SCharles.Forsyth iob=nil; 121*37da2899SCharles.Forsyth name2fid[i]=(nil,"",0); 122*37da2899SCharles.Forsyth return nil; 123*37da2899SCharles.Forsyth} 124*37da2899SCharles.Forsyth 125*37da2899SCharles.Forsythdo_eof(argv : array of string) : string { 126*37da2899SCharles.Forsyth name : string; 127*37da2899SCharles.Forsyth j : int; 128*37da2899SCharles.Forsyth iob : ref Iobuf; 129*37da2899SCharles.Forsyth if (len argv!=2) 130*37da2899SCharles.Forsyth return notify(1,"eof fileId"); 131*37da2899SCharles.Forsyth for(i:=0;i<len name2fid;i++){ 132*37da2899SCharles.Forsyth (iob,name,j)=name2fid[i]; 133*37da2899SCharles.Forsyth if (name==argv[1]) 134*37da2899SCharles.Forsyth return string j; 135*37da2899SCharles.Forsyth } 136*37da2899SCharles.Forsyth return notify(0,sys->sprint("bad file identifier \"%s\"",argv[1])); 137*37da2899SCharles.Forsyth} 138*37da2899SCharles.Forsyth 139*37da2899SCharles.Forsyth 140*37da2899SCharles.Forsythdo_gets(argv : array of string) : string { 141*37da2899SCharles.Forsyth iob : ref Iobuf; 142*37da2899SCharles.Forsyth line : string; 143*37da2899SCharles.Forsyth if (len argv==1 || len argv > 3) 144*37da2899SCharles.Forsyth return notify(1,"gets fileId ?varName?"); 145*37da2899SCharles.Forsyth if (argv[1]=="stdin") 146*37da2899SCharles.Forsyth line = <- tclmod.lines; 147*37da2899SCharles.Forsyth else{ 148*37da2899SCharles.Forsyth iob=lookup_iob(argv[1]); 149*37da2899SCharles.Forsyth if (iob==nil) 150*37da2899SCharles.Forsyth return notify(0,sys->sprint( 151*37da2899SCharles.Forsyth "bad file identifier \"%s\"",argv[1])); 152*37da2899SCharles.Forsyth line=iob.gets('\n'); 153*37da2899SCharles.Forsyth } 154*37da2899SCharles.Forsyth if (line==nil){ 155*37da2899SCharles.Forsyth set_eof(iob); 156*37da2899SCharles.Forsyth return nil; 157*37da2899SCharles.Forsyth } 158*37da2899SCharles.Forsyth return line[0:len line -1]; 159*37da2899SCharles.Forsyth} 160*37da2899SCharles.Forsyth 161*37da2899SCharles.Forsythdo_seek(argv : array of string) : string { 162*37da2899SCharles.Forsyth iob : ref Iobuf; 163*37da2899SCharles.Forsyth if (len argv < 3 || len argv > 4) 164*37da2899SCharles.Forsyth return notify(1,"seek fileId offset ?origin?"); 165*37da2899SCharles.Forsyth iob=lookup_iob(argv[1]); 166*37da2899SCharles.Forsyth if (iob==nil) 167*37da2899SCharles.Forsyth return notify(0,sys->sprint( 168*37da2899SCharles.Forsyth "bad file identifier \"%s\"",argv[1])); 169*37da2899SCharles.Forsyth flag := Sys->SEEKSTART; 170*37da2899SCharles.Forsyth if (len argv == 4) { 171*37da2899SCharles.Forsyth case argv[3] { 172*37da2899SCharles.Forsyth "SEEKSTART" => 173*37da2899SCharles.Forsyth flag = Sys->SEEKSTART; 174*37da2899SCharles.Forsyth "SEEKRELA" => 175*37da2899SCharles.Forsyth flag = Sys->SEEKRELA; 176*37da2899SCharles.Forsyth "SEEKEND" => 177*37da2899SCharles.Forsyth flag = Sys->SEEKEND; 178*37da2899SCharles.Forsyth * => 179*37da2899SCharles.Forsyth return notify(0,sys->sprint( 180*37da2899SCharles.Forsyth "illegal access mode \"%s\"", 181*37da2899SCharles.Forsyth argv[3])); 182*37da2899SCharles.Forsyth } 183*37da2899SCharles.Forsyth } 184*37da2899SCharles.Forsyth iob.seek(big argv[2],flag); 185*37da2899SCharles.Forsyth return nil; 186*37da2899SCharles.Forsyth} 187*37da2899SCharles.Forsyth 188*37da2899SCharles.Forsythdo_open(argv : array of string) : string { 189*37da2899SCharles.Forsyth flag : int; 190*37da2899SCharles.Forsyth if (len argv==1 || len argv > 3) 191*37da2899SCharles.Forsyth return notify(1, 192*37da2899SCharles.Forsyth "open filename ?access? ?permissions?"); 193*37da2899SCharles.Forsyth name:=argv[1]; 194*37da2899SCharles.Forsyth if (len argv == 2) 195*37da2899SCharles.Forsyth flag = bufmod->OREAD; 196*37da2899SCharles.Forsyth else { 197*37da2899SCharles.Forsyth case argv[2] { 198*37da2899SCharles.Forsyth "OREAD" => 199*37da2899SCharles.Forsyth flag = bufmod->OREAD; 200*37da2899SCharles.Forsyth "OWRITE" => 201*37da2899SCharles.Forsyth flag = bufmod->OWRITE; 202*37da2899SCharles.Forsyth "ORDWR" => 203*37da2899SCharles.Forsyth flag = bufmod->ORDWR; 204*37da2899SCharles.Forsyth * => 205*37da2899SCharles.Forsyth return notify(0,sys->sprint( 206*37da2899SCharles.Forsyth "illegal access mode \"%s\"", 207*37da2899SCharles.Forsyth argv[2])); 208*37da2899SCharles.Forsyth } 209*37da2899SCharles.Forsyth } 210*37da2899SCharles.Forsyth iob := bufmod->open(name,flag); 211*37da2899SCharles.Forsyth if (iob==nil) 212*37da2899SCharles.Forsyth return notify(0, 213*37da2899SCharles.Forsyth sys->sprint("couldn't open \"%s\": No" + 214*37da2899SCharles.Forsyth " such file or directory.",name)); 215*37da2899SCharles.Forsyth for (i:=0;i<len name2fid;i++){ 216*37da2899SCharles.Forsyth (iob2,name2,j):=name2fid[i]; 217*37da2899SCharles.Forsyth if (iob2==nil){ 218*37da2899SCharles.Forsyth name2fid[i]=(iob,"file"+string i,0); 219*37da2899SCharles.Forsyth return "file"+string i; 220*37da2899SCharles.Forsyth } 221*37da2899SCharles.Forsyth } 222*37da2899SCharles.Forsyth return notify(0,"File table full!"); 223*37da2899SCharles.Forsyth} 224*37da2899SCharles.Forsyth 225*37da2899SCharles.Forsythdo_puts(argv : array of string) : string { 226*37da2899SCharles.Forsyth iob : ref Iobuf; 227*37da2899SCharles.Forsyth if (len argv==1 || len argv >4) 228*37da2899SCharles.Forsyth return notify(1, 229*37da2899SCharles.Forsyth "puts ?-nonewline? ?fileId? string"); 230*37da2899SCharles.Forsyth if (argv[1]=="-nonewline"){ 231*37da2899SCharles.Forsyth if (len argv==2) 232*37da2899SCharles.Forsyth return notify(1, 233*37da2899SCharles.Forsyth "puts ?-nonewline? ?fileId? string"); 234*37da2899SCharles.Forsyth if (len argv==3) 235*37da2899SCharles.Forsyth sys->print("%s",argv[2]); 236*37da2899SCharles.Forsyth else{ 237*37da2899SCharles.Forsyth iob=lookup_iob(argv[2]); 238*37da2899SCharles.Forsyth if (iob==nil) 239*37da2899SCharles.Forsyth return notify(0,sys->sprint( 240*37da2899SCharles.Forsyth "bad file identifier \"%s\"", 241*37da2899SCharles.Forsyth argv[2])); 242*37da2899SCharles.Forsyth iob.puts(argv[3]); 243*37da2899SCharles.Forsyth iob.flush(); 244*37da2899SCharles.Forsyth } 245*37da2899SCharles.Forsyth } else { 246*37da2899SCharles.Forsyth if (len argv==2) 247*37da2899SCharles.Forsyth sys->print("%s\n",argv[1]); 248*37da2899SCharles.Forsyth if (len argv==3){ 249*37da2899SCharles.Forsyth iob=lookup_iob(argv[1]); 250*37da2899SCharles.Forsyth if (iob==nil) 251*37da2899SCharles.Forsyth return notify(0,sys->sprint( 252*37da2899SCharles.Forsyth "bad file identifier \"%s\"", 253*37da2899SCharles.Forsyth argv[1])); 254*37da2899SCharles.Forsyth iob.puts(argv[2]+"\n"); 255*37da2899SCharles.Forsyth iob.flush(); 256*37da2899SCharles.Forsyth 257*37da2899SCharles.Forsyth } 258*37da2899SCharles.Forsyth if (len argv==4) 259*37da2899SCharles.Forsyth return notify(0,sys->sprint( 260*37da2899SCharles.Forsyth "bad argument \"%s\": should be"+ 261*37da2899SCharles.Forsyth " \"nonewline\"",argv[3])); 262*37da2899SCharles.Forsyth } 263*37da2899SCharles.Forsyth return nil; 264*37da2899SCharles.Forsyth} 265*37da2899SCharles.Forsyth 266*37da2899SCharles.Forsythdo_read(argv : array of string) : string { 267*37da2899SCharles.Forsyth iob : ref Iobuf; 268*37da2899SCharles.Forsyth line :string; 269*37da2899SCharles.Forsyth if (len argv<2 || len argv>3) 270*37da2899SCharles.Forsyth return notify(1, 271*37da2899SCharles.Forsyth "read fileId ?numBytes?\" or \"read ?-nonewline? fileId"); 272*37da2899SCharles.Forsyth if (argv[1]!="-nonewline"){ 273*37da2899SCharles.Forsyth iob=lookup_iob(argv[1]); 274*37da2899SCharles.Forsyth if (iob==nil) 275*37da2899SCharles.Forsyth return notify(0,sys->sprint( 276*37da2899SCharles.Forsyth "bad file identifier \"%s\"", argv[1])); 277*37da2899SCharles.Forsyth if (len argv == 3){ 278*37da2899SCharles.Forsyth buf := array[int argv[2]] of byte; 279*37da2899SCharles.Forsyth n:=iob.read(buf,len buf); 280*37da2899SCharles.Forsyth if (n==0){ 281*37da2899SCharles.Forsyth set_eof(iob); 282*37da2899SCharles.Forsyth return nil; 283*37da2899SCharles.Forsyth } 284*37da2899SCharles.Forsyth return string buf[0:n]; 285*37da2899SCharles.Forsyth } 286*37da2899SCharles.Forsyth line=iob.gets('\n'); 287*37da2899SCharles.Forsyth if (line==nil) 288*37da2899SCharles.Forsyth set_eof(iob); 289*37da2899SCharles.Forsyth else 290*37da2899SCharles.Forsyth line[len line]='\n'; 291*37da2899SCharles.Forsyth return line; 292*37da2899SCharles.Forsyth }else{ 293*37da2899SCharles.Forsyth iob=lookup_iob(argv[2]); 294*37da2899SCharles.Forsyth if (iob==nil) 295*37da2899SCharles.Forsyth return notify(0,sys->sprint( 296*37da2899SCharles.Forsyth "bad file identifier \"%s\"", argv[2])); 297*37da2899SCharles.Forsyth line=iob.gets('\n'); 298*37da2899SCharles.Forsyth if (line==nil) 299*37da2899SCharles.Forsyth set_eof(iob); 300*37da2899SCharles.Forsyth return line; 301*37da2899SCharles.Forsyth } 302*37da2899SCharles.Forsyth} 303*37da2899SCharles.Forsyth 304*37da2899SCharles.Forsyth 305*37da2899SCharles.Forsyth 306*37da2899SCharles.Forsyth 307*37da2899SCharles.Forsyth 308*37da2899SCharles.Forsyth 309*37da2899SCharles.Forsyth 310*37da2899SCharles.Forsyth 311*37da2899SCharles.Forsythnotify(num : int,s : string) : string { 312*37da2899SCharles.Forsyth error=1; 313*37da2899SCharles.Forsyth case num{ 314*37da2899SCharles.Forsyth 1 => 315*37da2899SCharles.Forsyth return sys->sprint( 316*37da2899SCharles.Forsyth "wrong # args: should be \"%s\"",s); 317*37da2899SCharles.Forsyth * => 318*37da2899SCharles.Forsyth return s; 319*37da2899SCharles.Forsyth } 320*37da2899SCharles.Forsyth} 321*37da2899SCharles.Forsyth 322*37da2899SCharles.Forsyth 323*37da2899SCharles.Forsythlookup_iob(s:string) : ref Iobuf{ 324*37da2899SCharles.Forsyth iob : ref Iobuf; 325*37da2899SCharles.Forsyth name : string; 326*37da2899SCharles.Forsyth j : int; 327*37da2899SCharles.Forsyth for(i:=0;i<len name2fid;i++){ 328*37da2899SCharles.Forsyth (iob,name,j)=name2fid[i]; 329*37da2899SCharles.Forsyth if (name==s) 330*37da2899SCharles.Forsyth break; 331*37da2899SCharles.Forsyth } 332*37da2899SCharles.Forsyth if (i==len name2fid) 333*37da2899SCharles.Forsyth return nil; 334*37da2899SCharles.Forsyth return iob; 335*37da2899SCharles.Forsyth} 336*37da2899SCharles.Forsyth 337*37da2899SCharles.Forsythset_eof(iob : ref Iobuf) { 338*37da2899SCharles.Forsyth iob2 : ref Iobuf; 339*37da2899SCharles.Forsyth name : string; 340*37da2899SCharles.Forsyth j : int; 341*37da2899SCharles.Forsyth for(i:=0;i<len name2fid;i++){ 342*37da2899SCharles.Forsyth (iob2,name,j)=name2fid[i]; 343*37da2899SCharles.Forsyth if (iob==iob2) 344*37da2899SCharles.Forsyth break; 345*37da2899SCharles.Forsyth } 346*37da2899SCharles.Forsyth if (i!=len name2fid) 347*37da2899SCharles.Forsyth name2fid[i]=(iob,name,1); 348*37da2899SCharles.Forsyth return; 349*37da2899SCharles.Forsyth} 350*37da2899SCharles.Forsyth 351