xref: /386bsd/usr/src/usr.bin/gdb/utils.c (revision a2142627)
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
12 static 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 
18 This file is part of GDB.
19 
20 GDB is free software; you can redistribute it and/or modify
21 it under the terms of the GNU General Public License as published by
22 the Free Software Foundation; either version 1, or (at your option)
23 any later version.
24 
25 GDB is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28 GNU General Public License for more details.
29 
30 You should have received a copy of the GNU General Public License
31 along with GDB; see the file COPYING.  If not, write to
32 the 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 
53 extern FILE *instream;
54 
55 void error ();
56 void fatal ();
57 
58 /* Chain of cleanup actions established with make_cleanup,
59    to be executed if an error happens.  */
60 
61 static struct cleanup *cleanup_chain;
62 
63 /* Nonzero means a quit has been requested.  */
64 
65 int quit_flag;
66 
67 /* Nonzero means quit immediately if Control-C is typed now,
68    rather than waiting until QUIT is executed.  */
69 
70 int immediate_quit;
71 
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 
77 struct cleanup *
78 make_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 
97 void
do_cleanups(old_chain)98 do_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 
113 void
discard_cleanups(old_chain)114 discard_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.  */
126 struct cleanup *
save_cleanups()127 save_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.  */
136 void
restore_cleanups(chain)137 restore_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 
151 void
free_current_contents(location)152 free_current_contents (location)
153      char **location;
154 {
155   free (*location);
156 }
157 
158 /* Generally useful subroutines used throughout the program.  */
159 
160 /* Like malloc but get error if no storage available.  */
161 
162 char *
xmalloc(size)163 xmalloc (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 
174 char *
xrealloc(ptr,size)175 xrealloc (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 
189 void
perror_with_name(string)190 perror_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 
215 void
print_sys_errmsg(string,errcode)216 print_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 
238 void
quit()239 quit ()
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 
255 void
request_quit()256 request_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 
275 void
error(string,arg1,arg2,arg3)276 error (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 
291 void
fatal(string,arg)292 fatal (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.  */
305 void
fatal_dump_core(string,arg)306 fatal_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 
325 char *
savestring(ptr,size)326 savestring (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 
336 char *
concat(s1,s2,s3)337 concat (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 
348 void
print_spaces(n,file)349 print_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 
362 int
query(ctlstr,arg1,arg2)363 query (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 
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 
405 int
parse_escape(string_ptr)406 parse_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 
472 /* Print the character CH on STREAM as part of the contents
473    of a literal string whose delimiter is QUOTER.  */
474 
475 void
printchar(ch,stream,quoter)476 printchar (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 
518 static int lines_per_page, lines_printed, chars_per_line, chars_printed;
519 
520 /* Set values of page and line size.  */
521 static void
set_screensize_command(arg,from_tty)522 set_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 
561 static void
instream_cleanup(stream)562 instream_cleanup(stream)
563     FILE *stream;
564 {
565   instream = stream;
566 }
567 
568 static void
prompt_for_continue()569 prompt_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 
588 void
reinitialize_more_filter()589 reinitialize_more_filter ()
590 {
591   lines_printed = 0;
592   chars_printed = 0;
593 }
594 
595 static void
screensize_info(arg,from_tty)596 screensize_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 
622 void
fputs_filtered(linebuffer,stream)623 fputs_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 
692 void
fputs_demangled(linebuffer,stream,arg_mode)693 fputs_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 
769 void
fprintf_filtered(stream,format,arg1,arg2,arg3,arg4,arg5,arg6)770 fprintf_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 
804 void
printf_filtered(format,arg1,arg2,arg3,arg4,arg5,arg6)805 printf_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.  */
813 void
print_spaces_filtered(n,stream)814 print_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 
829 #ifdef USG
bcopy(from,to,count)830 bcopy (from, to, count)
831 char *from, *to;
832 {
833 	memcpy (to, from, count);
834 }
835 
bcmp(from,to,count)836 bcmp (from, to, count)
837 {
838 	return (memcmp (to, from, count));
839 }
840 
bzero(to,count)841 bzero (to, count)
842 char *to;
843 {
844 	while (count--)
845 		*to++ = 0;
846 }
847 
getwd(buf)848 getwd (buf)
849 char *buf;
850 {
851   getcwd (buf, MAXPATHLEN);
852 }
853 
854 char *
index(s,c)855 index (s, c)
856      char *s;
857 {
858   char *strchr ();
859   return strchr (s, c);
860 }
861 
862 char *
rindex(s,c)863 rindex (s, c)
864      char *s;
865 {
866   char *strrchr ();
867   return strrchr (s, c);
868 }
869 
870 #ifndef USG
871 char *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 
900 struct queue {
901 	struct queue *forw;
902 	struct queue *back;
903 };
904 
905 insque (item, after)
906 struct queue *item;
907 struct queue *after;
908 {
909 	item->forw = after->forw;
910 	after->forw->back = item;
911 
912 	item->back = after;
913 	after->forw = item;
914 }
915 
916 remque (item)
917 struct queue *item;
918 {
919 	item->forw->back = item->back;
920 	item->back->forw = item->forw;
921 }
922 #endif /* USG */
923 
924 #ifdef USG
925 /* There is too much variation in Sys V signal numbers and names, so
926    we must initialize them at runtime.  */
927 static char undoc[] = "(undocumented)";
928 
929 char *sys_siglist[NSIG];
930 #endif /* USG */
931 
932 extern struct cmd_list_element *setlist;
933 
934 void
_initialize_utils()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\
940 The first argument is the number of lines on a page.\n\
941 The 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 }
1097