Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / OS_NS_stdlib.cpp
blob1bef126ab39ece8416e13ab6b0918dcba2eb65d7
1 #include "ace/OS_NS_stdlib.h"
3 #include "ace/Default_Constants.h"
5 #if !defined (ACE_HAS_INLINED_OSCALLS)
6 # include "ace/OS_NS_stdlib.inl"
7 #endif /* ACE_HAS_INLINED_OSCALLS */
9 #include "ace/OS_Memory.h"
11 #include "ace/OS_NS_unistd.h"
12 #include "ace/OS_NS_ctype.h"
14 #if defined (ACE_LACKS_MKTEMP) \
15 || defined (ACE_LACKS_MKSTEMP) \
16 || defined (ACE_LACKS_REALPATH)
17 # include "ace/OS_NS_stdio.h"
18 # include "ace/OS_NS_sys_stat.h"
19 #endif /* ACE_LACKS_MKTEMP || ACE_LACKS_MKSTEMP || ACE_LACKS_REALPATH */
21 #if defined (ACE_LACKS_MKSTEMP)
22 # include "ace/OS_NS_fcntl.h"
23 # include "ace/OS_NS_ctype.h"
24 # include "ace/OS_NS_sys_time.h"
25 # include "ace/OS_NS_Thread.h"
26 # include "ace/Numeric_Limits.h"
27 #endif /* ACE_LACKS_MKSTEMP */
29 #if defined (ACE_HAS_ALLOC_HOOKS)
30 # include "ace/Malloc_Base.h"
31 #endif /* ACE_HAS_ALLOC_HOOKS */
33 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
35 ACE_EXIT_HOOK ACE_OS::exit_hook_ = 0;
37 void *
38 ACE_OS::calloc (size_t elements, size_t sizeof_elements)
40 return ACE_CALLOC_FUNC (elements, sizeof_elements);
43 void
44 ACE_OS::exit (int status)
46 ACE_OS_TRACE ("ACE_OS::exit");
48 #if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
49 // Shut down the ACE_Object_Manager, if it had registered its exit_hook.
50 // With ACE_HAS_NONSTATIC_OBJECT_MANAGER, the ACE_Object_Manager is
51 // instantiated on the main's stack. ::exit () doesn't destroy it.
52 if (exit_hook_)
53 (*exit_hook_) ();
54 #endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */
56 #if defined (ACE_WIN32)
57 ::ExitProcess ((UINT) status);
58 #elif !defined ACE_LACKS_EXIT
59 ::exit (status);
60 #else
61 ACE_UNUSED_ARG (status);
62 #endif /* ACE_WIN32 */
65 void
66 ACE_OS::free (void *ptr)
68 #if defined (ACE_LACKS_FREE)
69 ACE_UNUSED_ARG (ptr);
70 #else
71 ACE_FREE_FUNC (ACE_MALLOC_T (ptr));
72 #endif
75 // You may be asking yourself, why are we doing this? Well, in winbase.h,
76 // MS didn't follow their normal Api_FunctionA and Api_FunctionW style,
77 // so we have to #undef their define to get access to the unicode version.
78 // And because we don't want to #undef this for the users code, we keep
79 // this method in the .cpp file.
80 #if defined (ACE_WIN32) && defined (UNICODE) && !defined (ACE_USES_TCHAR)
81 #undef GetEnvironmentStrings
82 #endif /* ACE_WIN32 && UNICODE !ACE_USES_TCHAR */
84 ACE_TCHAR *
85 ACE_OS::getenvstrings ()
87 #if defined (ACE_WIN32)
88 # if defined (ACE_USES_WCHAR)
89 return ::GetEnvironmentStringsW ();
90 # else /* ACE_USES_WCHAR */
91 return ::GetEnvironmentStrings ();
92 # endif /* ACE_USES_WCHAR */
93 #else /* ACE_WIN32 */
94 ACE_NOTSUP_RETURN (0);
95 #endif /* ACE_WIN32 */
98 // Return a dynamically allocated duplicate of <str>, substituting the
99 // environment variables of form $VAR_NAME. Note that the pointer is
100 // allocated with <ACE_OS::malloc> and must be freed by
101 // <ACE_OS::free>.
102 ACE_TCHAR *
103 ACE_OS::strenvdup (const ACE_TCHAR *str)
105 const ACE_TCHAR * start = 0;
106 if ((start = ACE_OS::strchr (str, ACE_TEXT ('$'))) != 0)
108 ACE_TCHAR buf[ACE_DEFAULT_ARGV_BUFSIZ];
109 size_t var_len = ACE_OS::strcspn (&start[1],
110 ACE_TEXT ("$~!#%^&*()-+=\\|/?,.;:'\"`[]{} \t\n\r"));
111 ACE_OS::strncpy (buf, &start[1], var_len);
112 buf[var_len++] = ACE_TEXT ('\0');
113 # if defined (ACE_WIN32)
114 // Always use the ACE_TCHAR for Windows.
115 ACE_TCHAR *temp = ACE_OS::getenv (buf);
116 # else
117 // Use char * for environment on non-Windows.
118 char *temp = ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (buf));
119 # endif /* ACE_WIN32 */
120 size_t buf_len = ACE_OS::strlen (str) + 1;
121 if (temp != 0)
122 buf_len += ACE_OS::strlen (temp) - var_len;
123 ACE_TCHAR * buf_p =
124 #if defined (ACE_HAS_ALLOC_HOOKS)
125 (ACE_TCHAR *) ACE_Allocator::instance()->malloc (buf_len * sizeof (ACE_TCHAR));
126 #else
127 (ACE_TCHAR *) ACE_OS::malloc (buf_len * sizeof (ACE_TCHAR));
128 #endif /* ACE_HAS_ALLOC_HOOKS */
130 if (buf_p == 0)
132 errno = ENOMEM;
133 return 0;
135 ACE_TCHAR * p = buf_p;
136 size_t const len = start - str;
137 ACE_OS::strncpy (p, str, len);
138 p += len;
139 if (temp != 0)
141 # if defined (ACE_WIN32)
142 p = ACE_OS::strecpy (p, temp) - 1;
143 # else
144 p = ACE_OS::strecpy (p, ACE_TEXT_CHAR_TO_TCHAR (temp)) - 1;
145 # endif /* ACE_WIN32 */
147 else
149 ACE_OS::strncpy (p, start, var_len);
150 p += var_len;
151 *p = ACE_TEXT ('\0');
153 ACE_OS::strcpy (p, &start[var_len]);
154 return buf_p;
156 else
157 return ACE_OS::strdup (str);
160 #if !defined (ACE_HAS_ITOA)
161 char *
162 ACE_OS::itoa_emulation (int value, char *string, int radix)
164 char *e = string;
165 char *b = string;
167 // Short circuit if 0
168 if (value == 0)
170 string[0] = '0';
171 string[1] = 0;
172 return string;
175 // If negative and base 10, print a - and then do the
176 // number.
177 if (value < 0 && radix == 10)
179 string[0] = '-';
180 ++b;
181 ++e; // Don't overwrite the negative sign.
182 value = -value; // Drop negative sign so character selection is correct.
185 // Convert to base <radix>, but in reverse order
186 while (value != 0)
188 int const mod = value % radix;
189 value = value / radix;
191 *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10;
194 *e-- = 0;
196 // Now reverse the string to get the correct result
198 while (e > b)
200 char temp = *e;
201 *e = *b;
202 *b = temp;
203 ++b;
204 --e;
207 return string;
209 #endif /* !ACE_HAS_ITOA */
211 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_ITOW)
212 wchar_t *
213 ACE_OS::itow_emulation (int value, wchar_t *string, int radix)
215 wchar_t *e = string;
216 wchar_t *b = string;
218 // Short circuit if 0
220 if (value == 0)
222 string[0] = '0';
223 string[1] = 0;
224 return string;
227 // If negative and base 10, print a - and then do the
228 // number.
230 if (value < 0 && radix == 10)
232 string[0] = '-';
233 b++;
236 // Convert to base <radix>, but in reverse order
238 while (value != 0)
240 int mod = value % radix;
241 value = value / radix;
243 *e++ = (mod < 10) ? '0' + mod : 'a' + mod - 10;
246 *e-- = 0;
248 // Now reverse the string to get the correct result
250 while (e > b)
252 wchar_t temp = *e;
253 *e = *b;
254 *b = temp;
255 ++b;
256 --e;
259 return string;
261 #endif /* ACE_HAS_WCHAR && ACE_LACKS_ITOW */
263 void *
264 ACE_OS::malloc (size_t nbytes)
266 return ACE_MALLOC_FUNC (nbytes);
269 #if defined (ACE_LACKS_MKTEMP) && !defined (ACE_DISABLE_MKTEMP)
270 ACE_TCHAR *
271 ACE_OS::mktemp (ACE_TCHAR *s)
273 ACE_OS_TRACE ("ACE_OS::mktemp");
274 if (s == 0)
275 // check for null template string failed!
276 return 0;
278 ACE_TCHAR *xxxxxx = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX"));
279 if (xxxxxx == 0)
280 // the template string doesn't contain "XXXXXX"!
281 return s;
283 // Find an unused filename for this process. It is assumed
284 // that the user will open the file immediately after
285 // getting this filename back (so, yes, there is a race
286 // condition if multiple threads in a process use the same
287 // template). This appears to match the behavior of the
288 // SunOS 5.5 mktemp().
289 bool found = false;
290 for (ACE_TCHAR letter = ACE_TEXT ('a');
291 letter <= ACE_TEXT ('z');
292 ++letter)
294 ACE_stat sb;
295 ACE_OS::snprintf (xxxxxx, 7,
296 ACE_TEXT ("%05d%c"),
297 (int)ACE_OS::getpid () % 100000,
298 letter);
299 if (ACE_OS::stat (s, &sb) < 0)
301 found = true;
302 break;
305 if (!found)
306 // maximum of 26 unique files per template, per process
307 xxxxxx[0] = ACE_TEXT ('\0');
308 return s;
310 #endif /* ACE_LACKS_MKTEMP && !ACE_DISABLE_MKTEMP */
312 void *
313 ACE_OS::realloc (void *ptr, size_t nbytes)
315 #ifdef ACE_LACKS_REALLOC
316 ACE_UNUSED_ARG (ptr);
317 ACE_UNUSED_ARG (nbytes);
318 ACE_NOTSUP_RETURN (0);
319 #else
320 return ACE_REALLOC_FUNC (ACE_MALLOC_T (ptr), nbytes);
321 #endif
324 #if defined (ACE_LACKS_REALPATH)
325 char *
326 ACE_OS::realpath (const char *file_name,
327 char *resolved_name)
329 ACE_OS_TRACE ("ACE_OS::realpath");
331 if (file_name == 0)
333 // Single Unix Specification V3:
334 // Return an error if parameter is a null pointer.
335 errno = EINVAL;
336 return 0;
339 if (*file_name == '\0')
341 // Single Unix Specification V3:
342 // Return an error if the file_name argument points
343 // to an empty string.
344 errno = ENOENT;
345 return 0;
348 char* rpath;
350 if (resolved_name == 0)
352 // Single Unix Specification V3:
353 // Return an error if parameter is a null pointer.
355 // To match glibc realpath() and Win32 _fullpath() behavior,
356 // allocate room for the return value if resolved_name is
357 // a null pointer.
358 #if defined (ACE_HAS_ALLOC_HOOKS)
359 rpath = static_cast<char*>(ACE_Allocator::instance()->malloc (PATH_MAX));
360 #else
361 rpath = static_cast<char*>(ACE_OS::malloc (PATH_MAX));
362 #endif /* ACE_HAS_ALLOC_HOOKS */
363 if (rpath == 0)
365 errno = ENOMEM;
366 return 0;
369 else
371 rpath = resolved_name;
374 char* dest;
376 if (*file_name != '/')
378 // file_name is relative path so CWD needs to be added
379 if (ACE_OS::getcwd (rpath, PATH_MAX) == 0)
381 if (resolved_name == 0)
382 #if defined (ACE_HAS_ALLOC_HOOKS)
383 ACE_Allocator::instance()->free (rpath);
384 #else
385 ACE_OS::free (rpath);
386 #endif /* ACE_HAS_ALLOC_HOOKS */
387 return 0;
389 dest = ACE_OS::strchr (rpath, '\0');
391 else
393 dest = rpath;
396 #if !defined (ACE_LACKS_SYMLINKS)
397 char expand_buf[PATH_MAX]; // Extra buffer needed to expand symbolic links
398 int nlinks = 0;
399 #endif
401 while (*file_name)
403 *dest++ = '/';
405 // Skip multiple separators
406 while (*file_name == '/')
407 ++file_name;
409 char* start = dest;
411 // Process one path component
412 while (*file_name && *file_name != '/')
414 *dest++ = *file_name++;
415 if (dest - rpath > PATH_MAX)
417 errno = ENAMETOOLONG;
418 if (resolved_name == 0)
419 #if defined (ACE_HAS_ALLOC_HOOKS)
420 ACE_Allocator::instance()->free (rpath);
421 #else
422 ACE_OS::free (rpath);
423 #endif /* ACE_HAS_ALLOC_HOOKS */
424 return 0;
428 if (start == dest) // Are we done?
430 if (dest - rpath > 1)
431 --dest; // Remove trailing separator if not at root
432 break;
434 else if (dest - start == 1 && *start == '.')
436 dest -= 2; // Remove "./"
438 else if (dest - start == 2 && *start == '.' && *(start +1) == '.')
440 dest -= 3; // Remove "../"
441 if (dest > rpath) // Remove the last path component if not at root
442 while (*--dest != '/')
445 # if !defined (ACE_LACKS_SYMLINKS)
446 else
448 ACE_stat st;
450 *dest = '\0';
451 if (ACE_OS::lstat(rpath, &st) < 0)
453 if (resolved_name == 0)
454 #if defined (ACE_HAS_ALLOC_HOOKS)
455 ACE_Allocator::instance()->free (rpath);
456 #else
457 ACE_OS::free (rpath);
458 #endif /* ACE_HAS_ALLOC_HOOKS */
459 return 0;
462 // Check if current path is a link
463 if (S_ISLNK (st.st_mode))
465 if (++nlinks > MAXSYMLINKS)
467 errno = ELOOP;
468 if (resolved_name == 0)
469 #if defined (ACE_HAS_ALLOC_HOOKS)
470 ACE_Allocator::instance()->free (rpath);
471 #else
472 ACE_OS::free (rpath);
473 #endif /* ACE_HAS_ALLOC_HOOKS */
474 return 0;
477 char link_buf[PATH_MAX];
479 ssize_t link_len = ACE_OS::readlink (rpath, link_buf, PATH_MAX);
480 int tail_len = ACE_OS::strlen (file_name) + 1;
482 // Check if there is room to expand link?
483 if (link_len + tail_len > PATH_MAX)
485 errno = ENAMETOOLONG;
486 if (resolved_name == 0)
487 #if defined (ACE_HAS_ALLOC_HOOKS)
488 ACE_Allocator::instance()->free (rpath);
489 #else
490 ACE_OS::free (rpath);
491 #endif /* ACE_HAS_ALLOC_HOOKS */
492 return 0;
495 // Move tail and prefix it with expanded link
496 ACE_OS::memmove (expand_buf + link_len, file_name, tail_len);
497 ACE_OS::memcpy (expand_buf, link_buf, link_len);
499 if (*link_buf == '/') // Absolute link?
501 dest = rpath;
503 else // Relative link, remove expanded link component
505 --dest;
506 while (*--dest != '/')
509 file_name = expand_buf; // Source path is now in expand_buf
512 # endif /* ACE_LACKS_SYMLINKS */
515 *dest = '\0';
517 return rpath;
519 #endif /* ACE_LACKS_REALPATH */
521 #if defined (ACE_LACKS_STRTOL)
522 long
523 ACE_OS::strtol_emulation (const char *nptr, char **endptr, int base)
525 const char *s = nptr;
526 unsigned long acc;
527 int c;
528 unsigned long cutoff;
529 int neg = 0, any, cutlim;
532 * Skip white space and pick up leading +/- sign if any.
533 * If base is 0, allow 0x for hex and 0 for octal, else
534 * assume decimal; if base is already 16, allow 0x.
536 do {
537 c = *s++;
538 } while (ACE_OS::ace_isspace(c));
539 if (c == '-') {
540 neg = 1;
541 c = *s++;
542 } else if (c == '+')
543 c = *s++;
544 if ((base == 0 || base == 16) &&
545 c == '0' && (*s == 'x' || *s == 'X')) {
546 c = s[1];
547 s += 2;
548 base = 16;
550 if (base == 0)
551 base = c == '0' ? 8 : 10;
554 * Compute the cutoff value between legal numbers and illegal
555 * numbers. That is the largest legal value, divided by the
556 * base. An input number that is greater than this value, if
557 * followed by a legal input character, is too big. One that
558 * is equal to this value may be valid or not; the limit
559 * between valid and invalid numbers is then based on the last
560 * digit. For instance, if the range for longs is
561 * [-2147483648..2147483647] and the input base is 10,
562 * cutoff will be set to 214748364 and cutlim to either
563 * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
564 * a value > 214748364, or equal but the next digit is > 7 (or 8),
565 * the number is too big, and we will return a range error.
567 * Set any if any `digits' consumed; make it negative to indicate
568 * overflow.
570 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
571 cutlim = cutoff % (unsigned long)base;
572 cutoff /= (unsigned long)base;
573 for (acc = 0, any = 0;; c = *s++) {
574 if (ACE_OS::ace_isdigit(c))
575 c -= '0';
576 else if (ACE_OS::ace_isalpha(c))
577 c -= ACE_OS::ace_isupper(c) ? 'A' - 10 : 'a' - 10;
578 else
579 break;
580 if (c >= base)
581 break;
582 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
583 any = -1;
584 else {
585 any = 1;
586 acc *= base;
587 acc += c;
590 if (any < 0) {
591 acc = neg ? LONG_MIN : LONG_MAX;
592 errno = ERANGE;
593 } else if (neg)
594 acc = -acc;
595 if (endptr != 0)
596 *endptr = any ? (char *)s - 1 : (char *)nptr;
597 return (acc);
599 #endif /* ACE_LACKS_STRTOL */
601 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSTOL)
602 long
603 ACE_OS::wcstol_emulation (const wchar_t *nptr,
604 wchar_t **endptr,
605 int base)
607 const wchar_t *s = nptr;
608 unsigned long acc;
609 int c;
610 unsigned long cutoff;
611 int neg = 0, any, cutlim;
614 * Skip white space and pick up leading +/- sign if any.
615 * If base is 0, allow 0x for hex and 0 for octal, else
616 * assume decimal; if base is already 16, allow 0x.
618 do {
619 c = *s++;
620 } while (ACE_OS::ace_isspace(c));
621 if (c == L'-') {
622 neg = 1;
623 c = *s++;
624 } else if (c == L'+')
625 c = *s++;
626 if ((base == 0 || base == 16) &&
627 c == '0' && (*s == L'x' || *s == L'X')) {
628 c = s[1];
629 s += 2;
630 base = 16;
632 if (base == 0)
633 base = c == L'0' ? 8 : 10;
636 * See strtol for comments as to the logic used.
638 cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
639 cutlim = cutoff % (unsigned long)base;
640 cutoff /= (unsigned long)base;
641 for (acc = 0, any = 0;; c = *s++) {
642 if (ACE_OS::ace_isdigit(c))
643 c -= L'0';
644 else if (ACE_OS::ace_isalpha(c))
645 c -= ACE_OS::ace_isupper(c) ? L'A' - 10 : L'a' - 10;
646 else
647 break;
648 if (c >= base)
649 break;
650 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
651 any = -1;
652 else {
653 any = 1;
654 acc *= base;
655 acc += c;
658 if (any < 0) {
659 acc = neg ? LONG_MIN : LONG_MAX;
660 errno = ERANGE;
661 } else if (neg)
662 acc = -acc;
663 if (endptr != 0)
664 *endptr = any ? (wchar_t *)s - 1 : (wchar_t *)nptr;
665 return (acc);
667 #endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSTOL */
669 #if defined (ACE_LACKS_STRTOUL)
670 unsigned long
671 ACE_OS::strtoul_emulation (const char *nptr,
672 char **endptr,
673 int base)
675 const char *s = nptr;
676 unsigned long acc;
677 int c;
678 unsigned long cutoff;
679 int neg = 0, any, cutlim;
682 * See strtol for comments as to the logic used.
685 c = *s++;
686 while (ACE_OS::ace_isspace(c));
687 if (c == '-')
689 neg = 1;
690 c = *s++;
692 else if (c == '+')
693 c = *s++;
694 if ((base == 0 || base == 16) &&
695 c == '0' && (*s == 'x' || *s == 'X'))
697 c = s[1];
698 s += 2;
699 base = 16;
701 if (base == 0)
702 base = c == '0' ? 8 : 10;
703 cutoff = (unsigned long) ULONG_MAX / (unsigned long) base;
704 cutlim = (unsigned long) ULONG_MAX % (unsigned long) base;
706 for (acc = 0, any = 0;; c = *s++)
708 if (ACE_OS::ace_isdigit(c))
709 c -= '0';
710 else if (ACE_OS::ace_isalpha(c))
711 c -= ACE_OS::ace_isupper(c) ? 'A' - 10 : 'a' - 10;
712 else
713 break;
714 if (c >= base)
715 break;
716 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
717 any = -1;
718 else
720 any = 1;
721 acc *= base;
722 acc += c;
725 if (any < 0)
727 acc = ULONG_MAX;
728 errno = ERANGE;
730 else if (neg)
731 acc = -acc;
732 if (endptr != 0)
733 *endptr = any ? (char *) s - 1 : (char *) nptr;
734 return (acc);
736 #endif /* ACE_LACKS_STRTOUL */
739 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSTOUL)
740 unsigned long
741 ACE_OS::wcstoul_emulation (const wchar_t *nptr,
742 wchar_t **endptr,
743 int base)
745 const wchar_t *s = nptr;
746 unsigned long acc;
747 int c;
748 unsigned long cutoff;
749 int neg = 0, any, cutlim;
752 * See strtol for comments as to the logic used.
755 c = *s++;
756 while (ACE_OS::ace_isspace(c));
757 if (c == L'-')
759 neg = 1;
760 c = *s++;
762 else if (c == L'+')
763 c = *s++;
764 if ((base == 0 || base == 16) &&
765 c == L'0' && (*s == L'x' || *s == L'X'))
767 c = s[1];
768 s += 2;
769 base = 16;
771 if (base == 0)
772 base = c == L'0' ? 8 : 10;
773 cutoff = (unsigned long) ULONG_MAX / (unsigned long) base;
774 cutlim = (unsigned long) ULONG_MAX % (unsigned long) base;
776 for (acc = 0, any = 0;; c = *s++)
778 if (ACE_OS::ace_isdigit(c))
779 c -= L'0';
780 else if (ACE_OS::ace_isalpha(c))
781 c -= ACE_OS::ace_isupper(c) ? L'A' - 10 : L'a' - 10;
782 else
783 break;
784 if (c >= base)
785 break;
786 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
787 any = -1;
788 else
790 any = 1;
791 acc *= base;
792 acc += c;
795 if (any < 0)
797 acc = ULONG_MAX;
798 errno = ERANGE;
800 else if (neg)
801 acc = -acc;
802 if (endptr != 0)
803 *endptr = any ? (wchar_t *) s - 1 : (wchar_t *) nptr;
804 return (acc);
806 #endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSTOUL */
808 #if defined (ACE_LACKS_STRTOLL)
809 ACE_INT64
810 ACE_OS::strtoll_emulation (const char *nptr,
811 char **endptr,
812 int base)
814 const char *s = nptr;
815 ACE_UINT64 acc;
816 int c;
817 ACE_UINT64 cutoff;
818 int neg = 0, any, cutlim;
821 * Skip white space and pick up leading +/- sign if any.
822 * If base is 0, allow 0x for hex and 0 for octal, else
823 * assume decimal; if base is already 16, allow 0x.
825 do {
826 c = *s++;
827 } while (ACE_OS::ace_isspace(c));
828 if (c == '-') {
829 neg = 1;
830 c = *s++;
831 } else if (c == '+')
832 c = *s++;
833 if ((base == 0 || base == 16) &&
834 c == '0' && (*s == 'x' || *s == 'X')) {
835 c = s[1];
836 s += 2;
837 base = 16;
839 if (base == 0)
840 base = c == '0' ? 8 : 10;
843 * See strtol for comments as to the logic used.
845 cutoff = neg ? -(ACE_UINT64)ACE_INT64_MIN : ACE_INT64_MAX;
846 cutlim = cutoff % (ACE_UINT64)base;
847 cutoff /= (ACE_UINT64)base;
848 for (acc = 0, any = 0;; c = *s++) {
849 if (ACE_OS::ace_isdigit(c))
850 c -= '0';
851 else if (ACE_OS::ace_isalpha(c))
852 c -= ACE_OS::ace_isupper(c) ? 'A' - 10 : 'a' - 10;
853 else
854 break;
855 if (c >= base)
856 break;
857 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
858 any = -1;
859 else {
860 any = 1;
861 acc *= base;
862 acc += c;
865 if (any < 0) {
866 acc = neg ? ACE_INT64_MIN : ACE_INT64_MAX;
867 errno = ERANGE;
868 } else if (neg)
869 acc = -acc;
870 if (endptr != 0)
871 *endptr = any ? (char *)s - 1 : (char *)nptr;
872 return (acc);
874 #endif /* ACE_LACKS_STRTOLL */
876 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSTOLL)
877 ACE_INT64
878 ACE_OS::wcstoll_emulation (const wchar_t *nptr,
879 wchar_t **endptr,
880 int base)
882 const wchar_t *s = nptr;
883 ACE_UINT64 acc;
884 int c;
885 ACE_UINT64 cutoff;
886 int neg = 0, any, cutlim;
889 * Skip white space and pick up leading +/- sign if any.
890 * If base is 0, allow 0x for hex and 0 for octal, else
891 * assume decimal; if base is already 16, allow 0x.
893 do {
894 c = *s++;
895 } while (ACE_OS::ace_isspace(c));
896 if (c == L'-') {
897 neg = 1;
898 c = *s++;
899 } else if (c == L'+')
900 c = *s++;
901 if ((base == 0 || base == 16) &&
902 c == L'0' && (*s == L'x' || *s == L'X')) {
903 c = s[1];
904 s += 2;
905 base = 16;
907 if (base == 0)
908 base = c == L'0' ? 8 : 10;
911 * See strtol for comments as to the logic used.
913 cutoff = neg ? -(ACE_UINT64)ACE_INT64_MIN : ACE_INT64_MAX;
914 cutlim = cutoff % (ACE_UINT64)base;
915 cutoff /= (ACE_UINT64)base;
916 for (acc = 0, any = 0;; c = *s++) {
917 if (ACE_OS::ace_isdigit(c))
918 c -= L'0';
919 else if (ACE_OS::ace_isalpha(c))
920 c -= ACE_OS::ace_isupper(c) ? L'A' - 10 : L'a' - 10;
921 else
922 break;
923 if (c >= base)
924 break;
925 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
926 any = -1;
927 else {
928 any = 1;
929 acc *= base;
930 acc += c;
933 if (any < 0) {
934 acc = neg ? ACE_INT64_MIN : ACE_INT64_MAX;
935 errno = ERANGE;
936 } else if (neg)
937 acc = -acc;
938 if (endptr != 0)
939 *endptr = any ? (wchar_t *)s - 1 : (wchar_t *)nptr;
940 return (acc);
942 #endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSTOLL */
945 #if defined (ACE_LACKS_STRTOULL)
946 ACE_UINT64
947 ACE_OS::strtoull_emulation (const char *nptr,
948 char **endptr,
949 int base)
951 const char *s = nptr;
952 ACE_UINT64 acc;
953 int c;
954 ACE_UINT64 cutoff;
955 int neg = 0, any, cutlim;
958 * See strtol for comments as to the logic used.
961 c = *s++;
962 while (ACE_OS::ace_isspace(c));
963 if (c == '-')
965 neg = 1;
966 c = *s++;
968 else if (c == '+')
969 c = *s++;
970 if ((base == 0 || base == 16) &&
971 c == '0' && (*s == 'x' || *s == 'X'))
973 c = s[1];
974 s += 2;
975 base = 16;
977 if (base == 0)
978 base = c == '0' ? 8 : 10;
980 cutoff = (ACE_UINT64) ACE_UINT64_MAX / (ACE_UINT64) base;
981 cutlim = (ACE_UINT64) ACE_UINT64_MAX % (ACE_UINT64) base;
983 for (acc = 0, any = 0;; c = *s++)
985 if (ACE_OS::ace_isdigit(c))
986 c -= '0';
987 else if (ACE_OS::ace_isalpha(c))
988 c -= ACE_OS::ace_isupper(c) ? 'A' - 10 : 'a' - 10;
989 else
990 break;
991 if (c >= base)
992 break;
993 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
994 any = -1;
995 else
997 any = 1;
998 acc *= base;
999 acc += c;
1002 if (any < 0)
1004 acc = ACE_UINT64_MAX;
1005 errno = ERANGE;
1007 else if (neg)
1008 acc = -acc;
1009 if (endptr != 0)
1010 *endptr = any ? (char *) s - 1 : (char *) nptr;
1011 return (acc);
1013 #endif /* ACE_LACKS_STRTOULL */
1015 #if defined (ACE_HAS_WCHAR) && defined (ACE_LACKS_WCSTOULL)
1016 ACE_UINT64
1017 ACE_OS::wcstoull_emulation (const wchar_t *nptr,
1018 wchar_t **endptr,
1019 int base)
1021 const wchar_t *s = nptr;
1022 ACE_UINT64 acc;
1023 int c;
1024 ACE_UINT64 cutoff;
1025 int neg = 0, any, cutlim;
1028 * See strtol for comments as to the logic used.
1031 c = *s++;
1032 while (ACE_OS::ace_isspace(c));
1033 if (c == L'-')
1035 neg = 1;
1036 c = *s++;
1038 else if (c == L'+')
1039 c = *s++;
1040 if ((base == 0 || base == 16) &&
1041 c == L'0' && (*s == L'x' || *s == L'X'))
1043 c = s[1];
1044 s += 2;
1045 base = 16;
1047 if (base == 0)
1048 base = c == L'0' ? 8 : 10;
1050 cutoff = (ACE_UINT64) ACE_UINT64_MAX / (ACE_UINT64) base;
1051 cutlim = (ACE_UINT64) ACE_UINT64_MAX % (ACE_UINT64) base;
1053 for (acc = 0, any = 0;; c = *s++)
1055 if (ACE_OS::ace_isdigit(c))
1056 c -= L'0';
1057 else if (ACE_OS::ace_isalpha(c))
1058 c -= ACE_OS::ace_isupper(c) ? L'A' - 10 : L'a' - 10;
1059 else
1060 break;
1061 if (c >= base)
1062 break;
1063 if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
1064 any = -1;
1065 else
1067 any = 1;
1068 acc *= base;
1069 acc += c;
1072 if (any < 0)
1074 acc = ACE_UINT64_MAX;
1075 errno = ERANGE;
1077 else if (neg)
1078 acc = -acc;
1079 if (endptr != 0)
1080 *endptr = any ? (wchar_t *) s - 1 : (wchar_t *) nptr;
1081 return (acc);
1083 #endif /* ACE_HAS_WCHAR && ACE_LACKS_WCSTOULL */
1085 #if defined (ACE_LACKS_MKSTEMP)
1086 ACE_HANDLE
1087 ACE_OS::mkstemp_emulation (ACE_TCHAR * s)
1089 if (s == 0)
1091 errno = EINVAL;
1092 return ACE_INVALID_HANDLE;
1095 // The "XXXXXX" template to be filled in.
1096 ACE_TCHAR * const t = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX"));
1098 if (t == 0)
1100 errno = EINVAL;
1101 return ACE_INVALID_HANDLE;
1104 static unsigned int const NUM_RETRIES = 50;
1105 static unsigned int const NUM_CHARS = 6; // Do not change!
1107 // Use ACE_Time_Value::msec(ACE_UINT64&) as opposed to
1108 // ACE_Time_Value::msec() to avoid truncation.
1109 ACE_UINT64 msec;
1111 // Use a const ACE_Time_Value to resolve ambiguity between
1112 // ACE_Time_Value::msec (long) and ACE_Time_Value::msec(ACE_UINT64&) const.
1113 ACE_Time_Value const now = ACE_OS::gettimeofday();
1114 now.msec (msec);
1116 // Add the process and thread ids to ensure uniqueness.
1117 msec += ACE_OS::getpid();
1119 #ifndef ACE_THREAD_T_IS_A_STRUCT
1120 msec += (size_t) ACE_OS::thr_self();
1121 #endif
1123 // ACE_thread_t may be a char* (returned by ACE_OS::thr_self()) so
1124 // we need to use a C-style cast as a catch-all in order to use a
1125 // static_cast<> to an integral type.
1126 unsigned int seed = static_cast<unsigned int> (msec);
1128 // We only care about UTF-8 / ASCII characters in generated
1129 // filenames. A UTF-16 or UTF-32 character could potentially cause
1130 // a very large space to be searched in the below do/while() loop,
1131 // greatly slowing down this mkstemp() implementation. It is more
1132 // practical to limit the search space to UTF-8 / ASCII characters
1133 // (i.e. 127 characters).
1135 // Note that we can't make this constant static since the compiler
1136 // may not inline the return value of ACE_Numeric_Limits::max(),
1137 // meaning multiple threads could potentially initialize this value
1138 // in parallel.
1139 float const MAX_VAL =
1140 static_cast<float> (ACE_Numeric_Limits<char>::max ());
1142 // Use high-order bits rather than low-order ones (e.g. rand() %
1143 // MAX_VAL). See Numerical Recipes in C: The Art of Scientific
1144 // Computing (William H. Press, Brian P. Flannery, Saul
1145 // A. Teukolsky, William T. Vetterling; New York: Cambridge
1146 // University Press, 1992 (2nd ed., p. 277).
1148 // e.g.: MAX_VAL * rand() / (RAND_MAX + 1.0)
1150 // Factor out the constant coefficient.
1151 float const coefficient =
1152 static_cast<float> (MAX_VAL / (RAND_MAX + 1.0f));
1154 // @@ These nested loops may be ineffecient. Improvements are
1155 // welcome.
1156 for (unsigned int i = 0; i < NUM_RETRIES; ++i)
1158 for (unsigned int n = 0; n < NUM_CHARS; ++n)
1160 ACE_TCHAR r;
1162 // This do/while() loop allows this alphanumeric character
1163 // selection to work for EBCDIC, as well.
1166 r = static_cast<ACE_TCHAR> (coefficient * ACE_OS::rand_r (&seed));
1168 while (!ACE_OS::ace_isalnum (r));
1170 t[n] = r;
1173 static int const perms =
1174 #if defined (ACE_WIN32)
1175 0; /* Do not share while open. */
1176 #else
1177 0600; /* S_IRUSR | S_IWUSR */
1178 #endif /* ACE_WIN32 */
1180 // Create the file with the O_EXCL bit set to ensure that we're
1181 // not subject to a symbolic link attack.
1183 // Note that O_EXCL is subject to a race condition over NFS
1184 // filesystems.
1185 ACE_HANDLE const handle = ACE_OS::open (s,
1186 O_RDWR | O_CREAT | O_EXCL,
1187 perms);
1189 if (handle != ACE_INVALID_HANDLE)
1190 return handle;
1193 errno = EEXIST; // Couldn't create a unique temporary file.
1194 return ACE_INVALID_HANDLE;
1196 #endif /* ACE_LACKS_MKSTEMP */
1198 #if !defined (ACE_HAS_GETPROGNAME) && !defined (ACE_HAS_SETPROGNAME)
1199 static const char *__progname = "";
1200 #endif /* !ACE_HAS_GETPROGNAME && !ACE_HAS_SETPROGNAME */
1202 #if !defined (ACE_HAS_GETPROGNAME)
1203 const char*
1204 ACE_OS::getprogname_emulation ()
1206 return __progname;
1208 #endif /* !ACE_HAS_GETPROGNAME */
1210 #if !defined (ACE_HAS_SETPROGNAME)
1211 void
1212 ACE_OS::setprogname_emulation (const char* progname)
1214 const char *p = ACE_OS::strrchr (progname, '/');
1215 if (p != 0)
1216 __progname = p + 1;
1217 else
1218 __progname = progname;
1220 #endif /* !ACE_HAS_SETPROGNAME */
1222 ACE_END_VERSIONED_NAMESPACE_DECL