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