Mercurial > emacs
annotate src/termcap.c @ 23323:0800a4f84757
(underlying_strftime):
Set the buffer to a nonzero value before calling
strftime, and check to see whether strftime has set the buffer to zero.
This lets us distinguish between an empty buffer and an error.
I'm installing this patch by hand now; it will be superseded whenever
the glibc sources are propagated back to fsf.org.
| author | Paul Eggert <eggert@twinsun.com> |
|---|---|
| date | Fri, 25 Sep 1998 21:40:23 +0000 |
| parents | 3790e185acc0 |
| children | d8776351a540 |
| rev | line source |
|---|---|
| 7306 | 1 /* Work-alike for termcap, plus extra features. |
|
12675
8c9369149a9d
Move #define of bcopy to after #include <string.h>.
David J. MacKenzie <djm@gnu.org>
parents:
11264
diff
changeset
|
2 Copyright (C) 1985, 86, 93, 94, 95 Free Software Foundation, Inc. |
| 7306 | 3 |
| 4 This program is free software; you can redistribute it and/or modify | |
| 5 it under the terms of the GNU General Public License as published by | |
| 6 the Free Software Foundation; either version 2, or (at your option) | |
| 7 any later version. | |
| 8 | |
| 9 This program is distributed in the hope that it will be useful, | |
| 10 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 GNU General Public License for more details. | |
| 13 | |
| 14 You should have received a copy of the GNU General Public License | |
| 15 along with this program; see the file COPYING. If not, write to | |
| 14414 | 16 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
| 17 Boston, MA 02111-1307, USA. */ | |
| 7306 | 18 |
| 19 /* Emacs config.h may rename various library functions such as malloc. */ | |
| 20 #ifdef HAVE_CONFIG_H | |
|
12994
bd38619285f7
Don't assume that HAVE_CONFIG_H implies emacs.
David J. MacKenzie <djm@gnu.org>
parents:
12907
diff
changeset
|
21 #include <config.h> |
|
bd38619285f7
Don't assume that HAVE_CONFIG_H implies emacs.
David J. MacKenzie <djm@gnu.org>
parents:
12907
diff
changeset
|
22 #endif |
| 7785 | 23 |
|
12994
bd38619285f7
Don't assume that HAVE_CONFIG_H implies emacs.
David J. MacKenzie <djm@gnu.org>
parents:
12907
diff
changeset
|
24 #ifdef emacs |
| 7785 | 25 |
| 26 /* Get the O_* definitions for open et al. */ | |
| 27 #include <sys/file.h> | |
| 28 #ifdef USG5 | |
| 29 #include <fcntl.h> | |
| 30 #endif | |
| 31 | |
|
12994
bd38619285f7
Don't assume that HAVE_CONFIG_H implies emacs.
David J. MacKenzie <djm@gnu.org>
parents:
12907
diff
changeset
|
32 #else /* not emacs */ |
| 7306 | 33 |
| 34 #ifdef STDC_HEADERS | |
| 35 #include <stdlib.h> | |
| 36 #include <string.h> | |
| 37 #else | |
| 38 char *getenv (); | |
| 39 char *malloc (); | |
| 40 char *realloc (); | |
| 41 #endif | |
| 42 | |
|
12675
8c9369149a9d
Move #define of bcopy to after #include <string.h>.
David J. MacKenzie <djm@gnu.org>
parents:
11264
diff
changeset
|
43 /* Do this after the include, in case string.h prototypes bcopy. */ |
|
8c9369149a9d
Move #define of bcopy to after #include <string.h>.
David J. MacKenzie <djm@gnu.org>
parents:
11264
diff
changeset
|
44 #if (defined(HAVE_STRING_H) || defined(STDC_HEADERS)) && !defined(bcopy) |
|
8c9369149a9d
Move #define of bcopy to after #include <string.h>.
David J. MacKenzie <djm@gnu.org>
parents:
11264
diff
changeset
|
45 #define bcopy(s, d, n) memcpy ((d), (s), (n)) |
|
8c9369149a9d
Move #define of bcopy to after #include <string.h>.
David J. MacKenzie <djm@gnu.org>
parents:
11264
diff
changeset
|
46 #endif |
|
8c9369149a9d
Move #define of bcopy to after #include <string.h>.
David J. MacKenzie <djm@gnu.org>
parents:
11264
diff
changeset
|
47 |
| 7306 | 48 #ifdef HAVE_UNISTD_H |
| 49 #include <unistd.h> | |
| 50 #endif | |
| 51 #ifdef _POSIX_VERSION | |
| 52 #include <fcntl.h> | |
| 53 #endif | |
| 54 | |
|
12994
bd38619285f7
Don't assume that HAVE_CONFIG_H implies emacs.
David J. MacKenzie <djm@gnu.org>
parents:
12907
diff
changeset
|
55 #endif /* not emacs */ |
| 7306 | 56 |
| 57 #ifndef NULL | |
| 58 #define NULL (char *) 0 | |
| 59 #endif | |
| 60 | |
| 7685 | 61 #ifndef O_RDONLY |
| 62 #define O_RDONLY 0 | |
| 63 #endif | |
| 64 | |
| 7306 | 65 /* BUFSIZE is the initial size allocated for the buffer |
| 66 for reading the termcap file. | |
| 67 It is not a limit. | |
| 68 Make it large normally for speed. | |
| 69 Make it variable when debugging, so can exercise | |
| 70 increasing the space dynamically. */ | |
| 71 | |
| 72 #ifndef BUFSIZE | |
| 73 #ifdef DEBUG | |
| 74 #define BUFSIZE bufsize | |
| 75 | |
| 76 int bufsize = 128; | |
| 77 #else | |
| 78 #define BUFSIZE 2048 | |
| 79 #endif | |
| 80 #endif | |
| 81 | |
|
12679
a14b26e55f25
TERMCAP_NAME -> TERMCAP_FILE.
David J. MacKenzie <djm@gnu.org>
parents:
12675
diff
changeset
|
82 #ifndef TERMCAP_FILE |
|
a14b26e55f25
TERMCAP_NAME -> TERMCAP_FILE.
David J. MacKenzie <djm@gnu.org>
parents:
12675
diff
changeset
|
83 #define TERMCAP_FILE "/etc/termcap" |
| 7306 | 84 #endif |
| 85 | |
| 86 #ifndef emacs | |
| 87 static void | |
| 88 memory_out () | |
| 89 { | |
| 90 write (2, "virtual memory exhausted\n", 25); | |
| 91 exit (1); | |
| 92 } | |
| 93 | |
| 94 static char * | |
| 95 xmalloc (size) | |
| 96 unsigned size; | |
| 97 { | |
| 98 register char *tem = malloc (size); | |
| 99 | |
| 100 if (!tem) | |
| 101 memory_out (); | |
| 102 return tem; | |
| 103 } | |
| 104 | |
| 105 static char * | |
| 106 xrealloc (ptr, size) | |
| 107 char *ptr; | |
| 108 unsigned size; | |
| 109 { | |
| 110 register char *tem = realloc (ptr, size); | |
| 111 | |
| 112 if (!tem) | |
| 113 memory_out (); | |
| 114 return tem; | |
| 115 } | |
| 116 #endif /* not emacs */ | |
| 117 | |
| 118 /* Looking up capabilities in the entry already found. */ | |
| 119 | |
| 120 /* The pointer to the data made by tgetent is left here | |
| 121 for tgetnum, tgetflag and tgetstr to find. */ | |
| 122 static char *term_entry; | |
| 123 | |
| 124 static char *tgetst1 (); | |
| 125 | |
| 126 /* Search entry BP for capability CAP. | |
| 127 Return a pointer to the capability (in BP) if found, | |
| 128 0 if not found. */ | |
| 129 | |
| 130 static char * | |
| 131 find_capability (bp, cap) | |
| 132 register char *bp, *cap; | |
| 133 { | |
| 134 for (; *bp; bp++) | |
| 135 if (bp[0] == ':' | |
| 136 && bp[1] == cap[0] | |
| 137 && bp[2] == cap[1]) | |
| 138 return &bp[4]; | |
| 139 return NULL; | |
| 140 } | |
| 141 | |
| 142 int | |
| 143 tgetnum (cap) | |
| 144 char *cap; | |
| 145 { | |
| 146 register char *ptr = find_capability (term_entry, cap); | |
| 147 if (!ptr || ptr[-1] != '#') | |
| 148 return -1; | |
| 149 return atoi (ptr); | |
| 150 } | |
| 151 | |
| 152 int | |
| 153 tgetflag (cap) | |
| 154 char *cap; | |
| 155 { | |
| 156 register char *ptr = find_capability (term_entry, cap); | |
| 157 return ptr && ptr[-1] == ':'; | |
| 158 } | |
| 159 | |
| 160 /* Look up a string-valued capability CAP. | |
| 161 If AREA is non-null, it points to a pointer to a block in which | |
| 162 to store the string. That pointer is advanced over the space used. | |
| 163 If AREA is null, space is allocated with `malloc'. */ | |
| 164 | |
| 165 char * | |
| 166 tgetstr (cap, area) | |
| 167 char *cap; | |
| 168 char **area; | |
| 169 { | |
| 170 register char *ptr = find_capability (term_entry, cap); | |
| 171 if (!ptr || (ptr[-1] != '=' && ptr[-1] != '~')) | |
| 172 return NULL; | |
| 173 return tgetst1 (ptr, area); | |
| 174 } | |
| 175 | |
|
23071
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
176 #ifdef IS_EBCDIC_HOST |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
177 /* Table, indexed by a character in range 0200 to 0300 with 0200 subtracted, |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
178 gives meaning of character following \, or a space if no special meaning. |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
179 Sixteen characters per line within the string. */ |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
180 |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
181 static char esctab[] |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
182 = " \057\026 \047\014 \ |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
183 \025 \015 \ |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
184 \005 \013 \ |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
185 "; |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
186 #else |
| 7306 | 187 /* Table, indexed by a character in range 0100 to 0140 with 0100 subtracted, |
| 188 gives meaning of character following \, or a space if no special meaning. | |
| 189 Eight characters per line within the string. */ | |
| 190 | |
| 191 static char esctab[] | |
| 192 = " \007\010 \033\014 \ | |
| 193 \012 \ | |
| 194 \015 \011 \013 \ | |
| 195 "; | |
|
23071
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
196 #endif |
| 7306 | 197 |
| 198 /* PTR points to a string value inside a termcap entry. | |
| 199 Copy that value, processing \ and ^ abbreviations, | |
| 200 into the block that *AREA points to, | |
| 201 or to newly allocated storage if AREA is NULL. | |
| 202 Return the address to which we copied the value, | |
| 203 or NULL if PTR is NULL. */ | |
| 204 | |
| 205 static char * | |
| 206 tgetst1 (ptr, area) | |
| 207 char *ptr; | |
| 208 char **area; | |
| 209 { | |
| 210 register char *p, *r; | |
| 211 register int c; | |
| 212 register int size; | |
| 213 char *ret; | |
| 214 register int c1; | |
| 215 | |
| 216 if (!ptr) | |
| 217 return NULL; | |
| 218 | |
| 219 /* `ret' gets address of where to store the string. */ | |
| 220 if (!area) | |
| 221 { | |
| 222 /* Compute size of block needed (may overestimate). */ | |
| 223 p = ptr; | |
| 224 while ((c = *p++) && c != ':' && c != '\n') | |
| 225 ; | |
| 226 ret = (char *) xmalloc (p - ptr + 1); | |
| 227 } | |
| 228 else | |
| 229 ret = *area; | |
| 230 | |
| 231 /* Copy the string value, stopping at null or colon. | |
| 232 Also process ^ and \ abbreviations. */ | |
| 233 p = ptr; | |
| 234 r = ret; | |
| 235 while ((c = *p++) && c != ':' && c != '\n') | |
| 236 { | |
| 237 if (c == '^') | |
|
10186
af0b61d21a8f
(tgetst1): Let ^? stand for DEL character.
Richard M. Stallman <rms@gnu.org>
parents:
7785
diff
changeset
|
238 { |
|
af0b61d21a8f
(tgetst1): Let ^? stand for DEL character.
Richard M. Stallman <rms@gnu.org>
parents:
7785
diff
changeset
|
239 c = *p++; |
|
af0b61d21a8f
(tgetst1): Let ^? stand for DEL character.
Richard M. Stallman <rms@gnu.org>
parents:
7785
diff
changeset
|
240 if (c == '?') |
|
af0b61d21a8f
(tgetst1): Let ^? stand for DEL character.
Richard M. Stallman <rms@gnu.org>
parents:
7785
diff
changeset
|
241 c = 0177; |
|
af0b61d21a8f
(tgetst1): Let ^? stand for DEL character.
Richard M. Stallman <rms@gnu.org>
parents:
7785
diff
changeset
|
242 else |
|
af0b61d21a8f
(tgetst1): Let ^? stand for DEL character.
Richard M. Stallman <rms@gnu.org>
parents:
7785
diff
changeset
|
243 c &= 037; |
|
af0b61d21a8f
(tgetst1): Let ^? stand for DEL character.
Richard M. Stallman <rms@gnu.org>
parents:
7785
diff
changeset
|
244 } |
| 7306 | 245 else if (c == '\\') |
| 246 { | |
| 247 c = *p++; | |
| 248 if (c >= '0' && c <= '7') | |
| 249 { | |
| 250 c -= '0'; | |
| 251 size = 0; | |
| 252 | |
| 253 while (++size < 3 && (c1 = *p) >= '0' && c1 <= '7') | |
| 254 { | |
| 255 c *= 8; | |
| 256 c += c1 - '0'; | |
| 257 p++; | |
| 258 } | |
| 259 } | |
|
23071
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
260 #ifdef IS_EBCDIC_HOST |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
261 else if (c >= 0200 && c < 0360) |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
262 { |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
263 c1 = esctab[(c & ~0100) - 0200]; |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
264 if (c1 != ' ') |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
265 c = c1; |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
266 } |
|
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
267 #else |
| 7306 | 268 else if (c >= 0100 && c < 0200) |
| 269 { | |
| 270 c1 = esctab[(c & ~040) - 0100]; | |
| 271 if (c1 != ' ') | |
| 272 c = c1; | |
| 273 } | |
|
23071
3790e185acc0
(tgetst1): Supprt EBCDIC systems.
Richard M. Stallman <rms@gnu.org>
parents:
22066
diff
changeset
|
274 #endif |
| 7306 | 275 } |
| 276 *r++ = c; | |
| 277 } | |
| 278 *r = '\0'; | |
| 279 /* Update *AREA. */ | |
| 280 if (area) | |
| 281 *area = r + 1; | |
| 282 return ret; | |
| 283 } | |
| 284 | |
| 285 /* Outputting a string with padding. */ | |
| 286 | |
| 287 short ospeed; | |
| 288 /* If OSPEED is 0, we use this as the actual baud rate. */ | |
| 289 int tputs_baud_rate; | |
| 290 char PC; | |
| 291 | |
| 292 /* Actual baud rate if positive; | |
| 293 - baud rate / 100 if negative. */ | |
| 294 | |
|
10739
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
295 static int speeds[] = |
| 7306 | 296 { |
| 297 #ifdef VMS | |
| 298 0, 50, 75, 110, 134, 150, -3, -6, -12, -18, | |
| 299 -20, -24, -36, -48, -72, -96, -192 | |
| 300 #else /* not VMS */ | |
| 301 0, 50, 75, 110, 135, 150, -2, -3, -6, -12, | |
|
10739
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
302 -18, -24, -48, -96, -192, -288, -384, -576, -1152 |
| 7306 | 303 #endif /* not VMS */ |
| 304 }; | |
| 305 | |
| 306 void | |
| 307 tputs (str, nlines, outfun) | |
| 308 register char *str; | |
| 309 int nlines; | |
| 310 register int (*outfun) (); | |
| 311 { | |
| 312 register int padcount = 0; | |
| 313 register int speed; | |
| 314 | |
| 315 #ifdef emacs | |
| 316 extern baud_rate; | |
| 317 speed = baud_rate; | |
|
10739
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
318 /* For quite high speeds, convert to the smaller |
|
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
319 units to avoid overflow. */ |
|
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
320 if (speed > 10000) |
|
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
321 speed = - speed / 100; |
| 7306 | 322 #else |
| 323 if (ospeed == 0) | |
| 324 speed = tputs_baud_rate; | |
|
13677
ad4eada50462
(tputs): Don't let ospeed overrun the speeds array.
David J. MacKenzie <djm@gnu.org>
parents:
12994
diff
changeset
|
325 else if (ospeed > 0 && ospeed < (sizeof speeds / sizeof speeds[0])) |
|
ad4eada50462
(tputs): Don't let ospeed overrun the speeds array.
David J. MacKenzie <djm@gnu.org>
parents:
12994
diff
changeset
|
326 speed = speeds[ospeed]; |
| 7306 | 327 else |
|
13677
ad4eada50462
(tputs): Don't let ospeed overrun the speeds array.
David J. MacKenzie <djm@gnu.org>
parents:
12994
diff
changeset
|
328 speed = 0; |
| 7306 | 329 #endif |
| 330 | |
| 331 if (!str) | |
| 332 return; | |
| 333 | |
| 334 while (*str >= '0' && *str <= '9') | |
| 335 { | |
| 336 padcount += *str++ - '0'; | |
| 337 padcount *= 10; | |
| 338 } | |
| 339 if (*str == '.') | |
| 340 { | |
| 341 str++; | |
| 342 padcount += *str++ - '0'; | |
| 343 } | |
| 344 if (*str == '*') | |
| 345 { | |
| 346 str++; | |
| 347 padcount *= nlines; | |
| 348 } | |
| 349 while (*str) | |
| 350 (*outfun) (*str++); | |
| 351 | |
|
10739
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
352 /* PADCOUNT is now in units of tenths of msec. |
| 10753 | 353 SPEED is measured in characters per 10 seconds |
|
10739
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
354 or in characters per .1 seconds (if negative). |
|
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
355 We use the smaller units for larger speeds to avoid overflow. */ |
|
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
356 padcount *= speed; |
| 7306 | 357 padcount += 500; |
| 358 padcount /= 1000; | |
|
10739
97096cdf6e55
(speeds): Make it ints. Add some higher speeds.
Richard M. Stallman <rms@gnu.org>
parents:
10186
diff
changeset
|
359 if (speed < 0) |
| 7306 | 360 padcount = -padcount; |
| 361 else | |
| 362 { | |
| 363 padcount += 50; | |
| 364 padcount /= 100; | |
| 365 } | |
| 366 | |
| 367 while (padcount-- > 0) | |
| 368 (*outfun) (PC); | |
| 369 } | |
| 370 | |
| 371 /* Finding the termcap entry in the termcap data base. */ | |
| 372 | |
|
22066
a09f2b697d0a
Renamed "struct buffer" to "struct termcap_buffer" to
Richard M. Stallman <rms@gnu.org>
parents:
14414
diff
changeset
|
373 struct termcap_buffer |
| 7306 | 374 { |
| 375 char *beg; | |
| 376 int size; | |
| 377 char *ptr; | |
| 378 int ateof; | |
| 379 int full; | |
| 380 }; | |
| 381 | |
| 382 /* Forward declarations of static functions. */ | |
| 383 | |
| 384 static int scan_file (); | |
| 385 static char *gobble_line (); | |
| 386 static int compare_contin (); | |
| 387 static int name_match (); | |
| 388 | |
| 389 #ifdef VMS | |
| 390 | |
| 391 #include <rmsdef.h> | |
| 392 #include <fab.h> | |
| 393 #include <nam.h> | |
| 394 | |
| 395 static int | |
| 396 valid_filename_p (fn) | |
| 397 char *fn; | |
| 398 { | |
| 399 struct FAB fab = cc$rms_fab; | |
| 400 struct NAM nam = cc$rms_nam; | |
| 401 char esa[NAM$C_MAXRSS]; | |
| 402 | |
| 403 fab.fab$l_fna = fn; | |
| 404 fab.fab$b_fns = strlen(fn); | |
| 405 fab.fab$l_nam = &nam; | |
| 406 fab.fab$l_fop = FAB$M_NAM; | |
| 407 | |
| 408 nam.nam$l_esa = esa; | |
| 409 nam.nam$b_ess = sizeof esa; | |
| 410 | |
| 411 return SYS$PARSE(&fab, 0, 0) == RMS$_NORMAL; | |
| 412 } | |
| 413 | |
| 414 #else /* !VMS */ | |
| 415 | |
| 416 #ifdef MSDOS /* MW, May 1993 */ | |
| 417 static int | |
| 418 valid_filename_p (fn) | |
| 419 char *fn; | |
| 420 { | |
| 421 return *fn == '/' || fn[1] == ':'; | |
| 422 } | |
| 423 #else | |
| 424 #define valid_filename_p(fn) (*(fn) == '/') | |
| 425 #endif | |
| 426 | |
| 427 #endif /* !VMS */ | |
| 428 | |
| 429 /* Find the termcap entry data for terminal type NAME | |
| 430 and store it in the block that BP points to. | |
| 431 Record its address for future use. | |
| 432 | |
| 433 If BP is null, space is dynamically allocated. | |
| 434 | |
| 435 Return -1 if there is some difficulty accessing the data base | |
| 436 of terminal types, | |
| 437 0 if the data base is accessible but the type NAME is not defined | |
| 438 in it, and some other value otherwise. */ | |
| 439 | |
| 440 int | |
| 441 tgetent (bp, name) | |
| 442 char *bp, *name; | |
| 443 { | |
| 444 register char *termcap_name; | |
| 445 register int fd; | |
|
22066
a09f2b697d0a
Renamed "struct buffer" to "struct termcap_buffer" to
Richard M. Stallman <rms@gnu.org>
parents:
14414
diff
changeset
|
446 struct termcap_buffer buf; |
| 7306 | 447 register char *bp1; |
|
14132
85063feb159b
(tgetent): Find all the tc caps that there are.
Karl Heuer <kwzh@gnu.org>
parents:
13677
diff
changeset
|
448 char *tc_search_point; |
| 7306 | 449 char *term; |
| 450 int malloc_size = 0; | |
| 451 register int c; | |
| 452 char *tcenv; /* TERMCAP value, if it contains :tc=. */ | |
| 453 char *indirect = NULL; /* Terminal type in :tc= in TERMCAP value. */ | |
| 454 int filep; | |
| 455 | |
| 456 #ifdef INTERNAL_TERMINAL | |
| 457 /* For the internal terminal we don't want to read any termcap file, | |
| 458 so fake it. */ | |
| 459 if (!strcmp (name, "internal")) | |
| 460 { | |
| 461 term = INTERNAL_TERMINAL; | |
| 462 if (!bp) | |
| 463 { | |
| 464 malloc_size = 1 + strlen (term); | |
| 465 bp = (char *) xmalloc (malloc_size); | |
| 466 } | |
| 467 strcpy (bp, term); | |
| 468 goto ret; | |
| 469 } | |
| 470 #endif /* INTERNAL_TERMINAL */ | |
| 471 | |
|
12907
6cae53a06172
default to user-supplied buffer.
David J. MacKenzie <djm@gnu.org>
parents:
12679
diff
changeset
|
472 /* For compatibility with programs like `less' that want to |
|
6cae53a06172
default to user-supplied buffer.
David J. MacKenzie <djm@gnu.org>
parents:
12679
diff
changeset
|
473 put data in the termcap buffer themselves as a fallback. */ |
|
6cae53a06172
default to user-supplied buffer.
David J. MacKenzie <djm@gnu.org>
parents:
12679
diff
changeset
|
474 if (bp) |
|
6cae53a06172
default to user-supplied buffer.
David J. MacKenzie <djm@gnu.org>
parents:
12679
diff
changeset
|
475 term_entry = bp; |
|
6cae53a06172
default to user-supplied buffer.
David J. MacKenzie <djm@gnu.org>
parents:
12679
diff
changeset
|
476 |
| 7306 | 477 termcap_name = getenv ("TERMCAP"); |
| 478 if (termcap_name && *termcap_name == '\0') | |
| 479 termcap_name = NULL; | |
| 480 #if defined (MSDOS) && !defined (TEST) | |
| 481 if (termcap_name && (*termcap_name == '\\' | |
| 482 || *termcap_name == '/' | |
| 483 || termcap_name[1] == ':')) | |
| 484 dostounix_filename(termcap_name); | |
| 485 #endif | |
| 486 | |
| 487 filep = termcap_name && valid_filename_p (termcap_name); | |
| 488 | |
| 489 /* If termcap_name is non-null and starts with / (in the un*x case, that is), | |
| 490 it is a file name to use instead of /etc/termcap. | |
| 491 If it is non-null and does not start with /, | |
| 492 it is the entry itself, but only if | |
| 493 the name the caller requested matches the TERM variable. */ | |
| 494 | |
| 495 if (termcap_name && !filep && !strcmp (name, getenv ("TERM"))) | |
| 496 { | |
| 497 indirect = tgetst1 (find_capability (termcap_name, "tc"), (char **) 0); | |
| 498 if (!indirect) | |
| 499 { | |
| 500 if (!bp) | |
| 501 bp = termcap_name; | |
| 502 else | |
| 503 strcpy (bp, termcap_name); | |
| 504 goto ret; | |
| 505 } | |
| 506 else | |
| 507 { /* It has tc=. Need to read /etc/termcap. */ | |
| 508 tcenv = termcap_name; | |
| 509 termcap_name = NULL; | |
| 510 } | |
| 511 } | |
| 512 | |
| 513 if (!termcap_name || !filep) | |
|
12679
a14b26e55f25
TERMCAP_NAME -> TERMCAP_FILE.
David J. MacKenzie <djm@gnu.org>
parents:
12675
diff
changeset
|
514 termcap_name = TERMCAP_FILE; |
| 7306 | 515 |
| 516 /* Here we know we must search a file and termcap_name has its name. */ | |
| 517 | |
| 518 #ifdef MSDOS | |
| 7685 | 519 fd = open (termcap_name, O_RDONLY|O_TEXT, 0); |
| 7306 | 520 #else |
| 7685 | 521 fd = open (termcap_name, O_RDONLY, 0); |
| 7306 | 522 #endif |
| 523 if (fd < 0) | |
| 524 return -1; | |
| 525 | |
| 526 buf.size = BUFSIZE; | |
| 527 /* Add 1 to size to ensure room for terminating null. */ | |
| 528 buf.beg = (char *) xmalloc (buf.size + 1); | |
| 529 term = indirect ? indirect : name; | |
| 530 | |
| 531 if (!bp) | |
| 532 { | |
| 533 malloc_size = indirect ? strlen (tcenv) + 1 : buf.size; | |
| 534 bp = (char *) xmalloc (malloc_size); | |
| 535 } | |
|
14132
85063feb159b
(tgetent): Find all the tc caps that there are.
Karl Heuer <kwzh@gnu.org>
parents:
13677
diff
changeset
|
536 tc_search_point = bp1 = bp; |
| 7306 | 537 |
| 538 if (indirect) | |
| 539 /* Copy the data from the environment variable. */ | |
| 540 { | |
| 541 strcpy (bp, tcenv); | |
| 542 bp1 += strlen (tcenv); | |
| 543 } | |
| 544 | |
| 545 while (term) | |
| 546 { | |
| 547 /* Scan the file, reading it via buf, till find start of main entry. */ | |
| 548 if (scan_file (term, fd, &buf) == 0) | |
| 549 { | |
| 550 close (fd); | |
| 551 free (buf.beg); | |
| 552 if (malloc_size) | |
| 553 free (bp); | |
| 554 return 0; | |
| 555 } | |
| 556 | |
| 557 /* Free old `term' if appropriate. */ | |
| 558 if (term != name) | |
| 559 free (term); | |
| 560 | |
| 561 /* If BP is malloc'd by us, make sure it is big enough. */ | |
| 562 if (malloc_size) | |
| 563 { | |
| 564 malloc_size = bp1 - bp + buf.size; | |
| 565 termcap_name = (char *) xrealloc (bp, malloc_size); | |
| 566 bp1 += termcap_name - bp; | |
|
14132
85063feb159b
(tgetent): Find all the tc caps that there are.
Karl Heuer <kwzh@gnu.org>
parents:
13677
diff
changeset
|
567 tc_search_point += termcap_name - bp; |
| 7306 | 568 bp = termcap_name; |
| 569 } | |
| 570 | |
| 571 /* Copy the line of the entry from buf into bp. */ | |
| 572 termcap_name = buf.ptr; | |
| 573 while ((*bp1++ = c = *termcap_name++) && c != '\n') | |
| 574 /* Drop out any \ newline sequence. */ | |
| 575 if (c == '\\' && *termcap_name == '\n') | |
| 576 { | |
| 577 bp1--; | |
| 578 termcap_name++; | |
| 579 } | |
| 580 *bp1 = '\0'; | |
| 581 | |
| 582 /* Does this entry refer to another terminal type's entry? | |
| 583 If something is found, copy it into heap and null-terminate it. */ | |
|
14132
85063feb159b
(tgetent): Find all the tc caps that there are.
Karl Heuer <kwzh@gnu.org>
parents:
13677
diff
changeset
|
584 tc_search_point = find_capability (tc_search_point, "tc"); |
|
85063feb159b
(tgetent): Find all the tc caps that there are.
Karl Heuer <kwzh@gnu.org>
parents:
13677
diff
changeset
|
585 term = tgetst1 (tc_search_point, (char **) 0); |
| 7306 | 586 } |
| 587 | |
| 588 close (fd); | |
| 589 free (buf.beg); | |
| 590 | |
| 591 if (malloc_size) | |
| 592 bp = (char *) xrealloc (bp, bp1 - bp + 1); | |
| 593 | |
| 594 ret: | |
| 595 term_entry = bp; | |
| 596 return 1; | |
| 597 } | |
| 598 | |
| 599 /* Given file open on FD and buffer BUFP, | |
| 600 scan the file from the beginning until a line is found | |
| 601 that starts the entry for terminal type STR. | |
| 602 Return 1 if successful, with that line in BUFP, | |
| 603 or 0 if no entry is found in the file. */ | |
| 604 | |
| 605 static int | |
| 606 scan_file (str, fd, bufp) | |
| 607 char *str; | |
| 608 int fd; | |
|
22066
a09f2b697d0a
Renamed "struct buffer" to "struct termcap_buffer" to
Richard M. Stallman <rms@gnu.org>
parents:
14414
diff
changeset
|
609 register struct termcap_buffer *bufp; |
| 7306 | 610 { |
| 611 register char *end; | |
| 612 | |
| 613 bufp->ptr = bufp->beg; | |
| 614 bufp->full = 0; | |
| 615 bufp->ateof = 0; | |
| 616 *bufp->ptr = '\0'; | |
| 617 | |
| 618 lseek (fd, 0L, 0); | |
| 619 | |
| 620 while (!bufp->ateof) | |
| 621 { | |
| 622 /* Read a line into the buffer. */ | |
| 623 end = NULL; | |
| 624 do | |
| 625 { | |
| 626 /* if it is continued, append another line to it, | |
| 627 until a non-continued line ends. */ | |
| 628 end = gobble_line (fd, bufp, end); | |
| 629 } | |
| 630 while (!bufp->ateof && end[-2] == '\\'); | |
| 631 | |
| 632 if (*bufp->ptr != '#' | |
| 633 && name_match (bufp->ptr, str)) | |
| 634 return 1; | |
| 635 | |
| 636 /* Discard the line just processed. */ | |
| 637 bufp->ptr = end; | |
| 638 } | |
| 639 return 0; | |
| 640 } | |
| 641 | |
| 642 /* Return nonzero if NAME is one of the names specified | |
| 643 by termcap entry LINE. */ | |
| 644 | |
| 645 static int | |
| 646 name_match (line, name) | |
| 647 char *line, *name; | |
| 648 { | |
| 649 register char *tem; | |
| 650 | |
| 651 if (!compare_contin (line, name)) | |
| 652 return 1; | |
| 653 /* This line starts an entry. Is it the right one? */ | |
| 654 for (tem = line; *tem && *tem != '\n' && *tem != ':'; tem++) | |
| 655 if (*tem == '|' && !compare_contin (tem + 1, name)) | |
| 656 return 1; | |
| 657 | |
| 658 return 0; | |
| 659 } | |
| 660 | |
| 661 static int | |
| 662 compare_contin (str1, str2) | |
| 663 register char *str1, *str2; | |
| 664 { | |
| 665 register int c1, c2; | |
| 666 while (1) | |
| 667 { | |
| 668 c1 = *str1++; | |
| 669 c2 = *str2++; | |
| 670 while (c1 == '\\' && *str1 == '\n') | |
| 671 { | |
| 672 str1++; | |
| 673 while ((c1 = *str1++) == ' ' || c1 == '\t'); | |
| 674 } | |
| 675 if (c2 == '\0') | |
| 676 { | |
| 677 /* End of type being looked up. */ | |
| 678 if (c1 == '|' || c1 == ':') | |
| 679 /* If end of name in data base, we win. */ | |
| 680 return 0; | |
| 681 else | |
| 682 return 1; | |
| 683 } | |
| 684 else if (c1 != c2) | |
| 685 return 1; | |
| 686 } | |
| 687 } | |
| 688 | |
| 689 /* Make sure that the buffer <- BUFP contains a full line | |
| 690 of the file open on FD, starting at the place BUFP->ptr | |
| 691 points to. Can read more of the file, discard stuff before | |
| 692 BUFP->ptr, or make the buffer bigger. | |
| 693 | |
| 694 Return the pointer to after the newline ending the line, | |
| 695 or to the end of the file, if there is no newline to end it. | |
| 696 | |
| 697 Can also merge on continuation lines. If APPEND_END is | |
| 698 non-null, it points past the newline of a line that is | |
| 699 continued; we add another line onto it and regard the whole | |
| 700 thing as one line. The caller decides when a line is continued. */ | |
| 701 | |
| 702 static char * | |
| 703 gobble_line (fd, bufp, append_end) | |
| 704 int fd; | |
|
22066
a09f2b697d0a
Renamed "struct buffer" to "struct termcap_buffer" to
Richard M. Stallman <rms@gnu.org>
parents:
14414
diff
changeset
|
705 register struct termcap_buffer *bufp; |
| 7306 | 706 char *append_end; |
| 707 { | |
| 708 register char *end; | |
| 709 register int nread; | |
| 710 register char *buf = bufp->beg; | |
| 711 register char *tem; | |
| 712 | |
| 713 if (!append_end) | |
| 714 append_end = bufp->ptr; | |
| 715 | |
| 716 while (1) | |
| 717 { | |
| 718 end = append_end; | |
| 719 while (*end && *end != '\n') end++; | |
| 720 if (*end) | |
| 721 break; | |
| 722 if (bufp->ateof) | |
| 723 return buf + bufp->full; | |
| 724 if (bufp->ptr == buf) | |
| 725 { | |
| 726 if (bufp->full == bufp->size) | |
| 727 { | |
| 728 bufp->size *= 2; | |
| 729 /* Add 1 to size to ensure room for terminating null. */ | |
| 730 tem = (char *) xrealloc (buf, bufp->size + 1); | |
| 731 bufp->ptr = (bufp->ptr - buf) + tem; | |
| 732 append_end = (append_end - buf) + tem; | |
| 733 bufp->beg = buf = tem; | |
| 734 } | |
| 735 } | |
| 736 else | |
| 737 { | |
| 738 append_end -= bufp->ptr - buf; | |
| 739 bcopy (bufp->ptr, buf, bufp->full -= bufp->ptr - buf); | |
| 740 bufp->ptr = buf; | |
| 741 } | |
| 742 if (!(nread = read (fd, buf + bufp->full, bufp->size - bufp->full))) | |
| 743 bufp->ateof = 1; | |
| 744 bufp->full += nread; | |
| 745 buf[bufp->full] = '\0'; | |
| 746 } | |
| 747 return end + 1; | |
| 748 } | |
| 749 | |
| 750 #ifdef TEST | |
| 751 | |
| 752 #ifdef NULL | |
| 753 #undef NULL | |
| 754 #endif | |
| 755 | |
| 756 #include <stdio.h> | |
| 757 | |
| 758 main (argc, argv) | |
| 759 int argc; | |
| 760 char **argv; | |
| 761 { | |
| 762 char *term; | |
| 763 char *buf; | |
| 764 | |
| 765 term = argv[1]; | |
| 766 printf ("TERM: %s\n", term); | |
| 767 | |
| 768 buf = (char *) tgetent (0, term); | |
| 769 if ((int) buf <= 0) | |
| 770 { | |
| 771 printf ("No entry.\n"); | |
| 772 return 0; | |
| 773 } | |
| 774 | |
| 775 printf ("Entry: %s\n", buf); | |
| 776 | |
| 777 tprint ("cm"); | |
| 778 tprint ("AL"); | |
| 779 | |
| 780 printf ("co: %d\n", tgetnum ("co")); | |
| 781 printf ("am: %d\n", tgetflag ("am")); | |
| 782 } | |
| 783 | |
| 784 tprint (cap) | |
| 785 char *cap; | |
| 786 { | |
| 787 char *x = tgetstr (cap, 0); | |
| 788 register char *y; | |
| 789 | |
| 790 printf ("%s: ", cap); | |
| 791 if (x) | |
| 792 { | |
| 793 for (y = x; *y; y++) | |
| 794 if (*y <= ' ' || *y == 0177) | |
| 795 printf ("\\%0o", *y); | |
| 796 else | |
| 797 putchar (*y); | |
| 798 free (x); | |
| 799 } | |
| 800 else | |
| 801 printf ("none"); | |
| 802 putchar ('\n'); | |
| 803 } | |
| 804 | |
| 805 #endif /* TEST */ |
