home *** CD-ROM | disk | FTP | other *** search
/ linuxmafia.com 2016 / linuxmafia.com.tar / linuxmafia.com / pub / linux / backup / star-1.3.1.tar.gz / star-1.3.1.tar / star-1.3.1 / lib / raisecond.c < prev    next >
C/C++ Source or Header  |  2000-05-07  |  4KB  |  159 lines

  1. /* @(#)raisecond.c    1.12 00/05/07 Copyright 1985 J. Schilling */
  2. /*
  3.  *    raise a condition (software signal)
  4.  */
  5. /*
  6.  * This program 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 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program 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 this program; see the file COPYING.  If not, write to
  18.  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  */
  20. /*
  21.  *    Check for installed condition handlers.
  22.  *    If a handler is found, the function is called with the appropriate args.
  23.  *    If no handler is found or no handler signals success,
  24.  *    the program will be aborted.
  25.  *
  26.  *    Copyright (c) 1985 J. Schilling
  27.  */
  28. #include <mconfig.h>
  29. #include <stdio.h>
  30. #include <standard.h>
  31. #include <sigblk.h>
  32. #include <unixstd.h>
  33. #include <stdxlib.h>
  34. #include <strdefs.h>
  35. #include <avoffset.h>
  36. #include <schily.h>
  37.  
  38. #if    !defined(AV_OFFSET) || !defined(FP_INDIR)
  39. #    ifdef    HAVE_SCANSTACK
  40. #    undef    HAVE_SCANSTACK
  41. #    endif
  42. #endif
  43. #ifdef    NO_SCANSTACK
  44. #    ifdef    HAVE_SCANSTACK
  45. #    undef    HAVE_SCANSTACK
  46. #    endif
  47. #endif
  48.  
  49. /*
  50.  * Macros to print to stderr without stdio, to avoid screwing up.
  51.  */
  52. #ifndef    STDERR_FILENO
  53. #define    STDERR_FILENO    2
  54. #endif
  55. #define    eprints(a)    (void)write(STDERR_FILENO, (a), sizeof(a)-1)
  56. #define    eprintl(a)    (void)write(STDERR_FILENO, (a), strlen(a))
  57.  
  58. #define    is_even(p)    ((((long)(p)) & 1) == 0)
  59. #define    even(p)        (((long)(p)) & ~1L)
  60. #ifdef    __future__
  61. #define    even(p)        (((long)(p)) - 1)/* will this work with 64 bit ?? */
  62. #endif
  63.  
  64.  
  65. LOCAL    void raiseabort  __PR((const char *));
  66.  
  67. #ifdef    HAVE_SCANSTACK
  68.  
  69. #include <stkframe.h>
  70.  
  71. LOCAL    BOOL framehandle __PR((SIGBLK *, const char *, const char *, long));
  72.  
  73. /*
  74.  *    Loop through the chain of procedure frames on the stack.
  75.  *
  76.  *    Frame pointers normally have even values.
  77.  *    Frame pointers of procedures with an installed handler are marked odd.
  78.  *    The even base value, in this case actually points to a SIGBLK which
  79.  *    holds the saved "real" frame pointer.
  80.  *    The SIGBLK mentioned above may me the start of a chain of SIGBLK's,
  81.  *    containing different handlers.
  82.  */
  83. void raisecond(signame, arg2)
  84.     const char    *signame;
  85.     long        arg2;
  86. {
  87.     register struct frame *fp = (struct frame *)getfp();
  88.  
  89.     for(; fp; fp = (struct frame *)fp->fr_savfp) {
  90.         if (is_even(fp))
  91.             continue;
  92.         fp = (struct frame *)even(fp);    /* really is (SIGBLK *) */
  93.  
  94.         if (framehandle((SIGBLK *)fp, signame, signame, arg2))
  95.             return;
  96.         else if (framehandle((SIGBLK *)fp, "any_other", signame, arg2))
  97.             return;
  98.         fp = (struct frame *)((SIGBLK *)fp)->sb_savfp;
  99.     }
  100.     /*
  101.      * No matching handler that signals success found.
  102.      * Print error message and abort.
  103.      */
  104.     raiseabort(signame);
  105.     /* NOTREACHED */
  106. }
  107.  
  108. /*
  109.  *    Loop through the handler chain for a procedure frame.
  110.  *
  111.  *    If no handler with matching name is found, return FALSE,
  112.  *    otherwise the first handler with matching name is called.
  113.  *    The return value in the latter case depends on the called function.
  114.  */
  115. LOCAL BOOL framehandle(sp, handlename, signame, arg2)
  116.     register SIGBLK *sp;
  117.     const char    *handlename;
  118.     const char    *signame;
  119.     long        arg2;
  120. {
  121.     for(; sp; sp = sp->sb_signext) {
  122.         if (streql(sp->sb_signame, handlename)) {
  123.             if (sp->sb_sigfun == NULL) {    /* deactivated */
  124.                 return (FALSE);
  125.             } else {
  126.                 return (*sp->sb_sigfun)(signame,
  127.                             sp->sb_sigarg, arg2);
  128.             }
  129.         }
  130.     }
  131.     return (FALSE);
  132. }
  133.  
  134. #else    /* HAVE_SCANSTACK */
  135.  
  136. void raisecond(signame, arg2)
  137.     const char    *signame;
  138.     long        arg2;
  139. {
  140.     /*
  141.      * Print error message and abort.
  142.      */
  143.     raiseabort(signame);
  144.     /* NOTREACHED */
  145. }
  146.  
  147. #endif    /* HAVE_SCANSTACK */
  148.  
  149. LOCAL void raiseabort(signame)
  150.     const    char    *signame;
  151. {
  152.     eprints("Condition not caught: "); eprintl(signame); eprints(".\n");
  153. #ifndef    HAVE_SCANSTACK
  154.     eprints("Raisecond: not implemented.\n");
  155. #endif
  156.     abort();
  157.     /* NOTREACHED */
  158. }
  159.