xref: /plan9/sys/src/cmd/acid/builtin.c (revision 7c70c028d2d46a27a61ae88e6df0eb0935d9da7a)
1bd389b36SDavid du Colombier #include <u.h>
2bd389b36SDavid du Colombier #include <libc.h>
3bd389b36SDavid du Colombier #include <bio.h>
4bd389b36SDavid du Colombier #include <ctype.h>
5bd389b36SDavid du Colombier #include <mach.h>
6219b2ee8SDavid du Colombier #include <regexp.h>
7bd389b36SDavid du Colombier #define Extern extern
8bd389b36SDavid du Colombier #include "acid.h"
9bd389b36SDavid du Colombier #include "y.tab.h"
10bd389b36SDavid du Colombier 
11bd389b36SDavid du Colombier void	cvtatof(Node*, Node*);
12bd389b36SDavid du Colombier void	cvtatoi(Node*, Node*);
13bd389b36SDavid du Colombier void	cvtitoa(Node*, Node*);
14bd389b36SDavid du Colombier void	bprint(Node*, Node*);
15219b2ee8SDavid du Colombier void	funcbound(Node*, Node*);
16219b2ee8SDavid du Colombier void	printto(Node*, Node*);
17bd389b36SDavid du Colombier void	getfile(Node*, Node*);
18bd389b36SDavid du Colombier void	fmt(Node*, Node*);
19bd389b36SDavid du Colombier void	pcfile(Node*, Node*);
20bd389b36SDavid du Colombier void	pcline(Node*, Node*);
21bd389b36SDavid du Colombier void	setproc(Node*, Node*);
22bd389b36SDavid du Colombier void	strace(Node*, Node*);
23bd389b36SDavid du Colombier void	follow(Node*, Node*);
24bd389b36SDavid du Colombier void	reason(Node*, Node*);
25bd389b36SDavid du Colombier void	newproc(Node*, Node*);
26bd389b36SDavid du Colombier void	startstop(Node*, Node*);
27bd389b36SDavid du Colombier void	match(Node*, Node*);
28bd389b36SDavid du Colombier void	status(Node*, Node*);
29bd389b36SDavid du Colombier void	kill(Node*,Node*);
30bd389b36SDavid du Colombier void	waitstop(Node*, Node*);
31bd389b36SDavid du Colombier void	stop(Node*, Node*);
32bd389b36SDavid du Colombier void	start(Node*, Node*);
33bd389b36SDavid du Colombier void	filepc(Node*, Node*);
34bd389b36SDavid du Colombier void	doerror(Node*, Node*);
35bd389b36SDavid du Colombier void	rc(Node*, Node*);
36bd389b36SDavid du Colombier void	doaccess(Node*, Node*);
37219b2ee8SDavid du Colombier void	map(Node*, Node*);
38219b2ee8SDavid du Colombier void	readfile(Node*, Node*);
39219b2ee8SDavid du Colombier void	interpret(Node*, Node*);
40219b2ee8SDavid du Colombier void	include(Node*, Node*);
41219b2ee8SDavid du Colombier void	regexp(Node*, Node*);
429027b8f7SDavid du Colombier void	dosysr1(Node*, Node*);
43*7c70c028SDavid du Colombier void	fmtof(Node*, Node*) ;
44*7c70c028SDavid du Colombier void	dofmtsize(Node*, Node*) ;
45bd389b36SDavid du Colombier 
46bd389b36SDavid du Colombier typedef struct Btab Btab;
47bd389b36SDavid du Colombier struct Btab
48bd389b36SDavid du Colombier {
49bd389b36SDavid du Colombier 	char	*name;
50bd389b36SDavid du Colombier 	void	(*fn)(Node*, Node*);
51bd389b36SDavid du Colombier } tab[] =
52bd389b36SDavid du Colombier {
53bd389b36SDavid du Colombier 	"atof",		cvtatof,
54bd389b36SDavid du Colombier 	"atoi",		cvtatoi,
55bd389b36SDavid du Colombier 	"error",	doerror,
56bd389b36SDavid du Colombier 	"file",		getfile,
57219b2ee8SDavid du Colombier 	"readfile",	readfile,
58bd389b36SDavid du Colombier 	"access",	doaccess,
59bd389b36SDavid du Colombier 	"filepc",	filepc,
60219b2ee8SDavid du Colombier 	"fnbound",	funcbound,
61bd389b36SDavid du Colombier 	"fmt",		fmt,
62bd389b36SDavid du Colombier 	"follow",	follow,
63bd389b36SDavid du Colombier 	"itoa",		cvtitoa,
64bd389b36SDavid du Colombier 	"kill",		kill,
65bd389b36SDavid du Colombier 	"match",	match,
66bd389b36SDavid du Colombier 	"newproc",	newproc,
67bd389b36SDavid du Colombier 	"pcfile",	pcfile,
68bd389b36SDavid du Colombier 	"pcline",	pcline,
69bd389b36SDavid du Colombier 	"print",	bprint,
70219b2ee8SDavid du Colombier 	"printto",	printto,
71bd389b36SDavid du Colombier 	"rc",		rc,
72bd389b36SDavid du Colombier 	"reason",	reason,
73bd389b36SDavid du Colombier 	"setproc",	setproc,
74bd389b36SDavid du Colombier 	"start",	start,
75bd389b36SDavid du Colombier 	"startstop",	startstop,
76bd389b36SDavid du Colombier 	"status",	status,
77bd389b36SDavid du Colombier 	"stop",		stop,
78bd389b36SDavid du Colombier 	"strace",	strace,
799027b8f7SDavid du Colombier 	"sysr1",	dosysr1,
80bd389b36SDavid du Colombier 	"waitstop",	waitstop,
81219b2ee8SDavid du Colombier 	"map",		map,
82219b2ee8SDavid du Colombier 	"interpret",	interpret,
83219b2ee8SDavid du Colombier 	"include",	include,
84219b2ee8SDavid du Colombier 	"regexp",	regexp,
85*7c70c028SDavid du Colombier 	"fmtof",	fmtof,
86*7c70c028SDavid du Colombier 	"fmtsize",	dofmtsize,
87bd389b36SDavid du Colombier 	0
88bd389b36SDavid du Colombier };
89bd389b36SDavid du Colombier 
9037e88e97SDavid du Colombier char vfmt[] = "aBbcCdDfFgGiIoOqQrRsSuUVWxXYZ38";
917fb4e6f1SDavid du Colombier 
92bd389b36SDavid du Colombier void
mkprint(Lsym * s)93219b2ee8SDavid du Colombier mkprint(Lsym *s)
94219b2ee8SDavid du Colombier {
95219b2ee8SDavid du Colombier 	prnt = malloc(sizeof(Node));
967dd7cddfSDavid du Colombier 	memset(prnt, 0, sizeof(Node));
97219b2ee8SDavid du Colombier 	prnt->op = OCALL;
98219b2ee8SDavid du Colombier 	prnt->left = malloc(sizeof(Node));
997dd7cddfSDavid du Colombier 	memset(prnt->left, 0, sizeof(Node));
100219b2ee8SDavid du Colombier 	prnt->left->sym = s;
101219b2ee8SDavid du Colombier }
102219b2ee8SDavid du Colombier 
103219b2ee8SDavid du Colombier void
installbuiltin(void)104bd389b36SDavid du Colombier installbuiltin(void)
105bd389b36SDavid du Colombier {
106bd389b36SDavid du Colombier 	Btab *b;
107bd389b36SDavid du Colombier 	Lsym *s;
108bd389b36SDavid du Colombier 
109bd389b36SDavid du Colombier 	b = tab;
110bd389b36SDavid du Colombier 	while(b->name) {
111bd389b36SDavid du Colombier 		s = look(b->name);
112bd389b36SDavid du Colombier 		if(s == 0)
113bd389b36SDavid du Colombier 			s = enter(b->name, Tid);
114bd389b36SDavid du Colombier 
115bd389b36SDavid du Colombier 		s->builtin = b->fn;
116219b2ee8SDavid du Colombier 		if(b->fn == bprint)
117219b2ee8SDavid du Colombier 			mkprint(s);
118bd389b36SDavid du Colombier 		b++;
119bd389b36SDavid du Colombier 	}
120bd389b36SDavid du Colombier }
121bd389b36SDavid du Colombier 
122bd389b36SDavid du Colombier void
dosysr1(Node * r,Node *)1239027b8f7SDavid du Colombier dosysr1(Node *r, Node*)
1249027b8f7SDavid du Colombier {
1259027b8f7SDavid du Colombier 	extern int sysr1(void);
1269027b8f7SDavid du Colombier 
1279027b8f7SDavid du Colombier 	r->op = OCONST;
1289027b8f7SDavid du Colombier 	r->type = TINT;
1299027b8f7SDavid du Colombier 	r->fmt = 'D';
1309027b8f7SDavid du Colombier 	r->ival = sysr1();
1319027b8f7SDavid du Colombier }
1329027b8f7SDavid du Colombier 
1339027b8f7SDavid du Colombier void
match(Node * r,Node * args)134bd389b36SDavid du Colombier match(Node *r, Node *args)
135bd389b36SDavid du Colombier {
136bd389b36SDavid du Colombier 	int i;
137bd389b36SDavid du Colombier 	List *f;
138bd389b36SDavid du Colombier 	Node *av[Maxarg];
139bd389b36SDavid du Colombier 	Node resi, resl;
140bd389b36SDavid du Colombier 
141bd389b36SDavid du Colombier 	na = 0;
142bd389b36SDavid du Colombier 	flatten(av, args);
143bd389b36SDavid du Colombier 	if(na != 2)
144bd389b36SDavid du Colombier 		error("match(obj, list): arg count");
145bd389b36SDavid du Colombier 
146bd389b36SDavid du Colombier 	expr(av[1], &resl);
147bd389b36SDavid du Colombier 	if(resl.type != TLIST)
148bd389b36SDavid du Colombier 		error("match(obj, list): need list");
149bd389b36SDavid du Colombier 	expr(av[0], &resi);
150bd389b36SDavid du Colombier 
151bd389b36SDavid du Colombier 	r->op = OCONST;
152bd389b36SDavid du Colombier 	r->type = TINT;
153bd389b36SDavid du Colombier 	r->fmt = 'D';
154bd389b36SDavid du Colombier 	r->ival = -1;
155bd389b36SDavid du Colombier 
156bd389b36SDavid du Colombier 	i = 0;
157bd389b36SDavid du Colombier 	for(f = resl.l; f; f = f->next) {
158bd389b36SDavid du Colombier 		if(resi.type == f->type) {
159bd389b36SDavid du Colombier 			switch(resi.type) {
160bd389b36SDavid du Colombier 			case TINT:
161bd389b36SDavid du Colombier 				if(resi.ival == f->ival) {
162bd389b36SDavid du Colombier 					r->ival = i;
163bd389b36SDavid du Colombier 					return;
164bd389b36SDavid du Colombier 				}
165bd389b36SDavid du Colombier 				break;
166bd389b36SDavid du Colombier 			case TFLOAT:
167bd389b36SDavid du Colombier 				if(resi.fval == f->fval) {
168bd389b36SDavid du Colombier 					r->ival = i;
169bd389b36SDavid du Colombier 					return;
170bd389b36SDavid du Colombier 				}
171bd389b36SDavid du Colombier 				break;
172bd389b36SDavid du Colombier 			case TSTRING:
173bd389b36SDavid du Colombier 				if(scmp(resi.string, f->string)) {
174bd389b36SDavid du Colombier 					r->ival = i;
175bd389b36SDavid du Colombier 					return;
176bd389b36SDavid du Colombier 				}
177bd389b36SDavid du Colombier 				break;
178bd389b36SDavid du Colombier 			case TLIST:
179bd389b36SDavid du Colombier 				error("match(obj, list): not defined for list");
180bd389b36SDavid du Colombier 			}
181bd389b36SDavid du Colombier 		}
182bd389b36SDavid du Colombier 		i++;
183bd389b36SDavid du Colombier 	}
184bd389b36SDavid du Colombier }
185bd389b36SDavid du Colombier 
186bd389b36SDavid du Colombier void
newproc(Node * r,Node * args)187bd389b36SDavid du Colombier newproc(Node *r, Node *args)
188bd389b36SDavid du Colombier {
189bd389b36SDavid du Colombier 	int i;
190bd389b36SDavid du Colombier 	Node res;
191bd389b36SDavid du Colombier 	char *p, *e;
192219b2ee8SDavid du Colombier 	char *argv[Maxarg], buf[Strsize];
193bd389b36SDavid du Colombier 
194bd389b36SDavid du Colombier 	i = 1;
195bd389b36SDavid du Colombier 	argv[0] = aout;
196bd389b36SDavid du Colombier 
197bd389b36SDavid du Colombier 	if(args) {
198bd389b36SDavid du Colombier 		expr(args, &res);
199bd389b36SDavid du Colombier 		if(res.type != TSTRING)
200219b2ee8SDavid du Colombier 			error("newproc(): arg not string");
201bd389b36SDavid du Colombier 		if(res.string->len >= sizeof(buf))
202219b2ee8SDavid du Colombier 			error("newproc(): too many arguments");
203bd389b36SDavid du Colombier 		memmove(buf, res.string->string, res.string->len);
204219b2ee8SDavid du Colombier 		buf[res.string->len] = '\0';
205bd389b36SDavid du Colombier 		p = buf;
206bd389b36SDavid du Colombier 		e = buf+res.string->len;
207bd389b36SDavid du Colombier 		for(;;) {
208bd389b36SDavid du Colombier 			while(p < e && (*p == '\t' || *p == ' '))
209bd389b36SDavid du Colombier 				*p++ = '\0';
210bd389b36SDavid du Colombier 			if(p >= e)
211bd389b36SDavid du Colombier 				break;
212bd389b36SDavid du Colombier 			argv[i++] = p;
213219b2ee8SDavid du Colombier 			if(i >= Maxarg)
214219b2ee8SDavid du Colombier 				error("newproc: too many arguments");
215bd389b36SDavid du Colombier 			while(p < e && *p != '\t' && *p != ' ')
216bd389b36SDavid du Colombier 				p++;
217bd389b36SDavid du Colombier 		}
218bd389b36SDavid du Colombier 	}
219bd389b36SDavid du Colombier 	argv[i] = 0;
220bd389b36SDavid du Colombier 	r->op = OCONST;
221bd389b36SDavid du Colombier 	r->type = TINT;
222bd389b36SDavid du Colombier 	r->fmt = 'D';
223bd389b36SDavid du Colombier 	r->ival = nproc(argv);
224bd389b36SDavid du Colombier }
225bd389b36SDavid du Colombier 
226bd389b36SDavid du Colombier void
startstop(Node * r,Node * args)227bd389b36SDavid du Colombier startstop(Node *r, Node *args)
228bd389b36SDavid du Colombier {
229bd389b36SDavid du Colombier 	Node res;
230bd389b36SDavid du Colombier 
231bd389b36SDavid du Colombier 	USED(r);
232bd389b36SDavid du Colombier 	if(args == 0)
233bd389b36SDavid du Colombier 		error("startstop(pid): no pid");
234bd389b36SDavid du Colombier 	expr(args, &res);
235bd389b36SDavid du Colombier 	if(res.type != TINT)
236bd389b36SDavid du Colombier 		error("startstop(pid): arg type");
237bd389b36SDavid du Colombier 
238bd389b36SDavid du Colombier 	msg(res.ival, "startstop");
239bd389b36SDavid du Colombier 	notes(res.ival);
240bd389b36SDavid du Colombier 	dostop(res.ival);
241bd389b36SDavid du Colombier }
242bd389b36SDavid du Colombier 
243bd389b36SDavid du Colombier void
waitstop(Node * r,Node * args)244bd389b36SDavid du Colombier waitstop(Node *r, Node *args)
245bd389b36SDavid du Colombier {
246bd389b36SDavid du Colombier 	Node res;
247bd389b36SDavid du Colombier 
248bd389b36SDavid du Colombier 	USED(r);
249bd389b36SDavid du Colombier 	if(args == 0)
250bd389b36SDavid du Colombier 		error("waitstop(pid): no pid");
251bd389b36SDavid du Colombier 	expr(args, &res);
252bd389b36SDavid du Colombier 	if(res.type != TINT)
253bd389b36SDavid du Colombier 		error("waitstop(pid): arg type");
254bd389b36SDavid du Colombier 
255219b2ee8SDavid du Colombier 	Bflush(bout);
256bd389b36SDavid du Colombier 	msg(res.ival, "waitstop");
257bd389b36SDavid du Colombier 	notes(res.ival);
258bd389b36SDavid du Colombier 	dostop(res.ival);
259bd389b36SDavid du Colombier }
260bd389b36SDavid du Colombier 
261bd389b36SDavid du Colombier void
start(Node * r,Node * args)262bd389b36SDavid du Colombier start(Node *r, Node *args)
263bd389b36SDavid du Colombier {
264bd389b36SDavid du Colombier 	Node res;
265bd389b36SDavid du Colombier 
266bd389b36SDavid du Colombier 	USED(r);
267bd389b36SDavid du Colombier 	if(args == 0)
268bd389b36SDavid du Colombier 		error("start(pid): no pid");
269bd389b36SDavid du Colombier 	expr(args, &res);
270bd389b36SDavid du Colombier 	if(res.type != TINT)
271bd389b36SDavid du Colombier 		error("start(pid): arg type");
272bd389b36SDavid du Colombier 
273bd389b36SDavid du Colombier 	msg(res.ival, "start");
274bd389b36SDavid du Colombier }
275bd389b36SDavid du Colombier 
276bd389b36SDavid du Colombier void
stop(Node * r,Node * args)277bd389b36SDavid du Colombier stop(Node *r, Node *args)
278bd389b36SDavid du Colombier {
279bd389b36SDavid du Colombier 	Node res;
280bd389b36SDavid du Colombier 
281bd389b36SDavid du Colombier 	USED(r);
282bd389b36SDavid du Colombier 	if(args == 0)
283bd389b36SDavid du Colombier 		error("stop(pid): no pid");
284bd389b36SDavid du Colombier 	expr(args, &res);
285bd389b36SDavid du Colombier 	if(res.type != TINT)
286bd389b36SDavid du Colombier 		error("stop(pid): arg type");
287bd389b36SDavid du Colombier 
288219b2ee8SDavid du Colombier 	Bflush(bout);
289bd389b36SDavid du Colombier 	msg(res.ival, "stop");
290bd389b36SDavid du Colombier 	notes(res.ival);
291bd389b36SDavid du Colombier 	dostop(res.ival);
292bd389b36SDavid du Colombier }
293bd389b36SDavid du Colombier 
294bd389b36SDavid du Colombier void
kill(Node * r,Node * args)295bd389b36SDavid du Colombier kill(Node *r, Node *args)
296bd389b36SDavid du Colombier {
297bd389b36SDavid du Colombier 	Node res;
298bd389b36SDavid du Colombier 
299bd389b36SDavid du Colombier 	USED(r);
300bd389b36SDavid du Colombier 	if(args == 0)
301bd389b36SDavid du Colombier 		error("kill(pid): no pid");
302bd389b36SDavid du Colombier 	expr(args, &res);
303bd389b36SDavid du Colombier 	if(res.type != TINT)
304bd389b36SDavid du Colombier 		error("kill(pid): arg type");
305bd389b36SDavid du Colombier 
306bd389b36SDavid du Colombier 	msg(res.ival, "kill");
307bd389b36SDavid du Colombier 	deinstall(res.ival);
308bd389b36SDavid du Colombier }
309bd389b36SDavid du Colombier 
310bd389b36SDavid du Colombier void
status(Node * r,Node * args)311bd389b36SDavid du Colombier status(Node *r, Node *args)
312bd389b36SDavid du Colombier {
313bd389b36SDavid du Colombier 	Node res;
314219b2ee8SDavid du Colombier 	char *p;
315bd389b36SDavid du Colombier 
316bd389b36SDavid du Colombier 	USED(r);
317bd389b36SDavid du Colombier 	if(args == 0)
318bd389b36SDavid du Colombier 		error("status(pid): no pid");
319bd389b36SDavid du Colombier 	expr(args, &res);
320bd389b36SDavid du Colombier 	if(res.type != TINT)
321bd389b36SDavid du Colombier 		error("status(pid): arg type");
322bd389b36SDavid du Colombier 
323219b2ee8SDavid du Colombier 	p = getstatus(res.ival);
324219b2ee8SDavid du Colombier 	r->string = strnode(p);
325bd389b36SDavid du Colombier 	r->op = OCONST;
326bd389b36SDavid du Colombier 	r->fmt = 's';
327bd389b36SDavid du Colombier 	r->type = TSTRING;
328bd389b36SDavid du Colombier }
329bd389b36SDavid du Colombier 
330bd389b36SDavid du Colombier void
reason(Node * r,Node * args)331bd389b36SDavid du Colombier reason(Node *r, Node *args)
332bd389b36SDavid du Colombier {
333bd389b36SDavid du Colombier 	Node res;
334bd389b36SDavid du Colombier 
335bd389b36SDavid du Colombier 	if(args == 0)
336bd389b36SDavid du Colombier 		error("reason(cause): no cause");
337bd389b36SDavid du Colombier 	expr(args, &res);
338bd389b36SDavid du Colombier 	if(res.type != TINT)
339bd389b36SDavid du Colombier 		error("reason(cause): arg type");
340bd389b36SDavid du Colombier 
341bd389b36SDavid du Colombier 	r->op = OCONST;
342bd389b36SDavid du Colombier 	r->type = TSTRING;
343bd389b36SDavid du Colombier 	r->fmt = 's';
344219b2ee8SDavid du Colombier 	r->string = strnode((*machdata->excep)(cormap, rget));
345bd389b36SDavid du Colombier }
346bd389b36SDavid du Colombier 
347bd389b36SDavid du Colombier void
follow(Node * r,Node * args)348bd389b36SDavid du Colombier follow(Node *r, Node *args)
349bd389b36SDavid du Colombier {
350bd389b36SDavid du Colombier 	int n, i;
351bd389b36SDavid du Colombier 	Node res;
3524de34a7eSDavid du Colombier 	uvlong f[10];
353bd389b36SDavid du Colombier 	List **tail, *l;
354bd389b36SDavid du Colombier 
355bd389b36SDavid du Colombier 	if(args == 0)
356bd389b36SDavid du Colombier 		error("follow(addr): no addr");
357bd389b36SDavid du Colombier 	expr(args, &res);
358bd389b36SDavid du Colombier 	if(res.type != TINT)
359bd389b36SDavid du Colombier 		error("follow(addr): arg type");
360bd389b36SDavid du Colombier 
361219b2ee8SDavid du Colombier 	n = (*machdata->foll)(cormap, res.ival, rget, f);
362219b2ee8SDavid du Colombier 	if (n < 0)
363219b2ee8SDavid du Colombier 		error("follow(addr): %r");
364bd389b36SDavid du Colombier 	tail = &r->l;
365bd389b36SDavid du Colombier 	for(i = 0; i < n; i++) {
366bd389b36SDavid du Colombier 		l = al(TINT);
367bd389b36SDavid du Colombier 		l->ival = f[i];
368bd389b36SDavid du Colombier 		l->fmt = 'X';
369bd389b36SDavid du Colombier 		*tail = l;
370bd389b36SDavid du Colombier 		tail = &l->next;
371bd389b36SDavid du Colombier 	}
372bd389b36SDavid du Colombier }
373bd389b36SDavid du Colombier 
374bd389b36SDavid du Colombier void
funcbound(Node * r,Node * args)375219b2ee8SDavid du Colombier funcbound(Node *r, Node *args)
376219b2ee8SDavid du Colombier {
377219b2ee8SDavid du Colombier 	int n;
378219b2ee8SDavid du Colombier 	Node res;
3794de34a7eSDavid du Colombier 	uvlong bounds[2];
380219b2ee8SDavid du Colombier 	List *l;
381219b2ee8SDavid du Colombier 
382219b2ee8SDavid du Colombier 	if(args == 0)
383219b2ee8SDavid du Colombier 		error("fnbound(addr): no addr");
384219b2ee8SDavid du Colombier 	expr(args, &res);
385219b2ee8SDavid du Colombier 	if(res.type != TINT)
386219b2ee8SDavid du Colombier 		error("fnbound(addr): arg type");
387219b2ee8SDavid du Colombier 
388219b2ee8SDavid du Colombier 	n = fnbound(res.ival, bounds);
389219b2ee8SDavid du Colombier 	if (n != 0) {
390219b2ee8SDavid du Colombier 		r->l = al(TINT);
391219b2ee8SDavid du Colombier 		l = r->l;
392219b2ee8SDavid du Colombier 		l->ival = bounds[0];
393219b2ee8SDavid du Colombier 		l->fmt = 'X';
394219b2ee8SDavid du Colombier 		l->next = al(TINT);
395219b2ee8SDavid du Colombier 		l = l->next;
396219b2ee8SDavid du Colombier 		l->ival = bounds[1];
397219b2ee8SDavid du Colombier 		l->fmt = 'X';
398219b2ee8SDavid du Colombier 	}
399219b2ee8SDavid du Colombier }
400219b2ee8SDavid du Colombier 
401219b2ee8SDavid du Colombier void
setproc(Node * r,Node * args)402bd389b36SDavid du Colombier setproc(Node *r, Node *args)
403bd389b36SDavid du Colombier {
404bd389b36SDavid du Colombier 	Node res;
405bd389b36SDavid du Colombier 
406bd389b36SDavid du Colombier 	USED(r);
407bd389b36SDavid du Colombier 	if(args == 0)
408bd389b36SDavid du Colombier 		error("setproc(pid): no pid");
409bd389b36SDavid du Colombier 	expr(args, &res);
410bd389b36SDavid du Colombier 	if(res.type != TINT)
411bd389b36SDavid du Colombier 		error("setproc(pid): arg type");
412bd389b36SDavid du Colombier 
413bd389b36SDavid du Colombier 	sproc(res.ival);
414bd389b36SDavid du Colombier }
415bd389b36SDavid du Colombier 
416bd389b36SDavid du Colombier void
filepc(Node * r,Node * args)417bd389b36SDavid du Colombier filepc(Node *r, Node *args)
418bd389b36SDavid du Colombier {
419bd389b36SDavid du Colombier 	Node res;
420219b2ee8SDavid du Colombier 	char *p, c;
421bd389b36SDavid du Colombier 
422bd389b36SDavid du Colombier 	if(args == 0)
423bd389b36SDavid du Colombier 		error("filepc(filename:line): arg count");
424bd389b36SDavid du Colombier 	expr(args, &res);
425bd389b36SDavid du Colombier 	if(res.type != TSTRING)
426bd389b36SDavid du Colombier 		error("filepc(filename:line): arg type");
427bd389b36SDavid du Colombier 
428bd389b36SDavid du Colombier 	p = strchr(res.string->string, ':');
429bd389b36SDavid du Colombier 	if(p == 0)
430bd389b36SDavid du Colombier 		error("filepc(filename:line): bad arg format");
431bd389b36SDavid du Colombier 
432219b2ee8SDavid du Colombier 	c = *p;
433bd389b36SDavid du Colombier 	*p++ = '\0';
4344de34a7eSDavid du Colombier 	r->ival = file2pc(res.string->string, strtol(p, 0, 0));
435219b2ee8SDavid du Colombier 	p[-1] = c;
4364de34a7eSDavid du Colombier 	if(r->ival == ~0)
437bd389b36SDavid du Colombier 		error("filepc(filename:line): can't find address");
438bd389b36SDavid du Colombier 
439bd389b36SDavid du Colombier 	r->op = OCONST;
440bd389b36SDavid du Colombier 	r->type = TINT;
4414de34a7eSDavid du Colombier 	r->fmt = 'V';
442219b2ee8SDavid du Colombier }
443219b2ee8SDavid du Colombier 
444219b2ee8SDavid du Colombier void
interpret(Node * r,Node * args)445219b2ee8SDavid du Colombier interpret(Node *r, Node *args)
446219b2ee8SDavid du Colombier {
447219b2ee8SDavid du Colombier 	Node res;
448219b2ee8SDavid du Colombier 	int isave;
449219b2ee8SDavid du Colombier 
450219b2ee8SDavid du Colombier 	if(args == 0)
451219b2ee8SDavid du Colombier 		error("interpret(string): arg count");
452219b2ee8SDavid du Colombier 	expr(args, &res);
453219b2ee8SDavid du Colombier 	if(res.type != TSTRING)
454219b2ee8SDavid du Colombier 		error("interpret(string): arg type");
455219b2ee8SDavid du Colombier 
456219b2ee8SDavid du Colombier 	pushstr(&res);
457219b2ee8SDavid du Colombier 
458219b2ee8SDavid du Colombier 	isave = interactive;
459219b2ee8SDavid du Colombier 	interactive = 0;
460219b2ee8SDavid du Colombier 	r->ival = yyparse();
461219b2ee8SDavid du Colombier 	interactive = isave;
462219b2ee8SDavid du Colombier 	popio();
463219b2ee8SDavid du Colombier 	r->op = OCONST;
464219b2ee8SDavid du Colombier 	r->type = TINT;
465219b2ee8SDavid du Colombier 	r->fmt = 'D';
466219b2ee8SDavid du Colombier }
467219b2ee8SDavid du Colombier 
468219b2ee8SDavid du Colombier void
include(Node * r,Node * args)469219b2ee8SDavid du Colombier include(Node *r, Node *args)
470219b2ee8SDavid du Colombier {
471219b2ee8SDavid du Colombier 	Node res;
472219b2ee8SDavid du Colombier 	int isave;
473219b2ee8SDavid du Colombier 
474219b2ee8SDavid du Colombier 	if(args == 0)
475219b2ee8SDavid du Colombier 		error("include(string): arg count");
476219b2ee8SDavid du Colombier 	expr(args, &res);
477219b2ee8SDavid du Colombier 	if(res.type != TSTRING)
478219b2ee8SDavid du Colombier 		error("include(string): arg type");
479219b2ee8SDavid du Colombier 
480219b2ee8SDavid du Colombier 	pushfile(res.string->string);
481219b2ee8SDavid du Colombier 
482219b2ee8SDavid du Colombier 	isave = interactive;
483219b2ee8SDavid du Colombier 	interactive = 0;
484219b2ee8SDavid du Colombier 	r->ival = yyparse();
485219b2ee8SDavid du Colombier 	interactive = isave;
486219b2ee8SDavid du Colombier 	popio();
487219b2ee8SDavid du Colombier 	r->op = OCONST;
488219b2ee8SDavid du Colombier 	r->type = TINT;
489bd389b36SDavid du Colombier 	r->fmt = 'D';
490bd389b36SDavid du Colombier }
491bd389b36SDavid du Colombier 
492bd389b36SDavid du Colombier void
rc(Node * r,Node * args)493bd389b36SDavid du Colombier rc(Node *r, Node *args)
494bd389b36SDavid du Colombier {
495bd389b36SDavid du Colombier 	Node res;
496219b2ee8SDavid du Colombier 	int pid;
497219b2ee8SDavid du Colombier 	char *p, *q, *argv[4];
4989a747e4fSDavid du Colombier 	Waitmsg *w;
499bd389b36SDavid du Colombier 
500bd389b36SDavid du Colombier 	USED(r);
501bd389b36SDavid du Colombier 	if(args == 0)
502bd389b36SDavid du Colombier 		error("error(string): arg count");
503bd389b36SDavid du Colombier 	expr(args, &res);
504bd389b36SDavid du Colombier 	if(res.type != TSTRING)
505bd389b36SDavid du Colombier 		error("error(string): arg type");
506bd389b36SDavid du Colombier 
507bd389b36SDavid du Colombier 	argv[0] = "/bin/rc";
508bd389b36SDavid du Colombier 	argv[1] = "-c";
509bd389b36SDavid du Colombier 	argv[2] = res.string->string;
510bd389b36SDavid du Colombier 	argv[3] = 0;
511bd389b36SDavid du Colombier 
512bd389b36SDavid du Colombier 	pid = fork();
513bd389b36SDavid du Colombier 	switch(pid) {
514bd389b36SDavid du Colombier 	case -1:
515bd389b36SDavid du Colombier 		error("fork %r");
516bd389b36SDavid du Colombier 	case 0:
517bd389b36SDavid du Colombier 		exec("/bin/rc", argv);
518bd389b36SDavid du Colombier 		exits(0);
519bd389b36SDavid du Colombier 	default:
5209a747e4fSDavid du Colombier 		w = waitfor(pid);
521bd389b36SDavid du Colombier 		break;
522bd389b36SDavid du Colombier 	}
5239a747e4fSDavid du Colombier 	p = w->msg;
524219b2ee8SDavid du Colombier 	q = strrchr(p, ':');
525219b2ee8SDavid du Colombier 	if (q)
526219b2ee8SDavid du Colombier 		p = q+1;
527219b2ee8SDavid du Colombier 
528219b2ee8SDavid du Colombier 	r->op = OCONST;
529219b2ee8SDavid du Colombier 	r->type = TSTRING;
530219b2ee8SDavid du Colombier 	r->string = strnode(p);
5319a747e4fSDavid du Colombier 	free(w);
532219b2ee8SDavid du Colombier 	r->fmt = 's';
533bd389b36SDavid du Colombier }
534bd389b36SDavid du Colombier 
535bd389b36SDavid du Colombier void
doerror(Node * r,Node * args)536bd389b36SDavid du Colombier doerror(Node *r, Node *args)
537bd389b36SDavid du Colombier {
538bd389b36SDavid du Colombier 	Node res;
539bd389b36SDavid du Colombier 
540bd389b36SDavid du Colombier 	USED(r);
541bd389b36SDavid du Colombier 	if(args == 0)
542bd389b36SDavid du Colombier 		error("error(string): arg count");
543bd389b36SDavid du Colombier 	expr(args, &res);
544bd389b36SDavid du Colombier 	if(res.type != TSTRING)
545bd389b36SDavid du Colombier 		error("error(string): arg type");
546bd389b36SDavid du Colombier 
547bd389b36SDavid du Colombier 	error(res.string->string);
548bd389b36SDavid du Colombier }
549bd389b36SDavid du Colombier 
550bd389b36SDavid du Colombier void
doaccess(Node * r,Node * args)551bd389b36SDavid du Colombier doaccess(Node *r, Node *args)
552bd389b36SDavid du Colombier {
553bd389b36SDavid du Colombier 	Node res;
554bd389b36SDavid du Colombier 
555bd389b36SDavid du Colombier 	if(args == 0)
556bd389b36SDavid du Colombier 		error("access(filename): arg count");
557bd389b36SDavid du Colombier 	expr(args, &res);
558bd389b36SDavid du Colombier 	if(res.type != TSTRING)
559bd389b36SDavid du Colombier 		error("access(filename): arg type");
560bd389b36SDavid du Colombier 
561bd389b36SDavid du Colombier 	r->op = OCONST;
562bd389b36SDavid du Colombier 	r->type = TINT;
563bd389b36SDavid du Colombier 	r->ival = 0;
5647dd7cddfSDavid du Colombier 	if(access(res.string->string, 4) == 0)
565bd389b36SDavid du Colombier 		r->ival = 1;
566bd389b36SDavid du Colombier }
567bd389b36SDavid du Colombier 
568bd389b36SDavid du Colombier void
readfile(Node * r,Node * args)569219b2ee8SDavid du Colombier readfile(Node *r, Node *args)
570219b2ee8SDavid du Colombier {
571219b2ee8SDavid du Colombier 	Node res;
572219b2ee8SDavid du Colombier 	int n, fd;
573219b2ee8SDavid du Colombier 	char *buf;
5749a747e4fSDavid du Colombier 	Dir *db;
575219b2ee8SDavid du Colombier 
576219b2ee8SDavid du Colombier 	if(args == 0)
577219b2ee8SDavid du Colombier 		error("readfile(filename): arg count");
578219b2ee8SDavid du Colombier 	expr(args, &res);
579219b2ee8SDavid du Colombier 	if(res.type != TSTRING)
580219b2ee8SDavid du Colombier 		error("readfile(filename): arg type");
581219b2ee8SDavid du Colombier 
582219b2ee8SDavid du Colombier 	fd = open(res.string->string, OREAD);
583219b2ee8SDavid du Colombier 	if(fd < 0)
584219b2ee8SDavid du Colombier 		return;
585219b2ee8SDavid du Colombier 
5869a747e4fSDavid du Colombier 	db = dirfstat(fd);
5879a747e4fSDavid du Colombier 	if(db == nil || db->length == 0)
588219b2ee8SDavid du Colombier 		n = 8192;
589219b2ee8SDavid du Colombier 	else
5909a747e4fSDavid du Colombier 		n = db->length;
5919a747e4fSDavid du Colombier 	free(db);
592219b2ee8SDavid du Colombier 
593219b2ee8SDavid du Colombier 	buf = malloc(n);
594219b2ee8SDavid du Colombier 	n = read(fd, buf, n);
595219b2ee8SDavid du Colombier 
596219b2ee8SDavid du Colombier 	if(n > 0) {
597219b2ee8SDavid du Colombier 		r->op = OCONST;
598219b2ee8SDavid du Colombier 		r->type = TSTRING;
599219b2ee8SDavid du Colombier 		r->string = strnodlen(buf, n);
600219b2ee8SDavid du Colombier 		r->fmt = 's';
601219b2ee8SDavid du Colombier 	}
602219b2ee8SDavid du Colombier 	free(buf);
603219b2ee8SDavid du Colombier 	close(fd);
604219b2ee8SDavid du Colombier }
605219b2ee8SDavid du Colombier 
606219b2ee8SDavid du Colombier void
getfile(Node * r,Node * args)607bd389b36SDavid du Colombier getfile(Node *r, Node *args)
608bd389b36SDavid du Colombier {
609219b2ee8SDavid du Colombier 	int n;
610bd389b36SDavid du Colombier 	char *p;
611bd389b36SDavid du Colombier 	Node res;
612219b2ee8SDavid du Colombier 	String *s;
613bd389b36SDavid du Colombier 	Biobuf *bp;
614bd389b36SDavid du Colombier 	List **l, *new;
615bd389b36SDavid du Colombier 
616bd389b36SDavid du Colombier 	if(args == 0)
617bd389b36SDavid du Colombier 		error("file(filename): arg count");
618bd389b36SDavid du Colombier 	expr(args, &res);
619bd389b36SDavid du Colombier 	if(res.type != TSTRING)
620bd389b36SDavid du Colombier 		error("file(filename): arg type");
621bd389b36SDavid du Colombier 
622bd389b36SDavid du Colombier 	r->op = OCONST;
623bd389b36SDavid du Colombier 	r->type = TLIST;
624bd389b36SDavid du Colombier 	r->l = 0;
625bd389b36SDavid du Colombier 
626bd389b36SDavid du Colombier 	p = res.string->string;
627bd389b36SDavid du Colombier 	bp = Bopen(p, OREAD);
628bd389b36SDavid du Colombier 	if(bp == 0)
629bd389b36SDavid du Colombier 		return;
630bd389b36SDavid du Colombier 
631bd389b36SDavid du Colombier 	l = &r->l;
632bd389b36SDavid du Colombier 	for(;;) {
633bd389b36SDavid du Colombier 		p = Brdline(bp, '\n');
6347dd7cddfSDavid du Colombier 		n = Blinelen(bp);
635219b2ee8SDavid du Colombier 		if(p == 0) {
636219b2ee8SDavid du Colombier 			if(n == 0)
637bd389b36SDavid du Colombier 				break;
638219b2ee8SDavid du Colombier 			s = strnodlen(0, n);
639219b2ee8SDavid du Colombier 			Bread(bp, s->string, n);
640219b2ee8SDavid du Colombier 		}
641219b2ee8SDavid du Colombier 		else
642219b2ee8SDavid du Colombier 			s = strnodlen(p, n-1);
643219b2ee8SDavid du Colombier 
644bd389b36SDavid du Colombier 		new = al(TSTRING);
645219b2ee8SDavid du Colombier 		new->string = s;
646bd389b36SDavid du Colombier 		new->fmt = 's';
647bd389b36SDavid du Colombier 		*l = new;
648bd389b36SDavid du Colombier 		l = &new->next;
649bd389b36SDavid du Colombier 	}
650219b2ee8SDavid du Colombier 	Bterm(bp);
651bd389b36SDavid du Colombier }
652bd389b36SDavid du Colombier 
653bd389b36SDavid du Colombier void
cvtatof(Node * r,Node * args)654bd389b36SDavid du Colombier cvtatof(Node *r, Node *args)
655bd389b36SDavid du Colombier {
656bd389b36SDavid du Colombier 	Node res;
657bd389b36SDavid du Colombier 
658bd389b36SDavid du Colombier 	if(args == 0)
659bd389b36SDavid du Colombier 		error("atof(string): arg count");
660bd389b36SDavid du Colombier 	expr(args, &res);
661bd389b36SDavid du Colombier 	if(res.type != TSTRING)
662bd389b36SDavid du Colombier 		error("atof(string): arg type");
663bd389b36SDavid du Colombier 
664bd389b36SDavid du Colombier 	r->op = OCONST;
665bd389b36SDavid du Colombier 	r->type = TFLOAT;
666bd389b36SDavid du Colombier 	r->fval = atof(res.string->string);
667219b2ee8SDavid du Colombier 	r->fmt = 'f';
668bd389b36SDavid du Colombier }
669bd389b36SDavid du Colombier 
670bd389b36SDavid du Colombier void
cvtatoi(Node * r,Node * args)671bd389b36SDavid du Colombier cvtatoi(Node *r, Node *args)
672bd389b36SDavid du Colombier {
673bd389b36SDavid du Colombier 	Node res;
674bd389b36SDavid du Colombier 
675bd389b36SDavid du Colombier 	if(args == 0)
676bd389b36SDavid du Colombier 		error("atoi(string): arg count");
677bd389b36SDavid du Colombier 	expr(args, &res);
678bd389b36SDavid du Colombier 	if(res.type != TSTRING)
679bd389b36SDavid du Colombier 		error("atoi(string): arg type");
680bd389b36SDavid du Colombier 
681bd389b36SDavid du Colombier 	r->op = OCONST;
682bd389b36SDavid du Colombier 	r->type = TINT;
6834de34a7eSDavid du Colombier 	r->ival = strtoull(res.string->string, 0, 0);
6844de34a7eSDavid du Colombier 	r->fmt = 'V';
685bd389b36SDavid du Colombier }
686bd389b36SDavid du Colombier 
6877fb4e6f1SDavid du Colombier static char *fmtflags = "-0123456789. #,u";
6887fb4e6f1SDavid du Colombier static char *fmtverbs = "bdox";
6897fb4e6f1SDavid du Colombier 
6907fb4e6f1SDavid du Colombier static int
acidfmt(char * fmt,char * buf,int blen)6917fb4e6f1SDavid du Colombier acidfmt(char *fmt, char *buf, int blen)
6927fb4e6f1SDavid du Colombier {
6937fb4e6f1SDavid du Colombier 	char *r, *w, *e;
6947fb4e6f1SDavid du Colombier 
6957fb4e6f1SDavid du Colombier 	w = buf;
6967fb4e6f1SDavid du Colombier 	e = buf+blen;
6977fb4e6f1SDavid du Colombier 	for(r=fmt; *r; r++){
6987fb4e6f1SDavid du Colombier 		if(w >= e)
6997fb4e6f1SDavid du Colombier 			return -1;
7007fb4e6f1SDavid du Colombier 		if(*r != '%'){
7017fb4e6f1SDavid du Colombier 			*w++ = *r;
7027fb4e6f1SDavid du Colombier 			continue;
7037fb4e6f1SDavid du Colombier 		}
7047fb4e6f1SDavid du Colombier 		if(*r == '%'){
7057fb4e6f1SDavid du Colombier 			*w++ = *r++;
7067fb4e6f1SDavid du Colombier 			if(*r == '%'){
7077fb4e6f1SDavid du Colombier 				if(w >= e)
7087fb4e6f1SDavid du Colombier 					return -1;
7097fb4e6f1SDavid du Colombier 				*w++ = *r;
7107fb4e6f1SDavid du Colombier 				continue;
7117fb4e6f1SDavid du Colombier 			}
7127fb4e6f1SDavid du Colombier 			while(*r && strchr(fmtflags, *r)){
7137fb4e6f1SDavid du Colombier 				if(w >= e)
7147fb4e6f1SDavid du Colombier 					return -1;
7157fb4e6f1SDavid du Colombier 				*w++ = *r++;
7167fb4e6f1SDavid du Colombier 			}
7177fb4e6f1SDavid du Colombier 			if(*r == 0 || strchr(fmtverbs, *r) == nil)
7187fb4e6f1SDavid du Colombier 				return -1;
7197fb4e6f1SDavid du Colombier 			if(w+3 > e)
7207fb4e6f1SDavid du Colombier 				return -1;
7217fb4e6f1SDavid du Colombier 			*w++ = 'l';
7227fb4e6f1SDavid du Colombier 			*w++ = 'l';
7237fb4e6f1SDavid du Colombier 			*w++ = *r;
7247fb4e6f1SDavid du Colombier 		}
7257fb4e6f1SDavid du Colombier 	}
7267fb4e6f1SDavid du Colombier 	if(w >= e)
7277fb4e6f1SDavid du Colombier 		return -1;
7287fb4e6f1SDavid du Colombier 	*w = 0;
7297fb4e6f1SDavid du Colombier 
7307fb4e6f1SDavid du Colombier 	return 0;
7317fb4e6f1SDavid du Colombier }
7327fb4e6f1SDavid du Colombier 
733bd389b36SDavid du Colombier void
cvtitoa(Node * r,Node * args)734bd389b36SDavid du Colombier cvtitoa(Node *r, Node *args)
735bd389b36SDavid du Colombier {
736bd389b36SDavid du Colombier 	Node res;
7379a747e4fSDavid du Colombier 	Node *av[Maxarg];
7384de34a7eSDavid du Colombier 	vlong ival;
7397fb4e6f1SDavid du Colombier 	char buf[128], fmt[32];
740bd389b36SDavid du Colombier 
741bd389b36SDavid du Colombier 	if(args == 0)
7429a747e4fSDavid du Colombier err:
7437fb4e6f1SDavid du Colombier 		error("itoa(number [, fmt]): arg count");
7449a747e4fSDavid du Colombier 	na = 0;
7459a747e4fSDavid du Colombier 	flatten(av, args);
7469a747e4fSDavid du Colombier 	if(na == 0 || na > 2)
7479a747e4fSDavid du Colombier 		goto err;
7489a747e4fSDavid du Colombier 	expr(av[0], &res);
749bd389b36SDavid du Colombier 	if(res.type != TINT)
7507fb4e6f1SDavid du Colombier 		error("itoa(number [, fmt]): arg type");
7514de34a7eSDavid du Colombier 	ival = res.ival;
7527fb4e6f1SDavid du Colombier 	strncpy(fmt, "%lld", sizeof(fmt));
7539a747e4fSDavid du Colombier 	if(na == 2){
7549a747e4fSDavid du Colombier 		expr(av[1], &res);
7559a747e4fSDavid du Colombier 		if(res.type != TSTRING)
7567fb4e6f1SDavid du Colombier 			error("itoa(number [, fmt]): fmt type");
7577fb4e6f1SDavid du Colombier 		if(acidfmt(res.string->string, fmt, sizeof(buf)))
7587fb4e6f1SDavid du Colombier 			error("itoa(number [, fmt]): malformed fmt");
7599a747e4fSDavid du Colombier 	}
760bd389b36SDavid du Colombier 
7614de34a7eSDavid du Colombier 	snprint(buf, sizeof(buf), fmt, ival);
762bd389b36SDavid du Colombier 	r->op = OCONST;
763bd389b36SDavid du Colombier 	r->type = TSTRING;
764bd389b36SDavid du Colombier 	r->string = strnode(buf);
765219b2ee8SDavid du Colombier 	r->fmt = 's';
766219b2ee8SDavid du Colombier }
767219b2ee8SDavid du Colombier 
768219b2ee8SDavid du Colombier List*
mapent(Map * m)769219b2ee8SDavid du Colombier mapent(Map *m)
770219b2ee8SDavid du Colombier {
771219b2ee8SDavid du Colombier 	int i;
772219b2ee8SDavid du Colombier 	List *l, *n, **t, *h;
773219b2ee8SDavid du Colombier 
774219b2ee8SDavid du Colombier 	h = 0;
775219b2ee8SDavid du Colombier 	t = &h;
776219b2ee8SDavid du Colombier 	for(i = 0; i < m->nsegs; i++) {
777219b2ee8SDavid du Colombier 		if(m->seg[i].inuse == 0)
778219b2ee8SDavid du Colombier 			continue;
779219b2ee8SDavid du Colombier 		l = al(TSTRING);
780219b2ee8SDavid du Colombier 		n = al(TLIST);
781219b2ee8SDavid du Colombier 		n->l = l;
782219b2ee8SDavid du Colombier 		*t = n;
783219b2ee8SDavid du Colombier 		t = &n->next;
784219b2ee8SDavid du Colombier 		l->string = strnode(m->seg[i].name);
785219b2ee8SDavid du Colombier 		l->fmt = 's';
786219b2ee8SDavid du Colombier 		l->next = al(TINT);
787219b2ee8SDavid du Colombier 		l = l->next;
788219b2ee8SDavid du Colombier 		l->ival = m->seg[i].b;
7894de34a7eSDavid du Colombier 		l->fmt = 'W';
790219b2ee8SDavid du Colombier 		l->next = al(TINT);
791219b2ee8SDavid du Colombier 		l = l->next;
792219b2ee8SDavid du Colombier 		l->ival = m->seg[i].e;
7934de34a7eSDavid du Colombier 		l->fmt = 'W';
794219b2ee8SDavid du Colombier 		l->next = al(TINT);
795219b2ee8SDavid du Colombier 		l = l->next;
796219b2ee8SDavid du Colombier 		l->ival = m->seg[i].f;
7974de34a7eSDavid du Colombier 		l->fmt = 'W';
798219b2ee8SDavid du Colombier 	}
799219b2ee8SDavid du Colombier 	return h;
800219b2ee8SDavid du Colombier }
801219b2ee8SDavid du Colombier 
802219b2ee8SDavid du Colombier void
map(Node * r,Node * args)803219b2ee8SDavid du Colombier map(Node *r, Node *args)
804219b2ee8SDavid du Colombier {
805219b2ee8SDavid du Colombier 	int i;
806219b2ee8SDavid du Colombier 	Map *m;
807219b2ee8SDavid du Colombier 	List *l;
808219b2ee8SDavid du Colombier 	char *ent;
809219b2ee8SDavid du Colombier 	Node *av[Maxarg], res;
810219b2ee8SDavid du Colombier 
811219b2ee8SDavid du Colombier 	na = 0;
812219b2ee8SDavid du Colombier 	flatten(av, args);
813219b2ee8SDavid du Colombier 
814219b2ee8SDavid du Colombier 	if(na != 0) {
815219b2ee8SDavid du Colombier 		expr(av[0], &res);
816219b2ee8SDavid du Colombier 		if(res.type != TLIST)
817219b2ee8SDavid du Colombier 			error("map(list): map needs a list");
818219b2ee8SDavid du Colombier 		if(listlen(res.l) != 4)
819219b2ee8SDavid du Colombier 			error("map(list): list must have 4 entries");
820219b2ee8SDavid du Colombier 
821219b2ee8SDavid du Colombier 		l = res.l;
822219b2ee8SDavid du Colombier 		if(l->type != TSTRING)
823219b2ee8SDavid du Colombier 			error("map name must be a string");
824219b2ee8SDavid du Colombier 		ent = l->string->string;
825219b2ee8SDavid du Colombier 		m = symmap;
826219b2ee8SDavid du Colombier 		i = findseg(m, ent);
827219b2ee8SDavid du Colombier 		if(i < 0) {
828219b2ee8SDavid du Colombier 			m = cormap;
829219b2ee8SDavid du Colombier 			i = findseg(m, ent);
830219b2ee8SDavid du Colombier 		}
831219b2ee8SDavid du Colombier 		if(i < 0)
832219b2ee8SDavid du Colombier 			error("%s is not a map entry", ent);
833219b2ee8SDavid du Colombier 		l = l->next;
834219b2ee8SDavid du Colombier 		if(l->type != TINT)
835219b2ee8SDavid du Colombier 			error("map entry not int");
836219b2ee8SDavid du Colombier 		m->seg[i].b = l->ival;
837219b2ee8SDavid du Colombier 		if (strcmp(ent, "text") == 0)
838219b2ee8SDavid du Colombier 			textseg(l->ival, &fhdr);
839219b2ee8SDavid du Colombier 		l = l->next;
840219b2ee8SDavid du Colombier 		if(l->type != TINT)
841219b2ee8SDavid du Colombier 			error("map entry not int");
842219b2ee8SDavid du Colombier 		m->seg[i].e = l->ival;
843219b2ee8SDavid du Colombier 		l = l->next;
844219b2ee8SDavid du Colombier 		if(l->type != TINT)
845219b2ee8SDavid du Colombier 			error("map entry not int");
846219b2ee8SDavid du Colombier 		m->seg[i].f = l->ival;
847219b2ee8SDavid du Colombier 	}
848219b2ee8SDavid du Colombier 
849219b2ee8SDavid du Colombier 	r->type = TLIST;
850219b2ee8SDavid du Colombier 	r->l = 0;
851219b2ee8SDavid du Colombier 	if(symmap)
852219b2ee8SDavid du Colombier 		r->l = mapent(symmap);
853219b2ee8SDavid du Colombier 	if(cormap) {
854219b2ee8SDavid du Colombier 		if(r->l == 0)
855219b2ee8SDavid du Colombier 			r->l = mapent(cormap);
856219b2ee8SDavid du Colombier 		else {
857219b2ee8SDavid du Colombier 			for(l = r->l; l->next; l = l->next)
858219b2ee8SDavid du Colombier 				;
859219b2ee8SDavid du Colombier 			l->next = mapent(cormap);
860219b2ee8SDavid du Colombier 		}
861219b2ee8SDavid du Colombier 	}
862bd389b36SDavid du Colombier }
863bd389b36SDavid du Colombier 
864bd389b36SDavid du Colombier void
flatten(Node ** av,Node * n)865bd389b36SDavid du Colombier flatten(Node **av, Node *n)
866bd389b36SDavid du Colombier {
867bd389b36SDavid du Colombier 	if(n == 0)
868bd389b36SDavid du Colombier 		return;
869bd389b36SDavid du Colombier 
870bd389b36SDavid du Colombier 	switch(n->op) {
871bd389b36SDavid du Colombier 	case OLIST:
872bd389b36SDavid du Colombier 		flatten(av, n->left);
873bd389b36SDavid du Colombier 		flatten(av, n->right);
874bd389b36SDavid du Colombier 		break;
875bd389b36SDavid du Colombier 	default:
876bd389b36SDavid du Colombier 		av[na++] = n;
877bd389b36SDavid du Colombier 		if(na >= Maxarg)
878bd389b36SDavid du Colombier 			error("too many function arguments");
879bd389b36SDavid du Colombier 		break;
880bd389b36SDavid du Colombier 	}
881bd389b36SDavid du Colombier }
882bd389b36SDavid du Colombier 
883bd389b36SDavid du Colombier void
strace(Node * r,Node * args)884bd389b36SDavid du Colombier strace(Node *r, Node *args)
885bd389b36SDavid du Colombier {
886bd389b36SDavid du Colombier 	Node *av[Maxarg], *n, res;
8874de34a7eSDavid du Colombier 	uvlong pc, sp;
888bd389b36SDavid du Colombier 
889bd389b36SDavid du Colombier 	na = 0;
890bd389b36SDavid du Colombier 	flatten(av, args);
891219b2ee8SDavid du Colombier 	if(na != 3)
892219b2ee8SDavid du Colombier 		error("strace(pc, sp, link): arg count");
893bd389b36SDavid du Colombier 
894bd389b36SDavid du Colombier 	n = av[0];
895bd389b36SDavid du Colombier 	expr(n, &res);
896bd389b36SDavid du Colombier 	if(res.type != TINT)
897219b2ee8SDavid du Colombier 		error("strace(pc, sp, link): pc bad type");
898219b2ee8SDavid du Colombier 	pc = res.ival;
899219b2ee8SDavid du Colombier 
900bd389b36SDavid du Colombier 	n = av[1];
901bd389b36SDavid du Colombier 	expr(n, &res);
902bd389b36SDavid du Colombier 	if(res.type != TINT)
903219b2ee8SDavid du Colombier 		error("strace(pc, sp, link): sp bad type");
904219b2ee8SDavid du Colombier 	sp = res.ival;
905219b2ee8SDavid du Colombier 
906219b2ee8SDavid du Colombier 	n = av[2];
907219b2ee8SDavid du Colombier 	expr(n, &res);
908219b2ee8SDavid du Colombier 	if(res.type != TINT)
909219b2ee8SDavid du Colombier 		error("strace(pc, sp, link): link bad type");
910219b2ee8SDavid du Colombier 
911219b2ee8SDavid du Colombier 	tracelist = 0;
912219b2ee8SDavid du Colombier 	if ((*machdata->ctrace)(cormap, pc, sp, res.ival, trlist) <= 0)
9134de34a7eSDavid du Colombier 		error("no stack frame: %r");
914bd389b36SDavid du Colombier 	r->type = TLIST;
915219b2ee8SDavid du Colombier 	r->l = tracelist;
916bd389b36SDavid du Colombier }
917bd389b36SDavid du Colombier 
918219b2ee8SDavid du Colombier void
regerror(char * msg)919219b2ee8SDavid du Colombier regerror(char *msg)
920219b2ee8SDavid du Colombier {
921219b2ee8SDavid du Colombier 	error(msg);
922219b2ee8SDavid du Colombier }
923219b2ee8SDavid du Colombier 
924219b2ee8SDavid du Colombier void
regexp(Node * r,Node * args)925219b2ee8SDavid du Colombier regexp(Node *r, Node *args)
926219b2ee8SDavid du Colombier {
927219b2ee8SDavid du Colombier 	Node res;
928219b2ee8SDavid du Colombier 	Reprog *rp;
929219b2ee8SDavid du Colombier 	Node *av[Maxarg];
930219b2ee8SDavid du Colombier 
931219b2ee8SDavid du Colombier 	na = 0;
932219b2ee8SDavid du Colombier 	flatten(av, args);
933219b2ee8SDavid du Colombier 	if(na != 2)
934219b2ee8SDavid du Colombier 		error("regexp(pattern, string): arg count");
935219b2ee8SDavid du Colombier 	expr(av[0], &res);
936219b2ee8SDavid du Colombier 	if(res.type != TSTRING)
937219b2ee8SDavid du Colombier 		error("regexp(pattern, string): pattern must be string");
938219b2ee8SDavid du Colombier 	rp = regcomp(res.string->string);
939219b2ee8SDavid du Colombier 	if(rp == 0)
940219b2ee8SDavid du Colombier 		return;
941219b2ee8SDavid du Colombier 
942219b2ee8SDavid du Colombier 	expr(av[1], &res);
943219b2ee8SDavid du Colombier 	if(res.type != TSTRING)
944219b2ee8SDavid du Colombier 		error("regexp(pattern, string): bad string");
945219b2ee8SDavid du Colombier 
946219b2ee8SDavid du Colombier 	r->fmt = 'D';
947219b2ee8SDavid du Colombier 	r->type = TINT;
948219b2ee8SDavid du Colombier 	r->ival = regexec(rp, res.string->string, 0, 0);
949219b2ee8SDavid du Colombier 	free(rp);
950219b2ee8SDavid du Colombier }
951219b2ee8SDavid du Colombier 
952bd389b36SDavid du Colombier void
fmt(Node * r,Node * args)953bd389b36SDavid du Colombier fmt(Node *r, Node *args)
954bd389b36SDavid du Colombier {
955bd389b36SDavid du Colombier 	Node res;
956bd389b36SDavid du Colombier 	Node *av[Maxarg];
957bd389b36SDavid du Colombier 
958bd389b36SDavid du Colombier 	na = 0;
959bd389b36SDavid du Colombier 	flatten(av, args);
960bd389b36SDavid du Colombier 	if(na != 2)
961bd389b36SDavid du Colombier 		error("fmt(obj, fmt): arg count");
962bd389b36SDavid du Colombier 	expr(av[1], &res);
963bd389b36SDavid du Colombier 	if(res.type != TINT || strchr(vfmt, res.ival) == 0)
9647dd7cddfSDavid du Colombier 		error("fmt(obj, fmt): bad format '%c'", (char)res.ival);
965bd389b36SDavid du Colombier 	expr(av[0], r);
966bd389b36SDavid du Colombier 	r->fmt = res.ival;
967bd389b36SDavid du Colombier }
968bd389b36SDavid du Colombier 
969bd389b36SDavid du Colombier void
patom(char type,Store * res)970bd389b36SDavid du Colombier patom(char type, Store *res)
971bd389b36SDavid du Colombier {
972219b2ee8SDavid du Colombier 	int i;
973219b2ee8SDavid du Colombier 	char buf[512];
97480ee5cbfSDavid du Colombier 	extern char *typenames[];
975bd389b36SDavid du Colombier 
976bd389b36SDavid du Colombier 	switch(res->fmt) {
977bd389b36SDavid du Colombier 	case 'c':
9787dd7cddfSDavid du Colombier 		Bprint(bout, "%c", (int)res->ival);
979bd389b36SDavid du Colombier 		break;
980bd389b36SDavid du Colombier 	case 'C':
981bd389b36SDavid du Colombier 		if(res->ival < ' ' || res->ival >= 0x7f)
9827dd7cddfSDavid du Colombier 			Bprint(bout, "%3d", (int)res->ival&0xff);
983bd389b36SDavid du Colombier 		else
9847dd7cddfSDavid du Colombier 			Bprint(bout, "%3c", (int)res->ival);
985bd389b36SDavid du Colombier 		break;
986bd389b36SDavid du Colombier 	case 'r':
9877dd7cddfSDavid du Colombier 		Bprint(bout, "%C", (int)res->ival);
988bd389b36SDavid du Colombier 		break;
989219b2ee8SDavid du Colombier 	case 'B':
990219b2ee8SDavid du Colombier 		memset(buf, '0', 34);
991219b2ee8SDavid du Colombier 		buf[1] = 'b';
992219b2ee8SDavid du Colombier 		for(i = 0; i < 32; i++) {
993219b2ee8SDavid du Colombier 			if(res->ival & (1<<i))
994219b2ee8SDavid du Colombier 				buf[33-i] = '1';
995219b2ee8SDavid du Colombier 		}
996219b2ee8SDavid du Colombier 		buf[35] = '\0';
997219b2ee8SDavid du Colombier 		Bprint(bout, "%s", buf);
998219b2ee8SDavid du Colombier 		break;
9997dd7cddfSDavid du Colombier 	case 'b':
100059c21d95SDavid du Colombier 		Bprint(bout, "%.2x", (int)res->ival&0xff);
10017dd7cddfSDavid du Colombier 		break;
1002bd389b36SDavid du Colombier 	case 'X':
10037dd7cddfSDavid du Colombier 		Bprint(bout, "%.8lux", (ulong)res->ival);
1004bd389b36SDavid du Colombier 		break;
1005bd389b36SDavid du Colombier 	case 'x':
10067dd7cddfSDavid du Colombier 		Bprint(bout, "%.4lux", (ulong)res->ival&0xffff);
10077dd7cddfSDavid du Colombier 		break;
1008bd389b36SDavid du Colombier 	case 'D':
10097dd7cddfSDavid du Colombier 		Bprint(bout, "%d", (int)res->ival);
1010bd389b36SDavid du Colombier 		break;
1011bd389b36SDavid du Colombier 	case 'd':
1012bd389b36SDavid du Colombier 		Bprint(bout, "%d", (ushort)res->ival);
1013bd389b36SDavid du Colombier 		break;
1014bd389b36SDavid du Colombier 	case 'u':
10157dd7cddfSDavid du Colombier 		Bprint(bout, "%d", (int)res->ival&0xffff);
1016bd389b36SDavid du Colombier 		break;
1017bd389b36SDavid du Colombier 	case 'U':
10187dd7cddfSDavid du Colombier 		Bprint(bout, "%lud", (ulong)res->ival);
10197dd7cddfSDavid du Colombier 		break;
10207dd7cddfSDavid du Colombier 	case 'Z':
10217dd7cddfSDavid du Colombier 		Bprint(bout, "%llud", res->ival);
10227dd7cddfSDavid du Colombier 		break;
10237dd7cddfSDavid du Colombier 	case 'V':
10247dd7cddfSDavid du Colombier 		Bprint(bout, "%lld", res->ival);
10257dd7cddfSDavid du Colombier 		break;
10264de34a7eSDavid du Colombier 	case 'W':
10274de34a7eSDavid du Colombier 		Bprint(bout, "%.8llux", res->ival);
10284de34a7eSDavid du Colombier 		break;
10297dd7cddfSDavid du Colombier 	case 'Y':
10307dd7cddfSDavid du Colombier 		Bprint(bout, "%.16llux", res->ival);
1031bd389b36SDavid du Colombier 		break;
1032bd389b36SDavid du Colombier 	case 'o':
10337dd7cddfSDavid du Colombier 		Bprint(bout, "0%.11uo", (int)res->ival&0xffff);
1034bd389b36SDavid du Colombier 		break;
1035bd389b36SDavid du Colombier 	case 'O':
10367dd7cddfSDavid du Colombier 		Bprint(bout, "0%.6uo", (int)res->ival);
1037bd389b36SDavid du Colombier 		break;
1038bd389b36SDavid du Colombier 	case 'q':
1039bd389b36SDavid du Colombier 		Bprint(bout, "0%.11o", (short)(res->ival&0xffff));
1040bd389b36SDavid du Colombier 		break;
1041bd389b36SDavid du Colombier 	case 'Q':
10427dd7cddfSDavid du Colombier 		Bprint(bout, "0%.6o", (int)res->ival);
1043bd389b36SDavid du Colombier 		break;
1044bd389b36SDavid du Colombier 	case 'f':
1045bd389b36SDavid du Colombier 	case 'F':
104637e88e97SDavid du Colombier 	case '3':
104737e88e97SDavid du Colombier 	case '8':
1048219b2ee8SDavid du Colombier 		if(type != TFLOAT)
104980ee5cbfSDavid du Colombier 			Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
1050219b2ee8SDavid du Colombier 		else
1051219b2ee8SDavid du Colombier 			Bprint(bout, "%g", res->fval);
1052bd389b36SDavid du Colombier 		break;
1053bd389b36SDavid du Colombier 	case 's':
1054219b2ee8SDavid du Colombier 	case 'g':
1055219b2ee8SDavid du Colombier 	case 'G':
1056bd389b36SDavid du Colombier 		if(type != TSTRING)
105780ee5cbfSDavid du Colombier 			Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
1058219b2ee8SDavid du Colombier 		else
1059219b2ee8SDavid du Colombier 			Bwrite(bout, res->string->string, res->string->len);
1060bd389b36SDavid du Colombier 		break;
1061bd389b36SDavid du Colombier 	case 'R':
1062bd389b36SDavid du Colombier 		if(type != TSTRING)
106380ee5cbfSDavid du Colombier 			Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
1064219b2ee8SDavid du Colombier 		else
10657dd7cddfSDavid du Colombier 			Bprint(bout, "%S", (Rune*)res->string->string);
1066bd389b36SDavid du Colombier 		break;
1067bd389b36SDavid du Colombier 	case 'a':
1068219b2ee8SDavid du Colombier 	case 'A':
1069219b2ee8SDavid du Colombier 		symoff(buf, sizeof(buf), res->ival, CANY);
1070219b2ee8SDavid du Colombier 		Bprint(bout, "%s", buf);
1071bd389b36SDavid du Colombier 		break;
1072bd389b36SDavid du Colombier 	case 'I':
1073bd389b36SDavid du Colombier 	case 'i':
1074bd389b36SDavid du Colombier 		if(type != TINT)
107580ee5cbfSDavid du Colombier 			Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
1076219b2ee8SDavid du Colombier 		else {
10779a747e4fSDavid du Colombier 			if (symmap == nil || (*machdata->das)(symmap, res->ival, res->fmt, buf, sizeof(buf)) < 0)
10789a747e4fSDavid du Colombier 				Bprint(bout, "no instruction");
1079219b2ee8SDavid du Colombier 			else
1080219b2ee8SDavid du Colombier 				Bprint(bout, "%s", buf);
1081219b2ee8SDavid du Colombier 		}
1082bd389b36SDavid du Colombier 		break;
1083bd389b36SDavid du Colombier 	}
1084bd389b36SDavid du Colombier }
1085bd389b36SDavid du Colombier 
1086bd389b36SDavid du Colombier void
blprint(List * l)1087bd389b36SDavid du Colombier blprint(List *l)
1088bd389b36SDavid du Colombier {
1089bd389b36SDavid du Colombier 	Bprint(bout, "{");
1090bd389b36SDavid du Colombier 	while(l) {
1091219b2ee8SDavid du Colombier 		switch(l->type) {
1092219b2ee8SDavid du Colombier 		default:
1093bd389b36SDavid du Colombier 			patom(l->type, &l->Store);
1094219b2ee8SDavid du Colombier 			break;
1095219b2ee8SDavid du Colombier 		case TSTRING:
1096219b2ee8SDavid du Colombier 			Bputc(bout, '"');
1097219b2ee8SDavid du Colombier 			patom(l->type, &l->Store);
1098219b2ee8SDavid du Colombier 			Bputc(bout, '"');
1099219b2ee8SDavid du Colombier 			break;
1100219b2ee8SDavid du Colombier 		case TLIST:
1101bd389b36SDavid du Colombier 			blprint(l->l);
1102219b2ee8SDavid du Colombier 			break;
1103219b2ee8SDavid du Colombier 		case TCODE:
1104219b2ee8SDavid du Colombier 			pcode(l->cc, 0);
1105219b2ee8SDavid du Colombier 			break;
1106219b2ee8SDavid du Colombier 		}
1107bd389b36SDavid du Colombier 		l = l->next;
1108bd389b36SDavid du Colombier 		if(l)
1109bd389b36SDavid du Colombier 			Bprint(bout, ", ");
1110bd389b36SDavid du Colombier 	}
1111bd389b36SDavid du Colombier 	Bprint(bout, "}");
1112bd389b36SDavid du Colombier }
1113bd389b36SDavid du Colombier 
1114219b2ee8SDavid du Colombier int
comx(Node res)1115219b2ee8SDavid du Colombier comx(Node res)
1116219b2ee8SDavid du Colombier {
1117219b2ee8SDavid du Colombier 	Lsym *sl;
1118219b2ee8SDavid du Colombier 	Node *n, xx;
1119219b2ee8SDavid du Colombier 
1120219b2ee8SDavid du Colombier 	if(res.fmt != 'a' && res.fmt != 'A')
1121219b2ee8SDavid du Colombier 		return 0;
1122219b2ee8SDavid du Colombier 
1123219b2ee8SDavid du Colombier 	if(res.comt == 0 || res.comt->base == 0)
1124219b2ee8SDavid du Colombier 		return 0;
1125219b2ee8SDavid du Colombier 
1126219b2ee8SDavid du Colombier 	sl = res.comt->base;
1127219b2ee8SDavid du Colombier 	if(sl->proc) {
1128219b2ee8SDavid du Colombier 		res.left = ZN;
1129219b2ee8SDavid du Colombier 		res.right = ZN;
1130219b2ee8SDavid du Colombier 		n = an(ONAME, ZN, ZN);
1131219b2ee8SDavid du Colombier 		n->sym = sl;
1132219b2ee8SDavid du Colombier 		n = an(OCALL, n, &res);
1133219b2ee8SDavid du Colombier 			n->left->sym = sl;
1134219b2ee8SDavid du Colombier 		expr(n, &xx);
1135219b2ee8SDavid du Colombier 		return 1;
1136219b2ee8SDavid du Colombier 	}
1137219b2ee8SDavid du Colombier 	print("(%s)", sl->name);
1138219b2ee8SDavid du Colombier 	return 0;
1139219b2ee8SDavid du Colombier }
1140219b2ee8SDavid du Colombier 
1141bd389b36SDavid du Colombier void
bprint(Node * r,Node * args)1142bd389b36SDavid du Colombier bprint(Node *r, Node *args)
1143bd389b36SDavid du Colombier {
1144bd389b36SDavid du Colombier 	int i, nas;
1145bd389b36SDavid du Colombier 	Node res, *av[Maxarg];
1146bd389b36SDavid du Colombier 
1147bd389b36SDavid du Colombier 	USED(r);
1148bd389b36SDavid du Colombier 	na = 0;
1149bd389b36SDavid du Colombier 	flatten(av, args);
1150bd389b36SDavid du Colombier 	nas = na;
1151bd389b36SDavid du Colombier 	for(i = 0; i < nas; i++) {
1152bd389b36SDavid du Colombier 		expr(av[i], &res);
1153bd389b36SDavid du Colombier 		switch(res.type) {
1154bd389b36SDavid du Colombier 		default:
1155219b2ee8SDavid du Colombier 			if(comx(res))
1156219b2ee8SDavid du Colombier 				break;
1157219b2ee8SDavid du Colombier 			patom(res.type, &res.Store);
1158219b2ee8SDavid du Colombier 			break;
1159219b2ee8SDavid du Colombier 		case TCODE:
1160219b2ee8SDavid du Colombier 			pcode(res.cc, 0);
1161219b2ee8SDavid du Colombier 			break;
1162219b2ee8SDavid du Colombier 		case TLIST:
1163219b2ee8SDavid du Colombier 			blprint(res.l);
1164219b2ee8SDavid du Colombier 			break;
1165219b2ee8SDavid du Colombier 		}
1166219b2ee8SDavid du Colombier 	}
1167219b2ee8SDavid du Colombier 	if(ret == 0)
1168219b2ee8SDavid du Colombier 		Bputc(bout, '\n');
1169219b2ee8SDavid du Colombier }
1170219b2ee8SDavid du Colombier 
1171219b2ee8SDavid du Colombier void
printto(Node * r,Node * args)1172219b2ee8SDavid du Colombier printto(Node *r, Node *args)
1173219b2ee8SDavid du Colombier {
1174219b2ee8SDavid du Colombier 	int fd;
1175219b2ee8SDavid du Colombier 	Biobuf *b;
1176219b2ee8SDavid du Colombier 	int i, nas;
1177219b2ee8SDavid du Colombier 	Node res, *av[Maxarg];
1178219b2ee8SDavid du Colombier 
1179219b2ee8SDavid du Colombier 	USED(r);
1180219b2ee8SDavid du Colombier 	na = 0;
1181219b2ee8SDavid du Colombier 	flatten(av, args);
1182219b2ee8SDavid du Colombier 	nas = na;
1183219b2ee8SDavid du Colombier 
1184219b2ee8SDavid du Colombier 	expr(av[0], &res);
1185219b2ee8SDavid du Colombier 	if(res.type != TSTRING)
1186219b2ee8SDavid du Colombier 		error("printto(string, ...): need string");
1187219b2ee8SDavid du Colombier 
1188219b2ee8SDavid du Colombier 	fd = create(res.string->string, OWRITE, 0666);
1189219b2ee8SDavid du Colombier 	if(fd < 0)
1190219b2ee8SDavid du Colombier 		fd = open(res.string->string, OWRITE);
1191219b2ee8SDavid du Colombier 	if(fd < 0)
1192219b2ee8SDavid du Colombier 		error("printto: open %s: %r", res.string->string);
1193219b2ee8SDavid du Colombier 
1194219b2ee8SDavid du Colombier 	b = gmalloc(sizeof(Biobuf));
1195219b2ee8SDavid du Colombier 	Binit(b, fd, OWRITE);
1196219b2ee8SDavid du Colombier 
1197219b2ee8SDavid du Colombier 	Bflush(bout);
1198219b2ee8SDavid du Colombier 	io[iop++] = bout;
1199219b2ee8SDavid du Colombier 	bout = b;
1200219b2ee8SDavid du Colombier 
1201219b2ee8SDavid du Colombier 	for(i = 1; i < nas; i++) {
1202219b2ee8SDavid du Colombier 		expr(av[i], &res);
1203219b2ee8SDavid du Colombier 		switch(res.type) {
1204219b2ee8SDavid du Colombier 		default:
1205219b2ee8SDavid du Colombier 			if(comx(res))
1206219b2ee8SDavid du Colombier 				break;
1207bd389b36SDavid du Colombier 			patom(res.type, &res.Store);
1208bd389b36SDavid du Colombier 			break;
1209bd389b36SDavid du Colombier 		case TLIST:
1210bd389b36SDavid du Colombier 			blprint(res.l);
1211bd389b36SDavid du Colombier 			break;
1212bd389b36SDavid du Colombier 		}
1213bd389b36SDavid du Colombier 	}
1214bd389b36SDavid du Colombier 	if(ret == 0)
1215bd389b36SDavid du Colombier 		Bputc(bout, '\n');
1216219b2ee8SDavid du Colombier 
1217219b2ee8SDavid du Colombier 	Bterm(b);
1218219b2ee8SDavid du Colombier 	close(fd);
1219219b2ee8SDavid du Colombier 	free(b);
1220219b2ee8SDavid du Colombier 	bout = io[--iop];
1221bd389b36SDavid du Colombier }
1222bd389b36SDavid du Colombier 
1223bd389b36SDavid du Colombier void
pcfile(Node * r,Node * args)1224bd389b36SDavid du Colombier pcfile(Node *r, Node *args)
1225bd389b36SDavid du Colombier {
1226bd389b36SDavid du Colombier 	Node res;
1227bd389b36SDavid du Colombier 	char *p, buf[128];
1228bd389b36SDavid du Colombier 
1229bd389b36SDavid du Colombier 	if(args == 0)
1230bd389b36SDavid du Colombier 		error("pcfile(addr): arg count");
1231bd389b36SDavid du Colombier 	expr(args, &res);
1232bd389b36SDavid du Colombier 	if(res.type != TINT)
1233bd389b36SDavid du Colombier 		error("pcfile(addr): arg type");
1234bd389b36SDavid du Colombier 
1235bd389b36SDavid du Colombier 	r->type = TSTRING;
1236bd389b36SDavid du Colombier 	r->fmt = 's';
1237bd389b36SDavid du Colombier 	if(fileline(buf, sizeof(buf), res.ival) == 0) {
1238bd389b36SDavid du Colombier 		r->string = strnode("?file?");
1239bd389b36SDavid du Colombier 		return;
1240bd389b36SDavid du Colombier 	}
1241bd389b36SDavid du Colombier 	p = strrchr(buf, ':');
1242bd389b36SDavid du Colombier 	if(p == 0)
1243bd389b36SDavid du Colombier 		error("pcfile(addr): funny file %s", buf);
1244bd389b36SDavid du Colombier 	*p = '\0';
1245bd389b36SDavid du Colombier 	r->string = strnode(buf);
1246bd389b36SDavid du Colombier }
1247bd389b36SDavid du Colombier 
1248bd389b36SDavid du Colombier void
pcline(Node * r,Node * args)1249bd389b36SDavid du Colombier pcline(Node *r, Node *args)
1250bd389b36SDavid du Colombier {
1251bd389b36SDavid du Colombier 	Node res;
1252bd389b36SDavid du Colombier 	char *p, buf[128];
1253bd389b36SDavid du Colombier 
1254bd389b36SDavid du Colombier 	if(args == 0)
1255bd389b36SDavid du Colombier 		error("pcline(addr): arg count");
1256bd389b36SDavid du Colombier 	expr(args, &res);
1257bd389b36SDavid du Colombier 	if(res.type != TINT)
1258bd389b36SDavid du Colombier 		error("pcline(addr): arg type");
1259bd389b36SDavid du Colombier 
1260bd389b36SDavid du Colombier 	r->type = TINT;
1261bd389b36SDavid du Colombier 	r->fmt = 'D';
1262bd389b36SDavid du Colombier 	if(fileline(buf, sizeof(buf), res.ival) == 0) {
1263bd389b36SDavid du Colombier 		r->ival = 0;
1264bd389b36SDavid du Colombier 		return;
1265bd389b36SDavid du Colombier 	}
1266bd389b36SDavid du Colombier 
1267bd389b36SDavid du Colombier 	p = strrchr(buf, ':');
1268bd389b36SDavid du Colombier 	if(p == 0)
1269bd389b36SDavid du Colombier 		error("pcline(addr): funny file %s", buf);
12704de34a7eSDavid du Colombier 	r->ival = strtol(p+1, 0, 0);
1271bd389b36SDavid du Colombier }
1272*7c70c028SDavid du Colombier 
fmtof(Node * r,Node * args)1273*7c70c028SDavid du Colombier void fmtof(Node *r, Node *args)
1274*7c70c028SDavid du Colombier {
1275*7c70c028SDavid du Colombier 	Node *av[Maxarg];
1276*7c70c028SDavid du Colombier 	Node res;
1277*7c70c028SDavid du Colombier 
1278*7c70c028SDavid du Colombier 	na = 0;
1279*7c70c028SDavid du Colombier 	flatten(av, args);
1280*7c70c028SDavid du Colombier 	if(na < 1)
1281*7c70c028SDavid du Colombier 		error("fmtof(obj): no argument");
1282*7c70c028SDavid du Colombier 	if(na > 1)
1283*7c70c028SDavid du Colombier 		error("fmtof(obj): too many arguments") ;
1284*7c70c028SDavid du Colombier 	expr(av[0], &res);
1285*7c70c028SDavid du Colombier 
1286*7c70c028SDavid du Colombier 	r->op = OCONST;
1287*7c70c028SDavid du Colombier 	r->type = TINT ;
1288*7c70c028SDavid du Colombier 	r->ival = res.fmt ;
1289*7c70c028SDavid du Colombier 	r->fmt = 'c';
1290*7c70c028SDavid du Colombier }
1291*7c70c028SDavid du Colombier 
dofmtsize(Node * r,Node * args)1292*7c70c028SDavid du Colombier void dofmtsize(Node *r, Node *args)
1293*7c70c028SDavid du Colombier {
1294*7c70c028SDavid du Colombier 	Node *av[Maxarg];
1295*7c70c028SDavid du Colombier 	Node res;
1296*7c70c028SDavid du Colombier 	Store * s ;
1297*7c70c028SDavid du Colombier 	Value v ;
1298*7c70c028SDavid du Colombier 
1299*7c70c028SDavid du Colombier 	na = 0;
1300*7c70c028SDavid du Colombier 	flatten(av, args);
1301*7c70c028SDavid du Colombier 	if(na < 1)
1302*7c70c028SDavid du Colombier 		error("fmtsize(obj): no argument");
1303*7c70c028SDavid du Colombier 	if(na > 1)
1304*7c70c028SDavid du Colombier 		error("fmtsize(obj): too many arguments") ;
1305*7c70c028SDavid du Colombier 	expr(av[0], &res);
1306*7c70c028SDavid du Colombier 
1307*7c70c028SDavid du Colombier 	v.type = res.type ;
1308*7c70c028SDavid du Colombier 	s = &v.Store ;
1309*7c70c028SDavid du Colombier 	*s = res ;
1310*7c70c028SDavid du Colombier 
1311*7c70c028SDavid du Colombier 	r->op = OCONST;
1312*7c70c028SDavid du Colombier 	r->type = TINT ;
1313*7c70c028SDavid du Colombier 	r->ival = fmtsize(&v) ;
1314*7c70c028SDavid du Colombier 	r->fmt = 'D';
1315*7c70c028SDavid du Colombier }
1316