xref: /inferno-os/appl/lib/tcl_io.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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