xref: /inferno-os/appl/lib/tcl_list.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 "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