1 /////////////////////////////////////////////////////////////////////////
2 // $Id: osdep.cc 13297 2017-09-14 16:18:12Z vruppert $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 //  Copyright (C) 2001-2017  The Bochs Project
6 //
7 //  This library is free software; you can redistribute it and/or
8 //  modify it under the terms of the GNU Lesser General Public
9 //  License as published by the Free Software Foundation; either
10 //  version 2 of the License, or (at your option) any later version.
11 //
12 //  This library is distributed in the hope that it will be useful,
13 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 //  Lesser General Public License for more details.
16 //
17 //  You should have received a copy of the GNU Lesser General Public
18 //  License along with this library; if not, write to the Free Software
19 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20 /////////////////////////////////////////////////////////////////////////
21 
22 //
23 // osdep.cc
24 //
25 // Provide definition of library functions that are missing on various
26 // systems.  The only reason this is a .cc file rather than a .c file
27 // is so that it can include bochs.h.  Bochs.h includes all the required
28 // system headers, with appropriate #ifdefs for different compilers and
29 // platforms.
30 //
31 
32 #include "bochs.h"
33 #include "bxthread.h"
34 
35 //////////////////////////////////////////////////////////////////////
36 // Missing library functions.  These should work on any platform
37 // that needs them.
38 //////////////////////////////////////////////////////////////////////
39 
40 #if !BX_HAVE_SNPRINTF
41 /* XXX use real snprintf */
42 /* if they don't have snprintf, just use sprintf */
bx_snprintf(char * s,size_t maxlen,const char * format,...)43 int bx_snprintf (char *s, size_t maxlen, const char *format, ...)
44 {
45   va_list arg;
46   int done;
47 
48   va_start (arg, format);
49   done = vsprintf (s, format, arg);
50   va_end (arg);
51 
52   return done;
53 }
54 
55 #endif  /* !BX_HAVE_SNPRINTF */
56 
57 #if !BX_HAVE_VSNPRINTF
bx_vsnprintf(char * s,size_t maxlen,const char * format,va_list arg)58 int bx_vsnprintf (char *s, size_t maxlen, const char *format, va_list arg)
59 {
60   return vsprintf (s, format, arg);
61 }
62 #endif /* !BX_HAVE_VSNPRINTF*/
63 
64 #if (!BX_HAVE_STRTOULL && !BX_HAVE_STRTOUQ)
65 /* taken from glibc-2.2.2: strtod.c, and stripped down a lot.  There are
66    still a few leftover references to decimal points and exponents,
67    but it works for bases 10 and 16 */
68 
69 #define RETURN(val,end)							      \
70     do { if (endptr != NULL) *endptr = (char *) (end);		      \
71 	 return val; } while (0)
72 
bx_strtoull(const char * nptr,char ** endptr,int baseignore)73 Bit64u bx_strtoull (const char *nptr, char **endptr, int baseignore)
74 {
75   int negative;			/* The sign of the number.  */
76   int exponent;			/* Exponent of the number.  */
77 
78   /* Numbers starting `0X' or `0x' have to be processed with base 16.  */
79   int base = 10;
80 
81   /* Number of bits currently in result value.  */
82   int bits;
83 
84   /* Running pointer after the last character processed in the string.  */
85   const char *cp, *tp;
86   /* Start of significant part of the number.  */
87   const char *startp, *start_of_digits;
88   /* Total number of digit and number of digits in integer part.  */
89   int dig_no;
90   /* Contains the last character read.  */
91   char c;
92 
93   Bit64s n = 0;
94   char const *p;
95 
96   /* Prepare number representation.  */
97   exponent = 0;
98   negative = 0;
99   bits = 0;
100 
101   /* Parse string to get maximal legal prefix.  We need the number of
102      characters of the integer part, the fractional part and the exponent.  */
103   cp = nptr - 1;
104   /* Ignore leading white space.  */
105   do
106     c = *++cp;
107   while (isspace (c));
108 
109   /* Get sign of the result.  */
110   if (c == '-')
111   {
112      negative = 1;
113      c = *++cp;
114   }
115   else if (c == '+')
116     c = *++cp;
117 
118   if (c < '0' || c > '9')
119   {
120      /* It is really a text we do not recognize.  */
121      RETURN (0, nptr);
122   }
123 
124   /* First look whether we are faced with a hexadecimal number.  */
125   if (c == '0' && tolower (cp[1]) == 'x')
126   {
127      /* Okay, it is a hexa-decimal number.  Remember this and skip
128         the characters.  BTW: hexadecimal numbers must not be
129         grouped.  */
130      base = 16;
131      cp += 2;
132      c = *cp;
133   }
134 
135   /* Record the start of the digits, in case we will check their grouping.  */
136   start_of_digits = startp = cp;
137 
138   /* Ignore leading zeroes.  This helps us to avoid useless computations.  */
139   while (c == '0')
140     c = *++cp;
141 
142   /* If no other digit but a '0' is found the result is 0.0.
143      Return current read pointer.  */
144   if ((c < '0' || c > '9')
145       && (base == 16 && (c < tolower ('a') || c > tolower ('f')))
146       && (base == 16 && (cp == start_of_digits || tolower (c) != 'p'))
147       && (base != 16 && tolower (c) != 'e'))
148     {
149       tp = start_of_digits;
150       /* If TP is at the start of the digits, there was no correctly
151 	 grouped prefix of the string; so no number found.  */
152       RETURN (0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp);
153     }
154 
155   /* Remember first significant digit and read following characters until the
156      decimal point, exponent character or any non-FP number character.  */
157   startp = cp;
158   dig_no = 0;
159   while (1)
160   {
161       if ((c >= '0' && c <= '9')
162 	  || (base == 16 && tolower (c) >= 'a' && tolower (c) <= 'f'))
163 	++dig_no;
164       else
165 	break;
166       c = *++cp;
167   }
168 
169   /* The whole string is parsed.  Store the address of the next character.  */
170   if (endptr)
171     *endptr = (char *) cp;
172 
173   if (dig_no == 0)
174     return 0;
175 
176   for (p=start_of_digits; p!=cp; p++) {
177     n = n * (Bit64s)base;
178     c = tolower (*p);
179     c = (c >= 'a') ? (10+c-'a') : c-'0';
180     n = n + (Bit64s)c;
181     //printf ("after shifting in digit %c, n is %lld\n", *p, n);
182   }
183   return negative? -n : n;
184 }
185 #endif  /* !BX_HAVE_STRTOULL */
186 
187 #if BX_TEST_STRTOULL_MAIN
188 /* test driver for strtoull.  Do not compile by default. */
main(int argc,char ** argv)189 int main (int argc, char **argv)
190 {
191   char buf[256], *endbuf;
192   long l;
193   Bit64s ll;
194   while (1) {
195     printf ("Enter a long int: ");
196     fgets (buf, sizeof(buf), stdin);
197     l = strtoul (buf, &endbuf, 10);
198     printf ("As a long, %ld\n", l);
199     printf ("Endbuf is at buf[%d]\n", endbuf-buf);
200     ll = bx_strtoull(buf, &endbuf, 10);
201     printf ("As a long long, %lld\n", ll);
202     printf ("Endbuf is at buf[%d]\n", endbuf-buf);
203   }
204   return 0;
205 }
206 #endif  /* BX_TEST_STRTOULL_MAIN */
207 
208 #if !BX_HAVE_STRDUP
209 /* XXX use real strdup */
bx_strdup(const char * s)210 char *bx_strdup(const char *s)
211 {
212   char *p = malloc (strlen (s) + 1);   // allocate memory
213   if (p != NULL)
214       strcpy (p,s);                    // copy string
215   return p;                            // return the memory
216 }
217 #endif  /* !BX_HAVE_STRDUP */
218 
219 #if !BX_HAVE_STRREV
bx_strrev(char * str)220 char *bx_strrev(char *str)
221 {
222   char *p1, *p2;
223 
224   if (! str || ! *str)
225     return str;
226 
227   for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) {
228     *p1 ^= *p2;
229     *p2 ^= *p1;
230     *p1 ^= *p2;
231   }
232   return str;
233 }
234 #endif  /* !BX_HAVE_STRREV */
235 
236 #if BX_WITH_MACOS
237 namespace std{extern "C" {char *mktemp(char *tpl);}}
238 #endif
239 #if !BX_HAVE_MKSTEMP
bx_mkstemp(char * tpl)240 int bx_mkstemp(char *tpl)
241 {
242   mktemp(tpl);
243   return ::open(tpl, O_RDWR | O_CREAT | O_TRUNC
244 #  ifdef O_BINARY
245             | O_BINARY
246 #  endif
247               , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
248 }
249 #endif // !BX_HAVE_MKSTEMP
250 
251 //////////////////////////////////////////////////////////////////////
252 // Missing library functions, implemented for MacOS only
253 //////////////////////////////////////////////////////////////////////
254 
255 #if BX_WITH_MACOS
256 // these functions are part of MacBochs.  They are not intended to be
257 // portable!
258 #include <Devices.h>
259 #include <Files.h>
260 #include <Disks.h>
261 
fd_read(char * buffer,Bit32u offset,Bit32u bytes)262 int fd_read(char *buffer, Bit32u offset, Bit32u bytes)
263 {
264   OSErr err;
265   IOParam param;
266 
267   param.ioRefNum=-5; // Refnum of the floppy disk driver
268   param.ioVRefNum=1;
269   param.ioPosMode=fsFromStart;
270   param.ioPosOffset=offset;
271   param.ioBuffer=buffer;
272   param.ioReqCount=bytes;
273   err = PBReadSync((union ParamBlockRec *)(&param));
274   return param.ioActCount;
275 }
276 
fd_write(char * buffer,Bit32u offset,Bit32u bytes)277 int fd_write(char *buffer, Bit32u offset, Bit32u bytes)
278 {
279   OSErr   err;
280   IOParam param;
281 
282   param.ioRefNum=-5; // Refnum of the floppy disk driver
283   param.ioVRefNum=1;
284   param.ioPosMode=fsFromStart;
285   param.ioPosOffset=offset;
286   param.ioBuffer=buffer;
287   param.ioReqCount=bytes;
288   err = PBWriteSync((union ParamBlockRec *)(&param));
289   return param.ioActCount;
290 }
291 
fd_stat(struct stat * buf)292 int fd_stat(struct stat *buf)
293 {
294   OSErr   err;
295   DrvSts  status;
296   int     result = 0;
297 
298   err = DriveStatus(1, &status);
299   if (status.diskInPlace <1 || status.diskInPlace > 2)
300     result = -1;
301   buf->st_mode = S_IFCHR;
302   return result;
303 }
304 #endif /* BX_WITH_MACOS */
305 
306 //////////////////////////////////////////////////////////////////////
307 // Missing library functions, implemented for MorphOS only
308 //////////////////////////////////////////////////////////////////////
309 
310 #ifdef __MORPHOS__
311 #include <stdio.h>
312 #include <time.h>
313 typedef unsigned int u_int32_t;
314 typedef unsigned short u_int16_t;
315 typedef unsigned char u_int8_t;
316 
fseeko(FILE * stream,off_t offset,int whence)317 int fseeko(FILE *stream, off_t offset, int whence)
318 {
319   while(offset != (long) offset)
320   {
321      long pos = (offset < 0) ? LONG_MIN : LONG_MAX;
322      if(fseek(stream, pos, whence) != 0)
323        return -1;
324      offset -= pos;
325      whence = SEEK_CUR;
326   }
327   return fseek(stream, (long) offset, whence);
328 }
329 
localtime_r(const time_t * timep,struct tm * result)330 struct tm *localtime_r(const time_t *timep, struct tm *result)
331 {
332   struct tm *s = localtime(timep);
333   if(s == NULL)
334     return NULL;
335   *result = *s;
336   return(result);
337 }
338 #endif
339 
340 //////////////////////////////////////////////////////////////////////
341 // New functions to replace library functions
342 //   with OS-independent versions
343 //////////////////////////////////////////////////////////////////////
344 
345 #if BX_HAVE_REALTIME_USEC
346 #if defined(WIN32)
347 static Bit64u last_realtime64_top = 0;
348 static Bit64u last_realtime64_bottom = 0;
349 
bx_get_realtime64_usec(void)350 Bit64u bx_get_realtime64_usec(void)
351 {
352   Bit64u new_bottom = ((Bit64u) GetTickCount()) & BX_CONST64(0x0FFFFFFFF);
353   if(new_bottom < last_realtime64_bottom) {
354     last_realtime64_top += BX_CONST64(0x0000000100000000);
355   }
356   last_realtime64_bottom = new_bottom;
357   Bit64u interim_realtime64 =
358     (last_realtime64_top & BX_CONST64(0xFFFFFFFF00000000)) |
359     (new_bottom          & BX_CONST64(0x00000000FFFFFFFF));
360   return interim_realtime64*(BX_CONST64(1000));
361 }
362 #elif BX_HAVE_GETTIMEOFDAY
bx_get_realtime64_usec(void)363 Bit64u bx_get_realtime64_usec(void)
364 {
365   timeval thetime;
366   gettimeofday(&thetime,0);
367   Bit64u mytime;
368   mytime=(Bit64u)thetime.tv_sec*(Bit64u)1000000+(Bit64u)thetime.tv_usec;
369   return mytime;
370 }
371 #endif
372 #endif
373