NHDT->ANH, nethack->anethack, nhdat->anhdat
[aNetHack.git] / sys / vms / oldcrtl.c
blob130cc24f8599207e219d0707c545299c3fa1d49e
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 */
5 #ifdef VERYOLD_VMS
6 /*
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].
17 #define REG register
18 #define const
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 *
26 memset(dst, fil, cnt)
27 REG char *dst;
28 REG char fil;
29 REG int cnt;
31 char *dst_p = dst;
32 while (--cnt >= 0)
33 *dst++ = fil;
34 return dst_p;
37 /* void *memcpy(void *, const void *, size_t) -- copy chunk of memory.
39 char *
40 memcpy(dst, src, cnt)
41 REG char *dst;
42 REG const char *src;
43 REG int cnt;
45 char *dst_p = dst;
46 while (--cnt >= 0)
47 *dst++ = *src++;
48 return dst_p;
51 /* void *memmove(void *, const void *, size_t) -- copy possibly overlapping
52 * mem.
54 char *
55 memmove(dst, src, cnt)
56 REG char *dst;
57 REG const char *src;
58 REG int cnt;
60 char *dst_p = dst;
61 if (src == dst || cnt <= 0) {
62 ; /* do nothing */
63 } else if (dst < src || dst >= src + cnt) {
64 while (--cnt >= 0)
65 *dst++ = *src++;
66 } else { /* work backwards */
67 dst += cnt, src += cnt;
68 while (--cnt >= 0)
69 *--dst = *--src;
71 return dst_p;
74 /* void *memchr(const void *, int, size_t) -- search for a byte.
76 char *
77 memchr(buf, byt, len)
78 REG const char *buf;
79 REG char byt;
80 REG int len;
82 while (--len >= 0)
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.
90 int
91 memcmp(buf1, buf2, len)
92 REG const char *buf1;
93 REG const char *buf2;
94 REG int len;
96 while (--len >= 0)
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) */
107 struct ex_hndlr {
108 long reserved, (*routine)(), arg_count, *arg1_addr;
110 static int ex_cnt = 0; /* number of handlers registered so far */
111 static struct {
112 long dummy_arg;
113 struct ex_hndlr handler; /*(black box)*/
114 } ex_data[MAX_EXIT_FUNCS]; /* static handler data */
115 extern unsigned long sys$dclexh();
118 atexit(function)
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;
127 (void) sys$dclexh(
128 &ex_data[ex_cnt].handler); /* declare exit handler */
129 return ++ex_cnt; /*(non-zero)*/
130 } else
131 return 0;
133 #endif /*!SUPPRESS_ATEXIT*/
135 #ifndef SUPPRESS_RENAME
136 /* int rename(const char *, const char *) -- rename a file (on same device).
138 #ifndef EVMSERR
139 #include <errno.h>
140 #define C$$TRANSLATE(status) (errno = EVMSERR, vaxc$errno = (status))
141 #endif
142 extern unsigned long lib$rename_file();
145 rename(old_name, new_name)
146 const char *old_name;
147 const char *new_name;
149 struct dsc {
150 unsigned short len, mbz;
151 const char *adr;
152 } old_dsc, new_dsc;
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);
162 return -1;
163 } else /* odd => success */
164 return 0;
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 */
172 extern void free();
174 void
175 qsort(base, count, size, compare)
176 char *base;
177 int count;
178 REG int size;
179 int (*compare)();
181 REG int i, cmp;
182 REG char *next, *prev, *tmp = 0;
183 char wrk_buf[512];
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
192 if (!tmp)
193 tmp = size > (int) (sizeof wrk_buf) ? malloc(size) : wrk_buf;
194 memcpy(tmp, next, size); /* save smaller element */
195 while (cmp < 0) {
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)
204 free(tmp);
205 return;
207 #endif /*!SUPPRESS_QSORT*/
209 #endif /*VERYOLD_VMS*/