/* SCCS Id: @(#)oldcrtl.c 3.0 90/05/24 /* Pat Rankin May'90 */ /* VMS NetHack support, not needed for vms 4.6,4.7,or 5.x. */ #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 * is available) to avoid the need for vprintf & vsprintf]. * */ #define REG register #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 ) /*[functionally equivalent to memmove()]*/ REG char *dst; REG 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 char *buf; REG char byt; REG int len; { while ( --len >= 0 ) if ( *buf++ == byt ) /* found */ return --buf; return (char *)0; /* not found */ } /* int memcmp(const void *, const void *, size_t) -- compare two chunks. */ int memcmp( buf1, buf2, len ) REG char *buf1; REG 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 */ int atexit( function ) int (*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 = function; ex_data[ex_cnt].handler.arg_count = 1; /*(required)*/ ex_data[ex_cnt].handler.arg1_addr = &ex_data[ex_cnt].dummy_arg; 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 #define C$$TRANSLATE(status) (errno = EVMSERR, vaxc$errno = (status)) #endif int rename( old_name, new_name ) char *old_name; char *new_name; { struct _dsc { int len; char *adr; } old_dsc, new_dsc; unsigned long status, LIB$RENAME_FILE(); /* put strings into descriptors and call run-time library routine */ 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. */ 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], *malloc(); /* assume no alloca() available */ /* 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 > 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*/