home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / trace.c < prev    next >
C/C++ Source or Header  |  1998-04-26  |  7KB  |  378 lines

  1. /*
  2.  * debugging support -- tom dickey.
  3.  *
  4.  * $Header: /usr/build/vile/vile/RCS/trace.c,v 1.8 1998/04/26 12:36:05 tom Exp $
  5.  *
  6.  */
  7. #include "estruct.h"
  8. #include <ctype.h>
  9.  
  10. #undef fopen    /* avoid conflict with 'fakevms.c' */
  11.  
  12. #ifndef _trace_h
  13. #include "trace.h"
  14. #endif
  15.  
  16. #if SYS_UNIX
  17. #include <sys/time.h>
  18. #endif
  19.  
  20. #if    defined(sun) && !defined(__SVR4)
  21. extern    void    perror ( const char *s );
  22. extern    int    gettimeofday ( struct timeval *t, struct timezone *z );
  23. extern    int    vfprintf ( FILE *fp, const char *fmt, va_list v );
  24. extern    int    fflush ( FILE *fp );
  25. #endif
  26.  
  27. #include <stdarg.h>
  28.  
  29. #if    DOALLOC
  30. #undef    calloc
  31. #undef    malloc
  32. #undef    realloc
  33. #undef    free
  34. #endif    /* DOALLOC */
  35.  
  36. static const char *bad_form;
  37.  
  38. void
  39. Trace(const char *fmt, ...)
  40. {
  41.     static    FILE    *fp;
  42.     va_list ap;
  43.  
  44.     if (!fp)
  45.         fp = fopen("Trace.out", "w");
  46.     if (!fp)
  47.         abort();
  48.  
  49.     va_start(ap,fmt);
  50.     if (fmt != bad_form) {
  51.         vfprintf(fp, fmt, ap);
  52.         va_end(ap);
  53.         (void)fflush(fp);
  54.     } else {
  55.         (void)fclose(fp);
  56.         (void)fflush(stdout);
  57.         (void)fflush(stderr);
  58.     }
  59. }
  60.  
  61. char *
  62. tb_visible(TBUFF *p)
  63. {
  64.     static char *result;
  65.     size_t j, k = 0;
  66.  
  67.     if (result != 0)
  68.         free(result);
  69.     result = malloc(tb_length(p)*4 + 1);
  70.  
  71.     for (j = 0; j < tb_length(p); j++) {
  72.         int c = tb_values(p)[j] & 0xff;
  73.         if (isprint(c)) {
  74.             result[k++] = c;
  75.         } else {
  76.             if (c >= 128)
  77.                 sprintf(result+k, "\\%03o", c);
  78.             else if (c == 127)
  79.                 strcpy(result+k, "^?");
  80.             else
  81.                 sprintf(result+k, "^%c", c | '@');
  82.             k = strlen(result);
  83.         }
  84.     }
  85.     result[k] = 0;
  86.     return result;
  87. }
  88.  
  89. #define    SECS(tv)    (tv.tv_sec + (tv.tv_usec / 1.0e6))
  90.  
  91. void
  92. Elapsed(char *msg)
  93. {
  94. #if SYS_UNIX
  95.     struct    timeval        tv1;
  96.     struct    timezone    tz1;
  97.     static    struct    timeval    tv0;
  98.     static    int    init;
  99.     gettimeofday(&tv1, &tz1);
  100.     if (!init++)
  101.         tv0 = tv1;
  102.     Trace("%10.3f %s\n", SECS(tv1) - SECS(tv0), msg);
  103.     tv0 = tv1;
  104. #endif
  105. }
  106.  
  107. #ifdef    apollo
  108. static int
  109. contains(char *ref, char *tst)
  110. {
  111.     size_t    len    = strlen(ref);
  112.     while (*tst) {
  113.         if (!strncmp(ref,tst++,len))
  114.             return TRUE;
  115.     }
  116.     return FALSE;
  117. }
  118. #endif    /* apollo */
  119.  
  120. void
  121. WalkBack(void)
  122. {
  123. #ifdef    apollo
  124.     static    char    *first    = "\"WalkBack\"",
  125.             *last    = "\"unix_$main\"";
  126.     auto    FILE    *pp;
  127.     auto    char    bfr[BUFSIZ];
  128.     auto    int    ok    = FALSE;
  129.     static    int    count;
  130.  
  131.     Trace("%s %d\n", first, ++count);
  132.     sprintf(bfr, "/com/tb %d", getpid());
  133.     if (!(pp = popen(bfr, "r")))
  134.         perror(bfr);
  135.  
  136.     while (fgets(bfr, sizeof(bfr), pp)) {
  137.         if (ok && contains(last, bfr))
  138.             break;
  139.         else if (contains(first, bfr))
  140.             ok = TRUE;
  141.         else if (ok)
  142.             Trace("%s", bfr);
  143.     }
  144.     (void)fclose(pp);
  145. #endif    /* apollo */
  146. }
  147.  
  148. static    int    count_alloc,
  149.         count_freed;
  150.  
  151. void
  152. fail_alloc(char *msg, char *ptr)
  153. {
  154.     Trace("%s: %p\n", msg, ptr);
  155.     Trace("allocs %d, frees %d\n", count_alloc, count_freed);
  156.     WalkBack();
  157. #if NO_LEAKS
  158.     show_alloc();
  159. #endif
  160.     Trace(bad_form);
  161.     abort();
  162. }
  163.  
  164. #if    DOALLOC
  165. typedef    struct    {
  166.     long    size;    /* ...its size */
  167.     char    *text;    /* the actual segment */
  168.     int    note;    /* ...last value of 'count_alloc' */
  169.     } AREA;
  170.  
  171. static    AREA    *area;
  172.  
  173. static    long    maxAllocated,    /* maximum # of bytes allocated */
  174.         nowAllocated;    /* current # of bytes allocated */
  175. static    int    nowPending,    /* current end of 'area[]' table */
  176.         maxPending;    /* maximum # of segments allocated */
  177.  
  178. static void
  179. InitArea(void)
  180. {
  181.     if (area == 0) {
  182.         area = (AREA *)calloc(DOALLOC,sizeof(AREA));
  183.         if (area == 0)
  184.             abort();
  185.         Trace("Initialized doalloc (%d * %d) = %ld\n",
  186.             DOALLOC,
  187.             sizeof(AREA),
  188.             (long)sizeof(AREA) * (long)DOALLOC);
  189.     }
  190. }
  191.  
  192. static int
  193. FindArea(char *ptr)
  194. {
  195.     register int j;
  196.  
  197.     InitArea();
  198.     for (j = 0; j < DOALLOC; j++)
  199.         if (area[j].text == ptr) {
  200.             if (j >= nowPending) {
  201.                 nowPending = j+1;
  202.                 if (nowPending > maxPending)
  203.                     maxPending = nowPending;
  204.             }
  205.             return j;
  206.         }
  207.     return -1;
  208. }
  209.  
  210. static int
  211. record_freed(char *ptr)
  212. {
  213.     register int j;
  214.  
  215.     if ((j = FindArea(ptr)) >= 0) {
  216.         nowAllocated -= area[j].size;
  217.         area[j].size = 0;
  218.         area[j].text = 0;
  219.         area[j].note = count_freed;
  220.         if ((j+1) == nowPending) {
  221.             register int    k;
  222.             for (k = j; (k >= 0) && !area[k].size; k--)
  223.                 nowPending = k;
  224.         }
  225.     }
  226.     return j;
  227. }
  228.  
  229. static int
  230. record_alloc(char *newp, char *oldp, unsigned len)
  231. {
  232.     register int    j;
  233.  
  234.     if (newp == oldp) {
  235.         if ((j = FindArea(oldp)) >= 0) {
  236.             nowAllocated -= area[j].size;
  237.             area[j].size = len;
  238.             area[j].note = count_alloc;
  239.         } else
  240.             fail_alloc("could not find", oldp);
  241.     } else {
  242.         if (oldp != 0)
  243.             record_freed(oldp);
  244.         if ((j = FindArea((char *)0)) >= 0) {
  245.             area[j].text = newp;
  246.             area[j].size = len;
  247.             area[j].note = count_alloc;
  248.         } else
  249.             fail_alloc("no room in table", newp);
  250.     }
  251.  
  252.     nowAllocated += len;
  253.     if (nowAllocated > maxAllocated)
  254.         maxAllocated = nowAllocated;
  255.     return len;
  256. }
  257.  
  258. #define    OK_ALLOC(p,q,n)    ((p != 0) && (record_alloc(p,q,n) >= 0))
  259. #define    OK_FREE(p)    ((p != 0) && (record_freed(p) >= 0))
  260. #else
  261. #define    OK_ALLOC(p,q,n)    (p != 0)
  262. #define    OK_FREE(p)    (p != 0)
  263. #endif    /* DOALLOC */
  264.  
  265. #ifdef    DEBUG2
  266. #define    LOG_PTR(msg,num)    Trace("%s %p\n", msg, num);
  267. #define    LOG_LEN(msg,num)    Trace("%s %d\n", msg, num);
  268. #else
  269. #define LOG_PTR(msg,num)
  270. #define    LOG_LEN(msg,num)
  271. #endif
  272.  
  273. /************************************************************************
  274.  *    public entrypoints                        *
  275.  ************************************************************************/
  276. #if DOALLOC
  277. char *
  278. doalloc (char *oldp, unsigned amount)
  279. {
  280.     register char    *newp;
  281.  
  282.     count_alloc += (oldp == 0);
  283.     LOG_LEN("allocate", amount)
  284.     LOG_PTR("  old = ", oldp)
  285.  
  286.     newp = (oldp != 0) ? realloc(oldp, amount) : malloc(amount);
  287.     if (!OK_ALLOC(newp,oldp,amount)) {
  288.         perror("doalloc");
  289.         fail_alloc("doalloc", oldp);
  290.         /*NOT REACHED*/
  291.     }
  292.  
  293.     LOG_PTR("  new = ", newp)
  294.     return (newp);
  295. }
  296.  
  297. char *
  298. do_calloc (unsigned nmemb, unsigned size)
  299. {
  300.     unsigned len = nmemb * size;
  301.     char    *result = doalloc((char *)0, len);
  302.     memset(result, 0, len);
  303.     return result;
  304. }
  305.  
  306. /*
  307.  * Entrypoint so we can validate pointers
  308.  */
  309. void
  310. dofree(void *oldp)
  311. {
  312.     count_freed++;
  313.     LOG_PTR("dealloc ", oldp)
  314.  
  315.     if (OK_FREE(oldp)) {
  316.         free(oldp);
  317.         return;
  318.     }
  319.  
  320.     fail_alloc("free (not found)", oldp);
  321. }
  322.  
  323. /*
  324.  * Write over the area if it is valid.
  325.  */
  326. void
  327. dopoison(void *oldp, long len)
  328. {
  329.     int j;
  330.  
  331.     if ((j = FindArea(oldp)) >= 0) {
  332.         if (area[j].size >= len)
  333.             (void)memset((char *)oldp, 0xdf, len);
  334.         else
  335.             fail_alloc("incorrect length", oldp);
  336.     } else {
  337.         fail_alloc("cannot find to poison", oldp);
  338.     }
  339. }
  340. #endif
  341.  
  342. #ifndef show_alloc
  343. void
  344. show_alloc(void)
  345. {
  346. #if    DOALLOC
  347.     static    char    *fmt = ".. %-24.24s %10ld\n";
  348.  
  349.     printf("show_alloc\n"); /* patch */
  350.     Trace("** allocator metrics:\n");
  351.     Trace(fmt, "allocs:", count_alloc);
  352.     Trace(fmt, "frees:",  count_freed);
  353.     {
  354.         register int    j, count = 0;
  355.         register long    total    = 0;
  356.  
  357.         for (j = 0; j < nowPending; j++) {
  358.             if (area[j].text) {
  359.                 if (count++ < 10)
  360.                     Trace("...%5d) %5ld bytes in alloc #%-5d @%p\n",
  361.                         j,
  362.                         area[j].size,
  363.                         area[j].note,
  364.                         area[j].text);
  365.                 total += area[j].size;
  366.             }
  367.         }
  368.         Trace(fmt, "total bytes allocated:",   total);
  369.         Trace(fmt, "current bytes allocated:", nowAllocated);
  370.         Trace(fmt, "maximum bytes allocated:", maxAllocated);
  371.         Trace(fmt, "segment-table length:",    nowPending);
  372.         Trace(fmt, "current # of segments:",   (long)count);
  373.         Trace(fmt, "maximum # of segments:",   maxPending);
  374.     }
  375. #endif
  376. }
  377. #endif    /* show_alloc */
  378.