- added instructions how to update the online documentation
[bochs-mirror.git] / osdep.cc
blob4272de19b819a3d8a0a3ae5ba03cffe6a71e51f5
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: osdep.cc,v 1.18 2008/02/05 22:57:40 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2001 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 // osdep.cc
30 // Provide definition of library functions that are missing on various
31 // systems. The only reason this is a .cc file rather than a .c file
32 // is so that it can include bochs.h. Bochs.h includes all the required
33 // system headers, with appropriate #ifdefs for different compilers and
34 // platforms.
37 #include "bochs.h"
39 //////////////////////////////////////////////////////////////////////
40 // Missing library functions. These should work on any platform
41 // that needs them.
42 //////////////////////////////////////////////////////////////////////
44 #if !BX_HAVE_SNPRINTF
45 /* XXX use real snprintf */
46 /* if they don't have snprintf, just use sprintf */
47 int bx_snprintf (char *s, size_t maxlen, const char *format, ...)
49 va_list arg;
50 int done;
52 va_start (arg, format);
53 done = vsprintf (s, format, arg);
54 va_end (arg);
56 return done;
59 #endif /* !BX_HAVE_SNPRINTF */
61 #if !BX_HAVE_VSNPRINTF
62 int bx_vsnprintf (char *s, size_t maxlen, const char *format, va_list arg)
64 return vsprintf (s, format, arg);
66 #endif /* !BX_HAVE_VSNPRINTF*/
68 #if (!BX_HAVE_STRTOULL && !BX_HAVE_STRTOUQ)
69 /* taken from glibc-2.2.2: strtod.c, and stripped down a lot. There are
70 still a few leftover references to decimal points and exponents,
71 but it works for bases 10 and 16 */
73 #define RETURN(val,end) \
74 do { if (endptr != NULL) *endptr = (char *) (end); \
75 return val; } while (0)
77 Bit64u
78 bx_strtoull (const char *nptr, char **endptr, int baseignore)
80 int negative; /* The sign of the number. */
81 int exponent; /* Exponent of the number. */
83 /* Numbers starting `0X' or `0x' have to be processed with base 16. */
84 int base = 10;
86 /* Number of bits currently in result value. */
87 int bits;
89 /* Running pointer after the last character processed in the string. */
90 const char *cp, *tp;
91 /* Start of significant part of the number. */
92 const char *startp, *start_of_digits;
93 /* Total number of digit and number of digits in integer part. */
94 int dig_no;
95 /* Contains the last character read. */
96 char c;
98 Bit64s n = 0;
99 char const *p;
101 /* Prepare number representation. */
102 exponent = 0;
103 negative = 0;
104 bits = 0;
106 /* Parse string to get maximal legal prefix. We need the number of
107 characters of the integer part, the fractional part and the exponent. */
108 cp = nptr - 1;
109 /* Ignore leading white space. */
111 c = *++cp;
112 while (isspace (c));
114 /* Get sign of the result. */
115 if (c == '-')
117 negative = 1;
118 c = *++cp;
120 else if (c == '+')
121 c = *++cp;
123 if (c < '0' || c > '9')
125 /* It is really a text we do not recognize. */
126 RETURN (0, nptr);
129 /* First look whether we are faced with a hexadecimal number. */
130 if (c == '0' && tolower (cp[1]) == 'x')
132 /* Okay, it is a hexa-decimal number. Remember this and skip
133 the characters. BTW: hexadecimal numbers must not be
134 grouped. */
135 base = 16;
136 cp += 2;
137 c = *cp;
140 /* Record the start of the digits, in case we will check their grouping. */
141 start_of_digits = startp = cp;
143 /* Ignore leading zeroes. This helps us to avoid useless computations. */
144 while (c == '0')
145 c = *++cp;
147 /* If no other digit but a '0' is found the result is 0.0.
148 Return current read pointer. */
149 if ((c < '0' || c > '9')
150 && (base == 16 && (c < tolower ('a') || c > tolower ('f')))
151 && (base == 16 && (cp == start_of_digits || tolower (c) != 'p'))
152 && (base != 16 && tolower (c) != 'e'))
154 tp = start_of_digits;
155 /* If TP is at the start of the digits, there was no correctly
156 grouped prefix of the string; so no number found. */
157 RETURN (0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp);
160 /* Remember first significant digit and read following characters until the
161 decimal point, exponent character or any non-FP number character. */
162 startp = cp;
163 dig_no = 0;
164 while (1)
166 if ((c >= '0' && c <= '9')
167 || (base == 16 && tolower (c) >= 'a' && tolower (c) <= 'f'))
168 ++dig_no;
169 else
170 break;
171 c = *++cp;
174 /* The whole string is parsed. Store the address of the next character. */
175 if (endptr)
176 *endptr = (char *) cp;
178 if (dig_no == 0)
179 return 0;
181 for (p=start_of_digits; p!=cp; p++) {
182 n = n * (Bit64s)base;
183 c = tolower (*p);
184 c = (c >= 'a') ? (10+c-'a') : c-'0';
185 n = n + (Bit64s)c;
186 //printf ("after shifting in digit %c, n is %lld\n", *p, n);
188 return negative? -n : n;
190 #endif /* !BX_HAVE_STRTOULL */
192 #if BX_TEST_STRTOULL_MAIN
193 /* test driver for strtoull. Do not compile by default. */
194 int main (int argc, char **argv)
196 char buf[256], *endbuf;
197 long l;
198 Bit64s ll;
199 while (1) {
200 printf ("Enter a long int: ");
201 gets (buf);
202 l = strtoul (buf, &endbuf, 10);
203 printf ("As a long, %ld\n", l);
204 printf ("Endbuf is at buf[%d]\n", endbuf-buf);
205 ll = bx_strtoull (buf, &endbuf, 10);
206 printf ("As a long long, %lld\n", ll);
207 printf ("Endbuf is at buf[%d]\n", endbuf-buf);
209 return 0;
211 #endif /* BX_TEST_STRTOULL_MAIN */
213 #if !BX_HAVE_STRDUP
214 /* XXX use real strdup */
215 char *bx_strdup(const char *str)
217 char *temp;
219 temp = (char*)malloc(strlen(str)+1);
220 sprintf(temp, "%s", str);
221 return temp;
223 // Well, I'm sure this isn't how strdup is REALLY implemented,
224 // but it works...
226 #endif /* !BX_HAVE_STRDUP */
228 #if !BX_HAVE_STRREV
229 char *bx_strrev(char *str)
231 char *p1, *p2;
233 if (! str || ! *str)
234 return str;
236 for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) {
237 *p1 ^= *p2;
238 *p2 ^= *p1;
239 *p1 ^= *p2;
241 return str;
243 #endif /* !BX_HAVE_STRREV */
245 #if BX_WITH_MACOS
246 namespace std{extern "C" {char *mktemp(char *tpl);}}
247 #endif
248 #if !BX_HAVE_MKSTEMP
249 int bx_mkstemp(char *tpl)
251 mktemp(tpl);
252 return ::open(tpl, O_RDWR | O_CREAT | O_TRUNC
253 # ifdef O_BINARY
254 | O_BINARY
255 # endif
256 , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
258 #endif // !BX_HAVE_MKSTEMP
260 //////////////////////////////////////////////////////////////////////
261 // Missing library functions, implemented for MacOS only
262 //////////////////////////////////////////////////////////////////////
264 #if BX_WITH_MACOS
265 // these functions are part of MacBochs. They are not intended to be
266 // portable!
267 #include <Devices.h>
268 #include <Files.h>
269 #include <Disks.h>
271 int fd_read(char *buffer, Bit32u offset, Bit32u bytes)
273 OSErr err;
274 IOParam param;
276 param.ioRefNum=-5; // Refnum of the floppy disk driver
277 param.ioVRefNum=1;
278 param.ioPosMode=fsFromStart;
279 param.ioPosOffset=offset;
280 param.ioBuffer=buffer;
281 param.ioReqCount=bytes;
282 err = PBReadSync((union ParamBlockRec *)(&param));
283 return param.ioActCount;
286 int fd_write(char *buffer, Bit32u offset, Bit32u bytes)
288 OSErr err;
289 IOParam param;
291 param.ioRefNum=-5; // Refnum of the floppy disk driver
292 param.ioVRefNum=1;
293 param.ioPosMode=fsFromStart;
294 param.ioPosOffset=offset;
295 param.ioBuffer=buffer;
296 param.ioReqCount=bytes;
297 err = PBWriteSync((union ParamBlockRec *)(&param));
298 return param.ioActCount;
301 int fd_stat(struct stat *buf)
303 OSErr err;
304 DrvSts status;
305 int result;
307 result = 0;
308 err = DriveStatus(1, &status);
309 if (status.diskInPlace <1 || status.diskInPlace > 2)
310 result = -1;
311 buf->st_mode = S_IFCHR;
312 return result;
314 #endif /* BX_WITH_MACOS */
318 //////////////////////////////////////////////////////////////////////
319 // New functions to replace library functions
320 // with OS-independent versions
321 //////////////////////////////////////////////////////////////////////
323 #if BX_HAVE_REALTIME_USEC
324 #if defined(WIN32)
325 static Bit64u last_realtime64_top = 0;
326 static Bit64u last_realtime64_bottom = 0;
328 Bit64u bx_get_realtime64_usec(void)
330 Bit64u new_bottom = ((Bit64u) GetTickCount()) & BX_CONST64(0x0FFFFFFFF);
331 if(new_bottom < last_realtime64_bottom) {
332 last_realtime64_top += BX_CONST64(0x0000000100000000);
334 last_realtime64_bottom = new_bottom;
335 Bit64u interim_realtime64 =
336 (last_realtime64_top & BX_CONST64(0xFFFFFFFF00000000)) |
337 (new_bottom & BX_CONST64(0x00000000FFFFFFFF));
338 return interim_realtime64*(BX_CONST64(1000));
340 #elif BX_HAVE_GETTIMEOFDAY
341 Bit64u bx_get_realtime64_usec(void)
343 timeval thetime;
344 gettimeofday(&thetime,0);
345 Bit64u mytime;
346 mytime=(Bit64u)thetime.tv_sec*(Bit64u)1000000+(Bit64u)thetime.tv_usec;
347 return mytime;
349 #endif
350 #endif