builtin.c 20 KB

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