xref: /inferno-os/appl/cmd/sh/string.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Shellbuiltin;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth	sys: Sys;
5*37da2899SCharles.Forsythinclude "draw.m";
6*37da2899SCharles.Forsythinclude "sh.m";
7*37da2899SCharles.Forsyth	sh: Sh;
8*37da2899SCharles.Forsyth	Listnode, Context: import sh;
9*37da2899SCharles.Forsyth	myself: Shellbuiltin;
10*37da2899SCharles.Forsythinclude "string.m";
11*37da2899SCharles.Forsyth	str: String;
12*37da2899SCharles.Forsyth
13*37da2899SCharles.Forsythinitbuiltin(ctxt: ref Context, shmod: Sh): string
14*37da2899SCharles.Forsyth{
15*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
16*37da2899SCharles.Forsyth	sh = shmod;
17*37da2899SCharles.Forsyth	myself = load Shellbuiltin "$self";
18*37da2899SCharles.Forsyth	if (myself == nil)
19*37da2899SCharles.Forsyth		ctxt.fail("bad module", sys->sprint("string: cannot load self: %r"));
20*37da2899SCharles.Forsyth	str = load String String->PATH;
21*37da2899SCharles.Forsyth	if (str == nil)
22*37da2899SCharles.Forsyth		ctxt.fail("bad module",
23*37da2899SCharles.Forsyth			sys->sprint("string: cannot load %s: %r", String->PATH));
24*37da2899SCharles.Forsyth	ctxt.addbuiltin("prefix", myself);
25*37da2899SCharles.Forsyth	ctxt.addbuiltin("in", myself);
26*37da2899SCharles.Forsyth	names := array[] of {
27*37da2899SCharles.Forsyth	"splitl", "splitr", "drop", "take", "splitstrl", "splitstrr",
28*37da2899SCharles.Forsyth	"tolower", "toupper", "len", "alen", "slice", "fields",
29*37da2899SCharles.Forsyth	"padl", "padr",
30*37da2899SCharles.Forsyth	};
31*37da2899SCharles.Forsyth	for (i := 0; i < len names; i++)
32*37da2899SCharles.Forsyth		ctxt.addsbuiltin(names[i], myself);
33*37da2899SCharles.Forsyth	return nil;
34*37da2899SCharles.Forsyth}
35*37da2899SCharles.Forsyth
36*37da2899SCharles.Forsythwhatis(nil: ref Sh->Context, nil: Sh, nil: string, nil: int): string
37*37da2899SCharles.Forsyth{
38*37da2899SCharles.Forsyth	return nil;
39*37da2899SCharles.Forsyth}
40*37da2899SCharles.Forsyth
41*37da2899SCharles.Forsythgetself(): Shellbuiltin
42*37da2899SCharles.Forsyth{
43*37da2899SCharles.Forsyth	return myself;
44*37da2899SCharles.Forsyth}
45*37da2899SCharles.Forsyth
46*37da2899SCharles.Forsythrunbuiltin(ctxt: ref Context, nil: Sh,
47*37da2899SCharles.Forsyth			argv: list of ref Listnode, nil: int): string
48*37da2899SCharles.Forsyth{
49*37da2899SCharles.Forsyth	case (hd argv).word {
50*37da2899SCharles.Forsyth	"prefix" =>
51*37da2899SCharles.Forsyth		(a, b) := earg2("prefix", ctxt, argv);
52*37da2899SCharles.Forsyth		if (!str->prefix(a, b))
53*37da2899SCharles.Forsyth			return "false";
54*37da2899SCharles.Forsyth	"in" =>
55*37da2899SCharles.Forsyth		(a, b) := earg2("in", ctxt, argv);
56*37da2899SCharles.Forsyth		if (a == nil || !str->in(a[0], b))
57*37da2899SCharles.Forsyth			return "false";
58*37da2899SCharles.Forsyth	}
59*37da2899SCharles.Forsyth	return nil;
60*37da2899SCharles.Forsyth}
61*37da2899SCharles.Forsyth
62*37da2899SCharles.Forsythrunsbuiltin(ctxt: ref Context, nil: Sh,
63*37da2899SCharles.Forsyth			argv: list of ref Listnode): list of ref Listnode
64*37da2899SCharles.Forsyth{
65*37da2899SCharles.Forsyth	name := (hd argv).word;
66*37da2899SCharles.Forsyth	case name {
67*37da2899SCharles.Forsyth	"splitl" =>
68*37da2899SCharles.Forsyth		(a, b) := earg2("splitl", ctxt, argv);
69*37da2899SCharles.Forsyth		return mk2(str->splitl(a, b));
70*37da2899SCharles.Forsyth	"splitr" =>
71*37da2899SCharles.Forsyth		(a, b) := earg2("splitr", ctxt, argv);
72*37da2899SCharles.Forsyth		return mk2(str->splitr(a, b));
73*37da2899SCharles.Forsyth	"drop" =>
74*37da2899SCharles.Forsyth		(a, b) := earg2("drop", ctxt, argv);
75*37da2899SCharles.Forsyth		return mk1(str->drop(a, b));
76*37da2899SCharles.Forsyth	"take" =>
77*37da2899SCharles.Forsyth		(a, b) := earg2("take", ctxt, argv);
78*37da2899SCharles.Forsyth		return mk1(str->take(a, b));
79*37da2899SCharles.Forsyth	"splitstrl" =>
80*37da2899SCharles.Forsyth		(a, b) := earg2("splitstrl", ctxt, argv);
81*37da2899SCharles.Forsyth		return mk2(str->splitstrl(a, b));
82*37da2899SCharles.Forsyth	"splitstrr" =>
83*37da2899SCharles.Forsyth		(a, b) := earg2("splitstrr", ctxt, argv);
84*37da2899SCharles.Forsyth		return mk2(str->splitstrr(a, b));
85*37da2899SCharles.Forsyth	"tolower" =>
86*37da2899SCharles.Forsyth		return mk1(str->tolower(earg1("tolower", ctxt, argv)));
87*37da2899SCharles.Forsyth	"toupper" =>
88*37da2899SCharles.Forsyth		return mk1(str->toupper(earg1("tolower", ctxt, argv)));
89*37da2899SCharles.Forsyth	"len" =>
90*37da2899SCharles.Forsyth		return mk1(string len earg1("len", ctxt, argv));
91*37da2899SCharles.Forsyth	"alen" =>
92*37da2899SCharles.Forsyth		return mk1(string len array of byte earg1("alen", ctxt, argv));
93*37da2899SCharles.Forsyth	"slice" =>
94*37da2899SCharles.Forsyth		return sbuiltin_slice(ctxt, argv);
95*37da2899SCharles.Forsyth	"fields" =>
96*37da2899SCharles.Forsyth		return sbuiltin_fields(ctxt, argv);
97*37da2899SCharles.Forsyth	"padl" =>
98*37da2899SCharles.Forsyth		return sbuiltin_pad(ctxt, argv, -1);
99*37da2899SCharles.Forsyth	"padr" =>
100*37da2899SCharles.Forsyth		return sbuiltin_pad(ctxt, argv, 1);
101*37da2899SCharles.Forsyth	}
102*37da2899SCharles.Forsyth	return nil;
103*37da2899SCharles.Forsyth}
104*37da2899SCharles.Forsyth
105*37da2899SCharles.Forsythsbuiltin_pad(ctxt: ref Context, argv: list of ref Listnode, dir: int): list of ref Listnode
106*37da2899SCharles.Forsyth{
107*37da2899SCharles.Forsyth	if (tl argv == nil || !isnum((hd tl argv).word))
108*37da2899SCharles.Forsyth		ctxt.fail("usage", "usage: " + (hd argv).word + " n [arg...]");
109*37da2899SCharles.Forsyth
110*37da2899SCharles.Forsyth	argv = tl argv;
111*37da2899SCharles.Forsyth	n := int (hd argv).word * dir;
112*37da2899SCharles.Forsyth	s := "";
113*37da2899SCharles.Forsyth	for (argv = tl argv; argv != nil; argv = tl argv) {
114*37da2899SCharles.Forsyth		s += word(hd argv);
115*37da2899SCharles.Forsyth		if (tl argv != nil)
116*37da2899SCharles.Forsyth			s[len s] = ' ';
117*37da2899SCharles.Forsyth	}
118*37da2899SCharles.Forsyth	if (n != 0)
119*37da2899SCharles.Forsyth		s =  sys->sprint("%*s", n, s);
120*37da2899SCharles.Forsyth	return ref Listnode(nil, s) :: nil;
121*37da2899SCharles.Forsyth}
122*37da2899SCharles.Forsyth
123*37da2899SCharles.Forsythsbuiltin_fields(ctxt: ref Context, argv: list of ref Listnode): list of ref Listnode
124*37da2899SCharles.Forsyth{
125*37da2899SCharles.Forsyth	argv = tl argv;
126*37da2899SCharles.Forsyth	if (len argv != 2)
127*37da2899SCharles.Forsyth		ctxt.fail("usage", "usage: fields cl s");
128*37da2899SCharles.Forsyth	cl := word(hd argv);
129*37da2899SCharles.Forsyth	s := word(hd tl argv);
130*37da2899SCharles.Forsyth
131*37da2899SCharles.Forsyth	r: list of string;
132*37da2899SCharles.Forsyth
133*37da2899SCharles.Forsyth	n := 0;
134*37da2899SCharles.Forsyth	for (i := 0; i < len s; i++) {
135*37da2899SCharles.Forsyth		if (str->in(s[i], cl)) {
136*37da2899SCharles.Forsyth			r = s[n:i] :: r;
137*37da2899SCharles.Forsyth			n = i + 1;
138*37da2899SCharles.Forsyth		}
139*37da2899SCharles.Forsyth	}
140*37da2899SCharles.Forsyth	r = s[n:i] :: r;
141*37da2899SCharles.Forsyth	rl: list of ref Listnode;
142*37da2899SCharles.Forsyth	for (; r != nil; r = tl r)
143*37da2899SCharles.Forsyth		rl = ref Listnode(nil, hd r) :: rl;
144*37da2899SCharles.Forsyth	return rl;
145*37da2899SCharles.Forsyth}
146*37da2899SCharles.Forsyth
147*37da2899SCharles.Forsyth
148*37da2899SCharles.Forsythsbuiltin_slice(ctxt: ref Context, argv: list of ref Listnode): list of ref Listnode
149*37da2899SCharles.Forsyth{
150*37da2899SCharles.Forsyth	argv = tl argv;
151*37da2899SCharles.Forsyth	if (len argv != 3 || !isnum((hd argv).word) ||
152*37da2899SCharles.Forsyth			(hd tl argv).word != "end" && !isnum((hd tl argv).word))
153*37da2899SCharles.Forsyth		ctxt.fail("usage", "usage: slice start end arg");
154*37da2899SCharles.Forsyth	n1 := int (hd argv).word;
155*37da2899SCharles.Forsyth	n2: int;
156*37da2899SCharles.Forsyth	s := word(hd tl tl argv);
157*37da2899SCharles.Forsyth	r := "";
158*37da2899SCharles.Forsyth	if ((hd tl argv).word == "end")
159*37da2899SCharles.Forsyth		n2 = len s;
160*37da2899SCharles.Forsyth	else
161*37da2899SCharles.Forsyth		n2 = int (hd tl argv).word;
162*37da2899SCharles.Forsyth	if (n2 > len s)
163*37da2899SCharles.Forsyth		n2 = len s;
164*37da2899SCharles.Forsyth	if (n1 > len s)
165*37da2899SCharles.Forsyth		n1 = len s;
166*37da2899SCharles.Forsyth	if (n2 > n1)
167*37da2899SCharles.Forsyth		r = s[n1:n2];
168*37da2899SCharles.Forsyth	return mk1(r);
169*37da2899SCharles.Forsyth}
170*37da2899SCharles.Forsyth
171*37da2899SCharles.Forsythearg2(cmd: string, ctxt: ref Context, argv: list of ref Listnode): (string, string)
172*37da2899SCharles.Forsyth{
173*37da2899SCharles.Forsyth	argv = tl argv;
174*37da2899SCharles.Forsyth	if (len argv != 2)
175*37da2899SCharles.Forsyth		ctxt.fail("usage", "usage: " + cmd + " arg1 arg2");
176*37da2899SCharles.Forsyth	return (word(hd argv), word(hd tl argv));
177*37da2899SCharles.Forsyth}
178*37da2899SCharles.Forsyth
179*37da2899SCharles.Forsythearg1(cmd: string, ctxt: ref Context, argv: list of ref Listnode): string
180*37da2899SCharles.Forsyth{
181*37da2899SCharles.Forsyth	if (len argv != 2)
182*37da2899SCharles.Forsyth		ctxt.fail("usage", "usage: " + cmd + " arg");
183*37da2899SCharles.Forsyth	return word(hd tl argv);
184*37da2899SCharles.Forsyth}
185*37da2899SCharles.Forsyth
186*37da2899SCharles.Forsythmk2(x: (string, string)): list of ref Listnode
187*37da2899SCharles.Forsyth{
188*37da2899SCharles.Forsyth	(a, b) := x;
189*37da2899SCharles.Forsyth	return ref Listnode(nil, a) :: ref Listnode(nil, b) :: nil;
190*37da2899SCharles.Forsyth}
191*37da2899SCharles.Forsyth
192*37da2899SCharles.Forsythmk1(x: string): list of ref Listnode
193*37da2899SCharles.Forsyth{
194*37da2899SCharles.Forsyth	return ref Listnode(nil, x) :: nil;
195*37da2899SCharles.Forsyth}
196*37da2899SCharles.Forsyth
197*37da2899SCharles.Forsythisnum(s: string): int
198*37da2899SCharles.Forsyth{
199*37da2899SCharles.Forsyth	for (i := 0; i < len s; i++)
200*37da2899SCharles.Forsyth		if (s[i] > '9' || s[i] < '0')
201*37da2899SCharles.Forsyth			return 0;
202*37da2899SCharles.Forsyth	return 1;
203*37da2899SCharles.Forsyth}
204*37da2899SCharles.Forsyth
205*37da2899SCharles.Forsythword(n: ref Listnode): string
206*37da2899SCharles.Forsyth{
207*37da2899SCharles.Forsyth	if (n.word != nil)
208*37da2899SCharles.Forsyth		return n.word;
209*37da2899SCharles.Forsyth	if (n.cmd != nil)
210*37da2899SCharles.Forsyth		n.word = sh->cmd2string(n.cmd);
211*37da2899SCharles.Forsyth	return n.word;
212*37da2899SCharles.Forsyth}
213