1 /* SCCS Id: @(#)oldcrtl.c 3.4 1995/06/01 */
2 /* Pat Rankin May'90 */
3 /* VMS NetHack support, not needed for vms 4.6,4.7,5.x,or later */
7 * The following routines are used by NetHack but were not available
8 * from the C Run-Time Library (VAXCRTL) prior to VMS V4.6.
10 * atexit, memcmp, memcpy, qsort, rename, vprintf, vsprintf
12 * Most of them are implemented here, but others will have to be worked
13 * around in another fashion [such as '#define USE_OLDARGS' (even though
14 * <varargs.h> is available) to avoid the need for vprintf & vsprintf].
20 #ifndef SUPPRESS_MEM_FUNCS
21 /* note: hand optimized for VAX (hardware pre-decrement & post-increment) */
23 /* void *memset(void *, int, size_t) -- fill chunk of memory.
25 char *memset( dst, fil, cnt )
36 /* void *memcpy(void *, const void *, size_t) -- copy chunk of memory.
38 char *memcpy( dst, src, cnt )
49 /* void *memmove(void *, const void *, size_t) -- copy possibly overlapping mem.
51 char *memmove( dst, src, cnt )
57 if ( src == dst || cnt <= 0 ) {
59 } else if ( dst < src || dst >= src + cnt ) {
62 } else { /* work backwards */
63 dst += cnt, src += cnt;
70 /* void *memchr(const void *, int, size_t) -- search for a byte.
72 char *memchr( buf, byt, len )
78 if ( *buf++ == byt ) /* found */
80 return (char *)0; /* not found */
83 /* int memcmp(const void *, const void *, size_t) -- compare two chunks.
85 int memcmp( buf1, buf2, len )
91 if ( *buf1++ != *buf2++ )
92 return (*--buf1 - *--buf2);
93 return 0; /* buffers matched */
95 #endif /*!SUPPRESS_MEM_FUNCS*/
98 #ifndef SUPPRESS_ATEXIT
99 /* int atexit(void (*)(void)) -- register an exit handler.
101 #define MAX_EXIT_FUNCS 32 /* arbitrary (32 matches VAX C v3.x docs) */
102 struct ex_hndlr { long reserved, (*routine)(), arg_count, *arg1_addr; };
103 static int ex_cnt = 0; /* number of handlers registered so far */
104 static struct { long dummy_arg; struct ex_hndlr handler; /*(black box)*/
105 } ex_data[MAX_EXIT_FUNCS]; /* static handler data */
106 extern unsigned long sys$dclexh();
108 int atexit( function )
109 void (*function)(); /* note: actually gets called with 1 arg */
111 if ( ex_cnt < MAX_EXIT_FUNCS ) {
112 ex_data[ex_cnt].dummy_arg = 0; /* ultimately receives exit reason */
113 ex_data[ex_cnt].handler.reserved = 0;
114 ex_data[ex_cnt].handler.routine = (long (*)()) function;
115 ex_data[ex_cnt].handler.arg_count = 1; /*(required)*/
116 ex_data[ex_cnt].handler.arg1_addr = &ex_data[ex_cnt].dummy_arg;
117 (void)sys$dclexh(&ex_data[ex_cnt].handler); /* declare exit handler */
118 return ++ex_cnt; /*(non-zero)*/
122 #endif /*!SUPPRESS_ATEXIT*/
125 #ifndef SUPPRESS_RENAME
126 /* int rename(const char *, const char *) -- rename a file (on same device).
130 #define C$$TRANSLATE(status) (errno = EVMSERR, vaxc$errno = (status))
132 extern unsigned long lib$rename_file();
134 int rename( old_name, new_name )
135 const char *old_name;
136 const char *new_name;
138 struct dsc { unsigned short len, mbz; const char *adr; } old_dsc, new_dsc;
139 unsigned long status;
141 /* put strings into descriptors and call run-time library routine */
142 new_dsc.mbz = old_dsc.mbz = 0; /* type and class unspecified */
143 old_dsc.len = strlen( old_dsc.adr = old_name );
144 new_dsc.len = strlen( new_dsc.adr = new_name );
145 status = lib$rename_file(&old_dsc, &new_dsc); /* omit optional args */
146 if ( !(status & 1) ) { /* even => failure */
147 C$$TRANSLATE(status);
149 } else /* odd => success */
152 #endif /*!SUPPRESS_RENAME*/
155 #ifndef SUPPRESS_QSORT
156 /* void qsort(void *, size_t, size_t, int (*)()) -- sort arbitrary collection.
158 extern char *malloc(); /* assume no alloca() available */
161 void qsort( base, count, size, compare )
168 REG char *next, *prev, *tmp = 0;
171 /* just use a shuffle sort (tradeoff between efficiency & simplicity) */
172 /* [Optimal if already sorted; worst case when initially reversed.] */
173 for ( next = base, i = 1; i < count; i++ ) {
174 prev = next, next += size; /* increment front pointer */
175 if ( (cmp = (*compare)( next, prev)) < 0 ) {
176 /* found element out of order; move other(s) up then re-insert it */
177 if ( !tmp ) tmp = size > (int)(sizeof wrk_buf) ? malloc(size) : wrk_buf;
178 memcpy( tmp, next, size); /* save smaller element */
180 memcpy( prev + size, prev, size); /* move larger elem. up */
181 prev -= size; /* decrement back pointer */
182 cmp = (prev >= base ? (*compare)( tmp, prev) : 0);
184 memcpy( prev + size, tmp, size); /* restore small element */
187 if ( tmp != 0 && tmp != wrk_buf ) free(tmp);
190 #endif /*!SUPPRESS_QSORT*/
192 #endif /*VERYOLD_VMS*/