home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1999 March B / SCO_CASTOR4RRT.iso / uccs / root.13 / usr / ccs / lib / ctrace / runtime.c
C/C++ Source or Header  |  1998-08-19  |  10KB  |  376 lines

  1. /*
  2.  * Copyright (c) 1998 The Santa Cruz Operation, Inc.. All Rights Reserved. 
  3.  *                                                                         
  4.  *        THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF THE               
  5.  *                   SANTA CRUZ OPERATION INC.                             
  6.  *                                                                         
  7.  *   The copyright notice above does not evidence any actual or intended   
  8.  *   publication of such source code.                                      
  9.  */
  10.  
  11. #ident    "@(#)ctrace:i386/runtime.c    1.1"
  12. /*    ctrace - C program debugging tool
  13.  *
  14.  *    run-time package of trace functions
  15.  *
  16.  */
  17. #ifndef va_dcl
  18. #include <varargs.h>
  19. #endif
  20.  
  21. #ifndef B_CT_
  22.  
  23. /* signal catching function used by u_ct_ */
  24. static jmp_buf sj_ct_;
  25. static
  26. f_ct_()
  27. {
  28.     longjmp(sj_ct_, 1);
  29. }
  30. #endif
  31.  
  32. #ifdef LM_CT_
  33. #define I_CT_(x)    ((x + LM_CT_) % LM_CT_)
  34.  
  35. /* global data used by loop detection code */
  36. static    int    ts_ct_;    /* trace state */
  37. #endif
  38.  
  39. /* global data used by duplicate variable trace code */
  40. static    int    vc_ct_;    /* var trace count within statement */
  41.  
  42. static    struct    {    /* var values within statement */
  43.     char    *vn_ct_;    /* var name */
  44.     int    vt_ct_;        /* var type (0 is string, > 0 is size) */
  45.     union    {        /* var value */
  46.         char    *vs_ct_;/* string */
  47.         int    vi_ct_;    /* int */
  48.         long    vl_ct_;    /* long */
  49.         double    vd_ct_;    /* double */
  50.         long double vL_ct_; /* long double */
  51.     } vv_ct_;
  52. } v_ct_[VM_CT_];
  53.  
  54. /* trace on/off control */
  55. static    int    tr_ct_ = 1;
  56.  
  57. static
  58. ctron()
  59. {
  60.     tr_ct_ = 1;
  61.     PF_CT_" \b\n    /* trace on */ \b");
  62. }
  63.  
  64. static
  65. ctroff()
  66. {
  67.     tr_ct_ = 0;
  68.     PF_CT_" \b\n    /* trace off */ \b");
  69. }
  70. /* print the statement text */
  71.  
  72. static
  73. t_ct_(text)
  74. register char    *text;
  75. {
  76. #ifdef LM_CT_
  77.     static    int    loop_start, next_stmt;
  78.     static    char    *stmt[LM_CT_];
  79.     static    long    loops;
  80.     register int    i;
  81.     register char    *s;
  82.     register char    c;
  83. #endif
  84.  
  85.     /* return if tracing is off */
  86.     if (!tr_ct_) {
  87.         return;
  88.     }
  89. #ifdef LM_CT_
  90.     if (ts_ct_ == 2)    /* if not tracing */
  91.         if (strcmp(text, stmt[next_stmt]) == 0) {
  92.             if (strcmp(text, stmt[loop_start]) == 0) {
  93.                 ++loops;
  94.                 if (loops % 1000 == 0)
  95.                     PF_CT_" \b\n    /* still repeating after %ld times */ \b", loops);
  96.                 next_stmt = loop_start;
  97.             }
  98.             next_stmt = I_CT_(next_stmt + 1);
  99.             vc_ct_ = 0;    /* reset the var count */
  100.             return;
  101.         }
  102.         else {    /* doesn't match next statement */
  103.             if (loops == 0)
  104.                 PF_CT_" \b\n    /* repeated < 1 time */ \b");
  105.             else
  106.                 PF_CT_" \b\n    /* repeated %ld times */ \b", loops);
  107.             loops = 0;
  108.             PF_CT_" \b%s \b", stmt[I_CT_(next_stmt - 1)]); /* print last statement */
  109.             ts_ct_ = 4;    /* force var printing */
  110.             for (i = 0; i < vc_ct_; ++i) /* print its vars */
  111.                 if (v_ct_[i].vt_ct_ == 0) /* string? */
  112.                     s_ct_(v_ct_[i].vn_ct_, v_ct_[i].vv_ct_.vs_ct_); /* yes */
  113.                 else if (v_ct_[i].vt_ct_ == sizeof(int))
  114.                     u_ct_(v_ct_[i].vn_ct_, v_ct_[i].vt_ct_, v_ct_[i].vv_ct_.vi_ct_);
  115.                 else if (v_ct_[i].vt_ct_ == sizeof(long))
  116.                     u_ct_(v_ct_[i].vn_ct_, v_ct_[i].vt_ct_, v_ct_[i].vv_ct_.vl_ct_);
  117.                 else if (v_ct_[i].vt_ct_ == sizeof(long double))
  118.                     u_ct_(v_ct_[i].vn_ct_, v_ct_[i].vt_ct_, v_ct_[i].vv_ct_.vL_ct_);
  119.                 else    /* double */
  120.                     u_ct_(v_ct_[i].vn_ct_, v_ct_[i].vt_ct_, v_ct_[i].vv_ct_.vd_ct_);
  121.             ts_ct_ = 0;    /* start tracing */
  122.         }
  123. #endif
  124.     vc_ct_ = 0;    /* reset the var count */
  125.  
  126. #ifdef LM_CT_
  127.     if (ts_ct_ == 0) {    /* if looking for the start of a loop */
  128.         /* if statement in list */
  129.         for (i = I_CT_(next_stmt - 2); i != I_CT_(next_stmt - 1); i = I_CT_(i - 1))
  130.             if ((s = stmt[i]) != 0 &&    /* saved text could be null */
  131.                 strcmp(text, s) == 0 &&    /* if text matches */
  132.                 (c = s[strlen(s) - 1]) != '{' && c != '}') { /* and is not a brace */
  133.                 ts_ct_ = 1;    /* look for the loop end */
  134.                 loop_start = i;
  135.                 next_stmt = I_CT_(loop_start + 1);
  136.                 goto print_stmt;
  137.             }
  138.     }
  139.     else    /* if looking for the loop end */
  140.         if (strcmp(text, stmt[loop_start]) == 0) { /* if start stmt */
  141.             ts_ct_ = 2;            /* stop tracing */
  142.             PF_CT_" \b\n    /* repeating */ \b");
  143.             stmt[next_stmt] = text;    /* save as end marker */
  144.             next_stmt = I_CT_(loop_start + 1);
  145.             return;
  146.         }
  147.         else if (strcmp(text, stmt[next_stmt]) != 0) /* if not next stmt */
  148.             ts_ct_ = 0; /* look for the start of a loop */
  149.     stmt[next_stmt] = text;    /* save this statement */
  150.     next_stmt = I_CT_(next_stmt + 1); /* inc the pointer */
  151. print_stmt:
  152. #endif
  153.     PF_CT_" \b%s \b", text); /* print this statement */
  154. #ifndef B_CT_
  155.     (void) fflush(stdout);        /* flush the output buffer */
  156. #endif
  157. }
  158. /* dump a string variable */
  159.  
  160. static
  161. s_ct_(name, value)
  162. register char    *name;
  163. register char    *value;
  164. {
  165.     /* return if tracing is off */
  166.     if (!tr_ct_) {
  167.         return;
  168.     }
  169. #ifdef LM_CT_
  170.     /* save the var name and value */
  171.     if (ts_ct_ != 4) {    /* if not forcing var printing */
  172.         v_ct_[vc_ct_].vn_ct_ = name;
  173.         v_ct_[vc_ct_].vt_ct_ = 0;    /* var type is string */
  174.         v_ct_[vc_ct_].vv_ct_.vs_ct_ = value;
  175.         ++vc_ct_;
  176.     }
  177.  
  178.     if (ts_ct_ == 2)    /* if not tracing */
  179.         return;
  180. #endif
  181.  
  182.     PF_CT_" \b\n    %s == \"", name);
  183.     /* flush before printing the string because it may cause an
  184.        abort if it is not null terminated */
  185. #ifndef B_CT_
  186.     (void) fflush(stdout);
  187. #endif
  188.     PF_CT_"%s\" */ \b", value);
  189. #ifndef B_CT_
  190.     (void) fflush(stdout);
  191. #endif
  192. }
  193. /* dump a variable of an unknown type */
  194.  
  195. static
  196. u_ct_(name, _size, va_alist)    /* size is a macro in <macros.h> */
  197. char    *name;
  198. register int    _size;
  199. va_dcl
  200. {
  201. #ifndef isprint
  202. #include <ctype.h>
  203. #endif
  204.     union value1{
  205.         char    *p;
  206.         int    i;
  207.         long    l;
  208.         double    d;
  209.         long double L;
  210.     } value;
  211.     va_list    ap;
  212.     register int    i;
  213.     register char    *s;
  214.     register char    c;
  215.  
  216.     va_start(ap);
  217.     /* return if tracing is off */
  218.     if (!tr_ct_) {
  219.         return;
  220.     }
  221.     /* normalize the size (pointer and float are the same size as either int or long) */
  222.     if (_size == sizeof(char) || _size == sizeof(short))
  223.         _size = sizeof(int);
  224.     else if (_size != sizeof(int) && _size != sizeof(long) && _size != sizeof(double) && _size != sizeof(long double))
  225.         /* this is an extern pointer (size=0), or array or struct address */
  226.         _size = sizeof(char *);
  227.  
  228.     if (_size == sizeof(int)) {
  229.         value.i = va_arg(ap, int);
  230.     }
  231.     else if (_size == sizeof(long)) {
  232.         value.l = va_arg(ap, long);
  233.     }
  234.     else if (_size == sizeof(double)) {
  235.         value.d = va_arg(ap, double);
  236.     }
  237.     else if (_size == sizeof(long double)) {
  238.         value.L = va_arg(ap, long double);
  239.     }
  240.     else    /* char * */
  241.         value.p = va_arg(ap, char *);
  242.  
  243. #ifdef LM_CT_
  244.     if (ts_ct_ != 4) {    /* if not forcing var printing */
  245. #endif
  246.         /* don't dump the variable if its value is the same */
  247.         for (i = 0; i < vc_ct_; ++i)
  248.             if (_size == v_ct_[i].vt_ct_ && strcmp(name, v_ct_[i].vn_ct_) == 0)
  249.                 if (_size == sizeof(int)) {
  250.                     if (value.i == v_ct_[i].vv_ct_.vi_ct_)
  251.                         return;
  252.                 }
  253.                 else if (_size == sizeof(long)) {
  254.                     if (value.l == v_ct_[i].vv_ct_.vl_ct_)
  255.                         return;
  256.                 }
  257.                 else if (_size == sizeof(long double)) {
  258.                     if (value.L == v_ct_[i].vv_ct_.vL_ct_)
  259.                         return;
  260.                 }
  261.                 else /* double */
  262.                     if (value.d == v_ct_[i].vv_ct_.vd_ct_)
  263.                         return;
  264.     
  265.         /* save the var name and value */
  266.         v_ct_[vc_ct_].vn_ct_ = name;
  267.         v_ct_[vc_ct_].vt_ct_ = _size;
  268.         if (_size == sizeof(int)) {
  269.             v_ct_[vc_ct_].vv_ct_.vi_ct_ = value.i;
  270.         }
  271.         else if (_size == sizeof(long)) {
  272.             v_ct_[vc_ct_].vv_ct_.vl_ct_ = value.l;
  273.         }
  274.         else if (_size == sizeof(long double)) {
  275.             v_ct_[vc_ct_].vv_ct_.vL_ct_ = value.L;
  276.         }
  277.         else /* double */
  278.             v_ct_[vc_ct_].vv_ct_.vd_ct_ = value.d;
  279.         ++vc_ct_;
  280. #ifdef LM_CT_
  281.     }
  282.  
  283.     if (ts_ct_ == 2)    /* if not tracing */
  284.         return;
  285. #endif
  286.     /* determine the variable type and print it */
  287.     PF_CT_" \b\n    %s == ", name);
  288.     if (_size == sizeof(int)) {
  289.         PF_CT_"%d", value.i);    /* decimal */
  290. #ifdef O_CT_
  291.         if ((unsigned) value.i > 7)    /* octal */
  292.             PF_CT_" or 0%o", value.i);
  293. #endif
  294. #ifdef X_CT_
  295.         if ((unsigned) value.i > 9)    /* hexadecimal */
  296.             PF_CT_" or 0x%x", value.i);
  297. #endif
  298. #ifdef U_CT_
  299.         if (value.i < 0)        /* unsigned */
  300.             PF_CT_" or %u", value.i);
  301. #endif
  302. #ifdef E_CT_
  303.         if (_size == sizeof(float))    /* float */
  304.             PF_CT_" or %e", value.i);
  305. #endif
  306.         if ((unsigned) value.i <= 255) /* character */
  307.             if (isprint(value.i))
  308.                 PF_CT_" or '%c'", value.i);
  309.             else if (iscntrl(value.i)) {
  310.                 switch (value.i) {
  311.                     case '\n': c = 'n'; break;
  312.                     case '\t': c = 't'; break;
  313.                     case '\b': c = 'b'; break;
  314.                     case '\r': c = 'r'; break;
  315.                     case '\f': c = 'f'; break;
  316.                     case '\v': c = 'v'; break;
  317.                     default:    c = '\0';
  318.                 }
  319.                 if (c != '\0')
  320.                     PF_CT_" or '\\%c'", c);
  321.             }
  322.     }
  323.     else if (_size == sizeof(long)) {
  324.         PF_CT_"%ld", value.l);    /* decimal */
  325. #ifdef O_CT_
  326.         if ((unsigned) value.l > 7)    /* octal */
  327.             PF_CT_" or 0%lo", value.l);
  328. #endif
  329. #ifdef X_CT_
  330.     if ((unsigned) value.l > 9)    /* hexadecimal */
  331.             PF_CT_" or 0x%lx", value.l);
  332. #endif
  333. #ifdef U_CT_
  334.         if (value.l < 0)        /* unsigned */
  335.             PF_CT_" or %lu", value.l);
  336. #endif
  337. #ifdef E_CT_
  338.         if (_size == sizeof(float))    /* float */
  339.             PF_CT_" or %e", value.l);
  340. #endif
  341.     }
  342.     else if (_size == sizeof(long double))    /* long double */
  343.         PF_CT_"%Le", value.L);
  344.     else if (_size == sizeof(double))    /* double */
  345.         PF_CT_"%e", value.d);
  346. #ifndef B_CT_
  347.     /* check for a possible non-null pointer */
  348.     if (_size == sizeof(char *) && value.p != 0) {
  349.         int    (*sigbus)(), (*sigsegv)();
  350.  
  351.         /* see if this is a non-null string */
  352.         if (setjmp(sj_ct_) == 0) {
  353.             sigbus = (int (*)()) signal(SIGBUS, (void (*)())f_ct_);
  354.             sigsegv = (int (*)()) signal(SIGSEGV, (void (*)())f_ct_);
  355.             if (*value.p != '\0')
  356.                 for (s = value.p; ; ++s) {
  357.                     if ((c = *s) == '\0') {
  358.                         PF_CT_" or \"%s\"", value.p);
  359.                         break;
  360.                     }
  361.                     /* don't use isspace(3) because \v and others will not print properly */
  362.                     if (!isprint(c) && c != '\t' && c != '\n')
  363.                         break;    /* not string */
  364.                 }
  365.         }
  366.         signal(SIGBUS, (void (*)())sigbus);
  367.         signal(SIGSEGV, (void (*)())sigsegv);
  368.     }
  369. #endif
  370.     PF_CT_" */ \b");
  371. #ifndef B_CT_
  372.     (void) fflush(stdout);
  373. #endif
  374.     va_end(ap);
  375. }
  376.