This is Lisp.m in view mode; [Download] [Up]
/* ** Lisp.m ** Lisp client object with message-based I/O. ** Lee Boynton, NeXT, Inc., 1989 */ #import <mach.h> #import <stdlib.h> #import <string.h> #import <fcntl.h> #import <signal.h> #import <sys/wait.h> #import <dpsclient/dpsclient.h> #import <appkit/defaults.h> #import <appkit/Application.h> #import <objc/List.h> #import "Lisp.h" @implementation Lisp #define READ_BUF_SIZE (8191) static char read_buf[READ_BUF_SIZE+1]; static void *read_lisp(int fd, Lisp *self) { extern int read(); NXEvent event; int count = read(fd,read_buf,READ_BUF_SIZE); id delegate = self->delegate; BOOL tellDelegate = NO; if (delegate && [delegate respondsTo:@selector(lispOutput:)]) tellDelegate = YES; while (count > 0) { read_buf[count] = '\0'; if (tellDelegate) [delegate lispOutput:(const char *)read_buf]; if ([NXApp peekNextEvent:-1 into:&event waitFor:0.0 threshold:1]) break; count = read(fd,read_buf,READ_BUF_SIZE); } } static int launch(const char *name, const char **argv, int *child_pid, int *write_child_fd, int *read_child_fd) { extern int pipe(); extern int fork(); extern int dup2(); extern int close(); extern int execvp(); extern int fcntl(); extern int close(); int err, pid; int p_to_child[2], p_from_child[2]; if ((err = pipe(p_to_child)) < 0) return err; if ((err = pipe(p_from_child)) < 0) { close(p_to_child[0]); close(p_to_child[1]); return err; } if ((pid = fork()) == 0) { dup2(p_to_child[0], 0); dup2(p_from_child[1], 1); dup2(p_from_child[1], 2); close(p_to_child[1]); close(p_from_child[0]); execvp(name, argv); exit(127); } if (pid == -1) { close(p_to_child[0]); close(p_to_child[1]); close(p_from_child[0]); close(p_from_child[1]); return -1; } *child_pid = pid; *write_child_fd = p_to_child[1]; close(p_to_child[0]); *read_child_fd = p_from_child[0]; close(p_from_child[1]); return fcntl(*read_child_fd,F_SETFL,FNDELAY); } static id lispList = nil; static id findLispForPid(int pid) { Lisp *self; int i, max = [lispList count]; for (i=0; i<max; i++) { self = (Lisp *)[lispList objectAt:i]; if (self->lisp_pid == pid) return self; } return nil; } static void lispDied(int ignore) { union wait epitaph; int pid; Lisp *self; while (1) { pid = wait3(&epitaph,WNOHANG,0); if (pid > 0) { if (self = findLispForPid(pid)) { self->lisp_pid = 0; break; } } else break; } signal(SIGCHLD,&lispDied); } + initialize { if (!lispList) lispList = [List new]; signal(SIGCHLD,&lispDied); return self; } + new { int err; const char *argv[2]; const char *imageName = NXGetDefaultValue([NXApp appName],"LispImage"); self = [super new]; argv[0] = imageName; argv[1] = NULL; [lispList addObject:self]; err = launch(imageName,argv,&lisp_pid, &lisp_in_fd,&lisp_out_fd); if (err) { [self free]; return nil; } DPSAddFD(lisp_out_fd,(DPSFDProc)read_lisp,(void *)self,1); return self; } - free { extern int kill(); DPSRemoveFD(lisp_out_fd); [lispList removeObject:self]; if (lisp_pid) kill(lisp_pid,9); return [super free]; } - setDelegate:anObject { delegate = anObject; return self; } - delegate { return delegate; } - inputLisp:(const char *)theString { extern int write(); int i, count = strlen(theString); if (!lisp_pid || (count != write(lisp_in_fd,theString,count))) return nil; return self; } - interruptLisp { extern int kill(); if (lisp_pid && kill(lisp_pid,2)) return nil; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.