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