386BSD 0.1 development
[unix-history] / usr / src / usr.bin / gdb / utils.c
CommitLineData
cc61838f
WJ
1/*-
2 * This code is derived from software copyrighted by the Free Software
3 * Foundation.
4 *
5 * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6 * Modified 1990 by Van Jacobson at Lawrence Berkeley Laboratory.
7 *
8 * $Header: utils.c,v 1.6 91/03/07 17:44:30 mccanne Exp $;
9 */
10
11#ifndef lint
12static char sccsid[] = "@(#)utils.c 6.4 (Berkeley) 5/8/91";
13#endif /* not lint */
14
15/* General utility routines for GDB, the GNU debugger.
16 Copyright (C) 1986, 1989 Free Software Foundation, Inc.
17
18This file is part of GDB.
19
20GDB is free software; you can redistribute it and/or modify
21it under the terms of the GNU General Public License as published by
22the Free Software Foundation; either version 1, or (at your option)
23any later version.
24
25GDB is distributed in the hope that it will be useful,
26but WITHOUT ANY WARRANTY; without even the implied warranty of
27MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28GNU General Public License for more details.
29
30You should have received a copy of the GNU General Public License
31along with GDB; see the file COPYING. If not, write to
32the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
33
34#include "param.h"
35
36#include <stdio.h>
37#include <ctype.h>
38#include <signal.h>
39#include <sys/ioctl.h>
40#include <sys/param.h>
41#include <pwd.h>
42#include "defs.h"
43#ifdef HAVE_TERMIO
44#include <termio.h>
45#endif
46
47/* If this definition isn't overridden by the header files, assume
48 that isatty and fileno exist on this system. */
49#ifndef ISATTY
50#define ISATTY(FP) (isatty (fileno (FP)))
51#endif
52
53extern FILE *instream;
54
55void error ();
56void fatal ();
57
58/* Chain of cleanup actions established with make_cleanup,
59 to be executed if an error happens. */
60
61static struct cleanup *cleanup_chain;
62
63/* Nonzero means a quit has been requested. */
64
65int quit_flag;
66
67/* Nonzero means quit immediately if Control-C is typed now,
68 rather than waiting until QUIT is executed. */
69
70int immediate_quit;
71\f
72/* Add a new cleanup to the cleanup_chain,
73 and return the previous chain pointer
74 to be passed later to do_cleanups or discard_cleanups.
75 Args are FUNCTION to clean up with, and ARG to pass to it. */
76
77struct cleanup *
78make_cleanup (function, arg)
79 void (*function) ();
80 int arg;
81{
82 register struct cleanup *new
83 = (struct cleanup *) xmalloc (sizeof (struct cleanup));
84 register struct cleanup *old_chain = cleanup_chain;
85
86 new->next = cleanup_chain;
87 new->function = function;
88 new->arg = arg;
89 cleanup_chain = new;
90
91 return old_chain;
92}
93
94/* Discard cleanups and do the actions they describe
95 until we get back to the point OLD_CHAIN in the cleanup_chain. */
96
97void
98do_cleanups (old_chain)
99 register struct cleanup *old_chain;
100{
101 register struct cleanup *ptr;
102 while ((ptr = cleanup_chain) != old_chain)
103 {
104 (*ptr->function) (ptr->arg);
105 cleanup_chain = ptr->next;
106 free (ptr);
107 }
108}
109
110/* Discard cleanups, not doing the actions they describe,
111 until we get back to the point OLD_CHAIN in the cleanup_chain. */
112
113void
114discard_cleanups (old_chain)
115 register struct cleanup *old_chain;
116{
117 register struct cleanup *ptr;
118 while ((ptr = cleanup_chain) != old_chain)
119 {
120 cleanup_chain = ptr->next;
121 free (ptr);
122 }
123}
124
125/* Set the cleanup_chain to 0, and return the old cleanup chain. */
126struct cleanup *
127save_cleanups ()
128{
129 struct cleanup *old_chain = cleanup_chain;
130
131 cleanup_chain = 0;
132 return old_chain;
133}
134
135/* Restore the cleanup chain from a previously saved chain. */
136void
137restore_cleanups (chain)
138 struct cleanup *chain;
139{
140 cleanup_chain = chain;
141}
142
143/* This function is useful for cleanups.
144 Do
145
146 foo = xmalloc (...);
147 old_chain = make_cleanup (free_current_contents, &foo);
148
149 to arrange to free the object thus allocated. */
150
151void
152free_current_contents (location)
153 char **location;
154{
155 free (*location);
156}
157\f
158/* Generally useful subroutines used throughout the program. */
159
160/* Like malloc but get error if no storage available. */
161
162char *
163xmalloc (size)
164 long size;
165{
166 register char *val = (char *) malloc (size);
167 if (!val)
168 fatal ("virtual memory exhausted.", 0);
169 return val;
170}
171
172/* Like realloc but get error if no storage available. */
173
174char *
175xrealloc (ptr, size)
176 char *ptr;
177 long size;
178{
179 register char *val = (char *) realloc (ptr, size);
180 if (!val)
181 fatal ("virtual memory exhausted.", 0);
182 return val;
183}
184
185/* Print the system error message for errno, and also mention STRING
186 as the file name for which the error was encountered.
187 Then return to command level. */
188
189void
190perror_with_name (string)
191 char *string;
192{
193 extern int sys_nerr;
194 extern char *sys_errlist[];
195 extern int errno;
196 char *err;
197 char *combined;
198
199 if (errno < sys_nerr)
200 err = sys_errlist[errno];
201 else
202 err = "unknown error";
203
204 combined = (char *) alloca (strlen (err) + strlen (string) + 3);
205 strcpy (combined, string);
206 strcat (combined, ": ");
207 strcat (combined, err);
208
209 error ("%s.", combined);
210}
211
212/* Print the system error message for ERRCODE, and also mention STRING
213 as the file name for which the error was encountered. */
214
215void
216print_sys_errmsg (string, errcode)
217 char *string;
218 int errcode;
219{
220 extern int sys_nerr;
221 extern char *sys_errlist[];
222 char *err;
223 char *combined;
224
225 if (errcode < sys_nerr)
226 err = sys_errlist[errcode];
227 else
228 err = "unknown error";
229
230 combined = (char *) alloca (strlen (err) + strlen (string) + 3);
231 strcpy (combined, string);
232 strcat (combined, ": ");
233 strcat (combined, err);
234
235 printf ("%s.\n", combined);
236}
237
238void
239quit ()
240{
241#ifdef HAVE_TERMIO
242 ioctl (fileno (stdout), TCFLSH, 1);
243#else /* not HAVE_TERMIO */
244 ioctl (fileno (stdout), TIOCFLUSH, 0);
245#endif /* not HAVE_TERMIO */
246#ifdef TIOCGPGRP
247 error ("Quit");
248#else
249 error ("Quit (expect signal %d when inferior is resumed)", SIGINT);
250#endif /* TIOCGPGRP */
251}
252
253/* Control C comes here */
254
255void
256request_quit ()
257{
258 extern int remote_debugging;
259
260 quit_flag = 1;
261
262#ifdef USG
263 /* Restore the signal handler. */
264 signal (SIGINT, request_quit);
265#endif
266
267 if (immediate_quit)
268 quit();
269}
270
271/* Print an error message and return to command level.
272 STRING is the error message, used as a fprintf string,
273 and ARG is passed as an argument to it. */
274
275void
276error (string, arg1, arg2, arg3)
277 char *string;
278 int arg1, arg2, arg3;
279{
280 terminal_ours (); /* Should be ok even if no inf. */
281 fflush (stdout);
282 fprintf (stderr, string, arg1, arg2, arg3);
283 fprintf (stderr, "\n");
284 return_to_top_level ();
285}
286
287/* Print an error message and exit reporting failure.
288 This is for a error that we cannot continue from.
289 STRING and ARG are passed to fprintf. */
290
291void
292fatal (string, arg)
293 char *string;
294 int arg;
295{
296 fprintf (stderr, "gdb: ");
297 fprintf (stderr, string, arg);
298 fprintf (stderr, "\n");
299 exit (1);
300}
301
302/* Print an error message and exit, dumping core.
303 STRING is a printf-style control string, and ARG is a corresponding
304 argument. */
305void
306fatal_dump_core (string, arg)
307 char *string;
308 int arg;
309{
310 /* "internal error" is always correct, since GDB should never dump
311 core, no matter what the input. */
312 fprintf (stderr, "gdb internal error: ");
313 fprintf (stderr, string, arg);
314 fprintf (stderr, "\n");
315 signal (SIGQUIT, SIG_DFL);
316 kill (getpid (), SIGQUIT);
317 /* We should never get here, but just in case... */
318 exit (1);
319}
320
321/* Make a copy of the string at PTR with SIZE characters
322 (and add a null character at the end in the copy).
323 Uses malloc to get the space. Returns the address of the copy. */
324
325char *
326savestring (ptr, size)
327 char *ptr;
328 int size;
329{
330 register char *p = (char *) xmalloc (size + 1);
331 bcopy (ptr, p, size);
332 p[size] = 0;
333 return p;
334}
335
336char *
337concat (s1, s2, s3)
338 char *s1, *s2, *s3;
339{
340 register int len = strlen (s1) + strlen (s2) + strlen (s3) + 1;
341 register char *val = (char *) xmalloc (len);
342 strcpy (val, s1);
343 strcat (val, s2);
344 strcat (val, s3);
345 return val;
346}
347
348void
349print_spaces (n, file)
350 register int n;
351 register FILE *file;
352{
353 while (n-- > 0)
354 fputc (' ', file);
355}
356
357/* Ask user a y-or-n question and return 1 iff answer is yes.
358 Takes three args which are given to printf to print the question.
359 The first, a control string, should end in "? ".
360 It should not say how to answer, because we do that. */
361
362int
363query (ctlstr, arg1, arg2)
364 char *ctlstr;
365{
366 register int answer;
367
368 /* Automatically answer "yes" if input is not from a terminal. */
369 if (!input_from_terminal_p ())
370 return 1;
371
372 while (1)
373 {
374 printf (ctlstr, arg1, arg2);
375 printf ("(y or n) ");
376 fflush (stdout);
377 answer = fgetc (stdin);
378 clearerr (stdin); /* in case of C-d */
379 if (answer != '\n')
380 while (fgetc (stdin) != '\n') clearerr (stdin);
381 if (answer >= 'a')
382 answer -= 040;
383 if (answer == 'Y')
384 return 1;
385 if (answer == 'N')
386 return 0;
387 printf ("Please answer y or n.\n");
388 }
389}
390\f
391/* Parse a C escape sequence. STRING_PTR points to a variable
392 containing a pointer to the string to parse. That pointer
393 is updated past the characters we use. The value of the
394 escape sequence is returned.
395
396 A negative value means the sequence \ newline was seen,
397 which is supposed to be equivalent to nothing at all.
398
399 If \ is followed by a null character, we return a negative
400 value and leave the string pointer pointing at the null character.
401
402 If \ is followed by 000, we return 0 and leave the string pointer
403 after the zeros. A value of 0 does not mean end of string. */
404
405int
406parse_escape (string_ptr)
407 char **string_ptr;
408{
409 register int c = *(*string_ptr)++;
410 switch (c)
411 {
412 case 'a':
413 return '\a';
414 case 'b':
415 return '\b';
416 case 'e':
417 return 033;
418 case 'f':
419 return '\f';
420 case 'n':
421 return '\n';
422 case 'r':
423 return '\r';
424 case 't':
425 return '\t';
426 case 'v':
427 return '\v';
428 case '\n':
429 return -2;
430 case 0:
431 (*string_ptr)--;
432 return 0;
433 case '^':
434 c = *(*string_ptr)++;
435 if (c == '\\')
436 c = parse_escape (string_ptr);
437 if (c == '?')
438 return 0177;
439 return (c & 0200) | (c & 037);
440
441 case '0':
442 case '1':
443 case '2':
444 case '3':
445 case '4':
446 case '5':
447 case '6':
448 case '7':
449 {
450 register int i = c - '0';
451 register int count = 0;
452 while (++count < 3)
453 {
454 if ((c = *(*string_ptr)++) >= '0' && c <= '7')
455 {
456 i *= 8;
457 i += c - '0';
458 }
459 else
460 {
461 (*string_ptr)--;
462 break;
463 }
464 }
465 return i;
466 }
467 default:
468 return c;
469 }
470}
471\f
472/* Print the character CH on STREAM as part of the contents
473 of a literal string whose delimiter is QUOTER. */
474
475void
476printchar (ch, stream, quoter)
477 unsigned char ch;
478 FILE *stream;
479 int quoter;
480{
481 register int c = ch;
482 if (c < 040 || c >= 0177)
483 switch (c)
484 {
485 case '\n':
486 fputs_filtered ("\\n", stream);
487 break;
488 case '\b':
489 fputs_filtered ("\\b", stream);
490 break;
491 case '\t':
492 fputs_filtered ("\\t", stream);
493 break;
494 case '\f':
495 fputs_filtered ("\\f", stream);
496 break;
497 case '\r':
498 fputs_filtered ("\\r", stream);
499 break;
500 case '\033':
501 fputs_filtered ("\\e", stream);
502 break;
503 case '\007':
504 fputs_filtered ("\\a", stream);
505 break;
506 default:
507 fprintf_filtered (stream, "\\%.3o", (unsigned int) c);
508 break;
509 }
510 else
511 {
512 if (c == '\\' || c == quoter)
513 fputs_filtered ("\\", stream);
514 fprintf_filtered (stream, "%c", c);
515 }
516}
517\f
518static int lines_per_page, lines_printed, chars_per_line, chars_printed;
519
520/* Set values of page and line size. */
521static void
522set_screensize_command (arg, from_tty)
523 char *arg;
524 int from_tty;
525{
526 char *p = arg;
527 char *p1;
528 int tolinesize = lines_per_page;
529 int tocharsize = chars_per_line;
530
531 if (p == 0)
532 error_no_arg ("set screensize");
533
534 while (*p >= '0' && *p <= '9')
535 p++;
536
537 if (*p && *p != ' ' && *p != '\t')
538 error ("Non-integral argument given to \"set screensize\".");
539
540 tolinesize = atoi (arg);
541
542 while (*p == ' ' || *p == '\t')
543 p++;
544
545 if (*p)
546 {
547 p1 = p;
548 while (*p1 >= '0' && *p1 <= '9')
549 p1++;
550
551 if (*p1)
552 error ("Non-integral second argument given to \"set screensize\".");
553
554 tocharsize = atoi (p);
555 }
556
557 lines_per_page = tolinesize;
558 chars_per_line = tocharsize;
559}
560
561static void
562instream_cleanup(stream)
563 FILE *stream;
564{
565 instream = stream;
566}
567
568static void
569prompt_for_continue ()
570{
571 if (ISATTY(stdin) && ISATTY(stdout))
572 {
573 struct cleanup *old_chain = make_cleanup(instream_cleanup, instream);
574 char *cp, *gdb_readline();
575
576 instream = stdin;
577 immediate_quit++;
578 if (cp = gdb_readline ("---Type <return> to continue---"))
579 free(cp);
580 chars_printed = lines_printed = 0;
581 immediate_quit--;
582 do_cleanups(old_chain);
583 }
584}
585
586/* Reinitialize filter; ie. tell it to reset to original values. */
587
588void
589reinitialize_more_filter ()
590{
591 lines_printed = 0;
592 chars_printed = 0;
593}
594
595static void
596screensize_info (arg, from_tty)
597 char *arg;
598 int from_tty;
599{
600 if (arg)
601 error ("\"info screensize\" does not take any arguments.");
602
603 if (!lines_per_page)
604 printf ("Output more filtering is disabled.\n");
605 else
606 {
607 printf ("Output more filtering is enabled with\n");
608 printf ("%d lines per page and %d characters per line.\n",
609 lines_per_page, chars_per_line);
610 }
611}
612
613/* Like fputs but pause after every screenful.
614 Unlike fputs, fputs_filtered does not return a value.
615 It is OK for LINEBUFFER to be NULL, in which case just don't print
616 anything.
617
618 Note that a longjmp to top level may occur in this routine
619 (since prompt_for_continue may do so) so this routine should not be
620 called when cleanups are not in place. */
621
622void
623fputs_filtered (linebuffer, stream)
624 char *linebuffer;
625 FILE *stream;
626{
627 char *lineptr;
628
629 if (linebuffer == 0)
630 return;
631
632 /* Don't do any filtering if it is disabled. */
633 if (stream != stdout || !ISATTY(stdout) || lines_per_page == 0)
634 {
635 fputs (linebuffer, stream);
636 return;
637 }
638
639 /* Go through and output each character. Show line extension
640 when this is necessary; prompt user for new page when this is
641 necessary. */
642
643 lineptr = linebuffer;
644 while (*lineptr)
645 {
646 /* Possible new page. */
647 if (lines_printed >= lines_per_page - 1)
648 prompt_for_continue ();
649
650 while (*lineptr && *lineptr != '\n')
651 {
652 /* Print a single line. */
653 if (*lineptr == '\t')
654 {
655 putc ('\t', stream);
656 /* Shifting right by 3 produces the number of tab stops
657 we have already passed, and then adding one and
658 shifting left 3 advances to the next tab stop. */
659 chars_printed = ((chars_printed >> 3) + 1) << 3;
660 lineptr++;
661 }
662 else
663 {
664 putc (*lineptr, stream);
665 chars_printed++;
666 lineptr++;
667 }
668
669 if (chars_printed >= chars_per_line)
670 {
671 chars_printed = 0;
672 lines_printed++;
673 /* Possible new page. */
674 if (lines_printed >= lines_per_page - 1)
675 prompt_for_continue ();
676 }
677 }
678
679 if (*lineptr == '\n')
680 {
681 lines_printed++;
682 putc ('\n', stream);
683 lineptr++;
684 chars_printed = 0;
685 }
686 }
687}
688
689/* fputs_demangled is a variant of fputs_filtered that
690 demangles g++ names.*/
691
692void
693fputs_demangled (linebuffer, stream, arg_mode)
694 char *linebuffer;
695 FILE *stream;
696{
697#ifdef __STDC__
698 extern char *cplus_demangle (const char *, int);
699#else
700 extern char *cplus_demangle ();
701#endif
702#define SYMBOL_MAX 1024
703
704#define SYMBOL_CHAR(c) (isascii(c) && (isalnum(c) || (c) == '_' || (c) == '$'))
705
706 char buf[SYMBOL_MAX+1];
707 char *p;
708
709 if (linebuffer == NULL)
710 return;
711
712 p = linebuffer;
713
714 while ( *p != (char) 0 ) {
715 int i = 0;
716
717 /* collect non-interesting characters into buf */
718 while ( *p != (char) 0 && !SYMBOL_CHAR(*p) ) {
719 buf[i++] = *p;
720 p++;
721 }
722 if (i > 0) {
723 /* output the non-interesting characters without demangling */
724 buf[i] = (char) 0;
725 fputs_filtered(buf, stream);
726 i = 0; /* reset buf */
727 }
728
729 /* and now the interesting characters */
730 while (i < SYMBOL_MAX && *p != (char) 0 && SYMBOL_CHAR(*p) ) {
731 buf[i++] = *p;
732 p++;
733 }
734 buf[i] = (char) 0;
735 if (i > 0) {
736 char * result;
737
738 if ( (result = cplus_demangle(buf, arg_mode)) != NULL ) {
739 fputs_filtered(result, stream);
740 free(result);
741 }
742 else {
743 fputs_filtered(buf, stream);
744 }
745 }
746 }
747}
748
749/* Print ARG1, ARG2, and ARG3 on stdout using format FORMAT. If this
750 information is going to put the amount written since the last call
751 to INIIALIZE_MORE_FILTER or the last page break over the page size,
752 print out a pause message and do a gdb_readline to get the users
753 permision to continue.
754
755 Unlike fprintf, this function does not return a value.
756
757 Note that this routine has a restriction that the length of the
758 final output line must be less than 255 characters *or* it must be
759 less than twice the size of the format string. This is a very
760 arbitrary restriction, but it is an internal restriction, so I'll
761 put it in. This means that the %s format specifier is almost
762 useless; unless the caller can GUARANTEE that the string is short
763 enough, fputs_filtered should be used instead.
764
765 Note also that a longjmp to top level may occur in this routine
766 (since prompt_for_continue may do so) so this routine should not be
767 called when cleanups are not in place. */
768
769void
770fprintf_filtered (stream, format, arg1, arg2, arg3, arg4, arg5, arg6)
771 FILE *stream;
772 char *format;
773 int arg1, arg2, arg3, arg4, arg5, arg6;
774{
775 static char *linebuffer = (char *) 0;
776 static int line_size;
777 int format_length = strlen (format);
778 int numchars;
779
780 /* Allocated linebuffer for the first time. */
781 if (!linebuffer)
782 {
783 linebuffer = (char *) xmalloc (255);
784 line_size = 255;
785 }
786
787 /* Reallocate buffer to a larger size if this is necessary. */
788 if (format_length * 2 > line_size)
789 {
790 line_size = format_length * 2;
791
792 /* You don't have to copy. */
793 free (linebuffer);
794 linebuffer = (char *) xmalloc (line_size);
795 }
796
797 /* This won't blow up if the restrictions described above are
798 followed. */
799 (void) sprintf (linebuffer, format, arg1, arg2, arg3, arg4, arg5, arg6);
800
801 fputs_filtered (linebuffer, stream);
802}
803
804void
805printf_filtered (format, arg1, arg2, arg3, arg4, arg5, arg6)
806 char *format;
807 int arg1, arg2, arg3, arg4, arg5, arg6;
808{
809 fprintf_filtered (stdout, format, arg1, arg2, arg3, arg4, arg5, arg6);
810}
811
812/* Print N spaces. */
813void
814print_spaces_filtered (n, stream)
815 int n;
816 FILE *stream;
817{
818 register char *s = (char *) alloca (n + 1);
819 register char *t = s;
820
821 while (n--)
822 *t++ = ' ';
823 *t = '\0';
824
825 fputs_filtered (s, stream);
826}
827
828\f
829#ifdef USG
830bcopy (from, to, count)
831char *from, *to;
832{
833 memcpy (to, from, count);
834}
835
836bcmp (from, to, count)
837{
838 return (memcmp (to, from, count));
839}
840
841bzero (to, count)
842char *to;
843{
844 while (count--)
845 *to++ = 0;
846}
847
848getwd (buf)
849char *buf;
850{
851 getcwd (buf, MAXPATHLEN);
852}
853
854char *
855index (s, c)
856 char *s;
857{
858 char *strchr ();
859 return strchr (s, c);
860}
861
862char *
863rindex (s, c)
864 char *s;
865{
866 char *strrchr ();
867 return strrchr (s, c);
868}
869
870#ifndef USG
871char *sys_siglist[32] = {
872 "SIG0",
873 "SIGHUP",
874 "SIGINT",
875 "SIGQUIT",
876 "SIGILL",
877 "SIGTRAP",
878 "SIGIOT",
879 "SIGEMT",
880 "SIGFPE",
881 "SIGKILL",
882 "SIGBUS",
883 "SIGSEGV",
884 "SIGSYS",
885 "SIGPIPE",
886 "SIGALRM",
887 "SIGTERM",
888 "SIGUSR1",
889 "SIGUSR2",
890 "SIGCLD",
891 "SIGPWR",
892 "SIGWIND",
893 "SIGPHONE",
894 "SIGPOLL",
895};
896#endif
897
898/* Queue routines */
899
900struct queue {
901 struct queue *forw;
902 struct queue *back;
903};
904
905insque (item, after)
906struct queue *item;
907struct queue *after;
908{
909 item->forw = after->forw;
910 after->forw->back = item;
911
912 item->back = after;
913 after->forw = item;
914}
915
916remque (item)
917struct queue *item;
918{
919 item->forw->back = item->back;
920 item->back->forw = item->forw;
921}
922#endif /* USG */
923\f
924#ifdef USG
925/* There is too much variation in Sys V signal numbers and names, so
926 we must initialize them at runtime. */
927static char undoc[] = "(undocumented)";
928
929char *sys_siglist[NSIG];
930#endif /* USG */
931
932extern struct cmd_list_element *setlist;
933
934void
935_initialize_utils ()
936{
937 int i;
938 add_cmd ("screensize", class_support, set_screensize_command,
939 "Change gdb's notion of the size of the output screen.\n\
940The first argument is the number of lines on a page.\n\
941The second argument (optional) is the number of characters on a line.",
942 &setlist);
943 add_info ("screensize", screensize_info,
944 "Show gdb's current notion of the size of the output screen.");
945
946 /* These defaults will be used if we are unable to get the correct
947 values from termcap. */
948 lines_per_page = 24;
949 chars_per_line = 80;
950 /* Initialize the screen height and width from termcap. */
951 {
952 int termtype = getenv ("TERM");
953
954 /* Positive means success, nonpositive means failure. */
955 int status;
956
957 /* 2048 is large enough for all known terminals, according to the
958 GNU termcap manual. */
959 char term_buffer[2048];
960
961 if (termtype)
962 {
963 status = tgetent (term_buffer, termtype);
964 if (status > 0)
965 {
966 int val;
967
968 val = tgetnum ("li");
969 if (val >= 0)
970 lines_per_page = val;
971 else
972 /* The number of lines per page is not mentioned
973 in the terminal description. This probably means
974 that paging is not useful (e.g. emacs shell window),
975 so disable paging. */
976 lines_per_page = 0;
977
978 val = tgetnum ("co");
979 if (val >= 0)
980 chars_per_line = val;
981 }
982 }
983 }
984
985#ifdef USG
986 /* Initialize signal names. */
987 for (i = 0; i < NSIG; i++)
988 sys_siglist[i] = undoc;
989
990#ifdef SIGHUP
991 sys_siglist[SIGHUP ] = "SIGHUP";
992#endif
993#ifdef SIGINT
994 sys_siglist[SIGINT ] = "SIGINT";
995#endif
996#ifdef SIGQUIT
997 sys_siglist[SIGQUIT ] = "SIGQUIT";
998#endif
999#ifdef SIGILL
1000 sys_siglist[SIGILL ] = "SIGILL";
1001#endif
1002#ifdef SIGTRAP
1003 sys_siglist[SIGTRAP ] = "SIGTRAP";
1004#endif
1005#ifdef SIGIOT
1006 sys_siglist[SIGIOT ] = "SIGIOT";
1007#endif
1008#ifdef SIGEMT
1009 sys_siglist[SIGEMT ] = "SIGEMT";
1010#endif
1011#ifdef SIGFPE
1012 sys_siglist[SIGFPE ] = "SIGFPE";
1013#endif
1014#ifdef SIGKILL
1015 sys_siglist[SIGKILL ] = "SIGKILL";
1016#endif
1017#ifdef SIGBUS
1018 sys_siglist[SIGBUS ] = "SIGBUS";
1019#endif
1020#ifdef SIGSEGV
1021 sys_siglist[SIGSEGV ] = "SIGSEGV";
1022#endif
1023#ifdef SIGSYS
1024 sys_siglist[SIGSYS ] = "SIGSYS";
1025#endif
1026#ifdef SIGPIPE
1027 sys_siglist[SIGPIPE ] = "SIGPIPE";
1028#endif
1029#ifdef SIGALRM
1030 sys_siglist[SIGALRM ] = "SIGALRM";
1031#endif
1032#ifdef SIGTERM
1033 sys_siglist[SIGTERM ] = "SIGTERM";
1034#endif
1035#ifdef SIGUSR1
1036 sys_siglist[SIGUSR1 ] = "SIGUSR1";
1037#endif
1038#ifdef SIGUSR2
1039 sys_siglist[SIGUSR2 ] = "SIGUSR2";
1040#endif
1041#ifdef SIGCLD
1042 sys_siglist[SIGCLD ] = "SIGCLD";
1043#endif
1044#ifdef SIGCHLD
1045 sys_siglist[SIGCHLD ] = "SIGCHLD";
1046#endif
1047#ifdef SIGPWR
1048 sys_siglist[SIGPWR ] = "SIGPWR";
1049#endif
1050#ifdef SIGTSTP
1051 sys_siglist[SIGTSTP ] = "SIGTSTP";
1052#endif
1053#ifdef SIGTTIN
1054 sys_siglist[SIGTTIN ] = "SIGTTIN";
1055#endif
1056#ifdef SIGTTOU
1057 sys_siglist[SIGTTOU ] = "SIGTTOU";
1058#endif
1059#ifdef SIGSTOP
1060 sys_siglist[SIGSTOP ] = "SIGSTOP";
1061#endif
1062#ifdef SIGXCPU
1063 sys_siglist[SIGXCPU ] = "SIGXCPU";
1064#endif
1065#ifdef SIGXFSZ
1066 sys_siglist[SIGXFSZ ] = "SIGXFSZ";
1067#endif
1068#ifdef SIGVTALRM
1069 sys_siglist[SIGVTALRM ] = "SIGVTALRM";
1070#endif
1071#ifdef SIGPROF
1072 sys_siglist[SIGPROF ] = "SIGPROF";
1073#endif
1074#ifdef SIGWINCH
1075 sys_siglist[SIGWINCH ] = "SIGWINCH";
1076#endif
1077#ifdef SIGCONT
1078 sys_siglist[SIGCONT ] = "SIGCONT";
1079#endif
1080#ifdef SIGURG
1081 sys_siglist[SIGURG ] = "SIGURG";
1082#endif
1083#ifdef SIGIO
1084 sys_siglist[SIGIO ] = "SIGIO";
1085#endif
1086#ifdef SIGWIND
1087 sys_siglist[SIGWIND ] = "SIGWIND";
1088#endif
1089#ifdef SIGPHONE
1090 sys_siglist[SIGPHONE ] = "SIGPHONE";
1091#endif
1092#ifdef SIGPOLL
1093 sys_siglist[SIGPOLL ] = "SIGPOLL";
1094#endif
1095#endif /* USG */
1096}