Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1105 lines
19 KiB

/* misc.c - miscellanous routines
*
* 06/16/88 MattS Created
*
* 10/15/89 MattS Added AutoDoc comment blocks
*/
#include <stdio.h>
#include <ctype.h>
#ifdef MSDOS
#include <io.h>
#include <stdlib.h>
#endif
#include <fcntl.h>
#include <malloc.h>
#include <string.h>
#include "misc.h"
#define FALSE 0
#define TRUE 1
/*
** Compare a string with a hi-bit terminates string
*/
#ifdef NOT_NEEDED
/*
* @doc MISC INTERNAL
*
* @func int | hb_strcmp | This function compares a string with a
* hi-bit terminated string. (instead of zero terminated)
*
* @parm unsigned char * | str | Zero terminated string.
*
* @parm unsigned char * | hb_str | High-bit terminated string.
*
* @rdesc The return is the same as strcmp.
*
*/
hb_strcmp(str, hb_str)
register unsigned char *str, *hb_str;
{
unsigned char hbc;
for (;;) {
hbc = *hb_str & (unsigned char)0x7f;
if (hbc == *str) {
if (*++str == 0)
return (*hb_str & 0x80) ? 0 : -1;
else if (*hb_str++ & 0x80)
return 1;
} else
return *str - hbc;
}
}
/*
* @doc MISC
*
* @func int | hex_nyb | This function converts the hex character into
* binary.
*
* @parm int | chr | The character to convert.
*
* @rdesc The return is the binary hex value of <p chr>.
*
*/
int hex_nyb(chr)
register int chr;
{
if (chr >= '0' && chr <= '9')
return chr - '0';
else
if (chr >= 'A' && chr <= 'Z')
return chr - 'A' + 0xA;
else
return chr - 'a' + 0xA;
}
/*
* @doc INTERNAL MISC
*
* @func int | hex_bytes | This function converts a hex string to binary.
*
* @parm char * | str | Specifies string to convert.
*
* @parm int | nbytes | Specifies length of string.
*
* @rdesc Returns binary value of hex string.
*
* @xref hex_nyb
*
*/
int hex_bytes(str, nbytes)
register char *str;
register int nbytes;
{
register int ret = 0;
while (nbytes--) {
ret <<= 4;
ret += hex_nyb(*str++);
}
return ret;
}
/*
* @doc INTERNAL MISC
*
* @func long | htoi | This function converts a hex string to a long.
*
* @parm char * | str | Specifies string to convert.
*
* @xref hex_bytes
*
*/
/*
* Interpret an ASCII string as a hex number, convert to long int.
*/
long htoi(str)
char *str;
{
register long ret = 0;
register unsigned char ch;
while (ch = *str++)
if (ch >= '0' && ch <= '9')
ret = (ret << 4) + ch - '0';
else if (ch >= 'A' && ch <= 'Z')
ret = (ret << 4) + ch - 'A' + 10;
else if (ch >= 'a' && ch <= 'z')
ret = (ret << 4) + ch - 'a' + 10;
else return ret;
return ret;
}
/* nindex --
*
*/
/*
*
* @doc INTERNAL MISC
*
* @func int | nindex | looks for pattern p in string s starting at position start.
*
* @parm char * | p | Specifies pattern.
*
* @parm char * | s | Specifies string.
*
* @parm int | start | Specifies starting offset in string.
*
* @rdesc It returns an index to the position AFTER p if it succeeds; else -1.
*/
int
nindex(p,s,start)
char p[];
char s[];
int start;
{
register int j = start;
register int i;
int match = -1;
int nLineLen = strlen(s);
int nPattLen = strlen(p);
while ( j < nLineLen )
{
/*find first letter of pattern
*/
while (j < nLineLen)
{
if (p[0] == s[j++])
{ /* found 1st char of pattern */
match = 1; /* toggle flag */
break; /* go on to next step */
}
}
if (match == 1)
{
/* look for rest of pattern
*/
for (i = 1; (i < nPattLen) && (j < nLineLen) ; i++,j++)
{
if (p[i] != s[j])
{
match = -1; /* pattern doesn't match: toggle flag */
break; /* stop looking */
}
}
if (j >= nLineLen) /* if we're at end, it doesn't matter */
{
match = -1;
break; /* break main loop with flag = fail */
}
else
{
if (match == 1) /* found the pattern */
{
match = j; /* match points to char after pattern */
break; /* break main loop with flag = success */
}
}
}
}
return(match);
}
/*
*
* @doc INTERNAL MISC
*
* @func int | parse | Split of the line, point <p fl> array to each record, records are seperated by
* <p sep> charactor.
*
* @parm char * | cp | Specifies line.
*
* @parm char ** | fl | Specifies array of argument pointers.
*
* @parm char | sep | Specifies argument seperator character.
*
* @rdesc This function returns the number of fields it found.
*/
int
parse(cp, fl, sep)
register char *cp, **fl, sep;
{
register int nfields = 1;
*fl++ = cp;
while (1) {
if (*cp == sep) {
nfields++;
*fl++ = cp + 1;
*cp = 0;
} else if (*cp == '\n' || *cp == '\0') {
*cp = 0;
return nfields;
}
cp++;
}
}
/*
*
* Progress routines
*
*
*/
long pinc, ploc, loc;
/*
*
* @doc INTERNAL MISC
*
* @func void | init_progress | This function initializes the progress
* indicator.
*
* @parm long | size | Specifies the total size.
*
* @xref show_progress
*
*/
void
init_progress(size)
long size;
{
ploc = pinc = size / 80;
loc = 0;
}
/*
*
* @doc INTERNAL MISC
*
* @func void | show_progress | This function displays the progress
* according to the initialized value in <f init_progress>.
*
* @parm int | amount | Specifies the delta processed since last call
*
*/
void
show_progress(int amt)
{
if( (loc + amt) >ploc)
{
while( (loc + pinc) <= ploc+ amt) {
loc+=pinc;
fputc('.', stdout);
fflush(stdout);
}
ploc += amt;
}
}
/*
** mem_to_long and long_to_mem are used to convert back and forth between
* the byte-order independant representation of integers and the
* the internal C format
*/
/*
*
* @doc INTERNAL MISC
*
* @func long | mem_to_long | Used to convert back and forth between
* the byte-order independant representation of integers and the
* the internal C format.
*
* @parm unsigned char * |cp| Specifies the memory to convert.
*
* @parm short |nbytes | Specifies the number of bytes to convert.
*
* @rdesc This function returns the Local version of the value contained
* in the memory location.
*
* @comm This function was meant to provide byte-order independence capability
* in C code and was used in Microsoft Bookshelf and the Microsoft Library
* products.
*
* @xref long_to_mem
*
*/
long
mem_to_long(cp, nbytes)
register unsigned char *cp;
register short nbytes;
{
register int i;
register long ret = 0;
for (i = nbytes; i > 0;) {
ret <<= 8;
ret += cp[--i];
}
return ret;
}
/*
*
* @doc INTERNAL MISC
*
* @func void | long_to_mem | This function is used to convert back and forth between
* the byte-order independant representation of integers and the
* the internal C format.
*
* @parm long | value | Specifies the value to save into the memory.
*
* @parm unsigned char * |cp| Specifies the memory buffer.
*
* @parm short |nbytes | Specifies the number of bytes to convert.
*
* @comm This function was meant to provide byte-order independence capability
* in C code and was used in Microsoft Bookshelf and the Microsoft Library
* products.
*
* @xref mem_to_long
*
*/
void
long_to_mem(val, cp, nbytes)
register long val;
register unsigned char *cp;
register int nbytes;
{
register int i;
for (i = 0; i < nbytes; i++) {
*cp++ = (unsigned char)val & (unsigned char)0xff;
val >>= 8;
}
}
/*
** This function is available under Sun 3.2 UNIX but not on MS-DOS so I
** had to write it in order to use the index building tools under MS-DOS
**
** getopt(argc, argv, template)
** argc, argv are the arguments to main
** template is a string of legal arguemnt characters.
** if a character in the template is followed by a ':', this means
** that the option takes an additional argument which will either be the
** remainder of the argument string if this argument strings ended,
** the next argument.
**
** RETURNS:
** '?' on error, print usage and exit
** EOF when end of options is hit, use "optind" to get non option args
** chr means that option "chr" was specified and if it takes an
** additional argument, that would be in the string "optarg"
**
** Here is an example program which just echos back how it parsed the command
** line, using getopt. This template says the program has flags 'a' and 'b'
** and options 'c' and 'd'. Legal commmand lines would be:
** D>prog hello there folks
** D>prog -a hello folks
** D>prog -ab -chello -d there folks
** D>prog -abc hello -dthere folks
**
** extern char *optarg;
** extern int optind;
** char *my_template = "abc:d:";
**
** main(argc, argv)
** char **argv;
** {
** int arg;
**
** while (arg = getopt(argv, argv, my_template))
** if (optarg)
** printf("-%c %s\n", arg, optarg);
** else if (arg == '?') {
** printf("Argument error\n");
** break;
** } else
** printf("-%c\n", arg);
** for (arg = optind; arg < argc - 1; arg++)
** printf("### %s\n", argv[arg]);
** }
*/
static int argNum;
static char *optparse;
int optind = 1;
char *optarg;
getopt(argc, argv, template)
int argc;
char **argv,
*template;
{
register char *arg, *tp;
optarg = NULL;
if (!optparse)
if (++argNum < argc) {
arg = argv[argNum];
if (*arg != '-') {
optind = argNum;
return EOF;
}
optparse = arg + 1;
} else
return EOF;
for (tp = template; *tp; tp++)
if (*tp == *optparse) {
if (tp[1] == ':') {
if (optparse[1]) {
optarg = optparse + 1;
optparse = 0;
} else
if (++argNum == argc)
return '?';
else
optarg = argv[argNum];
}
if (optparse && *++optparse == 0)
optparse = NULL;
return *tp;
}
return '?';
}
#endif
/*
/*
*
* @doc INTERNAL MISC
*
* @func int | findlshortname | This function returns the offset of the
* end of the complete path and file name not counting the file extension.
*
* @parm char * | fullname | Specifies the name to search.
*
* @rdesc The return value is the offset of the end of the complete path
* and file name not counting the file extension.
*
*/
int
findlshortname(fullname) /* find the length of the short name */
/* full path/file name not counting extension */
char *fullname;
{
char *ch;
int cnt;
if(!fullname || !*fullname)
return(0);
cnt=strlen(fullname);
ch=fullname+cnt;
while(*ch!='.' && *ch!='\\' && *ch!='/' && cnt)
{
ch--;
cnt--;
}
if(!cnt)
return(strlen(fullname));
return(ch - fullname);
}
/* getblong - get the next number from a buffer. Returns a long positive
* value if successful, otherwise returns -1. Scans-off leading BS.
* Parameters: takes a pointer to a char and a pointer to an int which
* will become a pointer the character following the number.
*/
/*
*
* @doc INTERNAL MISC
*
* @func long | getblong | ATOL for buffer.
*
* @parm char * | line | Specifies buffer.
*
* @parm int * | i | Specifies current offset into buffer. This value is
* updated as the buffer is scanned.
*
* @rdesc This function returns the Long value of the ASCII value contained
* in the buffer at the specified offset.
*
* The offset is updated to the next character after the last ASCII character.
*
*/
long
getblong(line, i)
char *line;
int *i;
{
int pos = *i;
long result = 0;
int nLineLen = strlen(line);
/* while (!isdigit(line[pos]) && pos < nLineLen) */
/* ++pos; */
if (pos == nLineLen)
return ((long)-1);
while (isdigit(line[pos]) && pos < nLineLen)
result = 10 * result + line[pos++] - '0';
*i = pos;
return (result);
}
#ifdef NOT_NEEDED
/*
*
* @doc INTERNAL MISC
*
* @func char * | parse_sec_name | This function parses the section
* name from a complete name.
*
* It was written for use in for Compound File indexing tools for
* Microsoft Library.
*
* @parm char ** | ppch | Specifies the name to parse.
*
* @rdesc Ack.
*
*/
char *
parse_sec_name(char **ppch)
{
char *pch;
char *p2ch;
int j;
if(!ppch || !*ppch)
return(NULL);
pch=*ppch;
while(*pch && *pch!='!')
pch++;
if(!*pch) /* default section name is file name */
return(*ppch);
*pch='\0';
pch++;
p2ch=*ppch;
*ppch=pch;
return(p2ch);
}
#endif
/* *
* *
* Memory Management routines *
* *
* *
* */
char _achmemout[]= "Oh my, we seem to be out of %smemory. %ld Allocated\n" ;
/* Generic memory management */
/*
*
* @doc INTERNAL MISC
*
* @func char * | cp_alloc | Allocates memory for the string and copies
* it into the buffer and returns it.
*
* @parm char * | pch| Specifies string to copy.
*
* @comm The buffer should be freed with <f my_free>.
*
*/
char *
cp_alloc(pch)
char *pch;
{
char *pch2;
if(!pch)
return(NULL);
pch2=my_malloc(strlen(pch)+1);
strcpy(pch2,pch);
return pch2;
}
/*
*
* @doc INTERNAL MISC
*
* @func void | memfil | Fills the memory with zero.
*
* @parm int * | mem | Specifies the memory block to fill.
*
* @parm unsigned int | size | Specifies the size of the memory block.
*
* @comm The size of the memory block does not have to be a multiple of 2.
*
*/
void
memfil(mem,size)
register int *mem;
register unsigned int size;
{
char flag=FALSE;
char *pch;
if(size&1) /* it's odd so int fill won't work all the way */
{
flag=TRUE;
size--;
}
size=size/2;
while(size--)
*mem++=0;
if(flag)
{
pch=(char *)mem;
*pch='\0';
}
}
/*
*
* @doc INTERNAL MISC
*
* @func char * | clear_alloc | This function allocates memory and
* initialized it to zeros.
*
* @parm unsigned int | size | Specifies the size of the memory to allocate.
*
* @comm The allocated memory should be freed with <f my_free>.
*
*/
char *
clear_alloc(size)
unsigned int size;
{
char *pmem;
pmem=my_malloc(size);
memfil((int *)pmem,size);
return pmem;
}
static long ivemalloc=0;
/*
*
* @doc INTERNAL MISC
*
* @func char * | my_malloc | Allocates memory and checks for errors.
*
* @parm unsigned int | size | Specifies the size of the memory to allocate.
*
* @comm The allocated memory should be freed with <f my_free>.
*
*/
char *
my_malloc(size)
unsigned int size;
{
char *pmem;
int hck;
if(size>32767)
{
fprintf(stderr,"Size >32K\n");
exit(666);
}
hck=_heapchk();
if(hck == _HEAPBADNODE)
{
fprintf(stderr,"Bad node in Heap. Ack!\n");
exit(666);
}
if(hck == _HEAPBADBEGIN)
{
fprintf(stderr,"Bad begin in Heap. Ack!\n");
exit(666);
}
pmem=(char *)malloc(size);
if(pmem==NULL)
{
fprintf(stderr,_achmemout,"",ivemalloc);
exit(777);
}
ivemalloc+=size;
return(pmem);
}
/*
*
* @doc INTERNAL MISC
*
* @func void | my_free | Frees the specified buffer.
*
* @parm void * | buffer | Specifies the buffe to free.
*
*/
void
my_free(void * buffer)
{
if(!buffer)
return;
ivemalloc-=_msize(buffer);
free(buffer);
return;
}
/* used by old indexing tools */
char *cpalloc(str)
char *str;
{
return(cp_alloc(str));
}
/*
*
* @doc INTERNAL MISC
*
* @func void | setmem | Sets the memory to the specified value.
*
* @parm char * | mem | Specifies the memory.
*
* @parm int | size | Specifies the size of the memory block.
*
* @parm char | val | Specifies the value to set the memory to.
*
* @comm Filling with zero is much faster with <f mem_fil>.
*
*/
void
setmem(src, size, val)
register char *src;
register int size;
register char val;
{
while (size-- > 0)
*src++ = val;
}
/*
*
* @doc INTERNAL MISC
*
* @func void | movmem | This function moves the specified memory.
* Overlap is not checked.
*
* @parm char * | src | Source of copy.
*
* @parm char * | dst | Destination of copy.
*
* @parm int | len | Specifies number of bytes to copy.
*
*/
void
movmem(src,dst,len)
register char *src, *dst;
register int len;
{
while (len-- > 0)
*dst++ = *src++;
}
#ifdef NOT_NEEDED
/* explicit NEAR memory management calls */
char near *
ncp_alloc(pch)
char near *pch;
{
char near *pch2;
if(!pch)
return(NULL);
pch2=nmy_malloc(strlen(pch)+1);
strcpy(pch2,pch);
return pch2;
}
void
nmemfil(mem,size)
register int near *mem;
register unsigned int size;
{
char flag=FALSE;
char near *pch;
if(size&1) /* it's odd so int fill won't work all the way */
{
flag=TRUE;
size--;
}
size=size/2;
while(size--)
*mem++=0;
if(flag)
{
pch=(char near *)mem;
*pch='\0';
}
}
char near *
nclear_alloc(size)
unsigned int size;
{
char near *pmem;
pmem=nmy_malloc(size);
memfil((int near*)pmem,size);
return pmem;
}
static long ivenmalloc=0;
char near *
nmy_malloc(size)
unsigned int size;
{
char near *pmem;
pmem=(char near *)_nmalloc(size);
if(pmem==NULL)
{
fprintf(stderr,_achmemout,"NEAR ",ivenmalloc);
exit(777);
}
ivenmalloc+=size;
return(pmem);
}
/* used by old indexing tools */
char near *
ncpalloc(str)
char near *str;
{
return(ncp_alloc(str));
}
void
nsetmem(src, size, val)
register char near *src;
register int size;
register char val;
{
while (size-- > 0)
*src++ = val;
}
void
nmovmem(src,dst,len)
register char near *src;
register char near *dst;
register int len;
{
while (len-- > 0)
*dst++ = *src++;
}
/* explicit FAR memory management calls */
char far *
fcp_alloc(pch)
char far *pch;
{
char far *pch2;
if(!pch)
return(NULL);
pch2=fmy_malloc(strlen(pch)+1);
strcpy(pch2,pch);
return pch2;
}
void
fmemfil(mem,size)
register int far *mem;
register unsigned int size;
{
char flag=FALSE;
char far *pch;
if(size&1) /* it's odd so int fill won't work all the way */
{
flag=TRUE;
size--;
}
size=size/2;
while(size--)
*mem++=0;
if(flag)
{
pch=(char far *)mem;
*pch='\0';
}
}
char far *
fclear_alloc(size)
unsigned int size;
{
char far *pmem;
pmem=fmy_malloc(size);
fmemfil((int far*)pmem,size);
return pmem;
}
static long ivefmalloc=0;
char far *
fmy_malloc(size)
unsigned int size;
{
char far *pmem;
pmem=(char far *)_fmalloc(size);
if(pmem==NULL)
{
fprintf(stderr,_achmemout,"FAR ",ivefmalloc);
exit(777);
}
ivefmalloc+=size;
return(pmem);
}
/* used by old indexing tools */
char far *
fcpalloc(str)
char far *str;
{
return(fcp_alloc(str));
}
void
fsetmem(src, size, val)
register char far *src;
register int size;
register char val;
{
while (size-- > 0)
*src++ = val;
}
void
fmovmem(src,dst,len)
register char far *src;
register char far *dst;
register int len;
{
while (len-- > 0)
*dst++ = *src++;
}
#endif
/*
*
* @doc INTERNAL MISC
*
* @func void | mymktemp | Make a temporary file. The returned file name is
* guranteed to be unique and not already exist.
*
* @parm char * | lpszpath | Specifies the path to create the file.
*
* @parm char * | lpszbuffer | Specifies the buffer to receive the
* full path/file name.
*
*
*/
void
mymktemp(char * lpszpath, char * lpszbuffer)
{
static int i=0;
FILE *fp;
sprintf(lpszbuffer,"%sdoc%05X.xxx",lpszpath,i++);
fp=fopen(lpszbuffer,"r");
if(!fp)
return;
fclose(fp);
while(fp)
{
if(i>30000)
{
fprintf(stderr,"ERROR: Cannot create temporary files on %s.\n",lpszpath);
exit(1);
}
sprintf(lpszbuffer,"%sdoc%05X.xxx",lpszpath,i++);
fp=fopen(lpszbuffer,"r");
if(fp)
fclose(fp);
}
}