1 /* aNetHack 0.0.1 oldcrtl.c $ANH-Date: 1432512789 2015/05/25 00:13:09 $ $ANH-Branch: master $:$ANH-Revision: 1.8 $ */
2 /* Pat Rankin May'90 */
3 /* VMS aNetHack support, not needed for vms 4.6,4.7,5.x,or later */
7 * The following routines are used by aNetHack 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.
37 /* void *memcpy(void *, const void *, size_t) -- copy chunk of memory.
51 /* void *memmove(void *, const void *, size_t) -- copy possibly overlapping
55 memmove(dst
, src
, cnt
)
61 if (src
== dst
|| cnt
<= 0) {
63 } else if (dst
< src
|| dst
>= src
+ cnt
) {
66 } else { /* work backwards */
67 dst
+= cnt
, src
+= cnt
;
74 /* void *memchr(const void *, int, size_t) -- search for a byte.
83 if (*buf
++ == byt
) /* found */
84 return (char *) --buf
;
85 return (char *) 0; /* not found */
88 /* int memcmp(const void *, const void *, size_t) -- compare two chunks.
91 memcmp(buf1
, buf2
, len
)
97 if (*buf1
++ != *buf2
++)
98 return (*--buf1
- *--buf2
);
99 return 0; /* buffers matched */
101 #endif /*!SUPPRESS_MEM_FUNCS*/
103 #ifndef SUPPRESS_ATEXIT
104 /* int atexit(void (*)(void)) -- register an exit handler.
106 #define MAX_EXIT_FUNCS 32 /* arbitrary (32 matches VAX C v3.x docs) */
108 long reserved
, (*routine
)(), arg_count
, *arg1_addr
;
110 static int ex_cnt
= 0; /* number of handlers registered so far */
113 struct ex_hndlr handler
; /*(black box)*/
114 } ex_data
[MAX_EXIT_FUNCS
]; /* static handler data */
115 extern unsigned long sys$
dclexh();
119 void (*function
)(); /* note: actually gets called with 1 arg */
121 if (ex_cnt
< MAX_EXIT_FUNCS
) {
122 ex_data
[ex_cnt
].dummy_arg
= 0; /* ultimately receives exit reason */
123 ex_data
[ex_cnt
].handler
.reserved
= 0;
124 ex_data
[ex_cnt
].handler
.routine
= (long (*) ()) function
;
125 ex_data
[ex_cnt
].handler
.arg_count
= 1; /*(required)*/
126 ex_data
[ex_cnt
].handler
.arg1_addr
= &ex_data
[ex_cnt
].dummy_arg
;
128 &ex_data
[ex_cnt
].handler
); /* declare exit handler */
129 return ++ex_cnt
; /*(non-zero)*/
133 #endif /*!SUPPRESS_ATEXIT*/
135 #ifndef SUPPRESS_RENAME
136 /* int rename(const char *, const char *) -- rename a file (on same device).
140 #define C$$TRANSLATE(status) (errno = EVMSERR, vaxc$errno = (status))
142 extern unsigned long lib$
rename_file();
145 rename(old_name
, new_name
)
146 const char *old_name
;
147 const char *new_name
;
150 unsigned short len
, mbz
;
153 unsigned long status
;
155 /* put strings into descriptors and call run-time library routine */
156 new_dsc
.mbz
= old_dsc
.mbz
= 0; /* type and class unspecified */
157 old_dsc
.len
= strlen(old_dsc
.adr
= old_name
);
158 new_dsc
.len
= strlen(new_dsc
.adr
= new_name
);
159 status
= lib$
rename_file(&old_dsc
, &new_dsc
); /* omit optional args */
160 if (!(status
& 1)) { /* even => failure */
161 C$$
TRANSLATE(status
);
163 } else /* odd => success */
166 #endif /*!SUPPRESS_RENAME*/
168 #ifndef SUPPRESS_QSORT
169 /* void qsort(void *, size_t, size_t, int (*)()) -- sort arbitrary collection.
171 extern char *malloc(); /* assume no alloca() available */
175 qsort(base
, count
, size
, compare
)
182 REG
char *next
, *prev
, *tmp
= 0;
185 /* just use a shuffle sort (tradeoff between efficiency & simplicity) */
186 /* [Optimal if already sorted; worst case when initially reversed.] */
187 for (next
= base
, i
= 1; i
< count
; i
++) {
188 prev
= next
, next
+= size
; /* increment front pointer */
189 if ((cmp
= (*compare
)(next
, prev
)) < 0) {
190 /* found element out of order; move other(s) up then re-insert it
193 tmp
= size
> (int) (sizeof wrk_buf
) ? malloc(size
) : wrk_buf
;
194 memcpy(tmp
, next
, size
); /* save smaller element */
196 memcpy(prev
+ size
, prev
, size
); /* move larger elem. up */
197 prev
-= size
; /* decrement back pointer */
198 cmp
= (prev
>= base
? (*compare
)(tmp
, prev
) : 0);
200 memcpy(prev
+ size
, tmp
, size
); /* restore small element */
203 if (tmp
!= 0 && tmp
!= wrk_buf
)
207 #endif /*!SUPPRESS_QSORT*/
209 #endif /*VERYOLD_VMS*/