|
|
1.1 ! root 1: #ifndef lint ! 2: static char *rcsid = ! 3: "$Header: lam7.c,v 1.9 87/12/14 18:48:02 sklower Exp $"; ! 4: #endif ! 5: ! 6: /* -[Fri Aug 5 12:51:31 1983 by jkf]- ! 7: * lam7.c $Locker: $ ! 8: * lambda functions ! 9: * ! 10: * (c) copyright 1982, Regents of the University of California ! 11: */ ! 12: ! 13: #include "global.h" ! 14: #include <signal.h> ! 15: ! 16: ! 17: lispval ! 18: Lfork() { ! 19: int pid; ! 20: ! 21: chkarg(0,"fork"); ! 22: if ((pid=fork())) { ! 23: return(inewint(pid)); ! 24: } else ! 25: return(nil); ! 26: } ! 27: ! 28: lispval ! 29: Lwait() ! 30: { ! 31: register lispval ret, temp; ! 32: int status = -1, pid; ! 33: Savestack(2); ! 34: ! 35: ! 36: chkarg(0,"wait"); ! 37: pid = wait(&status); ! 38: ret = newdot(); ! 39: protect(ret); ! 40: temp = inewint(pid); ! 41: ret->d.car = temp; ! 42: temp = inewint(status); ! 43: ret->d.cdr = temp; ! 44: Restorestack(); ! 45: return(ret); ! 46: } ! 47: ! 48: lispval ! 49: Lpipe() ! 50: { ! 51: register lispval ret, temp; ! 52: int pipes[2]; ! 53: Savestack(2); ! 54: ! 55: chkarg(0,"pipe"); ! 56: pipes[0] = -1; ! 57: pipes[1] = -1; ! 58: pipe(pipes); ! 59: ret = newdot(); ! 60: protect(ret); ! 61: temp = inewint(pipes[0]); ! 62: ret->d.car = temp; ! 63: temp = inewint(pipes[1]); ! 64: ret->d.cdr = temp; ! 65: Restorestack(); ! 66: return(ret); ! 67: } ! 68: ! 69: lispval ! 70: Lfdopen() ! 71: { ! 72: register lispval fd, type; ! 73: FILE *ptr; ! 74: ! 75: chkarg(2,"fdopen"); ! 76: type = (np-1)->val; ! 77: fd = lbot->val; ! 78: if( TYPE(fd)!=INT ) ! 79: return(nil); ! 80: if ( (ptr=fdopen((int)fd->i, (char *)type->a.pname))==NULL) ! 81: return(nil); ! 82: return(P(ptr)); ! 83: } ! 84: ! 85: lispval ! 86: Lexece() ! 87: { ! 88: lispval fname, arglist, envlist, temp; ! 89: char *args[100], *envs[100], estrs[1024]; ! 90: char *p, *cp, **argsp; ! 91: ! 92: fname = nil; ! 93: arglist = nil; ! 94: envlist = nil; ! 95: ! 96: switch(np-lbot) { ! 97: case 3: envlist = lbot[2].val; ! 98: case 2: arglist = lbot[1].val; ! 99: case 1: fname = lbot[0].val; ! 100: case 0: break; ! 101: default: ! 102: argerr("exece"); ! 103: } ! 104: ! 105: while (TYPE(fname)!=ATOM) ! 106: fname = error("exece: non atom function name",TRUE); ! 107: while (TYPE(arglist)!=DTPR && arglist!=nil) ! 108: arglist = error("exece: non list arglist",TRUE); ! 109: for (argsp=args; arglist!=nil; arglist=arglist->d.cdr) { ! 110: temp = arglist->d.car; ! 111: if (TYPE(temp)!=ATOM) ! 112: error("exece: non atom argument seen",FALSE); ! 113: *argsp++ = temp->a.pname; ! 114: } ! 115: *argsp = 0; ! 116: if (TYPE(envlist)!=DTPR && envlist!=nil) ! 117: return(nil); ! 118: for (argsp=envs,cp=estrs; envlist!=nil; envlist=envlist->d.cdr) { ! 119: temp = envlist->d.car; ! 120: if (TYPE(temp)!=DTPR || TYPE(temp->d.car)!=ATOM ! 121: || TYPE(temp->d.cdr)!=ATOM) ! 122: error("exece: Bad enviroment list",FALSE); ! 123: *argsp++ = cp; ! 124: for (p=temp->d.car->a.pname; (*cp++ = *p++);) ; ! 125: *(cp-1) = '='; ! 126: for (p=temp->d.cdr->a.pname; (*cp++ = *p++);) ; ! 127: } ! 128: *argsp = 0; ! 129: ! 130: return(inewint(execve(fname->a.pname, args, envs))); ! 131: } ! 132: ! 133: /* Lprocess - ! 134: * C code to implement the *process function ! 135: * call: ! 136: * (*process 'st_command ['s_readp ['s_writep]]) ! 137: * where st_command is the command to execute ! 138: * s_readp is non nil if you want a port to read from returned ! 139: * s_writep is non nil if you want a port to write to returned ! 140: * both flags default to nil ! 141: * *process returns ! 142: * the exit status of the process if s_readp and s_writep not given ! 143: * (in this case the parent waits for the child to finish) ! 144: * a list of (readport writeport childpid) if one of s_readp or s_writep ! 145: * is given. If only s_readp is non nil, then writeport will be nil, ! 146: * If only s_writep is non nil, then readport will be nil ! 147: */ ! 148: ! 149: lispval ! 150: Lprocess() ! 151: { ! 152: int wflag , childsi , childso , child; ! 153: lispval handy; ! 154: char *command, *p; ! 155: int writep, readp; ! 156: int itemp; ! 157: int (*handler)(), (*signal())(); ! 158: FILE *bufs[2],*obufs[2], *fpipe(); ! 159: Savestack(0); ! 160: ! 161: writep = readp = FALSE; ! 162: wflag = TRUE; ! 163: ! 164: switch(np-lbot) { ! 165: case 3: if(lbot[2].val != nil) writep = TRUE; ! 166: case 2: if(lbot[1].val != nil) readp = TRUE; ! 167: wflag = 0; ! 168: case 1: command = (char *) verify(lbot[0].val, ! 169: "*process: non atom first arg"); ! 170: break; ! 171: default: ! 172: argerr("*process"); ! 173: } ! 174: ! 175: childsi = 0; ! 176: childso = 1; ! 177: ! 178: /* if there will be communication between the processes, ! 179: * it will be through these pipes: ! 180: * parent -> bufs[1] -> bufs[0] -> child if writep ! 181: * parent <- obufs[0] <- obufs[1] <- parent if readp ! 182: */ ! 183: if(writep) { ! 184: fpipe(bufs); ! 185: childsi = fileno(bufs[0]); ! 186: } ! 187: ! 188: if(readp) { ! 189: fpipe(obufs); ! 190: childso = fileno(obufs[1]); ! 191: } ! 192: ! 193: handler = signal(SIGINT,SIG_IGN); ! 194: if((child = vfork()) == 0 ) { ! 195: /* if we will wait for the child to finish ! 196: * and if the process had ignored interrupts before ! 197: * we were called, then leave them ignored, else ! 198: * set it back the the default (death) ! 199: */ ! 200: if(wflag && handler != SIG_IGN) ! 201: signal(2,SIG_DFL); ! 202: ! 203: if(writep) { ! 204: close(0); ! 205: dup(childsi); ! 206: } ! 207: if (readp) { ! 208: close(1); ! 209: dup(childso); ! 210: } ! 211: if ((p = (char *)getenv("SHELL")) != (char *)0) { ! 212: execlp(p , p, "-c",command,0); ! 213: _exit(-1); /* if exec fails, signal problems*/ ! 214: } else { ! 215: execlp("csh", "csh", "-c",command,0); ! 216: execlp("sh", "sh", "-c",command,0); ! 217: _exit(-1); /* if exec fails, signal problems*/ ! 218: } ! 219: } ! 220: ! 221: /* close the duplicated file descriptors ! 222: * e.g. if writep is true then we've created two desriptors, ! 223: * bufs[0] and bufs[1], we will write to bufs[1] and the ! 224: * child (who has a copy of our bufs[0]) will read from bufs[0] ! 225: * We (the parent) close bufs[0] since we will not be reading ! 226: * from it. ! 227: */ ! 228: if(writep) fclose(bufs[0]); ! 229: if(readp) fclose(obufs[1]); ! 230: ! 231: if(wflag && child!= -1) { ! 232: int status=0; ! 233: /* we await the death of the child */ ! 234: while(wait(&status)!=child) {} ! 235: /* the child has died */ ! 236: signal(2,handler); /* restore the interrupt handler */ ! 237: itemp = status >> 8; ! 238: Restorestack(); ! 239: return(inewint(itemp)); /* return its status */ ! 240: } ! 241: /* we are not waiting for the childs death ! 242: * build a list containing the write and read ports ! 243: */ ! 244: protect(handy = newdot()); ! 245: handy->d.cdr = newdot(); ! 246: handy->d.cdr->d.cdr = newdot(); ! 247: if(readp) { ! 248: handy->d.car = P(obufs[0]); ! 249: ioname[PN(obufs[0])] = (lispval) inewstr((char *) "from-process"); ! 250: } ! 251: if(writep) { ! 252: handy->d.cdr->d.car = P(bufs[1]); ! 253: ioname[PN(bufs[1])] = (lispval) inewstr((char *) "to-process"); ! 254: } ! 255: handy->d.cdr->d.cdr->d.car = (lispval) inewint(child); ! 256: signal(SIGINT,handler); ! 257: Restorestack(); ! 258: return(handy); ! 259: } ! 260: ! 261: extern int gensymcounter; ! 262: ! 263: lispval ! 264: Lgensym() ! 265: { ! 266: lispval arg; ! 267: char leader; ! 268: ! 269: switch(np-lbot) ! 270: { ! 271: case 0: arg = nil; ! 272: break; ! 273: case 1: arg = lbot->val; ! 274: break; ! 275: default: argerr("gensym"); ! 276: } ! 277: leader = 'g'; ! 278: if (arg != nil && TYPE(arg)==ATOM) ! 279: leader = arg->a.pname[0]; ! 280: sprintf(strbuf, "%c%05d", leader, gensymcounter++); ! 281: atmlen = 7; ! 282: return((lispval)newatom(0)); ! 283: } ! 284: ! 285: extern struct types { ! 286: char *next_free; ! 287: int space_left, ! 288: space, ! 289: type, ! 290: type_len; /* note type_len is in units of int */ ! 291: lispval *items, ! 292: *pages, ! 293: *type_name; ! 294: struct heads ! 295: *first; ! 296: } atom_str ; ! 297: ! 298: lispval ! 299: Lremprop() ! 300: { ! 301: register struct argent *argp; ! 302: register lispval pptr, ind, opptr; ! 303: lispval atm; ! 304: int disemp = FALSE; ! 305: ! 306: chkarg(2,"remprop"); ! 307: argp = lbot; ! 308: ind = argp[1].val; ! 309: atm = argp->val; ! 310: switch (TYPE(atm)) { ! 311: case DTPR: ! 312: pptr = atm->d.cdr; ! 313: disemp = TRUE; ! 314: break; ! 315: case ATOM: ! 316: if((lispval)atm==nil) ! 317: pptr = nilplist; ! 318: else ! 319: pptr = atm->a.plist; ! 320: break; ! 321: default: ! 322: errorh1(Vermisc, "remprop: Illegal first argument :", ! 323: nil, FALSE, 0, atm); ! 324: } ! 325: opptr = nil; ! 326: if (pptr==nil) ! 327: return(nil); ! 328: while(TRUE) { ! 329: if (TYPE(pptr->d.cdr)!=DTPR) ! 330: errorh1(Vermisc, "remprop: Bad property list", ! 331: nil, FALSE, 0,atm); ! 332: if (pptr->d.car == ind) { ! 333: if( opptr != nil) ! 334: opptr->d.cdr = pptr->d.cdr->d.cdr; ! 335: else if(disemp) ! 336: atm->d.cdr = pptr->d.cdr->d.cdr; ! 337: else if(atm==nil) ! 338: nilplist = pptr->d.cdr->d.cdr; ! 339: else ! 340: atm->a.plist = pptr->d.cdr->d.cdr; ! 341: return(pptr->d.cdr); ! 342: } ! 343: if ((pptr->d.cdr)->d.cdr == nil) return(nil); ! 344: opptr = pptr->d.cdr; ! 345: pptr = (pptr->d.cdr)->d.cdr; ! 346: } ! 347: } ! 348: ! 349: lispval ! 350: Lbcdad() ! 351: { ! 352: lispval ret, temp; ! 353: ! 354: chkarg(1,"bcdad"); ! 355: temp = lbot->val; ! 356: if (TYPE(temp)!=ATOM) ! 357: error("ONLY ATOMS HAVE FUNCTION BINDINGS", FALSE); ! 358: temp = temp->a.fnbnd; ! 359: if (TYPE(temp)!=BCD) ! 360: return(nil); ! 361: ret = newint(); ! 362: ret->i = (int)temp; ! 363: return(ret); ! 364: } ! 365: ! 366: lispval ! 367: Lstringp() ! 368: { ! 369: chkarg(1,"stringp"); ! 370: if (TYPE(lbot->val)==STRNG) ! 371: return(tatom); ! 372: return(nil); ! 373: } ! 374: ! 375: lispval ! 376: Lsymbolp() ! 377: { ! 378: chkarg(1,"symbolp"); ! 379: if (TYPE(lbot->val)==ATOM) ! 380: return(tatom); ! 381: return(nil); ! 382: } ! 383: ! 384: lispval ! 385: Lrematom() ! 386: { ! 387: register lispval temp; ! 388: ! 389: chkarg(1,"rematom"); ! 390: temp = lbot->val; ! 391: if (TYPE(temp)!=ATOM) ! 392: return(nil); ! 393: temp->a.fnbnd = nil; ! 394: temp->a.pname = (char *)CNIL; ! 395: temp->a.plist = nil; ! 396: (atom_items->i)--; ! 397: (atom_str.space_left)++; ! 398: temp->a.clb=(lispval)atom_str.next_free; ! 399: atom_str.next_free=(char *) temp; ! 400: return(tatom); ! 401: } ! 402: ! 403: #define QUTMASK 0200 ! 404: #define VNUM 0000 ! 405: ! 406: lispval ! 407: Lprname() ! 408: { ! 409: lispval a, ret; ! 410: register lispval work, prev; ! 411: char *front, *temp; int clean; ! 412: char ctemp[100]; ! 413: extern unsigned char *ctable; ! 414: Savestack(2); ! 415: ! 416: chkarg(1,"prname"); ! 417: a = lbot->val; ! 418: switch (TYPE(a)) { ! 419: case INT: ! 420: sprintf(ctemp,"%d",a->i); ! 421: break; ! 422: ! 423: case DOUB: ! 424: sprintf(ctemp,"%f",a->r); ! 425: break; ! 426: ! 427: case ATOM: ! 428: temp = front = a->a.pname; ! 429: clean = *temp; ! 430: if (*temp == '-') temp++; ! 431: clean = clean && (ctable[*temp] != VNUM); ! 432: while (clean && *temp) ! 433: clean = (!(ctable[*temp++] & QUTMASK)); ! 434: if (clean) ! 435: strncpy(ctemp, front, 99); ! 436: else ! 437: sprintf(ctemp,"\"%s\"",front); ! 438: break; ! 439: ! 440: default: ! 441: error("prname does not support this type", FALSE); ! 442: } ! 443: temp = ctemp; ! 444: protect(ret = prev = newdot()); ! 445: while (*temp) { ! 446: prev->d.cdr = work = newdot(); ! 447: strbuf[0] = *temp++; ! 448: strbuf[1] = 0; ! 449: work->d.car = getatom(FALSE); ! 450: work->d.cdr = nil; ! 451: prev = work; ! 452: } ! 453: Restorestack(); ! 454: return(ret->d.cdr); ! 455: } ! 456: ! 457: lispval ! 458: Lexit() ! 459: { ! 460: register lispval handy; ! 461: if(np-lbot==0) franzexit(0); ! 462: handy = lbot->val; ! 463: if(TYPE(handy)==INT) ! 464: franzexit((int) handy->i); ! 465: franzexit(-1); ! 466: } ! 467: lispval ! 468: Iimplode(unintern) ! 469: { ! 470: register lispval handy, work; ! 471: register char *cp = strbuf; ! 472: extern int atmlen; /* used by newatom and getatom */ ! 473: extern char *atomtoolong(); ! 474: ! 475: chkarg(1,"implode"); ! 476: for(handy = lbot->val; handy!=nil; handy = handy->d.cdr) ! 477: { ! 478: work = handy->d.car; ! 479: if(cp >= endstrb) ! 480: cp = atomtoolong(cp); ! 481: again: ! 482: switch(TYPE(work)) ! 483: { ! 484: case ATOM: ! 485: *cp++ = work->a.pname[0]; ! 486: break; ! 487: case SDOT: ! 488: *cp++ = work->s.I; ! 489: break; ! 490: case INT: ! 491: *cp++ = work->i; ! 492: break; ! 493: case STRNG: ! 494: *cp++ = * (char *) work; ! 495: break; ! 496: default: ! 497: work = errorh1(Vermisc,"implode/maknam: Illegal type for this arg:",nil,FALSE,44,work); ! 498: goto again; ! 499: } ! 500: } ! 501: *cp = 0; ! 502: if(unintern) return((lispval)newatom(FALSE)); ! 503: else return((lispval) getatom(FALSE)); ! 504: } ! 505: ! 506: lispval ! 507: Lmaknam() ! 508: { ! 509: return(Iimplode(TRUE)); /* unintern result */ ! 510: } ! 511: ! 512: lispval ! 513: Limplode() ! 514: { ! 515: return(Iimplode(FALSE)); /* intern result */ ! 516: } ! 517: ! 518: lispval ! 519: Lntern() ! 520: { ! 521: register int hash; ! 522: register lispval handy,atpr; ! 523: ! 524: ! 525: chkarg(1,"intern"); ! 526: if(TYPE(handy=lbot->val) != ATOM) ! 527: errorh1(Vermisc,"non atom to intern ",nil,FALSE,0,handy); ! 528: /* compute hash of pname of arg */ ! 529: hash = hashfcn(handy->a.pname); ! 530: ! 531: /* search for atom with same pname on hash list */ ! 532: ! 533: atpr = (lispval) hasht[hash]; ! 534: for(atpr = (lispval) hasht[hash] ! 535: ; atpr != CNIL ! 536: ; atpr = (lispval)atpr->a.hshlnk) ! 537: { ! 538: if(strcmp(atpr->a.pname,handy->a.pname) == 0) return(atpr); ! 539: } ! 540: ! 541: /* not there yet, put the given one on */ ! 542: ! 543: handy->a.hshlnk = hasht[hash]; ! 544: hasht[hash] = (struct atom *)handy; ! 545: return(handy); ! 546: } ! 547: ! 548: /*** Ibindvars :: lambda bind values to variables ! 549: called with a list of variables and values. ! 550: does the special binding and returns a fixnum which represents ! 551: the value of bnp before the binding ! 552: Use by compiled progv's. ! 553: ***/ ! 554: lispval ! 555: Ibindvars() ! 556: { ! 557: register lispval vars,vals,handy; ! 558: struct nament *oldbnp = bnp; ! 559: ! 560: chkarg(2,"int:bindvars"); ! 561: ! 562: vars = lbot[0].val; ! 563: vals = lbot[1].val; ! 564: ! 565: if(vars == nil) return(inewint(oldbnp)); ! 566: ! 567: if(TYPE(vars) != DTPR) ! 568: errorh1(Vermisc,"progv (int:bindvars): bad first argument ", nil, ! 569: FALSE,0,vars); ! 570: if((vals != nil) && (TYPE(vals) != DTPR)) ! 571: errorh1(Vermisc,"progv (int:bindvars): bad second argument ",nil, ! 572: FALSE,0,vals); ! 573: ! 574: for( ; vars != nil ; vars = vars->d.cdr , vals=vals->d.cdr) ! 575: { ! 576: handy = vars->d.car; ! 577: if(TYPE(handy) != ATOM) ! 578: errorh1(Vermisc,"progv (int:bindvars): non symbol argument to bind ", ! 579: nil,FALSE,0,handy); ! 580: PUSHDOWN(handy,vals->d.car); ! 581: } ! 582: return(inewint(oldbnp)); ! 583: } ! 584: ! 585: ! 586: /*** Iunbindvars :: unbind the variable stacked by Ibindvars ! 587: called by compiled progv's ! 588: ***/ ! 589: ! 590: lispval ! 591: Iunbindvars() ! 592: { ! 593: struct nament *oldbnp; ! 594: ! 595: chkarg(1,"int:unbindvars"); ! 596: oldbnp = (struct nament *) (lbot[0].val->i); ! 597: if((oldbnp < orgbnp) || ( oldbnp > bnp)) ! 598: errorh1(Vermisc,"int:unbindvars: bad bnp value given ",nil,FALSE,0, ! 599: lbot[0].val); ! 600: popnames(oldbnp); ! 601: return(nil); ! 602: } ! 603: ! 604: /* ! 605: * (time-string ['x_milliseconds]) ! 606: * if given no argument, returns the current time as a string ! 607: * if given an argument which is a fixnum representing the current time ! 608: * as a fixnum, it generates a string from that ! 609: * ! 610: * the format of the string returned is that defined in the Unix manual ! 611: * except the trailing newline is removed. ! 612: * ! 613: */ ! 614: lispval ! 615: Ltymestr() ! 616: { ! 617: long timevalue; ! 618: char *retval; ! 619: ! 620: switch(np-lbot) ! 621: { ! 622: case 0: time(&timevalue); ! 623: break; ! 624: case 1: while (TYPE(lbot[0].val) != INT) ! 625: lbot[0].val = ! 626: errorh(Vermisc,"time-string: non fixnum argument ", ! 627: nil,TRUE,0,lbot[0].val); ! 628: timevalue = lbot[0].val->i; ! 629: break; ! 630: default: ! 631: argerr("time-string"); ! 632: } ! 633: ! 634: retval = (char *) ctime(&timevalue); ! 635: /* remove newline character */ ! 636: retval[strlen(retval)-1] = '\0'; ! 637: return((lispval) inewstr(retval)); ! 638: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.