OSDN Git Service

Initial Import
[nethackexpress/trunk.git] / sys / vms / oldcrtl.c
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   */
4
5 #ifdef VERYOLD_VMS
6 /*
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.
9  *
10  *      atexit, memcmp, memcpy, qsort, rename, vprintf, vsprintf
11  *
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].
15  *
16  */
17 #define REG register
18 #define const
19
20 #ifndef SUPPRESS_MEM_FUNCS
21 /* note: hand optimized for VAX (hardware pre-decrement & post-increment) */
22
23 /* void *memset(void *, int, size_t) -- fill chunk of memory.
24 */
25 char *memset( dst, fil, cnt )
26 REG char *dst;
27 REG char  fil;
28 REG int   cnt;
29 {
30     char *dst_p = dst;
31     while ( --cnt >= 0 )
32         *dst++ = fil;
33     return dst_p;
34 }
35
36 /* void *memcpy(void *, const void *, size_t) -- copy chunk of memory.
37 */
38 char *memcpy( dst, src, cnt )
39 REG char       *dst;
40 REG const char *src;
41 REG int         cnt;
42 {
43     char *dst_p = dst;
44     while ( --cnt >= 0 )
45         *dst++ = *src++;
46     return dst_p;
47 }
48
49 /* void *memmove(void *, const void *, size_t) -- copy possibly overlapping mem.
50 */
51 char *memmove( dst, src, cnt )
52 REG char       *dst;
53 REG const char *src;
54 REG int         cnt;
55 {
56     char *dst_p = dst;
57     if ( src == dst || cnt <= 0 ) {
58         ;       /* do nothing */
59     } else if ( dst < src || dst >= src + cnt ) {
60         while ( --cnt >= 0 )
61             *dst++ = *src++;
62     } else {    /* work backwards */
63         dst += cnt,  src += cnt;
64         while ( --cnt >= 0 )
65             *--dst = *--src;
66     }
67     return dst_p;
68 }
69
70 /* void *memchr(const void *, int, size_t) -- search for a byte.
71 */
72 char *memchr( buf, byt, len )
73 REG const char *buf;
74 REG char                byt;
75 REG int         len;
76 {
77     while ( --len >= 0 )
78         if ( *buf++ == byt )    /* found */
79             return (char *)--buf;
80     return (char *)0;       /* not found */
81 }
82
83 /* int memcmp(const void *, const void *, size_t) -- compare two chunks.
84 */
85 int memcmp( buf1, buf2, len )
86 REG const char *buf1;
87 REG const char *buf2;
88 REG int         len;
89 {
90     while ( --len >= 0 )
91         if ( *buf1++ != *buf2++ )
92             return (*--buf1 - *--buf2);
93     return 0;   /* buffers matched */
94 }
95 #endif /*!SUPPRESS_MEM_FUNCS*/
96
97
98 #ifndef SUPPRESS_ATEXIT
99 /* int atexit(void (*)(void)) -- register an exit handler.
100 */
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();
107
108 int atexit( function )
109     void (*function)();         /* note: actually gets called with 1 arg */
110 {
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)*/
119     } else
120         return 0;
121 }
122 #endif /*!SUPPRESS_ATEXIT*/
123
124
125 #ifndef SUPPRESS_RENAME
126 /* int rename(const char *, const char *) -- rename a file (on same device).
127 */
128 #ifndef EVMSERR
129 #include <errno.h>
130 #define C$$TRANSLATE(status)    (errno = EVMSERR,  vaxc$errno = (status))
131 #endif
132 extern unsigned long lib$rename_file();
133
134 int rename( old_name, new_name )
135     const char *old_name;
136     const char *new_name;
137 {
138     struct dsc { unsigned short len, mbz; const char *adr; } old_dsc, new_dsc;
139     unsigned long status;
140
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);
148         return -1;
149     } else                      /*  odd => success */
150         return 0;
151 }
152 #endif /*!SUPPRESS_RENAME*/
153
154
155 #ifndef SUPPRESS_QSORT
156 /* void qsort(void *, size_t, size_t, int (*)()) -- sort arbitrary collection.
157 */
158 extern char *malloc();                  /* assume no alloca() available */
159 extern void free();
160
161 void qsort( base, count, size, compare )
162     char *base;
163     int   count;
164 REG int   size;
165     int (*compare)();
166 {
167 REG int   i, cmp;
168 REG char *next, *prev, *tmp = 0;
169     char  wrk_buf[512];
170
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 */
179             while ( cmp < 0 ) {
180                 memcpy( prev + size, prev, size);   /* move larger elem. up */
181                 prev -= size;                   /* decrement back pointer */
182                 cmp = (prev >= base ? (*compare)( tmp, prev) : 0);
183             }
184             memcpy( prev + size, tmp, size);    /* restore small element */
185         }
186     }
187     if ( tmp != 0 && tmp != wrk_buf )  free(tmp);
188     return;
189 }
190 #endif /*!SUPPRESS_QSORT*/
191
192 #endif /*VERYOLD_VMS*/