home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1998 The Santa Cruz Operation, Inc.. All Rights Reserved.
- *
- * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF THE
- * SANTA CRUZ OPERATION INC.
- *
- * The copyright notice above does not evidence any actual or intended
- * publication of such source code.
- */
-
- #ident "@(#)ctrace:i386/runtime.c 1.1"
- /* ctrace - C program debugging tool
- *
- * run-time package of trace functions
- *
- */
- #ifndef va_dcl
- #include <varargs.h>
- #endif
-
- #ifndef B_CT_
-
- /* signal catching function used by u_ct_ */
- static jmp_buf sj_ct_;
- static
- f_ct_()
- {
- longjmp(sj_ct_, 1);
- }
- #endif
-
- #ifdef LM_CT_
- #define I_CT_(x) ((x + LM_CT_) % LM_CT_)
-
- /* global data used by loop detection code */
- static int ts_ct_; /* trace state */
- #endif
-
- /* global data used by duplicate variable trace code */
- static int vc_ct_; /* var trace count within statement */
-
- static struct { /* var values within statement */
- char *vn_ct_; /* var name */
- int vt_ct_; /* var type (0 is string, > 0 is size) */
- union { /* var value */
- char *vs_ct_;/* string */
- int vi_ct_; /* int */
- long vl_ct_; /* long */
- double vd_ct_; /* double */
- long double vL_ct_; /* long double */
- } vv_ct_;
- } v_ct_[VM_CT_];
-
- /* trace on/off control */
- static int tr_ct_ = 1;
-
- static
- ctron()
- {
- tr_ct_ = 1;
- PF_CT_" \b\n /* trace on */ \b");
- }
-
- static
- ctroff()
- {
- tr_ct_ = 0;
- PF_CT_" \b\n /* trace off */ \b");
- }
- /* print the statement text */
-
- static
- t_ct_(text)
- register char *text;
- {
- #ifdef LM_CT_
- static int loop_start, next_stmt;
- static char *stmt[LM_CT_];
- static long loops;
- register int i;
- register char *s;
- register char c;
- #endif
-
- /* return if tracing is off */
- if (!tr_ct_) {
- return;
- }
- #ifdef LM_CT_
- if (ts_ct_ == 2) /* if not tracing */
- if (strcmp(text, stmt[next_stmt]) == 0) {
- if (strcmp(text, stmt[loop_start]) == 0) {
- ++loops;
- if (loops % 1000 == 0)
- PF_CT_" \b\n /* still repeating after %ld times */ \b", loops);
- next_stmt = loop_start;
- }
- next_stmt = I_CT_(next_stmt + 1);
- vc_ct_ = 0; /* reset the var count */
- return;
- }
- else { /* doesn't match next statement */
- if (loops == 0)
- PF_CT_" \b\n /* repeated < 1 time */ \b");
- else
- PF_CT_" \b\n /* repeated %ld times */ \b", loops);
- loops = 0;
- PF_CT_" \b%s \b", stmt[I_CT_(next_stmt - 1)]); /* print last statement */
- ts_ct_ = 4; /* force var printing */
- for (i = 0; i < vc_ct_; ++i) /* print its vars */
- if (v_ct_[i].vt_ct_ == 0) /* string? */
- s_ct_(v_ct_[i].vn_ct_, v_ct_[i].vv_ct_.vs_ct_); /* yes */
- else if (v_ct_[i].vt_ct_ == sizeof(int))
- u_ct_(v_ct_[i].vn_ct_, v_ct_[i].vt_ct_, v_ct_[i].vv_ct_.vi_ct_);
- else if (v_ct_[i].vt_ct_ == sizeof(long))
- u_ct_(v_ct_[i].vn_ct_, v_ct_[i].vt_ct_, v_ct_[i].vv_ct_.vl_ct_);
- else if (v_ct_[i].vt_ct_ == sizeof(long double))
- u_ct_(v_ct_[i].vn_ct_, v_ct_[i].vt_ct_, v_ct_[i].vv_ct_.vL_ct_);
- else /* double */
- u_ct_(v_ct_[i].vn_ct_, v_ct_[i].vt_ct_, v_ct_[i].vv_ct_.vd_ct_);
- ts_ct_ = 0; /* start tracing */
- }
- #endif
- vc_ct_ = 0; /* reset the var count */
-
- #ifdef LM_CT_
- if (ts_ct_ == 0) { /* if looking for the start of a loop */
- /* if statement in list */
- for (i = I_CT_(next_stmt - 2); i != I_CT_(next_stmt - 1); i = I_CT_(i - 1))
- if ((s = stmt[i]) != 0 && /* saved text could be null */
- strcmp(text, s) == 0 && /* if text matches */
- (c = s[strlen(s) - 1]) != '{' && c != '}') { /* and is not a brace */
- ts_ct_ = 1; /* look for the loop end */
- loop_start = i;
- next_stmt = I_CT_(loop_start + 1);
- goto print_stmt;
- }
- }
- else /* if looking for the loop end */
- if (strcmp(text, stmt[loop_start]) == 0) { /* if start stmt */
- ts_ct_ = 2; /* stop tracing */
- PF_CT_" \b\n /* repeating */ \b");
- stmt[next_stmt] = text; /* save as end marker */
- next_stmt = I_CT_(loop_start + 1);
- return;
- }
- else if (strcmp(text, stmt[next_stmt]) != 0) /* if not next stmt */
- ts_ct_ = 0; /* look for the start of a loop */
- stmt[next_stmt] = text; /* save this statement */
- next_stmt = I_CT_(next_stmt + 1); /* inc the pointer */
- print_stmt:
- #endif
- PF_CT_" \b%s \b", text); /* print this statement */
- #ifndef B_CT_
- (void) fflush(stdout); /* flush the output buffer */
- #endif
- }
- /* dump a string variable */
-
- static
- s_ct_(name, value)
- register char *name;
- register char *value;
- {
- /* return if tracing is off */
- if (!tr_ct_) {
- return;
- }
- #ifdef LM_CT_
- /* save the var name and value */
- if (ts_ct_ != 4) { /* if not forcing var printing */
- v_ct_[vc_ct_].vn_ct_ = name;
- v_ct_[vc_ct_].vt_ct_ = 0; /* var type is string */
- v_ct_[vc_ct_].vv_ct_.vs_ct_ = value;
- ++vc_ct_;
- }
-
- if (ts_ct_ == 2) /* if not tracing */
- return;
- #endif
-
- PF_CT_" \b\n %s == \"", name);
- /* flush before printing the string because it may cause an
- abort if it is not null terminated */
- #ifndef B_CT_
- (void) fflush(stdout);
- #endif
- PF_CT_"%s\" */ \b", value);
- #ifndef B_CT_
- (void) fflush(stdout);
- #endif
- }
- /* dump a variable of an unknown type */
-
- static
- u_ct_(name, _size, va_alist) /* size is a macro in <macros.h> */
- char *name;
- register int _size;
- va_dcl
- {
- #ifndef isprint
- #include <ctype.h>
- #endif
- union value1{
- char *p;
- int i;
- long l;
- double d;
- long double L;
- } value;
- va_list ap;
- register int i;
- register char *s;
- register char c;
-
- va_start(ap);
- /* return if tracing is off */
- if (!tr_ct_) {
- return;
- }
- /* normalize the size (pointer and float are the same size as either int or long) */
- if (_size == sizeof(char) || _size == sizeof(short))
- _size = sizeof(int);
- else if (_size != sizeof(int) && _size != sizeof(long) && _size != sizeof(double) && _size != sizeof(long double))
- /* this is an extern pointer (size=0), or array or struct address */
- _size = sizeof(char *);
-
- if (_size == sizeof(int)) {
- value.i = va_arg(ap, int);
- }
- else if (_size == sizeof(long)) {
- value.l = va_arg(ap, long);
- }
- else if (_size == sizeof(double)) {
- value.d = va_arg(ap, double);
- }
- else if (_size == sizeof(long double)) {
- value.L = va_arg(ap, long double);
- }
- else /* char * */
- value.p = va_arg(ap, char *);
-
- #ifdef LM_CT_
- if (ts_ct_ != 4) { /* if not forcing var printing */
- #endif
- /* don't dump the variable if its value is the same */
- for (i = 0; i < vc_ct_; ++i)
- if (_size == v_ct_[i].vt_ct_ && strcmp(name, v_ct_[i].vn_ct_) == 0)
- if (_size == sizeof(int)) {
- if (value.i == v_ct_[i].vv_ct_.vi_ct_)
- return;
- }
- else if (_size == sizeof(long)) {
- if (value.l == v_ct_[i].vv_ct_.vl_ct_)
- return;
- }
- else if (_size == sizeof(long double)) {
- if (value.L == v_ct_[i].vv_ct_.vL_ct_)
- return;
- }
- else /* double */
- if (value.d == v_ct_[i].vv_ct_.vd_ct_)
- return;
-
- /* save the var name and value */
- v_ct_[vc_ct_].vn_ct_ = name;
- v_ct_[vc_ct_].vt_ct_ = _size;
- if (_size == sizeof(int)) {
- v_ct_[vc_ct_].vv_ct_.vi_ct_ = value.i;
- }
- else if (_size == sizeof(long)) {
- v_ct_[vc_ct_].vv_ct_.vl_ct_ = value.l;
- }
- else if (_size == sizeof(long double)) {
- v_ct_[vc_ct_].vv_ct_.vL_ct_ = value.L;
- }
- else /* double */
- v_ct_[vc_ct_].vv_ct_.vd_ct_ = value.d;
- ++vc_ct_;
- #ifdef LM_CT_
- }
-
- if (ts_ct_ == 2) /* if not tracing */
- return;
- #endif
- /* determine the variable type and print it */
- PF_CT_" \b\n %s == ", name);
- if (_size == sizeof(int)) {
- PF_CT_"%d", value.i); /* decimal */
- #ifdef O_CT_
- if ((unsigned) value.i > 7) /* octal */
- PF_CT_" or 0%o", value.i);
- #endif
- #ifdef X_CT_
- if ((unsigned) value.i > 9) /* hexadecimal */
- PF_CT_" or 0x%x", value.i);
- #endif
- #ifdef U_CT_
- if (value.i < 0) /* unsigned */
- PF_CT_" or %u", value.i);
- #endif
- #ifdef E_CT_
- if (_size == sizeof(float)) /* float */
- PF_CT_" or %e", value.i);
- #endif
- if ((unsigned) value.i <= 255) /* character */
- if (isprint(value.i))
- PF_CT_" or '%c'", value.i);
- else if (iscntrl(value.i)) {
- switch (value.i) {
- case '\n': c = 'n'; break;
- case '\t': c = 't'; break;
- case '\b': c = 'b'; break;
- case '\r': c = 'r'; break;
- case '\f': c = 'f'; break;
- case '\v': c = 'v'; break;
- default: c = '\0';
- }
- if (c != '\0')
- PF_CT_" or '\\%c'", c);
- }
- }
- else if (_size == sizeof(long)) {
- PF_CT_"%ld", value.l); /* decimal */
- #ifdef O_CT_
- if ((unsigned) value.l > 7) /* octal */
- PF_CT_" or 0%lo", value.l);
- #endif
- #ifdef X_CT_
- if ((unsigned) value.l > 9) /* hexadecimal */
- PF_CT_" or 0x%lx", value.l);
- #endif
- #ifdef U_CT_
- if (value.l < 0) /* unsigned */
- PF_CT_" or %lu", value.l);
- #endif
- #ifdef E_CT_
- if (_size == sizeof(float)) /* float */
- PF_CT_" or %e", value.l);
- #endif
- }
- else if (_size == sizeof(long double)) /* long double */
- PF_CT_"%Le", value.L);
- else if (_size == sizeof(double)) /* double */
- PF_CT_"%e", value.d);
- #ifndef B_CT_
- /* check for a possible non-null pointer */
- if (_size == sizeof(char *) && value.p != 0) {
- int (*sigbus)(), (*sigsegv)();
-
- /* see if this is a non-null string */
- if (setjmp(sj_ct_) == 0) {
- sigbus = (int (*)()) signal(SIGBUS, (void (*)())f_ct_);
- sigsegv = (int (*)()) signal(SIGSEGV, (void (*)())f_ct_);
- if (*value.p != '\0')
- for (s = value.p; ; ++s) {
- if ((c = *s) == '\0') {
- PF_CT_" or \"%s\"", value.p);
- break;
- }
- /* don't use isspace(3) because \v and others will not print properly */
- if (!isprint(c) && c != '\t' && c != '\n')
- break; /* not string */
- }
- }
- signal(SIGBUS, (void (*)())sigbus);
- signal(SIGSEGV, (void (*)())sigsegv);
- }
- #endif
- PF_CT_" */ \b");
- #ifndef B_CT_
- (void) fflush(stdout);
- #endif
- va_end(ap);
- }
-