home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / dos / memory / heapdbg / heap.dbg < prev    next >
Encoding:
Text File  |  1994-06-12  |  20.3 KB  |  667 lines

  1. /*********************************HEAP.H*****************************************/
  2.  
  3. #define malloc(size) my_malloc(__FILE__,__LINE__,(size))
  4. #define calloc(nitems,size) my_calloc(__FILE__,__LINE__,(nitems),(size))
  5. #define free(block)  my_free(__FILE__,__LINE__,(block))
  6.  
  7. void *my_malloc(char *file_name,unsigned int line_number,size_t size);
  8. void *my_calloc(char *file_name,unsigned int line_number,size_t nitems,size_t size);
  9. void my_free(char *file_name,unsigned int line_number, void *block);
  10.  
  11. /* Prototypes from SCREEN.C  */
  12.  
  13. void draw_boxes_and_titles(char *labels[],int row_count);
  14. void screenputc(int row,int col,char c);
  15. void screenputf(int row,int col,char *format,...);
  16. void screenputs(int row,int col,char *string);
  17. void screenclearline(int row);
  18. void initialize_screen(char *labels[],int widths[]);
  19. void setup_screen(char *labels[],int widths[],int rows);
  20. void restore_screen(void);
  21.  
  22. /* Prototypes from HEAP.C */
  23.  
  24. void screen_message(int immediate_return, int tag, char *format,...);
  25. void hide_screen(void);
  26. void my_free(char *file_name,unsigned int line_number, void *block);
  27. void *my_malloc(char *file_name,unsigned int line_number,size_t size);
  28. void initialize_tags(void);
  29. void display_tag_table(int last_tag);
  30. void add_tag_to_table(char far *pointer,char maverick,size_t size,char *file_name,unsigned int line_number);
  31. void delete_tag_from_table(int tag);
  32. void verify_heap(void);
  33. void heap_walk(void);
  34. *********************************HEAP.C*****************************************
  35.  
  36. /*
  37.  * Author:       Mark Nelson
  38.  *
  39.  * Date:         October 28, 1989
  40.  *
  41.  * Description:  This module contains the replacement routines used
  42.  *               to debug heap problems.  The routines are used in
  43.  *               conjunction with the HEAP.H header file.
  44.  */
  45. #include <stdio.h>
  46. #include <stdlib.h>
  47. #include <stdarg.h>
  48. #include <malloc.h>
  49. #include <conio.h>
  50. #include "_heap.h"
  51.  
  52. /*
  53.  * This structure defines all the fields that I use in the tag
  54.  * table database.
  55.  */
  56. #define TAG_MAX 100
  57.  
  58. struct tags {
  59.                 char far * returned_address;
  60.                 char far * real_address;
  61.                 size_t size;
  62.                 char *file_name;
  63.                 unsigned int line_number;
  64.                 char maverick;
  65.                 char tagged;
  66.             } tag_table[TAG_MAX];
  67.  
  68. int next_free_tag = -1;
  69.  
  70.  
  71. /*
  72.  * These are some odds and ends I use all around.
  73.  */
  74. char leading_picket[] = "0123456789ABCDE";
  75. char trailing_picket[] = "FEDCBA987654321";
  76. #define PICKET_SIZE sizeof( leading_picket )
  77.  
  78.  
  79. /*
  80.  * These are the labels and widths for each of the columns in the output
  81.  * screen.
  82.  */
  83. char *labels[]={"Tag #","File Name","Line #","Picket","Address","Size","Picket",""};
  84. int widths[]={5,12,6,15,9,6,15};
  85. extern int columns[];
  86. int screen_up=0;
  87. int message_line;
  88.  
  89.  
  90. /*
  91.  * This is the my_malloc routine that replaces malloc().  Before it does
  92.  * anything else, it performs the heap checkout stuff.  This will pop up
  93.  * a message if anything funny is detected.  It then gets the pointer
  94.  * for the caller, and adds it to the tag table.  The screen is then
  95.  * cleared up, and the pointer is returned.
  96.  */
  97.  
  98. void *my_malloc(char *file_name,unsigned int line_number,size_t size)
  99. {
  100.   void *malloc_pointer;
  101.   size_t real_size;
  102.  
  103.   verify_heap();
  104.   real_size = size + PICKET_SIZE*2;
  105.   malloc_pointer = malloc( real_size );
  106.   if ( malloc_pointer == NULL ) {
  107.     screen_message( 1, 0, "File: %s Line: %u requesting %u bytes",
  108.                     file_name, line_number, size );
  109.     screen_message( 0, 0, "Malloc failed! Null pointer will be returned." );
  110.   }
  111.   else
  112.     add_tag_to_table( malloc_pointer, 0, size, file_name, line_number );
  113.   hide_screen();
  114.   return( ( char * ) malloc_pointer + PICKET_SIZE );
  115. }
  116.  
  117.  
  118. /*
  119.  * my_free is set up to replace free().  Just like my_malloc(), it first
  120.  * checks out the heap and prints a message if anything funny shows up.
  121.  * Before I try to free the block, I have to check and see if it is in
  122.  * my tag table.  If it is, I free the real pointer, not the one I passed
  123.  * back to the caller.  If it isn't in the tag table, I print a message
  124.  * out to that effect, and return.
  125.  */
  126.  
  127. void my_free( char *file_name, unsigned int line_number, void *block )
  128. {
  129.   int tag;
  130.  
  131.   verify_heap();
  132.   for ( tag = 0; tag < TAG_MAX ; tag++ ) {
  133.     if ( tag_table[ tag ].returned_address == ( void far * ) block )
  134.       break;
  135.   }
  136.   if ( tag < TAG_MAX ) {
  137.     if ( tag_table[ tag ].maverick ) {
  138.         screen_message( 1, 0, "File: %s Line: %u freeing block %Fp",
  139.                         file_name, line_number, ( void far * ) block );
  140.         screen_message( 0, 0, "Tag is a maverick entry!" );
  141.         free( block );
  142.     }
  143.     else
  144.         free( ( char * ) block - PICKET_SIZE );
  145.     delete_tag_from_table( tag );
  146.   }
  147.   else {
  148.     screen_message( 1, 0, "File: %s Line: %u freeing block %Fp",
  149.                     file_name, line_number, ( void far * ) block );
  150.     screen_message( 0, 0, "Tag was not found in tag table!  Going to try and free() it." );
  151.     free( block );
  152.     screen_message( 0, 0, "Heap after freeing anonymous block!" );
  153.   }
  154.   hide_screen();
  155. }
  156.  
  157.  
  158. /*
  159.  * I need to initialize the tag table my first time through.  This
  160.  * routine gets called all the time, but only performs the initialization
  161.  * once, when next_free_tag is -1.
  162.  */
  163.  
  164. void initialize_tags()
  165. {
  166.   int i;
  167.  
  168.   if ( next_free_tag == -1 ) {
  169.     next_free_tag = 0;
  170.     for ( i = 0 ; i < TAG_MAX ; i++ ) {
  171.       tag_table[ i ].returned_address = NULL;
  172.       tag_table[ i ].file_name = "Not in use";
  173.       tag_table[ i ].line_number = 0;
  174.       tag_table[ i ].size = 0;
  175.     }
  176.   }
  177. }
  178.  
  179.  
  180. /*
  181.  * This is the routine called to display the tag table when something
  182.  * has gone wrong.  It sits in a loop displaying tag table entries, 15
  183.  * at a time.  The user can hit the 'u' or 'd' keys to move up or down
  184.  * in the table.  Any other key breaks the user out.
  185.  */
  186.  
  187. void display_tag_table( int last_tag )
  188. {
  189.   int first_tag;
  190.   int offset;
  191.   int tag;
  192.   char far *picket_pointer;
  193.   int key;
  194.  
  195.   if ( last_tag < 16 )
  196.     first_tag = 0;
  197.   else
  198.     first_tag = last_tag - 15;
  199.  
  200.     for ( ; ; ) {
  201.     for ( offset = 0 ; offset < 15 ; offset++ ) {
  202.       tag = first_tag + offset;
  203.       screenputf( offset + 3, columns[ 0 ] + 1, "%-3d", tag );
  204.       screenputf( offset + 3, columns[ 1 ] + 1, "%-12s",
  205.                   tag_table[ tag ].file_name );
  206.       screenputf( offset + 3, columns[ 2 ] + 1, "%-5d",
  207.                   tag_table[ tag ].line_number );
  208.       if ( tag_table[ tag ].returned_address != NULL ) {
  209.         picket_pointer = tag_table[ tag ].returned_address;
  210.         picket_pointer -= PICKET_SIZE ;
  211.         if ( tag_table[ tag ].maverick )
  212.           screenputf( offset + 3, columns[ 3 ] + 1,"%15s", "***MAVERICK***" );
  213.         else
  214.           screenputf( offset + 3, columns[ 3 ] + 1, "%15s", picket_pointer );
  215.         screenputf( offset + 3, columns[ 4 ] + 1, "%Fp",
  216.                     tag_table[ tag ].returned_address );
  217.         picket_pointer += PICKET_SIZE;
  218.         picket_pointer += tag_table[ tag ].size;
  219.         if ( tag_table[ tag ].maverick )
  220.           screenputf( offset + 3, columns[ 6 ] + 1, "%15s", "***MAVERICK***" );
  221.         else
  222.           screenputf( offset + 3, columns[ 6 ] + 1, "%15s", picket_pointer );
  223.       }
  224.       else {
  225.         screenputf( offset + 3, columns[ 3 ] + 1, "%15s", "" );
  226.         screenputf( offset + 3, columns[ 4 ] + 1, "  NULL   " );
  227.         screenputf( offset + 3, columns[ 6 ] + 1, "%15s", "" );
  228.       }
  229.       screenputf( offset + 3, columns[ 5 ] + 1, "%-5d", tag_table[ tag ].size );
  230.     }
  231.     key = getch();
  232.     if ( key == 'u' || key == 'U' ) {
  233.         first_tag -= 15;
  234.         if (first_tag < 0)
  235.           first_tag = 0;
  236.     }
  237.     else if ( key == 'd' || key == 'D' ) {
  238.       first_tag += 15;
  239.       if ( ( first_tag + 15 ) >= TAG_MAX )
  240.         first_tag = TAG_MAX - 15;
  241.     }
  242.     else
  243.       break;
  244.   }
  245. }
  246.  
  247.  
  248. /*
  249.  * This routine is called when a new pointer needs to be added to the tag
  250.  * table.  It can be a maverick pointer or a regular pointer.
  251.  */
  252.  
  253. void add_tag_to_table( char far *pointer,
  254.                        char maverick,
  255.                        size_t size,
  256.                        char *file_name,
  257.                        unsigned int line_number )
  258. {
  259.   int i;
  260.  
  261.   if ( next_free_tag >= TAG_MAX )
  262.     return;
  263.   tag_table[ next_free_tag ].returned_address = pointer;
  264.   tag_table[ next_free_tag ].real_address = pointer;
  265.   tag_table[ next_free_tag ].size = size;
  266.   tag_table[ next_free_tag ].file_name = file_name;
  267.   tag_table[ next_free_tag ].line_number = line_number;
  268.   tag_table[ next_free_tag ].maverick = maverick;
  269.   if ( !maverick ) {
  270.     for ( i = 0 ; i < PICKET_SIZE ; i++ )
  271.       pointer[ i ] = leading_picket[ i ];
  272.     pointer += size;
  273.     pointer += PICKET_SIZE ;
  274.     for ( i = 0 ; i < PICKET_SIZE ; i++ )
  275.       pointer[ i ] = trailing_picket[ i ];
  276.     tag_table[ next_free_tag ].returned_address += PICKET_SIZE;
  277.   }
  278.   next_free_tag++;
  279. }
  280.  
  281.  
  282. /*
  283.  * This routine is called when a tag needs to be deleted from the table.  This
  284.  * can happen when a call to free() is made, or when a heapwalk shows that
  285.  * one of the pointers is missing.
  286.  */
  287.  
  288. void delete_tag_from_table( int tag )
  289. {
  290.   int i;
  291.  
  292.   next_free_tag--;
  293.   for ( i = tag ; i < next_free_tag ; i++ )
  294.     tag_table[ i ] = tag_table[ i + 1 ];
  295.   tag_table[ i ].returned_address = NULL;
  296.   tag_table[ i ].file_name = "Not in use";
  297.   tag_table[ i ].line_number = 0;
  298.   tag_table[ i ].size = 0;
  299. }
  300.  
  301.  
  302. /*
  303.  *  This is the verify routine that is called on the entry to my_malloc()
  304.  *  or my_free().  It calls the heap_walk() routine first, to let it do
  305.  *  its check out of the heap.  It then goes through the entire tag table
  306.  *  and verifies that the pickets are all intact.
  307.  */
  308.  
  309. void verify_heap()
  310. {
  311.   int i;
  312.   int tag;
  313.   char far *picket_pointer;
  314.  
  315.   initialize_tags();
  316.   heap_walk();
  317.   for ( tag = 0 ; tag < next_free_tag ; tag++ ) {
  318.     if ( tag_table[ tag ].maverick )
  319.       continue;
  320.     picket_pointer = tag_table[ tag ].returned_address;
  321.     picket_pointer -= PICKET_SIZE ;
  322.     for ( i = 0 ; i < PICKET_SIZE ; i++ )
  323.       if ( picket_pointer[ i ] != leading_picket[ i ] ) {
  324.         screen_message( 0, i, "Error in leading picket, tag %3d", tag );
  325.         break;
  326.       }
  327.     picket_pointer += PICKET_SIZE ;
  328.     picket_pointer += tag_table[tag].size;
  329.     for ( i = 0 ; i < PICKET_SIZE ; i++ )
  330.       if ( picket_pointer[ i ] != trailing_picket[ i ] ) {
  331.         screen_message( 0, tag, "Error in trailing picket, tag %3d", tag );
  332.         break;
  333.       }
  334.   }
  335. }
  336.  
  337. /*
  338.  * This is the routine that walks through the heap.  If an heap entry
  339.  * is not found in the tag table, a message is printed, and it is added
  340.  * as a maverick.  Otherwise, the tag is noted.  After walking through
  341.  * the whole heap, a check is done to see if any of our tagged entries
  342.  * didn't show up, which generates another message.
  343.  *
  344.  * Remember that this code is MSC-specific.  You need to rewrite this
  345.  * routine for every different compiler.
  346.  */
  347.  
  348. void heap_walk()
  349. {
  350.   struct _heapinfo hinfo;
  351.   int heapstatus;
  352.   size_t size;
  353.   int i;
  354.  
  355.   hinfo._pentry = NULL;
  356.  
  357.   for ( i = 0 ; i < next_free_tag ; i++ )
  358.     tag_table[ i ].tagged = 0;
  359.  
  360.   for ( ; ; ) {
  361.     heapstatus = _heapwalk( &hinfo );
  362.     if ( heapstatus == _HEAPEMPTY )
  363.       break;
  364.     if ( heapstatus == _HEAPEND )
  365.       break;
  366.     if ( heapstatus != _HEAPOK ) {
  367.       screen_message( 0, 0, "Heap is corrupted! Going to exit." );
  368.       exit( 1 );
  369.     }
  370.     if ( hinfo._useflag != _USEDENTRY )
  371.       continue;
  372.     for ( i = 0 ; i < next_free_tag ; i++ ) {
  373.       if ( (int far *) tag_table[ i ].real_address == hinfo._pentry ) {
  374.         tag_table[ i ].tagged = 1;
  375.         break;
  376.       }
  377.     }
  378.     if ( i == next_free_tag ) {
  379.       size = hinfo._size;
  380.       if ( i < TAG_MAX )
  381.         tag_table[ i ].tagged = 1;
  382.       add_tag_to_table( (char far *) hinfo._pentry, 1, size, "MAVERICK",0 );
  383.       screen_message( 0, i, "Found a maverick heap entry: %Fp", hinfo._pentry );
  384.     }
  385.   }
  386. /*
  387.  * At this point every entry should have been tagged, so I can go through
  388.  * the table and look for ones that didn't get tagged.
  389.  */
  390.   for ( i = 0 ; i < next_free_tag ; i++ ) {
  391.     if ( tag_table[ i ].tagged == 0 ) {
  392.       screen_message( 0, i, "Didn't find heap entry in heapwalk, tag %d", i );
  393.       delete_tag_from_table( i );
  394.     }
  395.   }
  396. }
  397.  
  398.  
  399. /*
  400.  * During the process of checking out the heap, if I see anything worthy
  401.  * of a message, I call this routine.  If the screen is not already up,
  402.  * this guy pulls it up.  Then it prints the message.
  403.  */
  404.  
  405. void screen_message( int immediate_return, int tag, char *format, ... )
  406. {
  407.   char message[ 81 ];
  408.   va_list args;
  409.  
  410.   if ( screen_up == 0 ) {
  411.     screen_up = 1;
  412.     message_line = 20;
  413.     setup_screen( labels, widths, 15 );
  414.   }
  415.   va_start( args, format );
  416.   vsprintf( message, format, args );
  417.   screenputs( message_line, 0, message );
  418.   if ( ++message_line >= 25 )
  419.     message_line = 20;
  420.   if ( !immediate_return )
  421.     display_tag_table( tag );
  422. }
  423.  
  424. /*
  425.  * After all the work is done, I have to hide my heap screen so the user
  426.  * can see the application output.  This is pretty easy to do, a routine
  427.  * in SCREEN.C does the whole job for me.
  428.  */
  429. void hide_screen()
  430. {
  431.   if ( screen_up != 0 ) {
  432.     screen_up = 0;
  433.     restore_screen();
  434.   }
  435. }
  436.  
  437.  
  438.  
  439. *********************************SCREEN.C***************************************
  440.  
  441. /*
  442.  * Author:       Mark Nelson
  443.  *
  444.  * Date:         October 28, 1989
  445.  *
  446.  * Description:  This module contains the screen I/O routines used in
  447.  *               the heap debugger module.  These are very simplified
  448.  *               screen I/O routines.
  449.  */
  450.  
  451. #include <stdio.h>
  452. #include <stdarg.h>
  453. #include <string.h>
  454. #include "_heap.h"
  455. /*
  456.  * These are all the line drawing constants defined.
  457.  */
  458. #define UL_CORNER       218
  459. #define UR_CORNER       191
  460. #define LL_CORNER       192
  461. #define LR_CORNER       217
  462. #define UPPER_TEE       194
  463. #define LOWER_TEE       193
  464. #define LEFT_TEE        195
  465. #define RIGHT_TEE       180
  466. #define CENTER_TEE      197
  467. #define HORIZONTAL_LINE 196
  468. #define VERTICAL_LINE   179
  469.  
  470. /*
  471.  * I create a structure so I can write directly to screen as if it were
  472.  * a big array.  That way the compiler takes care of computing the
  473.  * addresses, all I have to do is insert the row and column.
  474.  */
  475. struct video_element {
  476.                           unsigned char character;
  477.                           unsigned char attribute;
  478.                      };
  479. struct video_element (far *physical_screen)[25][80];
  480. struct video_element saved_screen[25][80];
  481.  
  482. /*
  483.  * This routine draws the box I use up on the screen.  It is passed a
  484.  * list of labels to draw at the head of the columns, plus a count
  485.  * of how many rows are to be left open for data entry.  It depends
  486.  * on some earlier code somewhere to have initialized an array called
  487.  * columns[] that tells it where to draw each column on the screen.
  488.  * There is a lot of code here to draw the boxes, but it is all
  489.  * straightforward.
  490.  */
  491. int columns[10];
  492. int column_count=0;
  493.  
  494. void draw_boxes_and_titles(char *labels[],int row_count)
  495. {
  496. int col;
  497. int row;
  498. int i;
  499. int j;
  500. int rows[3];
  501. /*
  502.  * The three rows I define are the top and bottom of the box, plus the
  503.  * line that divides the title lines from the data lines.
  504.  */
  505.     rows[0]=0;
  506.     rows[1]=2;
  507.     rows[2]=3+row_count;
  508.     for (col=1;col<columns[column_count];col++)
  509.         for (i=0;i<3;i++)
  510.             (*physical_screen)[rows[i]][col].character = HORIZONTAL_LINE;
  511.     for (i=0;i<=column_count;i++)
  512.         for (row=0;row<(row_count+4);row++)
  513.             (*physical_screen)[row][columns[i]].character = VERTICAL_LINE;
  514.     (*physical_screen)[0][columns[0]].character = UL_CORNER;
  515.     (*physical_screen)[row_count+3][columns[0]].character = LL_CORNER;
  516.     (*physical_screen)[0][columns[column_count]].character = UR_CORNER;
  517.     (*physical_screen)[row_count+3][columns[column_count]].character = LR_CORNER;
  518.  
  519.     (*physical_screen)[rows[1]][columns[0]].character = LEFT_TEE;
  520.     (*physical_screen)[rows[1]][columns[column_count]].character = RIGHT_TEE;
  521.     for (j=1;j<column_count;j++)
  522.         (*physical_screen)[0][columns[j]].character = UPPER_TEE;
  523.     for (j=1;j<column_count;j++)
  524.         (*physical_screen)[row_count+3][columns[j]].character = LOWER_TEE;
  525.  
  526.     for (j=1;j<column_count;j++)
  527.         (*physical_screen)[rows[1]][columns[j]].character = CENTER_TEE;
  528. /*
  529.  * Here is where I draw the labels.  They need to go in the center of
  530.  * their little boxes.
  531.  */
  532.     for (i=0;i<column_count;i++)
  533.     {
  534.         col=columns[i]+1;
  535.         col += (columns[i+1]-columns[i]-1)/2;
  536.         col -= strlen(labels[i])/2;
  537.         screenputs(1,col,labels[i]);
  538.     }
  539. }
  540. /*
  541.  * This is a general purpose routine to print a formatted string on
  542.  * the screen.
  543.  */
  544. void screenputf(int row,int col,char *format,...)
  545. {
  546.     char buffer[81];
  547.     va_list args;
  548.  
  549.     va_start(args,format);
  550.     vsprintf(buffer,format,args);
  551.     screenputs(row,col,buffer);
  552. }
  553. /*
  554.  * This is a general purpose routine to put an unformatted string
  555.  * out to the screen.
  556.  */
  557. void screenputs(int row,int col,char *string)
  558. {
  559. char c;
  560.  
  561.     while (1)
  562.     {
  563.         c=*string++;
  564.         if (c=='\0')
  565.             break;
  566.         (*physical_screen)[row][col++].character=c;
  567.     }
  568. }
  569. /*
  570.  * This is a general purpose routine to clear a whole line on the
  571.  * screen.
  572.  */
  573. void screenclearline(int row)
  574. {
  575. int col;
  576.  
  577.     for (col=0;col<80;col++)
  578.         (*physical_screen)[row][col].character=' ';
  579. }
  580. /*
  581.  * This is the screen initialization code.  It is a trap door routine that
  582.  * gets called all the time, but only executes once.  It computes what
  583.  * columns the vertical lines are going to go in, based on the widths needed
  584.  * for each column, passed as a parameter.
  585.  * Note that if you are using a monochrome monitor, you need to change
  586.  * the screen pointer to be 0xb0000000L.
  587.  * This routine also initializes the tag table
  588.  */
  589. void initialize_screen(char *labels[],int widths[])
  590. {
  591. int row;
  592. int col;
  593. int i;
  594. static int first_time=0;
  595.  
  596.     if (first_time==0)
  597.     {
  598.         first_time=1;
  599.         columns[0]=1;
  600.         column_count=0;
  601.         while (strlen(labels[column_count]) != 0)
  602.         {
  603.             columns[column_count+1] = columns[column_count]+widths[column_count]+1;
  604.             column_count++;
  605.         }
  606.     }
  607.     physical_screen=(struct video_element (far *)[25][80])0xb8000000L;
  608.     for (row=0;row<25;row++)
  609.         for (col=0;col<80;col++)
  610.         {
  611.              saved_screen[row][col]=(*physical_screen)[row][col];
  612.              (*physical_screen)[row][col].character=' ';
  613.              (*physical_screen)[row][col].attribute=0x1b;
  614.         }
  615. }
  616.  
  617. /*
  618.  *  Whenever the heap routines decide they need to print a screen message,
  619.  *  they set up the screen first by calling this guy.
  620.  */
  621. void setup_screen(char *labels[],int widths[],int rows)
  622. {
  623.     initialize_screen(labels,widths);
  624.     draw_boxes_and_titles(labels,rows);
  625. }
  626.  
  627. /*
  628.  * After the heap routines are done printing debug information, they
  629.  * have to restore the screen back to where it was when they got called.
  630.  * This routine does that.
  631.  */
  632. void restore_screen()
  633. {
  634. int row;
  635. int col;
  636.  
  637.     for (row=0;row<25;row++)
  638.         for (col=0;col<80;col++)
  639.              (*physical_screen)[row][col]=saved_screen[row][col];
  640. }
  641.  
  642. *********************************_HEAP.H****************************************
  643.  
  644. /* Prototypes from SCREEN.C  */
  645.  
  646. void draw_boxes_and_titles(char *labels[],int row_count);
  647. void screenputc(int row,int col,char c);
  648. void screenputf(int row,int col,char *format,...);
  649. void screenputs(int row,int col,char *string);
  650. void screenclearline(int row);
  651. void initialize_screen(char *labels[],int widths[]);
  652. void setup_screen(char *labels[],int widths[],int rows);
  653. void restore_screen(void);
  654.  
  655. /* Prototypes from HEAP.C */
  656.  
  657. void screen_message(int immediate_return, int tag, char *format,...);
  658. void hide_screen(void);
  659. void my_free(char *file_name,unsigned int line_number, void *block);
  660. void *my_malloc(char *file_name,unsigned int line_number,size_t size);
  661. void initialize_tags(void);
  662. void display_tag_table(int last_tag);
  663. void add_tag_to_table(char far *pointer,char maverick,size_t size,char *file_name,unsigned int line_number);
  664. void delete_tag_from_table(int tag);
  665. void verify_heap(void);
  666. void heap_walk(void);
  667.