1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
|
/* SCCS Id: @(#)oldcrtl.c 3.4 1995/06/01 */
/* Pat Rankin May'90 */
/* VMS NetHack support, not needed for vms 4.6,4.7,5.x,or later */
#ifdef VERYOLD_VMS
/*
* The following routines are used by NetHack but were not available
* from the C Run-Time Library (VAXCRTL) prior to VMS V4.6.
*
* atexit, memcmp, memcpy, qsort, rename, vprintf, vsprintf
*
* Most of them are implemented here, but others will have to be worked
* around in another fashion [such as '#define USE_OLDARGS' (even though
* <varargs.h> is available) to avoid the need for vprintf & vsprintf].
*
*/
#define REG register
#define const
#ifndef SUPPRESS_MEM_FUNCS
/* note: hand optimized for VAX (hardware pre-decrement & post-increment) */
/* void *memset(void *, int, size_t) -- fill chunk of memory.
*/
char *memset( dst, fil, cnt )
REG char *dst;
REG char fil;
REG int cnt;
{
char *dst_p = dst;
while ( --cnt >= 0 )
*dst++ = fil;
return dst_p;
}
/* void *memcpy(void *, const void *, size_t) -- copy chunk of memory.
*/
char *memcpy( dst, src, cnt )
REG char *dst;
REG const char *src;
REG int cnt;
{
char *dst_p = dst;
while ( --cnt >= 0 )
*dst++ = *src++;
return dst_p;
}
/* void *memmove(void *, const void *, size_t) -- copy possibly overlapping mem.
*/
char *memmove( dst, src, cnt )
REG char *dst;
REG const char *src;
REG int cnt;
{
char *dst_p = dst;
if ( src == dst || cnt <= 0 ) {
; /* do nothing */
} else if ( dst < src || dst >= src + cnt ) {
while ( --cnt >= 0 )
*dst++ = *src++;
} else { /* work backwards */
dst += cnt, src += cnt;
while ( --cnt >= 0 )
*--dst = *--src;
}
return dst_p;
}
/* void *memchr(const void *, int, size_t) -- search for a byte.
*/
char *memchr( buf, byt, len )
REG const char *buf;
REG char byt;
REG int len;
{
while ( --len >= 0 )
if ( *buf++ == byt ) /* found */
return (char *)--buf;
return (char *)0; /* not found */
}
/* int memcmp(const void *, const void *, size_t) -- compare two chunks.
*/
int memcmp( buf1, buf2, len )
REG const char *buf1;
REG const char *buf2;
REG int len;
{
while ( --len >= 0 )
if ( *buf1++ != *buf2++ )
return (*--buf1 - *--buf2);
return 0; /* buffers matched */
}
#endif /*!SUPPRESS_MEM_FUNCS*/
#ifndef SUPPRESS_ATEXIT
/* int atexit(void (*)(void)) -- register an exit handler.
*/
#define MAX_EXIT_FUNCS 32 /* arbitrary (32 matches VAX C v3.x docs) */
struct ex_hndlr { long reserved, (*routine)(), arg_count, *arg1_addr; };
static int ex_cnt = 0; /* number of handlers registered so far */
static struct { long dummy_arg; struct ex_hndlr handler; /*(black box)*/
} ex_data[MAX_EXIT_FUNCS]; /* static handler data */
extern unsigned long sys$dclexh();
int atexit( function )
void (*function)(); /* note: actually gets called with 1 arg */
{
if ( ex_cnt < MAX_EXIT_FUNCS ) {
ex_data[ex_cnt].dummy_arg = 0; /* ultimately receives exit reason */
ex_data[ex_cnt].handler.reserved = 0;
ex_data[ex_cnt].handler.routine = (long (*)()) function;
ex_data[ex_cnt].handler.arg_count = 1; /*(required)*/
ex_data[ex_cnt].handler.arg1_addr = &ex_data[ex_cnt].dummy_arg;
(void)sys$dclexh(&ex_data[ex_cnt].handler); /* declare exit handler */
return ++ex_cnt; /*(non-zero)*/
} else
return 0;
}
#endif /*!SUPPRESS_ATEXIT*/
#ifndef SUPPRESS_RENAME
/* int rename(const char *, const char *) -- rename a file (on same device).
*/
#ifndef EVMSERR
#include <errno.h>
#define C$$TRANSLATE(status) (errno = EVMSERR, vaxc$errno = (status))
#endif
extern unsigned long lib$rename_file();
int rename( old_name, new_name )
const char *old_name;
const char *new_name;
{
struct dsc { unsigned short len, mbz; const char *adr; } old_dsc, new_dsc;
unsigned long status;
/* put strings into descriptors and call run-time library routine */
new_dsc.mbz = old_dsc.mbz = 0; /* type and class unspecified */
old_dsc.len = strlen( old_dsc.adr = old_name );
new_dsc.len = strlen( new_dsc.adr = new_name );
status = lib$rename_file(&old_dsc, &new_dsc); /* omit optional args */
if ( !(status & 1) ) { /* even => failure */
C$$TRANSLATE(status);
return -1;
} else /* odd => success */
return 0;
}
#endif /*!SUPPRESS_RENAME*/
#ifndef SUPPRESS_QSORT
/* void qsort(void *, size_t, size_t, int (*)()) -- sort arbitrary collection.
*/
extern char *malloc(); /* assume no alloca() available */
extern void free();
void qsort( base, count, size, compare )
char *base;
int count;
REG int size;
int (*compare)();
{
REG int i, cmp;
REG char *next, *prev, *tmp = 0;
char wrk_buf[512];
/* just use a shuffle sort (tradeoff between efficiency & simplicity) */
/* [Optimal if already sorted; worst case when initially reversed.] */
for ( next = base, i = 1; i < count; i++ ) {
prev = next, next += size; /* increment front pointer */
if ( (cmp = (*compare)( next, prev)) < 0 ) {
/* found element out of order; move other(s) up then re-insert it */
if ( !tmp ) tmp = size > (int)(sizeof wrk_buf) ? malloc(size) : wrk_buf;
memcpy( tmp, next, size); /* save smaller element */
while ( cmp < 0 ) {
memcpy( prev + size, prev, size); /* move larger elem. up */
prev -= size; /* decrement back pointer */
cmp = (prev >= base ? (*compare)( tmp, prev) : 0);
}
memcpy( prev + size, tmp, size); /* restore small element */
}
}
if ( tmp != 0 && tmp != wrk_buf ) free(tmp);
return;
}
#endif /*!SUPPRESS_QSORT*/
#endif /*VERYOLD_VMS*/
|