Mercurial > emacs
annotate 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 |
rev | line source |
---|---|
102 | 1 /* IBM has disclaimed copyright on this module. */ |
2 | |
3 /***************************************************************/ | |
4 /* */ | |
5 /* Function: hftctl */ | |
6 /* */ | |
7 /* Syntax: */ | |
8 /* #include <sys/ioctl.h> */ | |
9 /* #include <sys/hft.h> */ | |
10 /* */ | |
11 /* int hftctl(fildes, request, arg ) */ | |
485 | 12 /* int fildes, request; */ |
13 /* char *arg; */ | |
102 | 14 /* */ |
15 /* Description: */ | |
16 /* */ | |
17 /* Does the following: */ | |
18 /* 1. determines if fildes is pty */ | |
19 /* does normal ioctl it is not */ | |
20 /* 2. places fildes into raw mode */ | |
21 /* 3. converts ioctl arguments to datastream */ | |
22 /* 4. waits for 2 secs for acknowledgement before */ | |
3591
507f64624555
Apply typo patches from Paul Eggert.
Jim Blandy <jimb@redhat.com>
parents:
3470
diff
changeset
|
23 /* timing out. */ |
102 | 24 /* 5. places response in callers buffer ( just like */ |
25 /* ioctl. */ | |
26 /* 6. returns fildes to its original mode */ | |
27 /* */ | |
28 /* User of this program should review steps 1,4, and 3. */ | |
29 /* hftctl makes no check on the request type. It must be */ | |
30 /* a HFT ioctl that is supported remotely. */ | |
31 /* This program will use the SIGALRM and alarm(2). Any */ | |
32 /* Previous alarms are lost. */ | |
33 /* */ | |
34 /* Users of this program are free to modify it any way */ | |
35 /* they want. */ | |
36 /* */ | |
37 /* Return Value: */ | |
38 /* */ | |
39 /* If ioctl fails, a value of -1 is returned and errno */ | |
40 /* is set to indicate the error. */ | |
41 /* */ | |
42 /***************************************************************/ | |
43 | |
44 | |
45 #include <stdio.h> | |
46 #include <fcntl.h> | |
47 #include <errno.h> | |
48 #include <setjmp.h> | |
49 #include <sys/ioctl.h> | |
50 #include <sys/signal.h> | |
51 #include <sys/devinfo.h> | |
485 | 52 #include <termios.h> |
102 | 53 #include <termio.h> |
54 #include <sys/hft.h> | |
560 | 55 #include <sys/uio.h> |
102 | 56 #include <sys/tty.h> |
57 /* #include <sys/pty.h> */ | |
58 #define REMOTE 0x01 | |
59 | |
60 #undef ioctl | |
485 | 61 static char SCCSid[] = "com/gnuemacs/src,3.1,9021-90/05/03-5/3/90"; |
102 | 62 |
63 /*************** LOCAL DEFINES **********************************/ | |
64 | |
485 | 65 typedef int (*FUNC)(); /* pointer to a function */ |
102 | 66 |
67 #define QDEV ((HFQPDEVCH<<8)|HFQPDEVCL) | |
68 #define QLOC ((HFQLOCCH<<8)|HFQLOCCL) | |
69 #define QPS ((HFQPRESCH<<8)|HFQPRESCL) | |
70 | |
485 | 71 #ifndef TCGETS |
72 #define TCGETS TCGETA | |
73 #endif | |
74 #ifndef TCSETS | |
75 #define TCSETS TCSETA | |
76 #endif | |
77 | |
102 | 78 /*************** EXTERNAL / GLOBAL DATA AREA ********************/ |
79 | |
560 | 80 static int hfqry(); |
81 static int hfskbd(); | |
2439
b6c62e4abf59
Put interrupt input blocking in a separate file from xterm.h.
Jim Blandy <jimb@redhat.com>
parents:
560
diff
changeset
|
82 char *xmalloc(); |
102 | 83 |
485 | 84 extern int errno; |
85 static jmp_buf hftenv; | |
86 static int is_ack_vtd; | |
87 static FUNC sav_alrm; | |
102 | 88 static struct hfctlreq req = |
89 { 0x1b,'[','x',0,0,0,21,HFCTLREQCH,HFCTLREQCL}; | |
90 static struct hfctlack ACK = | |
91 { 0x1b,'[','x',0,0,0,21,HFCTLACKCH,HFCTLACKCL}; | |
92 | |
485 | 93 /* FUNC signal(); */ |
102 | 94 |
95 /*************** LOCAL MACROS ***********************************/ | |
96 | |
97 #define HFTYPE(p) ((p->hf_typehi<<8)|(p->hf_typelo)) | |
98 | |
485 | 99 #define BYTE4(p) ((p)[0]<<24 | (p)[1]<<16 | (p)[2]<<8 | (p)[3]) |
102 | 100 |
101 /* read a buffer */ | |
102 #define RD_BUF(f,p,l) \ | |
485 | 103 while ((l)) \ |
104 if ((j = read((f),(p),(l))) < 0) \ | |
105 if (errno != EINTR) return (-1); \ | |
106 else continue; \ | |
107 else { (l) -= j; (p) += j; } | |
108 | |
109 /*************** function prototypes ***************************/ | |
110 #ifdef __STDC__ | |
111 static GT_ACK (int fd, int req, char *buf); | |
112 static WR_REQ (int fd, int request, int cmdlen, char *cmd, int resplen); | |
3315
dcc64ab7de8c
* hftctl.c (hft_alrm): Declare and define this to return void, not
Jim Blandy <jimb@redhat.com>
parents:
2439
diff
changeset
|
113 static void hft_alrm(int sig); |
485 | 114 #else |
115 static GT_ACK (); | |
116 static WR_REQ (); | |
3470
a6dde97d8166
(hft_alrm): Don't return a value.
Richard M. Stallman <rms@gnu.org>
parents:
3315
diff
changeset
|
117 static void hft_alrm (); |
485 | 118 #endif |
102 | 119 |
120 /*************** HFTCTL FUNCTION *******************************/ | |
121 | |
485 | 122 hftctl (fd, request, arg) |
123 int fd; | |
124 int request; | |
125 union { | |
126 struct hfintro *intro; | |
127 struct hfquery *query; | |
128 char *c; | |
129 } arg; | |
102 | 130 { |
131 | |
485 | 132 int i; |
133 int fd_flag; /* fcntl flags */ | |
134 register union { | |
135 struct hfintro *cmd; /* p.cmd - intro des. */ | |
136 struct hfqphdevc *ph; /* p.ph - physical dev.*/ | |
137 char *c; /* p.c - char ptr */ | |
138 } p; /* general pointer */ | |
139 int pty_new; /* pty modes */ | |
140 int pty_old; | |
141 int retcode; | |
142 struct termios term_new; /* terminal attributes */ | |
143 struct termios term_old; | |
144 struct devinfo devInfo; /* defined in sys/devinfo.h */ | |
102 | 145 |
146 | |
485 | 147 if (ioctl (fd, IOCINFO, &devInfo) == -1) return(-1); |
102 | 148 |
485 | 149 if (devInfo.devtype != DD_PSEU) /* is it a pty? */ |
150 return (ioctl(fd, request, arg)); /* no, do IOCTL */ | |
102 | 151 |
485 | 152 /******* START PTY **************/ |
153 /** Pty found, possible HFT */ | |
154 /** set new file des as raw */ | |
155 /** as you can. */ | |
156 /********************************/ | |
102 | 157 |
485 | 158 /* Get current state of file */ |
159 /* descriptor & save */ | |
160 if ((fd_flag = fcntl (fd, F_GETFL, 0)) == -1) return (-1); | |
161 if (ioctl (fd, TCGETS, &term_old) == -1) return (-1); | |
162 /* set terminal attr to raw */ | |
163 /* and to delay on read */ | |
164 pty_new = pty_old | REMOTE; | |
165 memcpy (&term_new, &term_old, sizeof (term_new)); | |
166 term_new.c_iflag = 0; | |
167 term_new.c_oflag = 0; | |
168 term_new.c_lflag = 0; | |
169 /* term_new.c_line = 0; */ | |
170 for (i = 1; i <= 5; i++) | |
171 term_new.c_cc[i] = 0; | |
172 term_new.c_cc[0] = -1; | |
173 ioctl (fd, TCSETS, &term_new); | |
174 if (fcntl (fd, F_SETFL, fd_flag & ~O_NDELAY) == -1) | |
175 return(-1); | |
176 /* call spacific function */ | |
177 if (request == HFSKBD) | |
178 retcode = hfskbd (fd, request, arg.c); | |
179 else /* assume HFQUERY */ | |
180 retcode = hfqry (fd, request, arg.c); | |
102 | 181 |
485 | 182 fcntl (fd, F_SETFL, fd_flag); /* reset terminal to original */ |
183 ioctl (fd, TCSETS, &term_old); | |
102 | 184 |
185 | |
485 | 186 return (retcode); /* return error */ |
102 | 187 } |
188 | |
189 /*************** HFSKBD FUNCTION ******************************/ | |
485 | 190 static int |
191 hfskbd (fd, request, arg) | |
192 int fd; | |
193 int request; | |
194 struct hfbuf *arg; | |
102 | 195 { |
485 | 196 WR_REQ(fd, request, arg->hf_buflen, arg->hf_bufp,0); |
197 return (GT_ACK(fd, request, arg->hf_bufp)); | |
102 | 198 } |
199 | |
200 /*************** HFQUERY FUNCTION ******************************/ | |
485 | 201 static int |
202 hfqry (fd, request, arg) | |
203 int fd; | |
204 int request; | |
205 struct hfquery *arg; | |
102 | 206 { |
485 | 207 WR_REQ(fd, request, arg->hf_cmdlen, arg->hf_cmd, arg->hf_resplen); |
208 return (GT_ACK(fd, request, arg->hf_resp)); | |
102 | 209 } |
210 | |
211 | |
212 /*************** GT_ACK FUNCTION ******************************/ | |
485 | 213 static int |
214 GT_ACK (fd, req, buf) | |
215 int fd; | |
216 int req; | |
217 char *buf; | |
102 | 218 { |
485 | 219 struct hfctlack ack; |
220 int i = sizeof (ack); | |
221 int j = 0; | |
222 union { | |
223 char *c; | |
224 struct hfctlack *ack; | |
225 } p; | |
102 | 226 |
485 | 227 is_ack_vtd = 0; /* flag no ACT VTD yet */ |
102 | 228 |
485 | 229 if (setjmp (hftenv)) /* set environment in case */ |
230 { /* of time out */ | |
231 errno = ENODEV; /* if time out, set errno */ | |
232 return (-1); /* flag error */ | |
233 } | |
102 | 234 |
485 | 235 alarm(3); /* time out in 3 secs */ |
236 sav_alrm = signal (SIGALRM, hft_alrm); /* prepare to catch time out */ | |
102 | 237 |
485 | 238 p.ack = &ack; |
239 while (! is_ack_vtd) /* do until valid ACK VTD */ | |
240 { | |
241 RD_BUF(fd, p.c, i); /* read until a ACK VTD is fill*/ | |
102 | 242 |
485 | 243 if (! memcmp (&ack, &ACK, sizeof (HFINTROSZ)) /* the ACK intro & */ |
244 && (ack.hf_request == req)) /* is it the response we want ?*/ | |
245 { /* yes, ACK VTD found */ | |
246 is_ack_vtd = 1; /* quickly, flag it */ | |
247 break; /* get the %$%#@ out of here */ | |
248 } | |
102 | 249 |
485 | 250 p.ack = &ack; /* no, then skip 1st */ |
251 ++p.c; /* char and start over */ | |
252 i = sizeof (ack) - 1; /* one less ESC to cry over */ | |
102 | 253 |
485 | 254 while ((*p.c != 0x1b) && i) /* scan for next ESC */ |
255 { ++p.c; --i; } /* if any */ | |
102 | 256 |
485 | 257 (i ? memcpy (&ack, p.c, i) : 0); /* if any left over, then move */ |
258 p.ack = &ack; /* ESC to front of ack struct */ | |
259 p.c += i; /* skip over whats been read */ | |
260 i = sizeof (ack) - i; /* set whats left to be read */ | |
261 } /***** TRY AGAIN */ | |
102 | 262 |
485 | 263 alarm(0); /* ACK VTD received, reset alrm*/ |
264 signal (SIGALRM, sav_alrm); /* reset signal */ | |
102 | 265 |
485 | 266 if (i = ack.hf_arg_len) /* any data following ? */ |
267 { /* yes, */ | |
268 RD_BUF(fd,buf,i); /* read until it is received */ | |
269 } | |
102 | 270 |
485 | 271 if (errno = ack.hf_retcode) /* set errno based on returned */ |
272 return (-1); /* code, if 0, then no error */ | |
273 else | |
274 return (0); /* if set, then error returned */ | |
102 | 275 } |
276 | |
277 /*************** HFT_ALRM FUNCTION ******************************/ | |
3315
dcc64ab7de8c
* hftctl.c (hft_alrm): Declare and define this to return void, not
Jim Blandy <jimb@redhat.com>
parents:
2439
diff
changeset
|
278 static void |
dcc64ab7de8c
* hftctl.c (hft_alrm): Declare and define this to return void, not
Jim Blandy <jimb@redhat.com>
parents:
2439
diff
changeset
|
279 hft_alrm (sig) /* Function hft_alrm - handle */ |
dcc64ab7de8c
* hftctl.c (hft_alrm): Declare and define this to return void, not
Jim Blandy <jimb@redhat.com>
parents:
2439
diff
changeset
|
280 int sig; /* alarm signal */ |
102 | 281 { |
485 | 282 signal (SIGALRM, sav_alrm); /* reset to previous */ |
102 | 283 |
485 | 284 if (is_ack_vtd) /* has ack vtd arrived ? */ |
3470
a6dde97d8166
(hft_alrm): Don't return a value.
Richard M. Stallman <rms@gnu.org>
parents:
3315
diff
changeset
|
285 return; /* yes, then continue */ |
485 | 286 else /* no, then return with error */ |
287 longjmp (hftenv, -1); | |
102 | 288 |
289 } | |
290 | |
291 /*********************************************************************/ | |
292 /*** ***/ | |
293 /*** NOTE: Both the HFCTLREQ and the arg structure should be ***/ | |
294 /*** sent in one io write operation. If terminal ***/ | |
295 /*** emulators are in NODELAY mode then multiple writes ***/ | |
296 /*** may cause bogus information to be read by the emulator ***/ | |
297 /*** depending on the timing. ***/ | |
298 /*** ***/ | |
299 /*********************************************************************/ | |
300 | |
485 | 301 static int |
302 WR_REQ (fd, request, cmdlen, cmd, resplen) | |
303 int fd; | |
304 int request; | |
305 int cmdlen; | |
306 char *cmd; | |
307 int resplen; | |
102 | 308 { |
485 | 309 struct { |
310 char *c; | |
311 struct hfctlreq *req; | |
312 } p; | |
313 int size; | |
102 | 314 |
485 | 315 req.hf_request = request; |
316 req.hf_arg_len = cmdlen; | |
317 req.hf_rsp_len = resplen; | |
102 | 318 |
485 | 319 if (cmdlen) /* if arg structure to pass */ |
320 { | |
321 size = sizeof (struct hfctlreq) + cmdlen; | |
2439
b6c62e4abf59
Put interrupt input blocking in a separate file from xterm.h.
Jim Blandy <jimb@redhat.com>
parents:
560
diff
changeset
|
322 if ((p.c = xmalloc(size)) == NULL) /* malloc one area */ |
485 | 323 return (-1); |
102 | 324 |
485 | 325 memcpy (p.c, &req, sizeof (req)); /* copy CTL REQ struct */ |
326 memcpy (p.c + sizeof (req), cmd, cmdlen); /* copy arg struct */ | |
327 } | |
328 else | |
329 { | |
330 p.req = &req; /* otherwise use only CTL REQ */ | |
331 size = sizeof (req); | |
332 } | |
102 | 333 |
485 | 334 /* write request to terminal */ |
335 if (write(fd,p.c,size) == -1) return (-1); | |
336 if (p.req != &req) /* free if allocated */ | |
2439
b6c62e4abf59
Put interrupt input blocking in a separate file from xterm.h.
Jim Blandy <jimb@redhat.com>
parents:
560
diff
changeset
|
337 xfree (p.c); |
485 | 338 return (0); |
102 | 339 |
340 } |