Category : Files from Magazines
Archive   : CGAZV4N2.ZIP
Filename : ANASTACK.C

 
Output of file : ANASTACK.C contained in archive : CGAZV4N2.ZIP
#include

/******************************************************************
* Module: anastack.c
* Author: John Rex
* Compiler: MSC 5.1, TurboC 2.0
* Memory model: any
* Purpose: analyze and report on stack usage
*
* Usage: For use with MSC 5.1, getsp.asm must be assembled
* and linked in. Then,
*
* void start_anastack(), report_anastack();
*
* .. at beginning of code, in main():
* start_anastack();
*
* .. then, whenever desired:
* report_anastack("message");
*
* The first routine initializes some data areas and writes a unique byte
* into the stack area. The second routine then reports on this, labeling
* the report with the string passed to it.
*
* Compile switches:
* DEBUG - if == 1, compile a test driver
*
* Sources: This code was derived from study of the Turbo C and Microsoft
* C run-time libraries and startup code.
*
* Source code may be used freely if authorship is acknowledged.
* Object code may be used freely.
*************************************************************************/

#if defined(__TURBOC__)
#define TURBO
#if defined(__SMALL__) || defined(__MEDIUM__) || defined(__TINY__)
#define TURBOSMALL
#else
#define TURBOLARGE
#endif
#else
#define MSC
#endif

#define DEBUG 1

/* define our own pointer manipulation macros */
#define FP_OFF(x) ( (unsigned) x)
#define FP_SEG(x) ( (unsigned) ( ((long) x) >> 16) )
#define MK_FP(seg,off) ((char far *) ( (((long) seg) << 16) + off) )

/* the pattern we use in the stack */
#define PATTERN (char) 0xEF

#if defined(TURBO)
extern unsigned _stklen; /* stack length */

#else /* Microsoft C */
extern int end; /* the marker that locates the bottom of the stack */
unsigned getsp(); /* returns current value of SP, the stack pointer */
#endif

/* storage for stack's description */
static char far *stack_bottom;
static char far *stack_top;

/* initialize stack area */
void start_anastack()
{
char far *ptr;

#if defined(TURBO)

# if defined(TURBOSMALL)
extern char far *_heapbase; /* Points to beginning of the far heap.
* This location marks the true top of
* the stack.
*/
long bottom, ss_normal; /* for pointer conversions */

bottom = FP_SEG(_heapbase); /* true top of stack */
bottom <<= 4;
bottom -= _stklen; /* true bottom of stack */

/* now normalize bottom of stack to be SS relative */
ss_normal = ((long)_SS) << 4;
bottom -= ss_normal;
stack_bottom = MK_FP(_SS, ((unsigned) bottom) );

# else /* Turbo C Compact, Large, or Huge models */
stack_bottom = MK_FP(_SS,0); /* This is the simplest case, since in
* these models the stack has its own
* segment.
*/
# endif

stack_top = MK_FP(_SS, _SP); /* Top of usable stack */

#else /* Microsoft C */
stack_bottom = (char far *) &end; /* end is created by linker
at the bottom of the stack */
stack_top = MK_FP(FP_SEG(stack_bottom), getsp());
#endif

/* overwrite free stack area */
for (ptr = stack_bottom; ptr != stack_top; ptr++)
*ptr = PATTERN;
}

/* report on stack usage */
void report_anastack(char *message)
{
unsigned size, used, now_using;
char far *been_to, far *now_at;
int i=0;

/* compute a few things ... */

/* ... size of stack */
#if defined(TURBO)

# if defined(TURBOSMALL)
/* small/medium models--malloc() may actually steal some of the
* stack's area - must watch for this.
*/
extern unsigned __brklvl;

size = FP_OFF(stack_top) - __brklvl;
if (size > _stklen)
size = _stklen;

if (__brklvl > FP_OFF(stack_bottom))
/* malloc() has encroached on stack--must reset stack bottom */
stack_bottom = MK_FP(_SS, __brklvl);

# else
size = _stklen;
# endif

#else /* Microsoft C */
size = FP_OFF(stack_top) - FP_OFF(stack_bottom);
#endif

/* ... amount of stack used so far */
for (been_to = stack_bottom;
(*been_to == PATTERN) && (been_to != stack_top); been_to++, i++);
used = FP_OFF(stack_top) - FP_OFF(been_to);

/* ... where we are now */
#if defined(TURBO)
now_at = MK_FP(_SS, _SP);
#else
now_at = MK_FP(FP_SEG(stack_bottom), getsp());
#endif
now_using = FP_OFF(stack_top) - FP_OFF(now_at);

/* now print report */
printf("report_anastack(): %s\n", message);

printf(" The stack contains %u bytes and extends from %Fp to %Fp\n",
size, stack_bottom, stack_top);

printf(" The stack pointer is now at %Fp, using %u bytes (%d%%)\n",
now_at, now_using, (int) (100L * now_using / size));

printf(" The stack has been as low as %Fp, using %u bytes (%d%%)\n\n",
been_to, used, (int) (100L * used / size));
}

#pragma page()
#if DEBUG==1

#include
#include

#if defined(TURBOSMALL)
char *mode;

/* a routine to use up the heap */
void tell_more()
{
extern unsigned __brklvl;
char *ptr;
int count;

printf("tell_more:\n");
printf(" __brklvl is %x\n",__brklvl);

count = 0;
while((ptr = malloc(1024)) != NULL) {
memset(ptr,'w',1024);
count++;
}

printf(" Able to allocate %d blocks of 1024 bytes\n", count);
printf(" __brklvl is %x\n\n",__brklvl);
}
#endif

/* a routine to use the stack */
void recurse(int i)
{
if (i == 0) {
report_anastack("recurse() called with zero");

#if defined(TURBOSMALL)
if (strchr(mode, 'r') != NULL)
tell_more();
#endif

}
else
recurse(i-1);
}

/*
* test driver to demonstrate behavior of stack. Usage:
*
* I. Microsoft C (all models)
* Turbo C (Compact, Large, Huge)
*
* Just invoke the .exe file. No command line options.
*
* II. Turbo C (Tiny, Small, Medium)
*
* anastack command
*
* where command may be
* (1) Empty (i.e., no string)
* or (2) A string containing any or all of the chars "ser".
* This string controls calls to tell_more, a routine that
* allocates 1024 byte blocks on the heap until there is no
* more room. The letters mean:
* 's' => call tell_more at start of main()
* 'e' => call tell_more at end of main()
* 'r' => call tell_more at bottom of recursive descent
* See the text for a discussion of what this demonstrates.
*/

void main(int argc, char **argv)
{
#if defined(TURBOSMALL)
mode = argv[1]; /* controls use of tell_more */
#endif

start_anastack();

#if defined(TURBOSMALL)
if (strchr(mode, 's') != NULL)
tell_more();
#endif

report_anastack("beginning of main()");
report_anastack("second call in a row to report_anastack()");

recurse(200);

#if defined(TURBOSMALL)
if (strchr(mode, 'e') != NULL)
tell_more();
#endif

report_anastack("at end of main()");
}
#endif


  3 Responses to “Category : Files from Magazines
Archive   : CGAZV4N2.ZIP
Filename : ANASTACK.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/