This source file includes following definitions.
- find_capability
- tgetnum
- tgetflag
- tgetstr
- tgetst1
- tputs
- valid_filename_p
- tgetent
- scan_file
- name_match
- compare_contin
- gobble_line
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 #include <config.h>
23
24 #include <stdlib.h>
25 #include <sys/file.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28
29 #include <intprops.h>
30
31 #include "lisp.h"
32 #include "tparam.h"
33 #ifdef MSDOS
34 #include "msdos.h"
35 #endif
36
37
38
39
40
41
42
43
44 #ifndef BUFSIZE
45 #ifdef DEBUG
46 #define BUFSIZE bufsize
47
48 int bufsize = 128;
49 #else
50 #define BUFSIZE 2048
51 #endif
52 #endif
53
54 #ifndef TERMCAP_FILE
55 #define TERMCAP_FILE "/etc/termcap"
56 #endif
57
58
59
60
61
62
63 static char *term_entry;
64
65 static char *tgetst1 (char *ptr, char **area);
66
67
68
69
70
71 static char *
72 find_capability (register char *bp, register const char *cap)
73 {
74 for (; *bp; bp++)
75 if (bp[0] == ':'
76 && bp[1] == cap[0]
77 && bp[2] == cap[1])
78 return &bp[4];
79 return NULL;
80 }
81
82 int
83 tgetnum (const char *cap)
84 {
85 register char *ptr = find_capability (term_entry, cap);
86 if (!ptr || ptr[-1] != '#')
87 return -1;
88 return atoi (ptr);
89 }
90
91 int
92 tgetflag (const char *cap)
93 {
94 register char *ptr = find_capability (term_entry, cap);
95 return ptr && ptr[-1] == ':';
96 }
97
98
99
100
101
102
103 char *
104 tgetstr (const char *cap, char **area)
105 {
106 register char *ptr = find_capability (term_entry, cap);
107 if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~'))
108 return NULL;
109 return tgetst1 (ptr, area);
110 }
111
112 #ifdef IS_EBCDIC_HOST
113
114
115
116
117 static const char esctab[]
118 = " \057\026 \047\014 \
119 \025 \015 \
120 \005 \013 \
121 ";
122 #else
123
124
125
126
127 static const char esctab[]
128 = " \007\010 \033\014 \
129 \012 \
130 \015 \011 \013 \
131 ";
132 #endif
133
134
135
136
137
138
139
140
141 static char *
142 tgetst1 (char *ptr, char **area)
143 {
144 register char *p, *r;
145 register int c;
146 register int size;
147 char *ret;
148 register int c1;
149
150 if (!ptr)
151 return NULL;
152
153
154 if (!area)
155 {
156
157 p = ptr;
158 while ((c = *p++) && c != ':' && c != '\n')
159 ;
160 ret = xmalloc (p - ptr + 1);
161 }
162 else
163 ret = *area;
164
165
166
167 p = ptr;
168 r = ret;
169 while ((c = *p++) && c != ':' && c != '\n')
170 {
171 if (c == '^')
172 {
173 c = *p++;
174 if (c == '?')
175 c = 0177;
176 else
177 c &= 037;
178 }
179 else if (c == '\\')
180 {
181 c = *p++;
182 if (c >= '0' && c <= '7')
183 {
184 c -= '0';
185 size = 0;
186
187 while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7')
188 {
189 c *= 8;
190 c += c1 - '0';
191 p++;
192 }
193 }
194 #ifdef IS_EBCDIC_HOST
195 else if (c >= 0200 && c < 0360)
196 {
197 c1 = esctab[(c & ~0100) - 0200];
198 if (c1 != ' ')
199 c = c1;
200 }
201 #else
202 else if (c >= 0100 && c < 0200)
203 {
204 c1 = esctab[(c & ~040) - 0100];
205 if (c1 != ' ')
206 c = c1;
207 }
208 #endif
209 }
210 *r++ = c;
211 }
212
213
214
215
216
217
218
219
220
221
222 {
223 int last_p_param = 0;
224 bool remove_p_params = 1;
225 struct { char *beg; int len; } cut[11];
226
227 for (cut[0].beg = p = ret; p < r - 3; p++)
228 {
229 if (!remove_p_params)
230 break;
231 if (*p == '%' && *(p + 1) == 'p')
232 {
233 if (*(p + 2) - '0' == 1 + last_p_param)
234 {
235 cut[last_p_param].len = p - cut[last_p_param].beg;
236 last_p_param++;
237 p += 3;
238 cut[last_p_param].beg = p;
239 }
240 else
241 remove_p_params = 0;
242 if (last_p_param > 10)
243 remove_p_params = 0;
244 }
245 }
246 if (remove_p_params && last_p_param)
247 {
248 register int i;
249 char *wp;
250
251 cut[last_p_param].len = r - cut[last_p_param].beg;
252 for (i = 0, wp = ret; i <= last_p_param; wp += cut[i++].len)
253 memcpy (wp, cut[i].beg, cut[i].len);
254 r = wp;
255 }
256 }
257
258 *r = '\0';
259
260 if (area)
261 *area = r + 1;
262 return ret;
263 }
264
265
266
267 char PC;
268
269 void
270 tputs (register const char *str, int nlines, int (*outfun) (int))
271 {
272 int padcount = 0;
273
274 if (!str)
275 return;
276
277 while (*str >= '0' && *str <= '9')
278 {
279 padcount += *str++ - '0';
280 padcount *= 10;
281 }
282 if (*str == '.')
283 {
284 str++;
285 padcount += *str++ - '0';
286 }
287 if (*str == '*')
288 {
289 str++;
290 padcount *= nlines;
291 }
292 while (*str)
293 (*outfun) (*str++);
294
295
296
297
298 intmax_t padfactor;
299 if (ckd_mul (&padfactor, padcount, baud_rate))
300 padfactor = baud_rate < 0 ? INTMAX_MIN : INTMAX_MAX;
301
302 for (; 50000 <= padfactor; padfactor -= 100000)
303 (*outfun) (PC);
304 }
305
306
307
308 struct termcap_buffer
309 {
310 char *beg;
311 ptrdiff_t size;
312 char *ptr;
313 bool ateof;
314 ptrdiff_t full;
315 };
316
317
318
319 static bool scan_file (char *, int, struct termcap_buffer *);
320 static char *gobble_line (int, struct termcap_buffer *, char *);
321 static bool compare_contin (char *, char *);
322 static bool name_match (char *, char *);
323
324 static bool
325 valid_filename_p (char *fn)
326 {
327 #ifdef MSDOS
328 return *fn == '/' || fn[1] == ':';
329 #else
330 return *fn == '/';
331 #endif
332 }
333
334
335
336
337
338
339
340
341
342
343
344
345 int
346 tgetent (char *bp, const char *name)
347 {
348 register char *termcap_name;
349 register int fd;
350 struct termcap_buffer buf;
351 register char *bp1;
352 char *tc_search_point;
353 char *term;
354 ptrdiff_t malloc_size = 0;
355 int c;
356 char *tcenv = NULL;
357 char *indirect = NULL;
358 bool filep;
359
360 #ifdef INTERNAL_TERMINAL
361
362
363 if (!strcmp (name, "internal"))
364 {
365 term = INTERNAL_TERMINAL;
366 if (!bp)
367 {
368 malloc_size = 1 + strlen (term);
369 bp = xmalloc (malloc_size);
370 }
371 strcpy (bp, term);
372 goto ret;
373 }
374 #endif
375
376
377
378 if (bp)
379 term_entry = bp;
380
381 termcap_name = getenv ("TERMCAP");
382 if (termcap_name && *termcap_name == '\0')
383 termcap_name = NULL;
384 #if defined (MSDOS) && !defined (TEST)
385 if (termcap_name && (*termcap_name == '\\'
386 || *termcap_name == '/'
387 || termcap_name[1] == ':'))
388 dostounix_filename (termcap_name);
389 #endif
390
391 filep = termcap_name && valid_filename_p (termcap_name);
392
393
394
395
396
397
398
399 if (termcap_name && !filep && !strcmp (name, getenv ("TERM")))
400 {
401 indirect = tgetst1 (find_capability (termcap_name, "tc"), 0);
402 if (!indirect)
403 {
404 if (!bp)
405 bp = termcap_name;
406 else
407 strcpy (bp, termcap_name);
408 goto ret;
409 }
410 else
411 {
412 tcenv = termcap_name;
413 termcap_name = NULL;
414 }
415 }
416
417 if (!termcap_name || !filep)
418 termcap_name = (char *) TERMCAP_FILE;
419
420
421
422 fd = emacs_open (termcap_name, O_RDONLY | O_TEXT, 0);
423 if (fd < 0)
424 return -1;
425
426 buf.size = BUFSIZE;
427
428 buf.beg = xmalloc (buf.size + 1);
429 term = indirect ? indirect : (char *)name;
430
431 if (!bp)
432 {
433 malloc_size = indirect ? strlen (tcenv) + 1 : buf.size;
434 bp = xmalloc (malloc_size);
435 }
436 tc_search_point = bp1 = bp;
437
438 if (indirect)
439
440 {
441 strcpy (bp, tcenv);
442 bp1 += strlen (tcenv);
443 }
444
445 while (term)
446 {
447
448 if (scan_file (term, fd, &buf) == 0)
449 {
450 emacs_close (fd);
451 xfree (buf.beg);
452 if (malloc_size)
453 xfree (bp);
454 return 0;
455 }
456
457
458 if (term != name)
459 xfree (term);
460
461
462 if (malloc_size)
463 {
464 ptrdiff_t offset1 = bp1 - bp, offset2 = tc_search_point - bp;
465 malloc_size = offset1 + buf.size;
466 bp = termcap_name = xrealloc (bp, malloc_size);
467 bp1 = termcap_name + offset1;
468 tc_search_point = termcap_name + offset2;
469 }
470
471
472 termcap_name = buf.ptr;
473 while ((*bp1++ = c = *termcap_name++) && c != '\n')
474
475 if (c == '\\' && *termcap_name == '\n')
476 {
477 bp1--;
478 termcap_name++;
479 }
480 *bp1 = '\0';
481
482
483
484 tc_search_point = find_capability (tc_search_point, "tc");
485 term = tgetst1 (tc_search_point, 0);
486 }
487
488 emacs_close (fd);
489 xfree (buf.beg);
490
491 if (malloc_size)
492 bp = xrealloc (bp, bp1 - bp + 1);
493
494 ret:
495 term_entry = bp;
496 return 1;
497 }
498
499
500
501
502
503
504
505 static bool
506 scan_file (char *str, int fd, struct termcap_buffer *bufp)
507 {
508 char *end;
509
510 bufp->ptr = bufp->beg;
511 bufp->full = 0;
512 bufp->ateof = 0;
513 *bufp->ptr = '\0';
514
515 lseek (fd, 0, 0);
516
517 while (!bufp->ateof)
518 {
519
520 end = NULL;
521 do
522 {
523
524
525 end = gobble_line (fd, bufp, end);
526 }
527 while (!bufp->ateof && end[-2] == '\\');
528
529 if (*bufp->ptr != '#'
530 && name_match (bufp->ptr, str))
531 return 1;
532
533
534 bufp->ptr = end;
535 }
536 return 0;
537 }
538
539
540
541
542 static bool
543 name_match (char *line, char *name)
544 {
545 char *tem;
546
547 if (!compare_contin (line, name))
548 return 1;
549
550 for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++)
551 if (*tem == '|' && !compare_contin (tem + 1, name))
552 return 1;
553
554 return 0;
555 }
556
557 static bool
558 compare_contin (char *str1, char *str2)
559 {
560 while (1)
561 {
562 int c1 = *str1++;
563 int c2 = *str2++;
564 while (c1 == '\\' && *str1 == '\n')
565 {
566 str1++;
567 while ((c1 = *str1++) == ' ' || c1 == '\t')
568 continue;
569 }
570 if (c2 == '\0')
571 {
572
573 if (c1 == '|' || c1 == ':')
574
575 return 0;
576 else
577 return 1;
578 }
579 else if (c1 != c2)
580 return 1;
581 }
582 }
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597 static char *
598 gobble_line (int fd, register struct termcap_buffer *bufp, char *append_end)
599 {
600 register char *end;
601 register int nread;
602 register char *buf = bufp->beg;
603
604 if (!append_end)
605 append_end = bufp->ptr;
606
607 while (1)
608 {
609 end = append_end;
610 while (*end && *end != '\n') end++;
611 if (*end)
612 break;
613 if (bufp->ateof)
614 return buf + bufp->full;
615 if (bufp->ptr == buf)
616 {
617 if (bufp->full == bufp->size)
618 {
619 ptrdiff_t ptr_offset = bufp->ptr - buf;
620 ptrdiff_t append_end_offset = append_end - buf;
621
622 ptrdiff_t size = bufp->size + 1;
623 bufp->beg = buf = xpalloc (buf, &size, 1, -1, 1);
624 bufp->size = size - 1;
625 bufp->ptr = buf + ptr_offset;
626 append_end = buf + append_end_offset;
627 }
628 }
629 else
630 {
631 append_end -= bufp->ptr - buf;
632 memcpy (buf, bufp->ptr, bufp->full -= bufp->ptr - buf);
633 bufp->ptr = buf;
634 }
635 if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full)))
636 bufp->ateof = 1;
637 bufp->full += nread;
638 buf[bufp->full] = '\0';
639 }
640 return end + 1;
641 }