home *** CD-ROM | disk | FTP | other *** search
- /***************************************************************************
- * TESTUTIL.C *
- * MODULE: TESTUTIL *
- * OS: DOS *
- * VERSION: 1.0 *
- * DATE: 11/15/91 *
- * *
- * Copyright (c) 1991 James W. Birdsall. All Rights Reserved. *
- * *
- * Requires testutil.h to compile. *
- * Compiles under Borland C++ 2.0, TC 2.0, or MSC 6.00A. *
- * *
- * This file contains various utility functions used to fill and check *
- * blocks of memory and perform other basic services. Many are coded in *
- * in-line assembly language to improve speed. The in-line assembly is *
- * compatible with both Turbo/Borland C[++] and MSC 6.00A. If your *
- * compiler does not support in-line assembly, or your compiler requires *
- * an external assembler which you do not have, or you simply do not wish *
- * to use the in-line assembly code, the functions also contain C code *
- * versions. The C code versions are the default; in order to use the *
- * in-line assembly, you must define the symbol INLINE_ASM when *
- * compiling. *
- * *
- ***************************************************************************/
-
- /*
- ** system includes <>
- */
-
- #include <string.h>
- #include <dos.h>
-
-
- /*
- ** custom includes ""
- */
-
- #include "testutil.h"
-
-
- /*
- ** local #defines
- */
-
- /*
- ** misc: copyright strings, version macros, etc.
- */
-
- /*
- ** typedefs
- */
-
- /*
- ** global variables
- */
-
- /*
- ** static globals
- */
-
- /*
- ** function prototypes
- */
-
- /*
- ** functions
- */
-
- /***************************************************************************
- * FUNCTION: FARMEMCHECK *
- * *
- * DESCRIPTION: *
- * *
- * This function scans a block of memory looking for bytes which do *
- * not match checkchar. *
- * *
- * ENTRY: *
- * *
- * buffer - pointer to block of memory to scan *
- * len - length of block *
- * checkchar - value which should be matched *
- * *
- * EXIT: *
- * *
- * Returns 0 if all bytes match, nonzero if mismatch found. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- int farmemcheck(unsigned char far *buffer, unsigned int len,
- unsigned char checkchar)
- {
- int retval = 0;
- unsigned char huge *temp;
-
- /* normalize far pointer and turn into huge pointer */
- temp = normptr(buffer);
-
- #ifdef INLINE_ASM
- ASM push bx /* preserve registers */
- ASM push cx
- ASM push si
- ASM push ds
- ASM lds si, [temp] /* load pointer into DS:SI */
- ASM mov cx, [len] /* load length into CX */
- ASM mov bl, [checkchar] /* load match value into BX */
- looptop:
- ASM lodsb /* load next byte into AL */
- ASM cmp al, bl /* test against BL */
- ASM jne nomatch /* if not equal, exit loop */
- ASM loop looptop /* otherwise loop */
- ASM jmp match
- nomatch:
- ASM mov WORD PTR [retval], 1 /* return nonzero on mismatch */
- match:
- ASM pop ds /* restore register values */
- ASM pop si
- ASM pop cx
- ASM pop bx
- #else
- for (; len; len--, temp++) /* do the same thing in C */
- {
- if (*temp != checkchar)
- {
- retval = 1;
- break;
- }
- }
- #endif
-
- return retval;
- } /* end of farmemcheck() */
-
-
- /***************************************************************************
- * FUNCTION: LFARMEMCHECK *
- * *
- * DESCRIPTION: *
- * *
- * This function scans a block of memory longer than 64K looking for *
- * bytes which do not match checkchar. *
- * *
- * ENTRY: *
- * *
- * buffer - pointer to block of memory to scan *
- * len - length of block *
- * checkchar - value which should be matched *
- * *
- * EXIT: *
- * *
- * Returns 0 if all bytes match, nonzero if mismatch found. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- int lfarmemcheck(unsigned char far *buffer, unsigned long len,
- unsigned char checkchar)
- {
- int retval;
- unsigned int copylen;
- unsigned char huge *temp;
-
- /* normalize far pointer and turn into huge pointer */
- temp = normptr(buffer);
-
- while (len > 0L)
- {
- copylen = ((len > 65000L) ? 65000U : (unsigned int) len);
- if ((retval = farmemcheck((void far *) temp, copylen, checkchar)) != 0)
- {
- return retval;
- }
- temp = normptr((unsigned char far *)(temp + copylen));
- len -= copylen;
- }
-
- return retval;
- } /* end of lfarmemcheck() */
-
-
- /***************************************************************************
- * FUNCTION: LFMEMCMP *
- * *
- * DESCRIPTION: *
- * *
- * Compares two regions of memory longer than 64K. *
- * *
- * ENTRY: *
- * *
- * buf1 - pointer to first region *
- * buf2 - pointer to second region *
- * n - length of regions *
- * *
- * EXIT: *
- * *
- * Returns 0 on match, negative if mismatch byte in buf1 is less than *
- * corresponding byte in buf2, positive if vice versa. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- int LFMEMCMP(void far *buf1, void far *buf2, unsigned long n)
- {
- unsigned char huge *temp1, huge *temp2;
- int retval = 0;
- unsigned int cmplen;
-
- /* normalize far pointers and turn into huge pointers */
- temp1 = normptr(buf1);
- temp2 = normptr(buf2);
-
- while (n > 0L)
- {
- cmplen = ((n > 65000L) ? 65000U : (unsigned int) n);
- retval = FMEMCMP((void far *) temp1, (void far *) temp2, cmplen);
- if (retval != 0)
- {
- return retval;
- }
- temp1 = normptr((unsigned char far *)(temp1 + cmplen));
- temp2 = normptr((unsigned char far *)(temp2 + cmplen));
- n -= cmplen;
- }
-
- return retval;
- } /* end of LFMEMCMP() */
-
-
- /***************************************************************************
- * FUNCTION: LFMEMSET *
- * *
- * DESCRIPTION: *
- * *
- * Sets a region of memory longer than 64K to a particular value. *
- * *
- * ENTRY: *
- * *
- * s - pointer to region of memory *
- * c - byte value to set memory to *
- * n - length of region *
- * *
- * EXIT: *
- * *
- * Void. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- void LFMEMSET(void far *s, int c, unsigned long n)
- {
- unsigned char huge *temp;
- unsigned int fill_len;
-
- /* normalize far pointer and turn into huge pointer */
- temp = normptr(s);
-
- while (n > 0L)
- {
- fill_len = ((n > 65000L) ? 65000U : (unsigned int) n);
- FMEMSET((void far *) temp, c, fill_len);
- temp = normptr((unsigned char far *)(temp + fill_len));
- n -= fill_len;
- }
-
- return;
- } /* end of LFMEMSET() */
-
-
- /***************************************************************************
- * FUNCTION: FARINCWORDFILL *
- * *
- * DESCRIPTION: *
- * *
- * Fill a region of memory with incrementing word (16 bit) values. *
- * Always starts at 0 value. *
- * *
- * ENTRY: *
- * *
- * buffer - pointer to block of memory *
- * len - length of block, must be even *
- * *
- * EXIT: *
- * *
- * Void. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- void farincwordfill(unsigned char far *buffer, unsigned int len,
- unsigned int start)
- {
- unsigned char huge *temp;
- #ifndef INLINE_ASM
- int loop;
- unsigned int huge *filler;
- unsigned int value;
- #endif
-
- /* turn length in bytes into length in words, convert pointer */
- len /= 2;
- temp = normptr(buffer);
-
- #ifdef INLINE_ASM
- ASM push ax /* preserve registers */
- ASM push cx
- ASM push di
- ASM push es
- ASM les di, [temp] /* load pointer into ES:DI */
- ASM mov cx, [len] /* load length into CX */
- ASM mov ax, [start] /* load starting value into AX */
- loop2top:
- ASM stosw /* store AX in memory, DI += 2 */
- ASM inc ax /* increment AX */
- ASM loop loop2top /* loop */
- ASM pop es /* restore register values */
- ASM pop di
- ASM pop cx
- ASM pop ax
- #else
- /* do the same thing in C */
- for (loop = 0, filler = (unsigned int huge *) temp, value = start;
- loop < len;
- loop++, value++)
- {
- filler[loop] = value;
- }
- #endif
-
- return;
- } /* end of farincwordfill() */
-
-
- /***************************************************************************
- * FUNCTION: LFARINCWORDFILL *
- * *
- * DESCRIPTION: *
- * *
- * This function fills a block of memory longer than 64K with *
- * incrementing word values. *
- * *
- * ENTRY: *
- * *
- * buffer - pointer to block of memory to fill *
- * len - length of block *
- * start - value at which incrementing words start *
- * *
- * EXIT: *
- * *
- * Void. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- void lfarincwordfill(unsigned char far *buffer, unsigned long len,
- unsigned int start)
- {
- unsigned int fill_len;
- unsigned char huge *temp;
- unsigned int value;
-
- /* normalize far pointer and turn into huge pointer */
- temp = normptr(buffer);
-
- value = start;
-
- while (len > 0L)
- {
- fill_len = ((len > 65000L) ? 65000U : (unsigned int) len);
- farincwordfill((void far *) temp, fill_len, value);
- temp = normptr((unsigned char far *)(temp + fill_len));
- len -= fill_len;
- value += (fill_len / 2);
- }
-
- return;
- } /* end of lfarincwordfill() */
-
-
- /***************************************************************************
- * FUNCTION: FARINCWORDCHECK *
- * *
- * DESCRIPTION: *
- * *
- * Scans a block of memory to make sure contents are incrementing *
- * word values. *
- * *
- * ENTRY: *
- * *
- * buffer - pointer to block of memory *
- * len - length of block of memory, must be even *
- * *
- * EXIT: *
- * *
- * Returns 0 if contents are OK, nonzero if mismatch found. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- int farincwordcheck(unsigned char far *buffer, unsigned int len,
- unsigned int start)
- {
- int retval = 0;
- unsigned char huge *temp;
- #ifndef INLINE_ASM
- int loop;
- unsigned int huge *filler;
- unsigned int value;
- #endif
-
- /* convert length in bytes to length in words, convert pointer */
- len /= 2;
- temp = normptr(buffer);
-
- #ifdef INLINE_ASM
- ASM push ax /* preserve register values */
- ASM push bx
- ASM push cx
- ASM push si
- ASM push ds
- ASM lds si, [temp] /* load pointer into DS:SI */
- ASM mov cx, [len] /* load length into CX */
- ASM mov bx, [start] /* load starting value into BX */
- ASM dec bx /* decrement BX, prep for loop */
- loop3top:
- ASM inc bx /* increment BX to next value */
- ASM lodsw /* load next word into AX */
- ASM cmp ax, bx /* compare word in AX and BX */
- ASM loope loop3top /* loop while words are equal */
- ASM je done /* exited loop -- if last cmp */
- /* was equal, jump to end, else */
- ASM mov WORD PTR [retval], 1 /* mismatch, set nonzero retval */
- done:
- ASM pop ds /* restore register values */
- ASM pop si
- ASM pop cx
- ASM pop bx
- ASM pop ax
- #else
- /* do the same thing in C */
- for (loop = 0, filler = (unsigned int huge *) temp, value = start;
- loop < len;
- loop++, value++)
- {
- if (filler[loop] != value)
- {
- retval = 1;
- break;
- }
- }
- #endif
-
- return retval;
- } /* end of farincwordcheck() */
-
-
- /***************************************************************************
- * FUNCTION: LFARINCWORDCHECK *
- * *
- * DESCRIPTION: *
- * *
- * This function checks a block of memory longer than 64K for *
- * incrementing word values. *
- * *
- * ENTRY: *
- * *
- * buffer - pointer to block of memory to check *
- * len - length of block *
- * start - value at which incrementing words start *
- * *
- * EXIT: *
- * *
- * Returns 0 if contents are OK, nonzero if mismatch found. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- int lfarincwordcheck(unsigned char far *buffer, unsigned long len,
- unsigned int start)
- {
- int retval;
- unsigned int checklen;
- unsigned char huge *temp;
- unsigned int value;
-
- /* normalize far pointer and turn into huge pointer */
- temp = normptr(buffer);
-
- value = start;
-
- while (len > 0L)
- {
- checklen = ((len > 65000L) ? 65000U : (unsigned int) len);
- if ((retval = farincwordcheck((void far *) temp, checklen, value)) != 0)
- {
- return retval;
- }
- temp = normptr((unsigned char far *)(temp + checklen));
- len -= checklen;
- value += (checklen / 2);
- }
-
- return retval;
- } /* end of lfarincwordcheck() */
-
-
- /***************************************************************************
- * FUNCTION: GET_TICK *
- * *
- * DESCRIPTION: *
- * *
- * Retrieves the current timer count via BIOS call. For use when *
- * timing copies. The timer ticks 18.2 times per second. The value *
- * returned by this function has a jitter of -0,+(1/18.2) seconds. *
- * *
- * ENTRY: *
- * *
- * Void. *
- * *
- * EXIT: *
- * *
- * Returns the timer count. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- unsigned long get_tick(void)
- {
- unsigned long retval;
-
- #ifdef INLINE_ASM
- ASM push cx /* push register values */
- ASM push dx
- ASM xor ah, ah /* AH = 00h, get count call */
- ASM int 1Ah /* make call */
- ASM mov WORD PTR [retval + 2], cx /* save returned value */
- ASM mov WORD PTR [retval], dx
- ASM pop dx
- ASM pop cx
- #else
- union REGS r;
-
- /* do the same thing in C */
- r.h.ah = 0x0;
- int86(0x1A, &r, &r);
- retval = r.x.cx;
- retval <<= 16;
- retval |= r.x.dx;
- #endif
-
- return retval;
- } /* end of get_tick() */
-
-
- /***************************************************************************
- * FUNCTION: NORMPTR *
- * *
- * DESCRIPTION: *
- * *
- * Normalizes a far pointer -- reduces the offset to the smallest *
- * possible value (somewhere between 0 and 0xF) by adding to the *
- * segment. *
- * *
- * ENTRY: *
- * *
- * norm - pointer to be normalized *
- * *
- * EXIT: *
- * *
- * Returns normalized pointer. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- unsigned char huge *normptr(unsigned char far *norm)
- {
- unsigned char huge *retval = (unsigned char huge *) norm;
-
- #ifdef INLINE_ASM
- ASM push cx /* preserve register values */
- ASM push di
- ASM push si
- ASM mov si, WORD PTR [retval] /* load offset into SI */
- ASM mov di, si /* load offset into DI too */
- ASM mov cl, 4 /* load 4 into CL */
- ASM shr di, cl /* shift DI right by 4, which */
- /* converts it to a segment */
- ASM add WORD PTR [retval + 2], di /* add to segment in pointer */
- ASM and si, 0Fh /* zero all but lowest nibble */
- /* of offset */
- ASM mov WORD PTR [retval], si /* put offset back in pointer */
- ASM pop si /* restore register values */
- ASM pop di
- ASM pop cx
- #else
- unsigned int segment, offset;
-
- /* do the same thing in C -- extract segment and offset from pointer */
- segment = FP_SEG(retval);
- offset = FP_OFF(retval);
- /* add high three nibbles of offset to segment */
- segment += (offset >> 4);
- /* preseve only lowest nibble of offset */
- offset &= 0xF;
- /* reconstruct pointer from modified segment and offset */
- retval = MK_FP(segment, offset);
- #endif
-
- return retval;
- } /* end of normptr() */
-
-
- /*
- ** The following group of functions is the same in spirit as the preceding
- ** group, but equivalents already exist in the libraries of some compilers.
- ** These functions are only used if the symbol NO_FFUNC is defined, which
- ** should only be done when the compiler's library does not already contain
- ** equivalent functions.
- */
-
- /***************************************************************************
- * FUNCTION: FMEMCMP *
- * *
- * DESCRIPTION: *
- * *
- * A replacement _fmemcmp() function for compilers which do not have *
- * it in their libraries. Compares two regions of memory. *
- * *
- * ENTRY: *
- * *
- * buf1 - pointer to first region *
- * buf2 - pointer to second region *
- * n - length of regions *
- * *
- * EXIT: *
- * *
- * Returns 0 on match, negative if mismatch byte in buf1 is less than *
- * corresponding byte in buf2, positive if vice versa. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- int Fmemcmp(void far *buf1, void far *buf2, unsigned int n)
- {
- unsigned char huge *temp1, huge *temp2;
- int retval = 0;
- #ifndef INLINE_ASM
- int loop;
- #endif
-
- /* normalize pointers */
- temp1 = normptr((unsigned char far *) buf1);
- temp2 = normptr((unsigned char far *) buf2);
-
- #ifdef INLINE_ASM
- ASM push cx /* preserve register values */
- ASM push di
- ASM push si
- ASM push ds
- ASM push es
- ASM lds si, [temp1] /* load first pointer in DS:SI */
- ASM les di, [temp2] /* load second pointer in ES:DI */
- ASM mov cx, [n] /* load length in CX */
- ASM repz cmpsb /* compare while equal */
- ASM jcxz alldone /* if CX is 0, all were equal */
- ASM ja higher /* not equal, set return value */
- ASM mov WORD PTR [retval], -1
- ASM jmp alldone
- higher:
- ASM mov WORD PTR [retval], 1
- alldone:
- ASM pop es /* restore register values */
- ASM pop ds
- ASM pop si
- ASM pop di
- ASM pop cx
- #else
- /* do the same thing in C */
- for (loop = 0; loop < n; loop++, temp1++, temp2++)
- {
- if (*temp1 == *temp2)
- {
- continue;
- }
- retval = (int) (*temp1 - *temp2);
- break;
- }
- #endif
-
- return retval;
- } /* end of Fmemcmp() */
-
-
- /***************************************************************************
- * FUNCTION: FMEMSET *
- * *
- * DESCRIPTION: *
- * *
- * A replacement _fmemset() function for compilers which do not have *
- * it in their libraries. Sets a region of memory to a particular *
- * value. *
- * *
- * ENTRY: *
- * *
- * s - pointer to region of memory *
- * c - byte value to set memory to *
- * n - length of region *
- * *
- * EXIT: *
- * *
- * Returns s. *
- * *
- * CONSTRAINTS/SIDE EFFECTS: *
- * *
- ***************************************************************************/
- void Fmemset(void far *s, int c, unsigned int n)
- {
- unsigned char huge *temp;
-
- /* normalize pointer */
- temp = normptr((unsigned char far *) s);
-
- #ifdef INLINE_ASM
- /* if length is odd, use slower way */
- if ((n % 2) == 1)
- {
- ASM push ax /* preserve register values */
- ASM push cx
- ASM push di
- ASM push es
- ASM les di, [temp] /* load pointer into ES:DI */
- ASM mov al, BYTE PTR [c] /* load value into AL */
- ASM mov cx, [n] /* load length into CX */
- ASM rep stosb /* store value in memory */
- ASM pop es /* restore register values */
- ASM pop di
- ASM pop cx
- ASM pop ax
- }
- else
- {
- /* otherwise use faster way, storing entire words at once */
- /* convert length in bytes to length in words */
- n /= 2;
- ASM push ax /* preserve register values */
- ASM push cx
- ASM push di
- ASM push es
- ASM les di, [temp] /* load pointer into ES:DI */
- ASM mov al, BYTE PTR [c] /* load value into AL */
- ASM mov ah, al /* load value into AH too */
- ASM mov cx, [n] /* load length into CX */
- ASM rep stosw /* store value in memory by words */
- ASM pop es /* restore register values */
- ASM pop di
- ASM pop cx
- ASM pop ax
- }
- #else
- /* do the same thing in C */
- for (; n; n--, temp++)
- {
- *temp = c;
- }
- #endif
-
- return;
- } /* end of Fmemset() */
-
-