Lines 570-598
find_subframework_header (cpp_reader *pfile, const char *header, cpp_dir **dirp)
Link Here
|
570 |
return 0; |
570 |
return 0; |
571 |
} |
571 |
} |
572 |
|
572 |
|
573 |
/* Return the value of darwin_macosx_version_min suitable for the |
573 |
/* Given a version string, return the version as a statically-allocated |
574 |
__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro, |
574 |
array of three non-negative integers. If the version string is |
575 |
so '10.4.2' becomes 1040. The lowest digit is always zero. |
575 |
invalid, return null. |
576 |
Print a warning if the version number can't be understood. */ |
576 |
|
|
|
577 |
Version strings must consist of one, two, or three tokens, each |
578 |
separated by a single period. Each token must contain only the |
579 |
characters '0' through '9' and is converted to an equivalent |
580 |
integer. Omitted tokens are treated as zeros. For example: |
581 |
|
582 |
"10" becomes {10,0,0} |
583 |
"10.10" becomes {10,10,0} |
584 |
"10.10.1" becomes {10,10,1} |
585 |
"10.000010.1" becomes {10,10,1} |
586 |
"10.010.001" becomes {10,10,1} |
587 |
"000010.10.00001" becomes {10,10,1} */ |
588 |
|
589 |
enum version_components { MAJOR, MINOR, TINY }; |
590 |
|
591 |
static const unsigned long * |
592 |
parse_version (const char *version_str) |
593 |
{ |
594 |
size_t version_len; |
595 |
char *end; |
596 |
static unsigned long version_array[3]; |
597 |
|
598 |
if (! version_str) |
599 |
return NULL; |
600 |
|
601 |
version_len = strlen (version_str); |
602 |
if (version_len < 1) |
603 |
return NULL; |
604 |
|
605 |
/* Version string must consist of digits and periods only. */ |
606 |
if (strspn (version_str, "0123456789.") != version_len) |
607 |
return NULL; |
608 |
|
609 |
if (! ISDIGIT (version_str[0]) || ! ISDIGIT (version_str[version_len - 1])) |
610 |
return NULL; |
611 |
|
612 |
version_array[MAJOR] = strtoul (version_str, &end, 10); |
613 |
version_str = end + ((*end == '.') ? 1 : 0); |
614 |
|
615 |
/* Version string must not contain adjacent periods. */ |
616 |
if (*version_str == '.') |
617 |
return NULL; |
618 |
|
619 |
version_array[MINOR] = strtoul (version_str, &end, 10); |
620 |
version_str = end + ((*end == '.') ? 1 : 0); |
621 |
|
622 |
version_array[TINY] = strtoul (version_str, &end, 10); |
623 |
|
624 |
/* Version string must contain no more than three tokens. */ |
625 |
if (*end != '\0') |
626 |
return NULL; |
627 |
|
628 |
return version_array; |
629 |
} |
630 |
|
631 |
/* Given a three-component version represented as an array of |
632 |
non-negative integers, return a statically-allocated string suitable |
633 |
for the legacy __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro. |
634 |
If the version is invalid and cannot be coerced into a valid form, |
635 |
return null. |
636 |
|
637 |
The legacy format is a four-character string -- two chars for the |
638 |
major number and one each for the minor and tiny numbers. Major |
639 |
numbers are zero-padded if necessary. Minor and tiny numbers from |
640 |
10 through 99 are permitted but are clamped to 9 (for example, |
641 |
{10,9,10} produces "1099"). Versions containing numbers greater |
642 |
than 99 are rejected. */ |
643 |
|
644 |
static const char * |
645 |
version_as_legacy_macro (const unsigned long *version) |
646 |
{ |
647 |
unsigned long major = version[MAJOR]; |
648 |
unsigned long minor = version[MINOR]; |
649 |
unsigned long tiny = version[TINY]; |
650 |
static char result[sizeof "9999"]; |
651 |
|
652 |
if (major > 99 || minor > 99 || tiny > 99) |
653 |
return NULL; |
654 |
|
655 |
minor = ((minor > 9) ? 9 : minor); |
656 |
tiny = ((tiny > 9) ? 9 : tiny); |
657 |
|
658 |
if (sprintf (result, "%02lu%lu%lu", major, minor, tiny) |
659 |
!= sizeof "9999" - 1) |
660 |
return NULL; |
661 |
|
662 |
return result; |
663 |
} |
664 |
|
665 |
/* Given a three-component version represented as an array of |
666 |
non-negative integers, return a statically-allocated string suitable |
667 |
for the modern __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro |
668 |
or the __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ macro. If the |
669 |
version is invalid, return null. |
670 |
|
671 |
The modern format is a five- or six-character string -- one or two |
672 |
chars for the major number and two each for the minor and tiny |
673 |
numbers, which are zero-padded if necessary (for example, {8,1,0} |
674 |
produces "80100", and {10,10,1} produces "101001"). Versions |
675 |
containing numbers greater than 99 are rejected. */ |
676 |
|
677 |
static const char * |
678 |
version_as_modern_macro (const unsigned long *version) |
679 |
{ |
680 |
unsigned long major = version[MAJOR]; |
681 |
unsigned long minor = version[MINOR]; |
682 |
unsigned long tiny = version[TINY]; |
683 |
static char result[sizeof "999999"]; |
684 |
|
685 |
if (major > 99 || minor > 99 || tiny > 99) |
686 |
return NULL; |
687 |
|
688 |
/* NOTE: 'sizeof "foo"' returns size of char array, but |
689 |
'sizeof ((x > y) ? "foo" : "bar")' returns size of char pointer. */ |
690 |
if (sprintf (result, "%lu%02lu%02lu", major, minor, tiny) |
691 |
!= ((major > 9) ? sizeof "999999" : sizeof "99999") - 1) |
692 |
return NULL; |
693 |
|
694 |
return result; |
695 |
} |
696 |
|
697 |
/* Return the value of darwin_macosx_version_min, suitably formatted |
698 |
for the __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro. (For |
699 |
example, "10.9" produces "1090", and "10.10.1" produces "101001".) |
700 |
If its value is invalid and cannot be coerced into a valid form, |
701 |
print a warning and return "1000". */ |
702 |
|
577 |
static const char * |
703 |
static const char * |
578 |
version_as_macro (void) |
704 |
macosx_version_as_macro (void) |
579 |
{ |
705 |
{ |
580 |
static char result[] = "1000"; |
706 |
const unsigned long *version_array; |
|
|
707 |
const char *version_macro; |
581 |
|
708 |
|
582 |
if (strncmp (darwin_macosx_version_min, "10.", 3) != 0) |
709 |
version_array = parse_version (darwin_macosx_version_min); |
|
|
710 |
if (! version_array) |
583 |
goto fail; |
711 |
goto fail; |
584 |
if (! ISDIGIT (darwin_macosx_version_min[3])) |
712 |
|
|
|
713 |
/* Do not assume that the major number will always be exactly 10. */ |
714 |
if (version_array[MAJOR] < 10 || version_array[MAJOR] > 10) |
585 |
goto fail; |
715 |
goto fail; |
586 |
result[2] = darwin_macosx_version_min[3]; |
716 |
|
587 |
if (darwin_macosx_version_min[4] != '\0' |
717 |
if (version_array[MAJOR] == 10 && version_array[MINOR] < 10) |
588 |
&& darwin_macosx_version_min[4] != '.') |
718 |
version_macro = version_as_legacy_macro (version_array); |
|
|
719 |
else |
720 |
version_macro = version_as_modern_macro (version_array); |
721 |
|
722 |
if (! version_macro) |
589 |
goto fail; |
723 |
goto fail; |
590 |
|
724 |
|
591 |
return result; |
725 |
return version_macro; |
592 |
|
726 |
|
593 |
fail: |
727 |
fail: |
594 |
error ("unknown value %qs of -mmacosx-version-min", |
728 |
error ("unknown value %qs of -mmacosx-version-min", |
595 |
darwin_macosx_version_min); |
729 |
darwin_macosx_version_min); |
596 |
return "1000"; |
730 |
return "1000"; |
597 |
} |
731 |
} |
598 |
|
732 |
|
Lines 614-620
darwin_cpp_builtins (cpp_reader *pfile)
Link Here
|
614 |
builtin_define ("__CONSTANT_CFSTRINGS__"); |
748 |
builtin_define ("__CONSTANT_CFSTRINGS__"); |
615 |
|
749 |
|
616 |
builtin_define_with_value ("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", |
750 |
builtin_define_with_value ("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", |
617 |
version_as_macro(), false); |
751 |
macosx_version_as_macro(), false); |
618 |
|
752 |
|
619 |
/* Since we do not (at 4.6) support ObjC gc for the NeXT runtime, the |
753 |
/* Since we do not (at 4.6) support ObjC gc for the NeXT runtime, the |
620 |
following will cause a syntax error if one tries to compile gc attributed |
754 |
following will cause a syntax error if one tries to compile gc attributed |