Mercurial > emacs
view src/hftctl.c @ 4139:0b32ee899a3a
Consistently use the mark bit of the root interval's parent field
to say whether or not the interval tree has been visited (and skip
it when revisited), and the mark bit of the plist field to say
whether or not that interval has been visited (and abort if
revisited); don't try to use the plist mark bit for both
meanings.
* alloc.c (mark_interval_tree): Don't test if the interval tree
has already been visited here; let the MARK_INTERVAL_TREE macro do
that; avoid function call overhead. Mark the interval tree as
having been visited by setting TREE->parent's mark bit.
(MARK_INTERVAL_TREE): If the tree has been visited (according to
I->parent's mark bit), don't call mark_interval_tree.
(gc_sweep): Rebalance the interval trees of those large strings
which are still alive. This also clears the mark bits of those
trees' root intervals' parent fields.
(compact_strings): Rebalance the interval tree of each small
strings which is still alive. This also clears the mark bits of
that tree's root interval's parent field. Since the string has
moved, update the root interval's parent pointer to contain the
new address.
* lisp.h (struct interval): Doc fix; explain the roles of the mark
bits of the parent and plist members.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Sun, 18 Jul 1993 06:26:10 +0000 |
parents | 507f64624555 |
children | a770e7708711 |
line wrap: on
line source
/* IBM has disclaimed copyright on this module. */ /***************************************************************/ /* */ /* Function: hftctl */ /* */ /* Syntax: */ /* #include <sys/ioctl.h> */ /* #include <sys/hft.h> */ /* */ /* int hftctl(fildes, request, arg ) */ /* int fildes, request; */ /* char *arg; */ /* */ /* Description: */ /* */ /* Does the following: */ /* 1. determines if fildes is pty */ /* does normal ioctl it is not */ /* 2. places fildes into raw mode */ /* 3. converts ioctl arguments to datastream */ /* 4. waits for 2 secs for acknowledgement before */ /* timing out. */ /* 5. places response in callers buffer ( just like */ /* ioctl. */ /* 6. returns fildes to its original mode */ /* */ /* User of this program should review steps 1,4, and 3. */ /* hftctl makes no check on the request type. It must be */ /* a HFT ioctl that is supported remotely. */ /* This program will use the SIGALRM and alarm(2). Any */ /* Previous alarms are lost. */ /* */ /* Users of this program are free to modify it any way */ /* they want. */ /* */ /* Return Value: */ /* */ /* If ioctl fails, a value of -1 is returned and errno */ /* is set to indicate the error. */ /* */ /***************************************************************/ #include <stdio.h> #include <fcntl.h> #include <errno.h> #include <setjmp.h> #include <sys/ioctl.h> #include <sys/signal.h> #include <sys/devinfo.h> #include <termios.h> #include <termio.h> #include <sys/hft.h> #include <sys/uio.h> #include <sys/tty.h> /* #include <sys/pty.h> */ #define REMOTE 0x01 #undef ioctl static char SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90"; /*************** LOCAL DEFINES **********************************/ typedef int (*FUNC)(); /* pointer to a function */ #define QDEV ((HFQPDEVCH<<8)|HFQPDEVCL) #define QLOC ((HFQLOCCH<<8)|HFQLOCCL) #define QPS ((HFQPRESCH<<8)|HFQPRESCL) #ifndef TCGETS #define TCGETS TCGETA #endif #ifndef TCSETS #define TCSETS TCSETA #endif /*************** EXTERNAL / GLOBAL DATA AREA ********************/ static int hfqry(); static int hfskbd(); char *xmalloc(); extern int errno; static jmp_buf hftenv; static int is_ack_vtd; static FUNC sav_alrm; static struct hfctlreq req = { 0x1b,'[','x',0,0,0,21,HFCTLREQCH,HFCTLREQCL}; static struct hfctlack ACK = { 0x1b,'[','x',0,0,0,21,HFCTLACKCH,HFCTLACKCL}; /* FUNC signal(); */ /*************** LOCAL MACROS ***********************************/ #define HFTYPE(p) ((p->hf_typehi<<8)|(p->hf_typelo)) #define BYTE4(p) ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3]) /* read a buffer */ #define RD_BUF(f,p,l) \ while ((l)) \ if ((j = read((f),(p),(l))) < 0) \ if (errno != EINTR) return (-1); \ else continue; \ else { (l) -= j; (p) += j; } /*************** function prototypes ***************************/ #ifdef __STDC__ static GT_ACK (int fd, int req, char *buf); static WR_REQ (int fd, int request, int cmdlen, char *cmd, int resplen); static void hft_alrm(int sig); #else static GT_ACK (); static WR_REQ (); static void hft_alrm (); #endif /*************** HFTCTL FUNCTION *******************************/ hftctl (fd, request, arg) int fd; int request; union { struct hfintro *intro; struct hfquery *query; char *c; } arg; { int i; int fd_flag; /* fcntl flags */ register union { struct hfintro *cmd; /* p.cmd - intro des. */ struct hfqphdevc *ph; /* p.ph - physical dev.*/ char *c; /* p.c - char ptr */ } p; /* general pointer */ int pty_new; /* pty modes */ int pty_old; int retcode; struct termios term_new; /* terminal attributes */ struct termios term_old; struct devinfo devInfo; /* defined in sys/devinfo.h */ if (ioctl (fd, IOCINFO, &devInfo) == -1) return(-1); if (devInfo.devtype != DD_PSEU) /* is it a pty? */ return (ioctl(fd, request, arg)); /* no, do IOCTL */ /******* START PTY **************/ /** Pty found, possible HFT */ /** set new file des as raw */ /** as you can. */ /********************************/ /* Get current state of file */ /* descriptor & save */ if ((fd_flag = fcntl (fd, F_GETFL, 0)) == -1) return (-1); if (ioctl (fd, TCGETS, &term_old) == -1) return (-1); /* set terminal attr to raw */ /* and to delay on read */ pty_new = pty_old | REMOTE; memcpy (&term_new, &term_old, sizeof (term_new)); term_new.c_iflag = 0; term_new.c_oflag = 0; term_new.c_lflag = 0; /* term_new.c_line = 0; */ for (i = 1; i <= 5; i++) term_new.c_cc[i] = 0; term_new.c_cc[0] = -1; ioctl (fd, TCSETS, &term_new); if (fcntl (fd, F_SETFL, fd_flag & ~O_NDELAY) == -1) return(-1); /* call spacific function */ if (request == HFSKBD) retcode = hfskbd (fd, request, arg.c); else /* assume HFQUERY */ retcode = hfqry (fd, request, arg.c); fcntl (fd, F_SETFL, fd_flag); /* reset terminal to original */ ioctl (fd, TCSETS, &term_old); return (retcode); /* return error */ } /*************** HFSKBD FUNCTION ******************************/ static int hfskbd (fd, request, arg) int fd; int request; struct hfbuf *arg; { WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0); return (GT_ACK(fd, request, arg->hf_bufp)); } /*************** HFQUERY FUNCTION ******************************/ static int hfqry (fd, request, arg) int fd; int request; struct hfquery *arg; { WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen); return (GT_ACK(fd, request, arg->hf_resp)); } /*************** GT_ACK FUNCTION ******************************/ static int GT_ACK (fd, req, buf) int fd; int req; char *buf; { struct hfctlack ack; int i = sizeof (ack); int j = 0; union { char *c; struct hfctlack *ack; } p; is_ack_vtd = 0; /* flag no ACT VTD yet */ if (setjmp (hftenv)) /* set environment in case */ { /* of time out */ errno = ENODEV; /* if time out, set errno */ return (-1); /* flag error */ } alarm(3); /* time out in 3 secs */ sav_alrm = signal (SIGALRM, hft_alrm); /* prepare to catch time out */ p.ack = &ack; while (! is_ack_vtd) /* do until valid ACK VTD */ { RD_BUF(fd, p.c, i); /* read until a ACK VTD is fill*/ if (! memcmp (&ack, &ACK, sizeof (HFINTROSZ)) /* the ACK intro & */ && (ack.hf_request == req)) /* is it the response we want ?*/ { /* yes, ACK VTD found */ is_ack_vtd = 1; /* quickly, flag it */ break; /* get the %$%#@ out of here */ } p.ack = &ack; /* no, then skip 1st */ ++p.c; /* char and start over */ i = sizeof (ack) - 1; /* one less ESC to cry over */ while ((*p.c != 0x1b) && i) /* scan for next ESC */ { ++p.c; --i; } /* if any */ (i ? memcpy (&ack, p.c, i) : 0); /* if any left over, then move */ p.ack = &ack; /* ESC to front of ack struct */ p.c += i; /* skip over whats been read */ i = sizeof (ack) - i; /* set whats left to be read */ } /***** TRY AGAIN */ alarm(0); /* ACK VTD received, reset alrm*/ signal (SIGALRM, sav_alrm); /* reset signal */ if (i = ack.hf_arg_len) /* any data following ? */ { /* yes, */ RD_BUF(fd,buf,i); /* read until it is received */ } if (errno = ack.hf_retcode) /* set errno based on returned */ return (-1); /* code, if 0, then no error */ else return (0); /* if set, then error returned */ } /*************** HFT_ALRM FUNCTION ******************************/ static void hft_alrm (sig) /* Function hft_alrm - handle */ int sig; /* alarm signal */ { signal (SIGALRM, sav_alrm); /* reset to previous */ if (is_ack_vtd) /* has ack vtd arrived ? */ return; /* yes, then continue */ else /* no, then return with error */ longjmp (hftenv, -1); } /*********************************************************************/ /*** ***/ /*** NOTE: Both the HFCTLREQ and the arg structure should be ***/ /*** sent in one io write operation. If terminal ***/ /*** emulators are in NODELAY mode then multiple writes ***/ /*** may cause bogus information to be read by the emulator ***/ /*** depending on the timing. ***/ /*** ***/ /*********************************************************************/ static int WR_REQ (fd, request, cmdlen, cmd, resplen) int fd; int request; int cmdlen; char *cmd; int resplen; { struct { char *c; struct hfctlreq *req; } p; int size; req.hf_request = request; req.hf_arg_len = cmdlen; req.hf_rsp_len = resplen; if (cmdlen) /* if arg structure to pass */ { size = sizeof (struct hfctlreq) + cmdlen; if ((p.c = xmalloc(size)) == NULL) /* malloc one area */ return (-1); memcpy (p.c, &req, sizeof (req)); /* copy CTL REQ struct */ memcpy (p.c + sizeof (req), cmd, cmdlen); /* copy arg struct */ } else { p.req = &req; /* otherwise use only CTL REQ */ size = sizeof (req); } /* write request to terminal */ if (write(fd,p.c,size) == -1) return (-1); if (p.req != &req) /* free if allocated */ xfree (p.c); return (0); }