Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/acid/builtin.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <bio.h>
4
#include <ctype.h>
5
#include <mach.h>
6
#include <regexp.h>
7
#define Extern extern
8
#include "acid.h"
9
#include "y.tab.h"
10
 
11
void	cvtatof(Node*, Node*);
12
void	cvtatoi(Node*, Node*);
13
void	cvtitoa(Node*, Node*);
14
void	bprint(Node*, Node*);
15
void	funcbound(Node*, Node*);
16
void	printto(Node*, Node*);
17
void	getfile(Node*, Node*);
18
void	fmt(Node*, Node*);
19
void	pcfile(Node*, Node*);
20
void	pcline(Node*, Node*);
21
void	setproc(Node*, Node*);
22
void	strace(Node*, Node*);
23
void	follow(Node*, Node*);
24
void	reason(Node*, Node*);
25
void	newproc(Node*, Node*);
26
void	startstop(Node*, Node*);
27
void	match(Node*, Node*);
28
void	status(Node*, Node*);
29
void	kill(Node*,Node*);
30
void	waitstop(Node*, Node*);
31
void	stop(Node*, Node*);
32
void	start(Node*, Node*);
33
void	filepc(Node*, Node*);
34
void	doerror(Node*, Node*);
35
void	rc(Node*, Node*);
36
void	doaccess(Node*, Node*);
37
void	map(Node*, Node*);
38
void	readfile(Node*, Node*);
39
void	interpret(Node*, Node*);
40
void	include(Node*, Node*);
41
void	regexp(Node*, Node*);
42
void	dosysr1(Node*, Node*);
43
void	fmtof(Node*, Node*) ;
44
void	dofmtsize(Node*, Node*) ;
45
 
46
typedef struct Btab Btab;
47
struct Btab
48
{
49
	char	*name;
50
	void	(*fn)(Node*, Node*);
51
} tab[] =
52
{
53
	"atof",		cvtatof,
54
	"atoi",		cvtatoi,
55
	"error",	doerror,
56
	"file",		getfile,
57
	"readfile",	readfile,
58
	"access",	doaccess,
59
	"filepc",	filepc,
60
	"fnbound",	funcbound,
61
	"fmt",		fmt,
62
	"follow",	follow,
63
	"itoa",		cvtitoa,
64
	"kill",		kill,
65
	"match",	match,
66
	"newproc",	newproc,
67
	"pcfile",	pcfile,
68
	"pcline",	pcline,
69
	"print",	bprint,
70
	"printto",	printto,
71
	"rc",		rc,
72
	"reason",	reason,
73
	"setproc",	setproc,
74
	"start",	start,
75
	"startstop",	startstop,
76
	"status",	status,
77
	"stop",		stop,
78
	"strace",	strace,
79
	"sysr1",	dosysr1,
80
	"waitstop",	waitstop,
81
	"map",		map,
82
	"interpret",	interpret,
83
	"include",	include,
84
	"regexp",	regexp,
85
	"fmtof",	fmtof,
86
	"fmtsize",	dofmtsize,
87
 
88
};
89
 
90
char vfmt[] = "aBbcCdDfFgGiIoOqQrRsSuUVWxXYZ38";
91
 
92
void
93
mkprint(Lsym *s)
94
{
95
	prnt = malloc(sizeof(Node));
96
	memset(prnt, 0, sizeof(Node));
97
	prnt->op = OCALL;
98
	prnt->left = malloc(sizeof(Node));
99
	memset(prnt->left, 0, sizeof(Node));
100
	prnt->left->sym = s;
101
}
102
 
103
void
104
installbuiltin(void)
105
{
106
	Btab *b;
107
	Lsym *s;
108
 
109
	b = tab;
110
	while(b->name) {
111
		s = look(b->name);
112
		if(s == 0)
113
			s = enter(b->name, Tid);
114
 
115
		s->builtin = b->fn;
116
		if(b->fn == bprint)
117
			mkprint(s);
118
		b++;
119
	}
120
}
121
 
122
void
123
dosysr1(Node *r, Node*)
124
{
125
	extern int sysr1(void);
126
 
127
	r->op = OCONST;
128
	r->type = TINT;
129
	r->fmt = 'D';
130
	r->ival = sysr1();
131
}
132
 
133
void
134
match(Node *r, Node *args)
135
{
136
	int i;
137
	List *f;
138
	Node *av[Maxarg];
139
	Node resi, resl;
140
 
141
	na = 0;
142
	flatten(av, args);
143
	if(na != 2)
144
		error("match(obj, list): arg count");
145
 
146
	expr(av[1], &resl);
147
	if(resl.type != TLIST)
148
		error("match(obj, list): need list");
149
	expr(av[0], &resi);
150
 
151
	r->op = OCONST;
152
	r->type = TINT;
153
	r->fmt = 'D';
154
	r->ival = -1;
155
 
156
	i = 0;
157
	for(f = resl.l; f; f = f->next) {
158
		if(resi.type == f->type) {
159
			switch(resi.type) {
160
			case TINT:
161
				if(resi.ival == f->ival) {
162
					r->ival = i;
163
					return;
164
				}
165
				break;
166
			case TFLOAT:
167
				if(resi.fval == f->fval) {
168
					r->ival = i;
169
					return;
170
				}
171
				break;
172
			case TSTRING:
173
				if(scmp(resi.string, f->string)) {
174
					r->ival = i;
175
					return;
176
				}
177
				break;
178
			case TLIST:
179
				error("match(obj, list): not defined for list");
180
			}
181
		}
182
		i++;
183
	}
184
}
185
 
186
void
187
newproc(Node *r, Node *args)
188
{
189
	int i;
190
	Node res;
191
	char *p, *e;
192
	char *argv[Maxarg], buf[Strsize];
193
 
194
	i = 1;
195
	argv[0] = aout;
196
 
197
	if(args) {
198
		expr(args, &res);
199
		if(res.type != TSTRING)
200
			error("newproc(): arg not string");
201
		if(res.string->len >= sizeof(buf))
202
			error("newproc(): too many arguments");
203
		memmove(buf, res.string->string, res.string->len);
204
		buf[res.string->len] = '\0';
205
		p = buf;
206
		e = buf+res.string->len;
207
		for(;;) {
208
			while(p < e && (*p == '\t' || *p == ' '))
209
				*p++ = '\0';
210
			if(p >= e)
211
				break;
212
			argv[i++] = p;
213
			if(i >= Maxarg)
214
				error("newproc: too many arguments");
215
			while(p < e && *p != '\t' && *p != ' ')
216
				p++;
217
		}
218
	}
219
	argv[i] = 0;
220
	r->op = OCONST;
221
	r->type = TINT;
222
	r->fmt = 'D';
223
	r->ival = nproc(argv);
224
}
225
 
226
void
227
startstop(Node *r, Node *args)
228
{
229
	Node res;
230
 
231
	USED(r);
232
	if(args == 0)
233
		error("startstop(pid): no pid");
234
	expr(args, &res);
235
	if(res.type != TINT)
236
		error("startstop(pid): arg type");
237
 
238
	msg(res.ival, "startstop");
239
	notes(res.ival);
240
	dostop(res.ival);
241
}
242
 
243
void
244
waitstop(Node *r, Node *args)
245
{
246
	Node res;
247
 
248
	USED(r);
249
	if(args == 0)
250
		error("waitstop(pid): no pid");
251
	expr(args, &res);
252
	if(res.type != TINT)
253
		error("waitstop(pid): arg type");
254
 
255
	Bflush(bout);
256
	msg(res.ival, "waitstop");
257
	notes(res.ival);
258
	dostop(res.ival);
259
}
260
 
261
void
262
start(Node *r, Node *args)
263
{
264
	Node res;
265
 
266
	USED(r);
267
	if(args == 0)
268
		error("start(pid): no pid");
269
	expr(args, &res);
270
	if(res.type != TINT)
271
		error("start(pid): arg type");
272
 
273
	msg(res.ival, "start");
274
}
275
 
276
void
277
stop(Node *r, Node *args)
278
{
279
	Node res;
280
 
281
	USED(r);
282
	if(args == 0)
283
		error("stop(pid): no pid");
284
	expr(args, &res);
285
	if(res.type != TINT)
286
		error("stop(pid): arg type");
287
 
288
	Bflush(bout);
289
	msg(res.ival, "stop");
290
	notes(res.ival);
291
	dostop(res.ival);
292
}
293
 
294
void
295
kill(Node *r, Node *args)
296
{
297
	Node res;
298
 
299
	USED(r);
300
	if(args == 0)
301
		error("kill(pid): no pid");
302
	expr(args, &res);
303
	if(res.type != TINT)
304
		error("kill(pid): arg type");
305
 
306
	msg(res.ival, "kill");
307
	deinstall(res.ival);
308
}
309
 
310
void
311
status(Node *r, Node *args)
312
{
313
	Node res;
314
	char *p;
315
 
316
	USED(r);
317
	if(args == 0)
318
		error("status(pid): no pid");
319
	expr(args, &res);
320
	if(res.type != TINT)
321
		error("status(pid): arg type");
322
 
323
	p = getstatus(res.ival);
324
	r->string = strnode(p);
325
	r->op = OCONST;
326
	r->fmt = 's';
327
	r->type = TSTRING;
328
}
329
 
330
void
331
reason(Node *r, Node *args)
332
{
333
	Node res;
334
 
335
	if(args == 0)
336
		error("reason(cause): no cause");
337
	expr(args, &res);
338
	if(res.type != TINT)
339
		error("reason(cause): arg type");
340
 
341
	r->op = OCONST;
342
	r->type = TSTRING;
343
	r->fmt = 's';
344
	r->string = strnode((*machdata->excep)(cormap, rget));
345
}
346
 
347
void
348
follow(Node *r, Node *args)
349
{
350
	int n, i;
351
	Node res;
352
	uvlong f[10];
353
	List **tail, *l;
354
 
355
	if(args == 0)
356
		error("follow(addr): no addr");
357
	expr(args, &res);
358
	if(res.type != TINT)
359
		error("follow(addr): arg type");
360
 
361
	n = (*machdata->foll)(cormap, res.ival, rget, f);
362
	if (n < 0)
363
		error("follow(addr): %r");
364
	tail = &r->l;
365
	for(i = 0; i < n; i++) {
366
		l = al(TINT);
367
		l->ival = f[i];
368
		l->fmt = 'X';
369
		*tail = l;
370
		tail = &l->next;
371
	}
372
}
373
 
374
void
375
funcbound(Node *r, Node *args)
376
{
377
	int n;
378
	Node res;
379
	uvlong bounds[2];
380
	List *l;
381
 
382
	if(args == 0)
383
		error("fnbound(addr): no addr");
384
	expr(args, &res);
385
	if(res.type != TINT)
386
		error("fnbound(addr): arg type");
387
 
388
	n = fnbound(res.ival, bounds);
389
	if (n != 0) {
390
		r->l = al(TINT);
391
		l = r->l;
392
		l->ival = bounds[0];
393
		l->fmt = 'X';
394
		l->next = al(TINT);
395
		l = l->next;
396
		l->ival = bounds[1];
397
		l->fmt = 'X';
398
	}
399
}
400
 
401
void
402
setproc(Node *r, Node *args)
403
{
404
	Node res;
405
 
406
	USED(r);
407
	if(args == 0)
408
		error("setproc(pid): no pid");
409
	expr(args, &res);
410
	if(res.type != TINT)
411
		error("setproc(pid): arg type");
412
 
413
	sproc(res.ival);
414
}
415
 
416
void
417
filepc(Node *r, Node *args)
418
{
419
	Node res;
420
	char *p, c;
421
 
422
	if(args == 0)
423
		error("filepc(filename:line): arg count");
424
	expr(args, &res);
425
	if(res.type != TSTRING)
426
		error("filepc(filename:line): arg type");
427
 
428
	p = strchr(res.string->string, ':');
429
	if(p == 0)
430
		error("filepc(filename:line): bad arg format");
431
 
432
	c = *p;
433
	*p++ = '\0';
434
	r->ival = file2pc(res.string->string, strtol(p, 0, 0));
435
	p[-1] = c;
436
	if(r->ival == ~0)
437
		error("filepc(filename:line): can't find address");
438
 
439
	r->op = OCONST;
440
	r->type = TINT;
441
	r->fmt = 'V';
442
}
443
 
444
void
445
interpret(Node *r, Node *args)
446
{
447
	Node res;
448
	int isave;
449
 
450
	if(args == 0)
451
		error("interpret(string): arg count");
452
	expr(args, &res);
453
	if(res.type != TSTRING)
454
		error("interpret(string): arg type");
455
 
456
	pushstr(&res);
457
 
458
	isave = interactive;
459
	interactive = 0;
460
	r->ival = yyparse();
461
	interactive = isave;
462
	popio();
463
	r->op = OCONST;
464
	r->type = TINT;
465
	r->fmt = 'D';
466
}
467
 
468
void
469
include(Node *r, Node *args)
470
{
471
	Node res;
472
	int isave;
473
 
474
	if(args == 0)
475
		error("include(string): arg count");
476
	expr(args, &res);
477
	if(res.type != TSTRING)
478
		error("include(string): arg type");
479
 
480
	pushfile(res.string->string);
481
 
482
	isave = interactive;
483
	interactive = 0;
484
	r->ival = yyparse();
485
	interactive = isave;
486
	popio();
487
	r->op = OCONST;
488
	r->type = TINT;
489
	r->fmt = 'D';
490
}
491
 
492
void
493
rc(Node *r, Node *args)
494
{
495
	Node res;
496
	int pid;
497
	char *p, *q, *argv[4];
498
	Waitmsg *w;
499
 
500
	USED(r);
501
	if(args == 0)
502
		error("error(string): arg count");
503
	expr(args, &res);
504
	if(res.type != TSTRING)
505
		error("error(string): arg type");
506
 
507
	argv[0] = "/bin/rc";
508
	argv[1] = "-c";
509
	argv[2] = res.string->string;
510
	argv[3] = 0;
511
 
512
	pid = fork();
513
	switch(pid) {
514
	case -1:
515
		error("fork %r");
516
	case 0:
517
		exec("/bin/rc", argv);
518
		exits(0);
519
	default:
520
		w = waitfor(pid);
521
		break;
522
	}
523
	p = w->msg;
524
	q = strrchr(p, ':');
525
	if (q)
526
		p = q+1;
527
 
528
	r->op = OCONST;
529
	r->type = TSTRING;
530
	r->string = strnode(p);
531
	free(w);
532
	r->fmt = 's';
533
}
534
 
535
void
536
doerror(Node *r, Node *args)
537
{
538
	Node res;
539
 
540
	USED(r);
541
	if(args == 0)
542
		error("error(string): arg count");
543
	expr(args, &res);
544
	if(res.type != TSTRING)
545
		error("error(string): arg type");
546
 
547
	error(res.string->string);
548
}
549
 
550
void
551
doaccess(Node *r, Node *args)
552
{
553
	Node res;
554
 
555
	if(args == 0)
556
		error("access(filename): arg count");
557
	expr(args, &res);
558
	if(res.type != TSTRING)
559
		error("access(filename): arg type");
560
 
561
	r->op = OCONST;
562
	r->type = TINT;
563
	r->ival = 0;		
564
	if(access(res.string->string, 4) == 0)
565
		r->ival = 1;
566
}
567
 
568
void
569
readfile(Node *r, Node *args)
570
{
571
	Node res;
572
	int n, fd;
573
	char *buf;
574
	Dir *db;
575
 
576
	if(args == 0)
577
		error("readfile(filename): arg count");
578
	expr(args, &res);
579
	if(res.type != TSTRING)
580
		error("readfile(filename): arg type");
581
 
582
	fd = open(res.string->string, OREAD);
583
	if(fd < 0)
584
		return;
585
 
586
	db = dirfstat(fd);
587
	if(db == nil || db->length == 0)
588
		n = 8192;
589
	else
590
		n = db->length;
591
	free(db);
592
 
593
	buf = malloc(n);
594
	n = read(fd, buf, n);
595
 
596
	if(n > 0) {
597
		r->op = OCONST;
598
		r->type = TSTRING;
599
		r->string = strnodlen(buf, n);
600
		r->fmt = 's';
601
	}
602
	free(buf);
603
	close(fd);
604
}
605
 
606
void
607
getfile(Node *r, Node *args)
608
{
609
	int n;
610
	char *p;
611
	Node res;
612
	String *s;
613
	Biobuf *bp;
614
	List **l, *new;
615
 
616
	if(args == 0)
617
		error("file(filename): arg count");
618
	expr(args, &res);
619
	if(res.type != TSTRING)
620
		error("file(filename): arg type");
621
 
622
	r->op = OCONST;
623
	r->type = TLIST;
624
	r->l = 0;
625
 
626
	p = res.string->string;
627
	bp = Bopen(p, OREAD);
628
	if(bp == 0)
629
		return;
630
 
631
	l = &r->l;
632
	for(;;) {
633
		p = Brdline(bp, '\n');
634
		n = Blinelen(bp);
635
		if(p == 0) {
636
			if(n == 0)
637
				break;
638
			s = strnodlen(0, n);
639
			Bread(bp, s->string, n);
640
		}
641
		else
642
			s = strnodlen(p, n-1);
643
 
644
		new = al(TSTRING);
645
		new->string = s;
646
		new->fmt = 's';
647
		*l = new;
648
		l = &new->next;
649
	}
650
	Bterm(bp);
651
}
652
 
653
void
654
cvtatof(Node *r, Node *args)
655
{
656
	Node res;
657
 
658
	if(args == 0)
659
		error("atof(string): arg count");
660
	expr(args, &res);
661
	if(res.type != TSTRING)
662
		error("atof(string): arg type");
663
 
664
	r->op = OCONST;
665
	r->type = TFLOAT;
666
	r->fval = atof(res.string->string);
667
	r->fmt = 'f';
668
}
669
 
670
void
671
cvtatoi(Node *r, Node *args)
672
{
673
	Node res;
674
 
675
	if(args == 0)
676
		error("atoi(string): arg count");
677
	expr(args, &res);
678
	if(res.type != TSTRING)
679
		error("atoi(string): arg type");
680
 
681
	r->op = OCONST;
682
	r->type = TINT;
683
	r->ival = strtoull(res.string->string, 0, 0);
684
	r->fmt = 'V';
685
}
686
 
687
static char *fmtflags = "-0123456789. #,u";
688
static char *fmtverbs = "bdox";
689
 
690
static int
691
acidfmt(char *fmt, char *buf, int blen)
692
{
693
	char *r, *w, *e;
694
 
695
	w = buf;
696
	e = buf+blen;
697
	for(r=fmt; *r; r++){
698
		if(w >= e)
699
			return -1;
700
		if(*r != '%'){
701
			*w++ = *r;
702
			continue;
703
		}
704
		if(*r == '%'){
705
			*w++ = *r++;
706
			if(*r == '%'){
707
				if(w >= e)
708
					return -1;
709
				*w++ = *r;
710
				continue;
711
			}
712
			while(*r && strchr(fmtflags, *r)){
713
				if(w >= e)
714
					return -1;
715
				*w++ = *r++;
716
			}
717
			if(*r == 0 || strchr(fmtverbs, *r) == nil)
718
				return -1;
719
			if(w+3 > e)
720
				return -1;
721
			*w++ = 'l';
722
			*w++ = 'l';
723
			*w++ = *r;
724
		}
725
	}
726
	if(w >= e)
727
		return -1;
728
	*w = 0;
729
 
730
	return 0;
731
}
732
 
733
void
734
cvtitoa(Node *r, Node *args)
735
{
736
	Node res;
737
	Node *av[Maxarg];
738
	vlong ival;
739
	char buf[128], fmt[32];
740
 
741
	if(args == 0)
742
err:
743
		error("itoa(number [, fmt]): arg count");
744
	na = 0;
745
	flatten(av, args);
746
	if(na == 0 || na > 2)
747
		goto err;
748
	expr(av[0], &res);
749
	if(res.type != TINT)
750
		error("itoa(number [, fmt]): arg type");
751
	ival = res.ival;
752
	strncpy(fmt, "%lld", sizeof(fmt));
753
	if(na == 2){
754
		expr(av[1], &res);
755
		if(res.type != TSTRING)
756
			error("itoa(number [, fmt]): fmt type");
757
		if(acidfmt(res.string->string, fmt, sizeof(buf)))
758
			error("itoa(number [, fmt]): malformed fmt");
759
	}
760
 
761
	snprint(buf, sizeof(buf), fmt, ival);
762
	r->op = OCONST;
763
	r->type = TSTRING;
764
	r->string = strnode(buf);
765
	r->fmt = 's';
766
}
767
 
768
List*
769
mapent(Map *m)
770
{
771
	int i;
772
	List *l, *n, **t, *h;
773
 
774
	h = 0;
775
	t = &h;
776
	for(i = 0; i < m->nsegs; i++) {
777
		if(m->seg[i].inuse == 0)
778
			continue;
779
		l = al(TSTRING);
780
		n = al(TLIST);
781
		n->l = l;
782
		*t = n;
783
		t = &n->next;
784
		l->string = strnode(m->seg[i].name);
785
		l->fmt = 's';
786
		l->next = al(TINT);
787
		l = l->next;
788
		l->ival = m->seg[i].b;
789
		l->fmt = 'W';
790
		l->next = al(TINT);
791
		l = l->next;
792
		l->ival = m->seg[i].e;
793
		l->fmt = 'W';
794
		l->next = al(TINT);
795
		l = l->next;
796
		l->ival = m->seg[i].f;
797
		l->fmt = 'W';
798
	}
799
	return h;
800
}
801
 
802
void
803
map(Node *r, Node *args)
804
{
805
	int i;
806
	Map *m;
807
	List *l;
808
	char *ent;
809
	Node *av[Maxarg], res;
810
 
811
	na = 0;
812
	flatten(av, args);
813
 
814
	if(na != 0) {
815
		expr(av[0], &res);
816
		if(res.type != TLIST)
817
			error("map(list): map needs a list");
818
		if(listlen(res.l) != 4)
819
			error("map(list): list must have 4 entries");
820
 
821
		l = res.l;
822
		if(l->type != TSTRING)
823
			error("map name must be a string");
824
		ent = l->string->string;
825
		m = symmap;
826
		i = findseg(m, ent);
827
		if(i < 0) {
828
			m = cormap;
829
			i = findseg(m, ent);
830
		}
831
		if(i < 0)
832
			error("%s is not a map entry", ent);	
833
		l = l->next;
834
		if(l->type != TINT)
835
			error("map entry not int");
836
		m->seg[i].b = l->ival;
837
		if (strcmp(ent, "text") == 0)
838
			textseg(l->ival, &fhdr);
839
		l = l->next;
840
		if(l->type != TINT)
841
			error("map entry not int");
842
		m->seg[i].e = l->ival;
843
		l = l->next;
844
		if(l->type != TINT)
845
			error("map entry not int");
846
		m->seg[i].f = l->ival;
847
	}
848
 
849
	r->type = TLIST;
850
	r->l = 0;
851
	if(symmap)
852
		r->l = mapent(symmap);
853
	if(cormap) {
854
		if(r->l == 0)
855
			r->l = mapent(cormap);
856
		else {
857
			for(l = r->l; l->next; l = l->next)
858
				;
859
			l->next = mapent(cormap);
860
		}
861
	}
862
}
863
 
864
void 
865
flatten(Node **av, Node *n)
866
{
867
	if(n == 0)
868
		return;
869
 
870
	switch(n->op) {
871
	case OLIST:
872
		flatten(av, n->left);
873
		flatten(av, n->right);
874
		break;
875
	default:
876
		av[na++] = n;
877
		if(na >= Maxarg)
878
			error("too many function arguments");
879
		break;
880
	}
881
}
882
 
883
void
884
strace(Node *r, Node *args)
885
{
886
	Node *av[Maxarg], *n, res;
887
	uvlong pc, sp;
888
 
889
	na = 0;
890
	flatten(av, args);
891
	if(na != 3)
892
		error("strace(pc, sp, link): arg count");
893
 
894
	n = av[0];
895
	expr(n, &res);
896
	if(res.type != TINT)
897
		error("strace(pc, sp, link): pc bad type");
898
	pc = res.ival;
899
 
900
	n = av[1];
901
	expr(n, &res);
902
	if(res.type != TINT)
903
		error("strace(pc, sp, link): sp bad type");
904
	sp = res.ival;
905
 
906
	n = av[2];
907
	expr(n, &res);
908
	if(res.type != TINT)
909
		error("strace(pc, sp, link): link bad type");
910
 
911
	tracelist = 0;
912
	if ((*machdata->ctrace)(cormap, pc, sp, res.ival, trlist) <= 0)
913
		error("no stack frame: %r");
914
	r->type = TLIST;
915
	r->l = tracelist;
916
}
917
 
918
void
919
regerror(char *msg)
920
{
921
	error(msg);
922
}
923
 
924
void
925
regexp(Node *r, Node *args)
926
{
927
	Node res;
928
	Reprog *rp;
929
	Node *av[Maxarg];
930
 
931
	na = 0;
932
	flatten(av, args);
933
	if(na != 2)
934
		error("regexp(pattern, string): arg count");
935
	expr(av[0], &res);
936
	if(res.type != TSTRING)
937
		error("regexp(pattern, string): pattern must be string");
938
	rp = regcomp(res.string->string);
939
	if(rp == 0)
940
		return;
941
 
942
	expr(av[1], &res);
943
	if(res.type != TSTRING)
944
		error("regexp(pattern, string): bad string");
945
 
946
	r->fmt = 'D';
947
	r->type = TINT;
948
	r->ival = regexec(rp, res.string->string, 0, 0);
949
	free(rp);
950
}
951
 
952
void
953
fmt(Node *r, Node *args)
954
{
955
	Node res;
956
	Node *av[Maxarg];
957
 
958
	na = 0;
959
	flatten(av, args);
960
	if(na != 2)
961
		error("fmt(obj, fmt): arg count");
962
	expr(av[1], &res);
963
	if(res.type != TINT || strchr(vfmt, res.ival) == 0)
964
		error("fmt(obj, fmt): bad format '%c'", (char)res.ival);
965
	expr(av[0], r);
966
	r->fmt = res.ival;
967
}
968
 
969
void
970
patom(char type, Store *res)
971
{
972
	int i;
973
	char buf[512];
974
	extern char *typenames[];
975
 
976
	switch(res->fmt) {
977
	case 'c':
978
		Bprint(bout, "%c", (int)res->ival);
979
		break;
980
	case 'C':
981
		if(res->ival < ' ' || res->ival >= 0x7f)
982
			Bprint(bout, "%3d", (int)res->ival&0xff);
983
		else
984
			Bprint(bout, "%3c", (int)res->ival);
985
		break;
986
	case 'r':
987
		Bprint(bout, "%C", (int)res->ival);
988
		break;
989
	case 'B':
990
		memset(buf, '0', 34);
991
		buf[1] = 'b';
992
		for(i = 0; i < 32; i++) {
993
			if(res->ival & (1<<i))
994
				buf[33-i] = '1';
995
		}
996
		buf[35] = '\0';
997
		Bprint(bout, "%s", buf);
998
		break;
999
	case 'b':
1000
		Bprint(bout, "%.2x", (int)res->ival&0xff);
1001
		break;
1002
	case 'X':
1003
		Bprint(bout, "%.8lux", (ulong)res->ival);
1004
		break;
1005
	case 'x':
1006
		Bprint(bout, "%.4lux", (ulong)res->ival&0xffff);
1007
		break;
1008
	case 'D':
1009
		Bprint(bout, "%d", (int)res->ival);
1010
		break;
1011
	case 'd':
1012
		Bprint(bout, "%d", (ushort)res->ival);
1013
		break;
1014
	case 'u':
1015
		Bprint(bout, "%d", (int)res->ival&0xffff);
1016
		break;
1017
	case 'U':
1018
		Bprint(bout, "%lud", (ulong)res->ival);
1019
		break;
1020
	case 'Z':
1021
		Bprint(bout, "%llud", res->ival);
1022
		break;
1023
	case 'V':
1024
		Bprint(bout, "%lld", res->ival);
1025
		break;
1026
	case 'W':
1027
		Bprint(bout, "%.8llux", res->ival);
1028
		break;
1029
	case 'Y':
1030
		Bprint(bout, "%.16llux", res->ival);
1031
		break;
1032
	case 'o':
1033
		Bprint(bout, "0%.11uo", (int)res->ival&0xffff);
1034
		break;
1035
	case 'O':
1036
		Bprint(bout, "0%.6uo", (int)res->ival);
1037
		break;
1038
	case 'q':
1039
		Bprint(bout, "0%.11o", (short)(res->ival&0xffff));
1040
		break;
1041
	case 'Q':
1042
		Bprint(bout, "0%.6o", (int)res->ival);
1043
		break;
1044
	case 'f':
1045
	case 'F':
1046
	case '3':
1047
	case '8':
1048
		if(type != TFLOAT)
1049
			Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
1050
		else
1051
			Bprint(bout, "%g", res->fval);
1052
		break;
1053
	case 's':
1054
	case 'g':
1055
	case 'G':
1056
		if(type != TSTRING)
1057
			Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
1058
		else
1059
			Bwrite(bout, res->string->string, res->string->len);
1060
		break;
1061
	case 'R':
1062
		if(type != TSTRING)
1063
			Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
1064
		else
1065
			Bprint(bout, "%S", (Rune*)res->string->string);
1066
		break;
1067
	case 'a':
1068
	case 'A':
1069
		symoff(buf, sizeof(buf), res->ival, CANY);
1070
		Bprint(bout, "%s", buf);
1071
		break;
1072
	case 'I':
1073
	case 'i':
1074
		if(type != TINT)
1075
			Bprint(bout, "*%c<%s>*", res->fmt, typenames[type]);
1076
		else {
1077
			if (symmap == nil || (*machdata->das)(symmap, res->ival, res->fmt, buf, sizeof(buf)) < 0)
1078
				Bprint(bout, "no instruction");
1079
			else
1080
				Bprint(bout, "%s", buf);
1081
		}
1082
		break;
1083
	}
1084
}
1085
 
1086
void
1087
blprint(List *l)
1088
{
1089
	Bprint(bout, "{");
1090
	while(l) {
1091
		switch(l->type) {
1092
		default:
1093
			patom(l->type, &l->Store);
1094
			break;
1095
		case TSTRING:
1096
			Bputc(bout, '"');
1097
			patom(l->type, &l->Store);
1098
			Bputc(bout, '"');
1099
			break;
1100
		case TLIST:
1101
			blprint(l->l);
1102
			break;
1103
		case TCODE:
1104
			pcode(l->cc, 0);
1105
			break;
1106
		}
1107
		l = l->next;
1108
		if(l)
1109
			Bprint(bout, ", ");
1110
	}
1111
	Bprint(bout, "}");
1112
}
1113
 
1114
int
1115
comx(Node res)
1116
{
1117
	Lsym *sl;
1118
	Node *n, xx;
1119
 
1120
	if(res.fmt != 'a' && res.fmt != 'A')
1121
		return 0;
1122
 
1123
	if(res.comt == 0 || res.comt->base == 0)
1124
		return 0;
1125
 
1126
	sl = res.comt->base;
1127
	if(sl->proc) {
1128
		res.left = ZN;
1129
		res.right = ZN;
1130
		n = an(ONAME, ZN, ZN);
1131
		n->sym = sl;
1132
		n = an(OCALL, n, &res);
1133
			n->left->sym = sl;
1134
		expr(n, &xx);
1135
		return 1;
1136
	}
1137
	print("(%s)", sl->name);
1138
	return 0;
1139
}
1140
 
1141
void
1142
bprint(Node *r, Node *args)
1143
{
1144
	int i, nas;
1145
	Node res, *av[Maxarg];
1146
 
1147
	USED(r);
1148
	na = 0;
1149
	flatten(av, args);
1150
	nas = na;
1151
	for(i = 0; i < nas; i++) {
1152
		expr(av[i], &res);
1153
		switch(res.type) {
1154
		default:
1155
			if(comx(res))
1156
				break;
1157
			patom(res.type, &res.Store);
1158
			break;
1159
		case TCODE:
1160
			pcode(res.cc, 0);
1161
			break;
1162
		case TLIST:
1163
			blprint(res.l);
1164
			break;
1165
		}
1166
	}
1167
	if(ret == 0)
1168
		Bputc(bout, '\n');
1169
}
1170
 
1171
void
1172
printto(Node *r, Node *args)
1173
{
1174
	int fd;
1175
	Biobuf *b;
1176
	int i, nas;
1177
	Node res, *av[Maxarg];
1178
 
1179
	USED(r);
1180
	na = 0;
1181
	flatten(av, args);
1182
	nas = na;
1183
 
1184
	expr(av[0], &res);
1185
	if(res.type != TSTRING)
1186
		error("printto(string, ...): need string");
1187
 
1188
	fd = create(res.string->string, OWRITE, 0666);
1189
	if(fd < 0)
1190
		fd = open(res.string->string, OWRITE);
1191
	if(fd < 0)
1192
		error("printto: open %s: %r", res.string->string);
1193
 
1194
	b = gmalloc(sizeof(Biobuf));
1195
	Binit(b, fd, OWRITE);
1196
 
1197
	Bflush(bout);
1198
	io[iop++] = bout;
1199
	bout = b;
1200
 
1201
	for(i = 1; i < nas; i++) {
1202
		expr(av[i], &res);
1203
		switch(res.type) {
1204
		default:
1205
			if(comx(res))
1206
				break;
1207
			patom(res.type, &res.Store);
1208
			break;
1209
		case TLIST:
1210
			blprint(res.l);
1211
			break;
1212
		}
1213
	}
1214
	if(ret == 0)
1215
		Bputc(bout, '\n');
1216
 
1217
	Bterm(b);
1218
	close(fd);
1219
	free(b);
1220
	bout = io[--iop];
1221
}
1222
 
1223
void
1224
pcfile(Node *r, Node *args)
1225
{
1226
	Node res;
1227
	char *p, buf[128];
1228
 
1229
	if(args == 0)
1230
		error("pcfile(addr): arg count");
1231
	expr(args, &res);
1232
	if(res.type != TINT)
1233
		error("pcfile(addr): arg type");
1234
 
1235
	r->type = TSTRING;
1236
	r->fmt = 's';
1237
	if(fileline(buf, sizeof(buf), res.ival) == 0) {
1238
		r->string = strnode("?file?");
1239
		return;
1240
	}
1241
	p = strrchr(buf, ':');
1242
	if(p == 0)
1243
		error("pcfile(addr): funny file %s", buf);
1244
	*p = '\0';
1245
	r->string = strnode(buf);	
1246
}
1247
 
1248
void
1249
pcline(Node *r, Node *args)
1250
{
1251
	Node res;
1252
	char *p, buf[128];
1253
 
1254
	if(args == 0)
1255
		error("pcline(addr): arg count");
1256
	expr(args, &res);
1257
	if(res.type != TINT)
1258
		error("pcline(addr): arg type");
1259
 
1260
	r->type = TINT;
1261
	r->fmt = 'D';
1262
	if(fileline(buf, sizeof(buf), res.ival) == 0) {
1263
		r->ival = 0;
1264
		return;
1265
	}
1266
 
1267
	p = strrchr(buf, ':');
1268
	if(p == 0)
1269
		error("pcline(addr): funny file %s", buf);
1270
	r->ival = strtol(p+1, 0, 0);	
1271
}
1272
 
1273
void fmtof(Node *r, Node *args)
1274
{
1275
	Node *av[Maxarg];
1276
	Node res;
1277
 
1278
	na = 0;
1279
	flatten(av, args);
1280
	if(na < 1)
1281
		error("fmtof(obj): no argument");
1282
	if(na > 1)
1283
		error("fmtof(obj): too many arguments") ;
1284
	expr(av[0], &res);
1285
 
1286
	r->op = OCONST;
1287
	r->type = TINT ;
1288
	r->ival = res.fmt ;
1289
	r->fmt = 'c';
1290
}
1291
 
1292
void dofmtsize(Node *r, Node *args)
1293
{
1294
	Node *av[Maxarg];
1295
	Node res;
1296
	Store * s ;
1297
	Value v ;
1298
 
1299
	na = 0;
1300
	flatten(av, args);
1301
	if(na < 1)
1302
		error("fmtsize(obj): no argument");
1303
	if(na > 1)
1304
		error("fmtsize(obj): too many arguments") ;
1305
	expr(av[0], &res);
1306
 
1307
	v.type = res.type ;
1308
	s = &v.Store ;
1309
	*s = res ;
1310
 
1311
	r->op = OCONST;
1312
	r->type = TINT ;
1313
	r->ival = fmtsize(&v) ;
1314
	r->fmt = 'D';
1315
}