home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gdb / sprite / utils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-13  |  21.6 KB  |  1,018 lines

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