| 2658 | |
| 2659 | return r; |
| 2660 | } |
| 2661 | |
| 2662 | static void |
| 2663 | writezone(const char *const name, const char *const string, char version, |
| 2664 | int defaulttype) |
| 2665 | { |
| 2666 | register FILE * fp; |
| 2667 | register ptrdiff_t i, j; |
| 2668 | register int pass; |
| 2669 | char *tempname = NULL; |
| 2670 | char const *outname = name; |
| 2671 | |
| 2672 | /* Allocate the ATS and TYPES arrays via a single malloc, |
| 2673 | as this is a bit faster. Do not malloc(0) if !timecnt, |
| 2674 | as that might return NULL even on success. */ |
| 2675 | zic_t *ats = xmalloc(align_to(size_product(timecnt + !timecnt, |
| 2676 | sizeof *ats + 1), |
| 2677 | alignof(zic_t))); |
| 2678 | void *typesptr = ats + timecnt; |
| 2679 | unsigned char *types = typesptr; |
| 2680 | struct timerange rangeall = {0}, range32, range64; |
| 2681 | |
| 2682 | /* |
| 2683 | ** Sort. |
| 2684 | */ |
| 2685 | if (timecnt > 1) |
| 2686 | qsort(attypes, timecnt, sizeof *attypes, atcomp); |
| 2687 | /* |
| 2688 | ** Optimize and skip unwanted transitions. |
| 2689 | */ |
| 2690 | { |
| 2691 | ptrdiff_t fromi, toi; |
| 2692 | |
| 2693 | toi = 0; |
| 2694 | fromi = 0; |
| 2695 | for ( ; fromi < timecnt; ++fromi) { |
| 2696 | if (toi != 0) { |
| 2697 | /* Skip the previous transition if it is unwanted |
| 2698 | because its local time is not earlier. |
| 2699 | The UT offset additions can't overflow because |
| 2700 | of how the times were calculated. */ |
| 2701 | unsigned char type_2 = |
| 2702 | toi == 1 ? 0 : attypes[toi - 2].type; |
| 2703 | if ((attypes[fromi].at |
| 2704 | + utoffs[attypes[toi - 1].type]) |
| 2705 | <= attypes[toi - 1].at + utoffs[type_2]) { |
| 2706 | if (attypes[fromi].type == type_2) |
| 2707 | toi--; |
| 2708 | else |
| 2709 | attypes[toi - 1].type = |
| 2710 | attypes[fromi].type; |
| 2711 | continue; |
| 2712 | } |
| 2713 | } |
| 2714 | |
| 2715 | /* Use a transition if it is the first one, |
| 2716 | or if it cannot be merged for other reasons, |
| 2717 | or if it transitions to different timekeeping. */ |
no test coverage detected