]> git.saurik.com Git - apple/cf.git/blobdiff - Base.subproj/uuid.c
CF-476.10.tar.gz
[apple/cf.git] / Base.subproj / uuid.c
diff --git a/Base.subproj/uuid.c b/Base.subproj/uuid.c
deleted file mode 100644 (file)
index 739396f..0000000
+++ /dev/null
@@ -1,1252 +0,0 @@
-/*
- * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- */
-/*     uuid.c
-       Copyright 1999-2002, Apple, Inc. All rights reserved.
-       Responsibility: Doug Davidson
-*/
-
-#include <CoreFoundation/CFBase.h>
-#include <CoreFoundation/CFDate.h>
-#include "CFInternal.h"
-#include "CFUtilitiesPriv.h"
-#include <string.h>
-
-typedef struct
-{
-    unsigned char eaddr[6];      /* 6 bytes of ethernet hardware address */
-} uuid_address_t;
-
-#if defined(__WIN32__)
-
-static OSErr GetEthernetAddr(uuid_address_t *addr) {
-    return -1;
-}
-
-#else
-
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/sockio.h>
-#include <sys/uio.h>
-#include <sys/errno.h>
-
-#include <netinet/in.h>
-#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
-
-#if !defined(MAX)
-#define MAX(a, b) ((a) < (b) ? (b) : (a))
-#endif
-
-#define IFR_NEXT(ifr)   \
-    ((struct ifreq *) ((char *) (ifr) + sizeof(*(ifr)) + \
-      MAX(0, (int) (ifr)->ifr_addr.sa_len - (int) sizeof((ifr)->ifr_addr))))
-
-static OSErr GetEthernetAddr(uuid_address_t *addr) {
-    struct ifconf ifc;
-    struct ifreq ifrbuf[30], *ifr;
-    register int s, i;
-    Boolean foundIt = false;
-
-    if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
-        return -1;
-    }
-
-    ifc.ifc_buf = (caddr_t)ifrbuf;
-    ifc.ifc_len = sizeof (ifrbuf);
-    if (ioctl(s, SIOCGIFCONF, &ifc) ==  -1) {
-        close(s);
-        return -1;
-    }
-
-    for (ifr = (struct ifreq *)ifc.ifc_buf, i=0; (char *)ifr < &ifc.ifc_buf[ifc.ifc_len]; ifr = IFR_NEXT(ifr), i++) {
-        unsigned char *p, c;
-
-        if (*ifr->ifr_name == '\0') {
-            continue;
-        }
-        /*
-         * Adapt to buggy kernel implementation (> 9 of a type)
-         */
-
-        p = &ifr->ifr_name[strlen(ifr->ifr_name)-1];
-        if ((c = *p) > '0'+9) {
-            snprintf(p, 2, "%d", c-'0'); // at least 3 bytes available here, we hope!
-        }
-
-        if (strcmp(ifr->ifr_name, "en0") == 0) {
-            if (ifr->ifr_addr.sa_family == AF_LINK) {
-                struct sockaddr_dl *sa = ((struct sockaddr_dl *)&ifr->ifr_addr);
-                if (sa->sdl_type == IFT_ETHER || sa->sdl_type == IFT_FDDI || sa->sdl_type == IFT_ISO88023 || sa->sdl_type == IFT_ISO88024 || sa->sdl_type == IFT_ISO88025) {
-                    for (i=0, p=&sa->sdl_data[sa->sdl_nlen] ; i++ < sa->sdl_alen; p++) {
-                        addr->eaddr[i-1] = *p;
-                    }
-                    foundIt = true;
-                    break;
-                }
-            }
-        }
-    }
-    close(s);
-    return (foundIt ? 0 : -1);
-}
-
-#undef IFR_NEXT
-
-#endif // __WIN32__
-
-__private_extern__ CFStringRef __CFCopyRegularEthernetAddrString(void) {
-    uuid_address_t addr;
-    static CFStringRef string = NULL;
-    static Boolean lookedUpAddr = false;
-    
-    if (!lookedUpAddr) {
-        if (GetEthernetAddr(&addr) == 0) {
-            string = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x:%02x:%02x:%02x:%02x:%02x"), addr.eaddr[0], addr.eaddr[1], addr.eaddr[2], addr.eaddr[3], addr.eaddr[4], addr.eaddr[5]);
-        }
-        lookedUpAddr = true;
-    }
-    return (string ? CFRetain(string) : NULL);
-}
-
-__private_extern__ CFStringRef __CFCopyEthernetAddrString(void) {
-    uuid_address_t addr;
-    static CFStringRef string = NULL;
-    static Boolean lookedUpAddr = false;
-    
-    if (!lookedUpAddr) {
-        if (GetEthernetAddr(&addr) == 0) {
-            string = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%02x%02x%02x%02x%02x%02x"), addr.eaddr[0], addr.eaddr[1], addr.eaddr[2], addr.eaddr[3], addr.eaddr[4], addr.eaddr[5]);
-        }
-        lookedUpAddr = true;
-    }
-    return (string ? CFRetain(string) : NULL);
-}
-
-#if defined(__WIN32__)
-/* _CFGenerateUUID function just calls the COM library's UUID generator
- * (Aleksey Dukhnyakov)
- */
-#include <windows.h>
-#include <ole2.h>
-#include <objbase.h>
-
-LONG _CFGenerateUUID(uint8_t *uuid_bytes) {
-    RPC_STATUS rStatus;
-
-    /* call GetScode() function to get RPC_STATUS, because
-     * CoCreateGuid(uuid) function return HRESULT type
-     */
-    rStatus = GetScode(CoCreateGuid((uuid_t *)uuid_bytes));
-
-    /* We accept only following results RPC_S_OK, RPC_S_UUID_LOCAL_ONLY
-     */
-    if ( rStatus == RPC_S_UUID_NO_ADDRESS)
-        return rStatus;
-
-    return 0;
-};
-
-#else
-
-/*    uuid.c
- *
- *        Modifications made by William Woody to make this thing
- *    work on the Macintosh.
- */
-
-/*
- * 
- * (c) Copyright 1989 OPEN SOFTWARE FOUNDATION, INC.
- * (c) Copyright 1989 HEWLETT-PACKARD COMPANY
- * (c) Copyright 1989 DIGITAL EQUIPMENT CORPORATION
- * To anyone who acknowledges that this file is provided "AS IS"
- * without any express or implied warranty:
- *                 permission to use, copy, modify, and distribute this
- * file for any purpose is hereby granted without fee, provided that
- * the above copyright notices and this notice appears in all source
- * code copies, and that none of the names of Open Software
- * Foundation, Inc., Hewlett-Packard Company, or Digital Equipment
- * Corporation be used in advertising or publicity pertaining to
- * distribution of the software without specific, written prior
- * permission.  Neither Open Software Foundation, Inc., Hewlett-
- * Packard Company, nor Digital Equipment Corporation makes any
- * representations about the suitability of this software for any
- * purpose.
- * 
- */
-/*
- */
-/*
-**
-**  NAME:
-**
-**      uuid.c
-**
-**  FACILITY:
-**
-**      UUID
-**
-**  ABSTRACT:
-**
-**      UUID - routines that manipulate uuid's
-**
-**
-*/
-
-
-/*    uuid
- *
- *        Universal Unique ID. Note this definition will result is a 16-byte
- *    structure regardless what platform it is on.
- */
-
-struct uuid_v1_t {
-    uint32_t        time_low;
-    uint16_t        time_mid;
-    uint16_t        time_hi_and_version;
-    unsigned char        clock_seq_hi_and_reserved;
-    unsigned char        clock_seq_low;
-    unsigned char        node[6];
-};
-
-typedef struct uuid_v1_t uuid_v1_t;
-
-enum {
-    kUUIDInternalError = -21001,
-    kUUIDInvalidString = -21002
-};
-
-typedef struct {
-    uint32_t lo;
-    uint32_t hi;
-} uuid_time_t;
-
-static OSErr GenRandomEthernet(uuid_address_t *addr);
-static OSErr ReadPrefData(void);
-
-/*
- *    Preferences file management
- */
-
-static uuid_address_t GSavedENetAddr = {{0, 0, 0, 0, 0, 0}};
-static uuid_time_t GLastTime = {0, 0};            /* Clock state info */
-static uint16_t GTimeAdjust = 0;
-static uint16_t GClockSeq = 0;
-
-
-/*
- * Internal structure of universal unique IDs (UUIDs).
- *
- * There are three "variants" of UUIDs that this code knows about.  The
- * variant #0 is what was defined in the 1989 HP/Apollo Network Computing
- * Architecture (NCA) specification and implemented in NCS 1.x and DECrpc
- * v1.  Variant #1 is what was defined for the joint HP/DEC specification
- * for the OSF (in DEC's "UID Architecture Functional Specification Version
- * X1.0.4") and implemented in NCS 2.0, DECrpc v2, and OSF 1.0 DCE RPC.
- * Variant #2 is defined by Microsoft.
- *
- * This code creates only variant #1 UUIDs.
- * 
- * The three UUID variants can exist on the same wire because they have
- * distinct values in the 3 MSB bits of octet 8 (see table below).  Do
- * NOT confuse the version number with these 3 bits.  (Note the distinct
- * use of the terms "version" and "variant".) Variant #0 had no version
- * field in it.  Changes to variant #1 (should any ever need to be made)
- * can be accomodated using the current form's 4 bit version field.
- * 
- * The UUID record structure MUST NOT contain padding between fields.
- * The total size = 128 bits.
- *
- * To minimize confusion about bit assignment within octets, the UUID
- * record definition is defined only in terms of fields that are integral
- * numbers of octets.
- *
- * Depending on the network data representation, the multi-octet unsigned
- * integer fields are subject to byte swapping when communicated between
- * dissimilar endian machines.  Note that all three UUID variants have
- * the same record structure; this allows this byte swapping to occur.
- * (The ways in which the contents of the fields are generated can and
- * do vary.)
- *
- * The following information applies to variant #1 UUIDs:
- *
- * The lowest addressed octet contains the global/local bit and the
- * unicast/multicast bit, and is the first octet of the address transmitted
- * on an 802.3 LAN.
- *
- * The adjusted time stamp is split into three fields, and the clockSeq
- * is split into two fields.
- *
- * |<------------------------- 32 bits -------------------------->|
- *
- * +--------------------------------------------------------------+
- * |                     low 32 bits of time                      |  0-3  .time_low
- * +-------------------------------+-------------------------------
- * |     mid 16 bits of time       |  4-5               .time_mid
- * +-------+-----------------------+
- * | vers. |   hi 12 bits of time  |  6-7               .time_hi_and_version
- * +-------+-------+---------------+
- * |Res|  clkSeqHi |  8                                 .clock_seq_hi_and_reserved
- * +---------------+
- * |   clkSeqLow   |  9                                 .clock_seq_low
- * +---------------+----------...-----+
- * |            node ID               |  8-16           .node
- * +--------------------------...-----+
- *
- * --------------------------------------------------------------------------
- *
- * The structure layout of all three UUID variants is fixed for all time.
- * I.e., the layout consists of a 32 bit int, 2 16 bit ints, and 8 8
- * bit ints.  The current form version field does NOT determine/affect
- * the layout.  This enables us to do certain operations safely on the
- * variants of UUIDs without regard to variant; this increases the utility
- * of this code even as the version number changes (i.e., this code does
- * NOT need to check the version field).
- *
- * The "Res" field in the octet #8 is the so-called "reserved" bit-field
- * and determines whether or not the uuid is a old, current or other
- * UUID as follows:
- *
- *      MS-bit  2MS-bit  3MS-bit      Variant
- *      ---------------------------------------------
- *         0       x        x       0 (NCS 1.5)
- *         1       0        x       1 (DCE 1.0 RPC)
- *         1       1        0       2 (Microsoft)
- *         1       1        1       unspecified
- *
- * --------------------------------------------------------------------------
- *
- * Internal structure of variant #0 UUIDs
- *
- * The first 6 octets are the number of 4 usec units of time that have
- * passed since 1/1/80 0000 GMT.  The next 2 octets are reserved for
- * future use.  The next octet is an address family.  The next 7 octets
- * are a host ID in the form allowed by the specified address family.
- *
- * Note that while the family field (octet 8) was originally conceived
- * of as being able to hold values in the range [0..255], only [0..13]
- * were ever used.  Thus, the 2 MSB of this field are always 0 and are
- * used to distinguish old and current UUID forms.
- *
- * +--------------------------------------------------------------+
- * |                    high 32 bits of time                      |  0-3  .time_high
- * +-------------------------------+-------------------------------
- * |     low 16 bits of time       |  4-5               .time_low
- * +-------+-----------------------+
- * |         reserved              |  6-7               .reserved
- * +---------------+---------------+
- * |    family     |   8                                .family
- * +---------------+----------...-----+
- * |            node ID               |  9-16           .node
- * +--------------------------...-----+
- *
- */
-
-/***************************************************************************
- *
- * Local definitions
- *
- **************************************************************************/
-
-static const long      uuid_c_version          = 1;
-
-/*
- * local defines used in uuid bit-diddling
- */
-#define HI_WORD(w)                  ((w) >> 16)
-#define RAND_MASK                   0x3fff      /* same as CLOCK_SEQ_LAST */
-
-#define TIME_MID_MASK               0x0000ffff
-#define TIME_HIGH_MASK              0x0fff0000
-#define TIME_HIGH_SHIFT_COUNT       16
-
-/*
- *    The following was modified in order to prevent overlap because
- *    our clock is (theoretically) accurate to 1us (or 1s in CarbonLib)
- */
-
-
-#define MAX_TIME_ADJUST             9            /* Max adjust before tick */
-
-#define CLOCK_SEQ_LOW_MASK          0xff
-#define CLOCK_SEQ_HIGH_MASK         0x3f00
-#define CLOCK_SEQ_HIGH_SHIFT_COUNT  8
-#define CLOCK_SEQ_FIRST             1
-#define CLOCK_SEQ_LAST              0x3fff      /* same as RAND_MASK */
-
-/*
- * Note: If CLOCK_SEQ_BIT_BANG == true, then we can avoid the modulo
- * operation.  This should save us a divide instruction and speed
- * things up.
- */
-
-#ifndef CLOCK_SEQ_BIT_BANG
-#define CLOCK_SEQ_BIT_BANG          1
-#endif
-
-#if CLOCK_SEQ_BIT_BANG
-#define CLOCK_SEQ_BUMP(seq)         ((*seq) = ((*seq) + 1) & CLOCK_SEQ_LAST)
-#else
-#define CLOCK_SEQ_BUMP(seq)         ((*seq) = ((*seq) + 1) % (CLOCK_SEQ_LAST+1))
-#endif
-
-#define UUID_VERSION_BITS           (uuid_c_version << 12)
-#define UUID_RESERVED_BITS          0x80
-
-#define IS_OLD_UUID(uuid) (((uuid)->clock_seq_hi_and_reserved & 0xc0) != 0x80)
-
-/****************************************************************************
- *
- * local data declarations
- *
- ****************************************************************************/
-
-typedef struct {
-    uint32_t lo;
-    uint32_t hi;
-} unsigned64_t;
-
-/*
- * declarations used in UTC time calculations
- */
-static uuid_time_t          time_now = {0, 0};     /* utc time as of last query        */
-//static uuid_time_t          time_last;    /* utc time last time I looked      */
-//static uint16_t       time_adjust;  /* 'adjustment' to ensure uniqness  */
-//static uint16_t       clock_seq;    /* 'adjustment' for backwards clocks*/
-
-/*
- * true_random variables
- */
-
-static uint32_t     rand_m = 0;         /* multiplier                       */
-static uint32_t     rand_ia = 0;        /* adder #1                         */
-static uint32_t     rand_ib = 0;        /* adder #2                         */
-static uint32_t     rand_irand = 0;     /* random value                     */
-
-typedef enum
-{
-    uuid_e_less_than, uuid_e_equal_to, uuid_e_greater_than
-} uuid_compval_t;
-
-
-
-
-/****************************************************************************
- *
- * local function declarations
- *
- ****************************************************************************/
-
-/*
- * I N I T
- *
- * Startup initialization routine for UUID module.
- */
-
-static OSErr init (void);
-
-/*
- * T R U E _ R A N D O M _ I N I T
- */
-
-static void true_random_init (void);
-
-/*
- * T R U E _ R A N D O M
- */
-static uint16_t true_random (void);
-
-
-/*
- * N E W _ C L O C K _ S E Q
- *
- * Ensure clock_seq is up-to-date
- *
- * Note: clock_seq is architected to be 14-bits (unsigned) but
- *       I've put it in here as 16-bits since there isn't a
- *       14-bit unsigned integer type (yet)
- */ 
-static void new_clock_seq ( uint16_t * /*clock_seq*/);
-
-
-/*
- * T I M E _ C M P
- *
- * Compares two UUID times (64-bit DEC UID UTC values)
- */
-static uuid_compval_t time_cmp (
-        uuid_time_t *        /*time1*/,
-        uuid_time_t *        /*time2*/
-    );
-
-
-/************************************************************************/
-/*                                                                        */
-/*    New Routines                                                        */
-/*                                                                        */
-/************************************************************************/
-
-/*
- * saved copy of our IEEE 802 address for quick reference
- */
-
-static uuid_address_t saved_addr = {{0, 0, 0, 0, 0, 0}};
-static int got_address = false;
-static int last_addr_result = false;
-
-static OSErr GenRandomEthernet(uuid_address_t *addr) {
-    unsigned int i;
-    for (i = 0; i < 6; i++) {
-        addr->eaddr[i] = (unsigned char)(true_random() & 0xff);
-    }
-    return 0;
-}
-
-/*
-**++
-**
-**  ROUTINE NAME:       uuid_get_address
-**
-**  SCOPE:              PUBLIC
-**
-**  DESCRIPTION:
-**
-**  Return our IEEE 802 address.
-**
-**  This function is not really "public", but more like the SPI functions
-**  -- available but not part of the official API.  We've done this so
-**  that other subsystems (of which there are hopefully few or none)
-**  that need the IEEE 802 address can use this function rather than
-**  duplicating the gore it does (or more specifically, the gore that
-**  "uuid__get_os_address" does).
-**
-**  INPUTS:             none
-**
-**  INPUTS/OUTPUTS:     none
-**
-**  OUTPUTS:
-**
-**      addr            IEEE 802 address
-**
-**      status          return status value
-**
-**  IMPLICIT INPUTS:    none
-**
-**  IMPLICIT OUTPUTS:   none
-**
-**  FUNCTION VALUE:     none
-**
-**  SIDE EFFECTS:       none
-**
-**--
-**/
-
-static int uuid_get_address(uuid_address_t *addr)
-{
-    
-    /*
-     * just return address we determined previously if we've
-     * already got one
-     */
-
-    if (got_address) {
-        memmove (addr, &saved_addr, sizeof (uuid_address_t));
-        return last_addr_result;
-    }
-
-    /*
-     * Otherwise, call the system specific routine.
-     */
-
-    last_addr_result = GetEthernetAddr(addr);
-    
-    /*
-     *    Was this an error? If so, I need to generate a random
-     *    sequence to use in place of an Ethernet address.
-     */
-    if (last_addr_result) {
-        last_addr_result = GenRandomEthernet(addr);
-    }
-    
-    got_address = true;
-    if (last_addr_result == 0) {
-        /* On no error copy */
-        memmove (&saved_addr, addr, sizeof (uuid_address_t));
-    }
-    return last_addr_result;
-}
-
-/*****************************************************************************
- *
- *  Macro definitions
- *
- ****************************************************************************/
-
-/*
- * ensure we've been initialized
- */
-static int uuid_init_done = false;
-
-#define EmptyArg
-#define UUID_VERIFY_INIT(Arg)          \
-    if (! uuid_init_done)           \
-    {                               \
-        init (status);              \
-        if (*status != uuid_s_ok)   \
-        {                           \
-            return Arg;                 \
-        }                           \
-    }
-
-/*
- * Check the reserved bits to make sure the UUID is of the known structure.
- */
-
-#define CHECK_STRUCTURE(uuid) \
-( \
-    (((uuid)->clock_seq_hi_and_reserved & 0x80) == 0x00) || /* var #0 */ \
-    (((uuid)->clock_seq_hi_and_reserved & 0xc0) == 0x80) || /* var #1 */ \
-    (((uuid)->clock_seq_hi_and_reserved & 0xe0) == 0xc0)    /* var #2 */ \
-)
-
-/*
- * The following macros invoke CHECK_STRUCTURE(), check that the return
- * value is okay and if not, they set the status variable appropriately
- * and return either a boolean false, nothing (for void procedures),
- * or a value passed to the macro.  This has been done so that checking
- * can be done more simply and values are returned where appropriate
- * to keep compilers happy.
- *
- * bCHECK_STRUCTURE - returns boolean false
- * vCHECK_STRUCTURE - returns nothing (void)
- * rCHECK_STRUCTURE - returns 'r' macro parameter
- */
-
-#define bCHECK_STRUCTURE(uuid, status) \
-{ \
-    if (!CHECK_STRUCTURE (uuid)) \
-    { \
-        *(status) = uuid_s_bad_version; \
-        return (false); \
-    } \
-}
-
-#define vCHECK_STRUCTURE(uuid, status) \
-{ \
-    if (!CHECK_STRUCTURE (uuid)) \
-    { \
-        *(status) = uuid_s_bad_version; \
-        return; \
-    } \
-}
-
-#define rCHECK_STRUCTURE(uuid, status, result) \
-{ \
-    if (!CHECK_STRUCTURE (uuid)) \
-    { \
-        *(status) = uuid_s_bad_version; \
-        return (result); \
-    } \
-}
-
-
-/*
- *  Define constant designation difference in Unix and DTSS base times:
- *  DTSS UTC base time is October 15, 1582.
- *  Unix base time is January 1, 1970.
- */
-#define uuid_c_os_base_time_diff_lo     0x13814000
-#define uuid_c_os_base_time_diff_hi     0x01B21DD2
-
-#ifndef UUID_C_100NS_PER_SEC
-#define UUID_C_100NS_PER_SEC            10000000
-#endif
-
-#ifndef UUID_C_100NS_PER_USEC
-#define UUID_C_100NS_PER_USEC           10
-#endif
-
-
-
-
-
-/*
- * UADD_UVLW_2_UVLW - macro to add two unsigned 64-bit long integers
- *                      (ie. add two unsigned 'very' long words)
- *
- * Important note: It is important that this macro accommodate (and it does)
- *                 invocations where one of the addends is also the sum.
- *
- * This macro was snarfed from the DTSS group and was originally:
- *
- * UTCadd - macro to add two UTC times
- *
- * add lo and high order longword separately, using sign bits of the low-order
- * longwords to determine carry.  sign bits are tested before addition in two
- * cases - where sign bits match. when the addend sign bits differ the sign of
- * the result is also tested:
- *
- *        sign            sign
- *      addend 1        addend 2        carry?
- *
- *          1               1            true
- *          1               0            true if sign of sum clear
- *          0               1            true if sign of sum clear
- *          0               0            false
- */
-#define UADD_UVLW_2_UVLW(add1, add2, sum)                               \
-    if (!(((add1)->lo&0x80000000UL) ^ ((add2)->lo&0x80000000UL)))           \
-    {                                                                   \
-        if (((add1)->lo&0x80000000UL))                                    \
-        {                                                               \
-            (sum)->lo = (add1)->lo + (add2)->lo ;                       \
-            (sum)->hi = (add1)->hi + (add2)->hi+1 ;                     \
-        }                                                               \
-        else                                                            \
-        {                                                               \
-            (sum)->lo  = (add1)->lo + (add2)->lo ;                      \
-            (sum)->hi = (add1)->hi + (add2)->hi ;                       \
-        }                                                               \
-    }                                                                   \
-    else                                                                \
-    {                                                                   \
-        (sum)->lo = (add1)->lo + (add2)->lo ;                           \
-        (sum)->hi = (add1)->hi + (add2)->hi ;                           \
-        if (!((sum)->lo&0x80000000UL))                                    \
-            (sum)->hi++ ;                                               \
-    }
-
-/*
- * UADD_UW_2_UVLW - macro to add a 16-bit unsigned integer to
- *                   a 64-bit unsigned integer
- *
- * Note: see the UADD_UVLW_2_UVLW() macro
- *
- */
-#define UADD_UW_2_UVLW(add1, add2, sum)                                 \
-{                                                                       \
-    (sum)->hi = (add2)->hi;                                             \
-    if ((add2)->lo & 0x80000000UL)                                        \
-    {                                                                   \
-        (sum)->lo = (*add1) + (add2)->lo;                               \
-        if (!((sum)->lo & 0x80000000UL))                                  \
-        {                                                               \
-            (sum)->hi++;                                                \
-        }                                                               \
-    }                                                                   \
-    else                                                                \
-    {                                                                   \
-        (sum)->lo = (*add1) + (add2)->lo;                               \
-    }                                                                   \
-}
-
-/*
- * U U I D _ _ G E T _ O S _ T I M E
- *
- * Get OS time - contains platform-specific code.
- */
-
-static const double utc_conversion_factor = 429.4967296; // 2^32 / 10^7
-
-static void uuid__get_os_time (uuid_time_t * uuid_time)
-{
-    unsigned64_t       utc,
-                        os_basetime_diff;
-    CFAbsoluteTime at = CFAbsoluteTimeGetCurrent() + kCFAbsoluteTimeIntervalSince1970;
-    double utc_at = at / utc_conversion_factor;
-    
-    /* Convert 'at' in double seconds to 100ns units in utc */
-    utc.hi = (uint32_t)utc_at;
-    utc_at -= (double)utc.hi;
-    utc_at *= utc_conversion_factor;
-    utc_at *= 10000000.0;
-    utc.lo = (uint32_t)utc_at;
-
-    /*
-     * Offset between DTSS formatted times and Unix formatted times.
-     */
-    os_basetime_diff.lo = uuid_c_os_base_time_diff_lo;
-    os_basetime_diff.hi = uuid_c_os_base_time_diff_hi;
-    UADD_UVLW_2_UVLW (&utc, &os_basetime_diff, uuid_time);
-
-}
-
-/*
-**++
-**
-**  ROUTINE NAME:       init
-**
-**  SCOPE:              INTERNAL - declared locally
-**
-**  DESCRIPTION:
-**
-**  Startup initialization routine for the UUID module.
-**
-**  INPUTS:             none
-**
-**  INPUTS/OUTPUTS:     none
-**
-**  OUTPUTS:
-**
-**      status          return status value
-**
-**          uuid_s_ok
-**          uuid_s_coding_error
-**
-**  IMPLICIT INPUTS:    none
-**
-**  IMPLICIT OUTPUTS:   none
-**
-**  FUNCTION VALUE:     void
-**
-**  SIDE EFFECTS:       sets uuid_init_done so this won't be done again
-**
-**--
-**/
-
-static OSErr init()
-{
-    /*
-     * init the random number generator
-     */
-    
-    true_random_init();
-
-    /*
-     *    Read the preferences data from the Macintosh pref file
-     */
-    
-    ReadPrefData();
-
-    /*
-     *    Get the time. Note that I renamed 'time_last' to
-     *    GLastTime to indicate that I'm using it elsewhere as
-     *    a shared library global.
-     */
-        
-    if ((GLastTime.hi == 0) && (GLastTime.lo == 0)) {
-        uuid__get_os_time (&GLastTime);
-        GClockSeq = true_random();
-    }
-    uuid_init_done = true;
-    return 0;
-}
-
-static uint32_t _CFGenerateV1UUID(uint8_t *uuid_bytes)
-{
-    uuid_v1_t *uuid = (uuid_v1_t *)uuid_bytes;
-    OSErr                    err;
-    uuid_address_t            eaddr;
-    int               got_no_time = false;
-
-    if (!uuid_init_done) {
-        err = init();
-        if (err) return err;
-    }
-    /*
-     * get our hardware network address
-     */
-     
-    if (0 != (err = uuid_get_address(&eaddr))) return err;
-
-    do
-    {
-        /*
-         * get the current time
-         */
-        uuid__get_os_time (&time_now);
-
-        /*
-         * do stuff like:
-         *
-         *  o check that our clock hasn't gone backwards and handle it
-         *    accordingly with clock_seq
-         *  o check that we're not generating uuid's faster than we
-         *    can accommodate with our time_adjust fudge factor
-         */
-        switch (time_cmp (&time_now, &GLastTime))
-        {
-            case uuid_e_less_than:
-                new_clock_seq (&GClockSeq);
-                GTimeAdjust = 0;
-                break;
-            case uuid_e_greater_than:
-                GTimeAdjust = 0;
-                break;
-            case uuid_e_equal_to:
-                if (GTimeAdjust == MAX_TIME_ADJUST)
-                {
-                    /*
-                     * spin your wheels while we wait for the clock to tick
-                     */
-                    got_no_time = true;
-                }
-                else
-                {
-                    GTimeAdjust++;
-                }
-                break;
-            default:
-                return kUUIDInternalError;
-        }
-    } while (got_no_time);
-
-    GLastTime.lo = time_now.lo;
-    GLastTime.hi = time_now.hi;
-
-    if (GTimeAdjust != 0)
-    {
-        UADD_UW_2_UVLW (&GTimeAdjust, &time_now, &time_now);
-    }
-
-    /*
-     * now construct a uuid with the information we've gathered
-     * plus a few constants
-     */
-    uuid->time_low = time_now.lo;
-    uuid->time_mid = time_now.hi & TIME_MID_MASK;
-
-    uuid->time_hi_and_version =
-        (time_now.hi & TIME_HIGH_MASK) >> TIME_HIGH_SHIFT_COUNT;
-    uuid->time_hi_and_version |= UUID_VERSION_BITS;
-
-    uuid->clock_seq_low = GClockSeq & CLOCK_SEQ_LOW_MASK;
-    uuid->clock_seq_hi_and_reserved =
-        (GClockSeq & CLOCK_SEQ_HIGH_MASK) >> CLOCK_SEQ_HIGH_SHIFT_COUNT;
-
-    uuid->clock_seq_hi_and_reserved |= UUID_RESERVED_BITS;
-
-    memmove (uuid->node, &eaddr, sizeof (uuid_address_t));
-
-    return 0;
-}
-
-#if defined(__MACH__)
-
-#include <uuid/uuid.h>
-
-__private_extern__ uint32_t _CFGenerateUUID(uuid_t *uuid_bytes) {
-    static Boolean useV1UUIDs = false, checked = false;
-    uuid_t uuid;
-    if (!checked) {
-        const char *value = getenv("CFUUIDVersionNumber");
-        if (value) {
-            if (1 == strtoul(value, NULL, 0)) useV1UUIDs = true;
-        } else {
-            if (!_CFExecutableLinkedOnOrAfter(CFSystemVersionTiger)) useV1UUIDs = true;
-        }
-        checked = true;
-    }
-    if (useV1UUIDs) return _CFGenerateV1UUID(uuid_bytes);
-    uuid_generate_random(uuid);
-    memcpy(uuid_bytes, uuid, sizeof(uuid));
-    return 0;
-} 
-
-#else
-
-__private_extern__ uint32_t _CFGenerateUUID(uuid_t *uuid_bytes) {
-    return _CFGenerateV1UUID(uuid_bytes);
-}
-
-#endif  // __MACH__
-
-
-/*****************************************************************************
- *
- *  LOCAL MATH PROCEDURES - math procedures used internally by the UUID module
- *
- ****************************************************************************/
-
-/*
-** T I M E _ C M P
-**
-** Compares two UUID times (64-bit UTC values)
-**/
-
-static uuid_compval_t time_cmp(uuid_time_t *time1,uuid_time_t *time2)
-{
-    /*
-     * first check the hi parts
-     */
-    if (time1->hi < time2->hi) return (uuid_e_less_than);
-    if (time1->hi > time2->hi) return (uuid_e_greater_than);
-
-    /*
-     * hi parts are equal, check the lo parts
-     */
-    if (time1->lo < time2->lo) return (uuid_e_less_than);
-    if (time1->lo > time2->lo) return (uuid_e_greater_than);
-
-    return (uuid_e_equal_to);
-}
-
-
-
-/****************************************************************************
-**
-**    U U I D   T R U E   R A N D O M   N U M B E R   G E N E R A T O R
-**
-*****************************************************************************
-**
-** This random number generator (RNG) was found in the ALGORITHMS Notesfile.
-**
-** (Note 16.7, July 7, 1989 by Robert (RDVAX::)Gries, Cambridge Research Lab,
-**  Computational Quality Group)
-**
-** It is really a "Multiple Prime Random Number Generator" (MPRNG) and is
-** completely discussed in reference #1 (see below).
-**
-**   References:
-**   1) "The Multiple Prime Random Number Generator" by Alexander Hass
-**      pp. 368 to 381 in ACM Transactions on Mathematical Software,
-**      December, 1987
-**   2) "The Art of Computer Programming: Seminumerical Algorithms
-**      (vol 2)" by Donald E. Knuth, pp. 39 to 113.
-**
-** A summary of the notesfile entry follows:
-**
-** Gries discusses the two RNG's available for ULTRIX-C.  The default RNG
-** uses a Linear Congruential Method (very popular) and the second RNG uses
-** a technique known as a linear feedback shift register.
-**
-** The first (default) RNG suffers from bit-cycles (patterns/repetition),
-** ie. it's "not that random."
-**
-** While the second RNG passes all the emperical tests, there are "states"
-** that become "stable", albeit contrived.
-**
-** Gries then presents the MPRNG and says that it passes all emperical
-** tests listed in reference #2.  In addition, the number of calls to the
-** MPRNG before a sequence of bit position repeats appears to have a normal
-** distribution.
-**
-** Note (mbs): I have coded the Gries's MPRNG with the same constants that
-** he used in his paper.  I have no way of knowing whether they are "ideal"
-** for the range of numbers we are dealing with.
-**
-****************************************************************************/
-
-/*
-** T R U E _ R A N D O M _ I N I T
-**
-** Note: we "seed" the RNG with the bits from the clock and the PID
-**
-**/
-
-static void true_random_init (void)
-{
-    uuid_time_t         t;
-    uint16_t          *seedp, seed=0;
-
-
-    /*
-     * optimal/recommended starting values according to the reference
-     */
-    static uint32_t   rand_m_init     = 971;
-    static uint32_t   rand_ia_init    = 11113;
-    static uint32_t   rand_ib_init    = 104322;
-    static uint32_t   rand_irand_init = 4181;
-
-    rand_m = rand_m_init;
-    rand_ia = rand_ia_init;
-    rand_ib = rand_ib_init;
-    rand_irand = rand_irand_init;
-
-    /*
-     * Generating our 'seed' value
-     *
-     * We start with the current time, but, since the resolution of clocks is
-     * system hardware dependent (eg. Ultrix is 10 msec.) and most likely
-     * coarser than our resolution (10 usec) we 'mixup' the bits by xor'ing
-     * all the bits together.  This will have the effect of involving all of
-     * the bits in the determination of the seed value while remaining system
-     * independent.  Then for good measure to ensure a unique seed when there
-     * are multiple processes creating UUID's on a system, we add in the PID.
-     */
-    uuid__get_os_time(&t);
-    seedp = (uint16_t *)(&t);
-    seed ^= *seedp++;
-    seed ^= *seedp++;
-    seed ^= *seedp++;
-    seed ^= *seedp++;
-    rand_irand += seed;
-}
-
-/*
-** T R U E _ R A N D O M
-**
-** Note: we return a value which is 'tuned' to our purposes.  Anyone
-** using this routine should modify the return value accordingly.
-**/
-
-static uint16_t true_random (void)
-{
-    rand_m += 7;
-    rand_ia += 1907;
-    rand_ib += 73939;
-
-    if (rand_m >= 9973) rand_m -= 9871;
-    if (rand_ia >= 99991) rand_ia -= 89989;
-    if (rand_ib >= 224729) rand_ib -= 96233;
-
-    rand_irand = (rand_irand * rand_m) + rand_ia + rand_ib;
-
-    return (HI_WORD (rand_irand) ^ (rand_irand & RAND_MASK));
-}
-
-/*****************************************************************************
- *
- *  LOCAL PROCEDURES - procedures used staticly by the UUID module
- *
- ****************************************************************************/
-
-/*
-** N E W _ C L O C K _ S E Q
-**
-** Ensure *clkseq is up-to-date
-**
-** Note: clock_seq is architected to be 14-bits (unsigned) but
-**       I've put it in here as 16-bits since there isn't a
-**       14-bit unsigned integer type (yet)
-**/
-
-static void new_clock_seq 
-#ifdef _DCE_PROTO_
-(
-    uint16_t              *clkseq
-)
-#else
-(clkseq)
-uint16_t              *clkseq;
-#endif
-{
-    /*
-     * A clkseq value of 0 indicates that it hasn't been initialized.
-     */
-    if (*clkseq == 0)
-    {
-#ifdef UUID_NONVOLATILE_CLOCK
-        *clkseq = uuid__read_clock();           /* read nonvolatile clock */
-        if (*clkseq == 0)                       /* still not init'd ???   */
-        {
-            *clkseq = true_random();      /* yes, set random        */
-        }
-#else
-        /*
-         * with a volatile clock, we always init to a random number
-         */
-        *clkseq = true_random();
-#endif
-    }
-
-    CLOCK_SEQ_BUMP (clkseq);
-    if (*clkseq == 0)
-    {
-        *clkseq = *clkseq + 1;
-    }
-
-#ifdef UUID_NONVOLATILE_CLOCK
-    uuid_write_clock (clkseq);
-#endif
-}
-
-
-
-/*    ReadPrefData
- *
- *        Read the preferences data into my global variables
- */
-
-static OSErr ReadPrefData(void)
-{
-    /*
-     *    Zero out the saved preferences information
-     */
-    
-    memset((void *)&GSavedENetAddr, 0, sizeof(GSavedENetAddr));
-    memset((void *)&GLastTime, 0, sizeof(GLastTime));
-    GTimeAdjust = 0;
-    GClockSeq = 0;
-
-
-    return 0;
-}
-
-#if 0
-// currently unused
-
-/*    WritePrefData
- *
- *        Write the preferences data back out to my global variables.
- *    This gets called a couple of times. First, this is called by
- *    my GetRandomEthernet routine if I generated a psudorandom MAC
- *    address. Second, this is called when the library is being
- *    terminated through the __terminate() CFM call.
- *
- *        Note this does it's best attempt at writing the data out,
- *    and relies on ReadPrefData to check for integrety of the actual
- *    saved file.
- */
-
-static void WritePrefData(void)
-{
-}
-
-#endif // 0
-
-#undef HI_WORD
-#undef RAND_MASK
-#undef TIME_MID_MASK
-#undef TIME_HIGH_MASK
-#undef TIME_HIGH_SHIFT_COUNT
-#undef MAX_TIME_ADJUST
-#undef CLOCK_SEQ_LOW_MASK
-#undef CLOCK_SEQ_HIGH_MASK
-#undef CLOCK_SEQ_HIGH_SHIFT_COUNT
-#undef CLOCK_SEQ_FIRST
-#undef CLOCK_SEQ_LAST
-#undef CLOCK_SEQ_BIT_BANG
-#undef CLOCK_SEQ_BUMP
-#undef UUID_VERSION_BITS
-#undef UUID_RESERVED_BITS
-#undef IS_OLD_UUID
-#undef EmptyArg
-#undef UUID_VERIFY_INIT
-#undef CHECK_STRUCTURE
-#undef bCHECK_STRUCTURE
-#undef vCHECK_STRUCTURE
-#undef rCHECK_STRUCTURE
-#undef uuid_c_os_base_time_diff_lo
-#undef uuid_c_os_base_time_diff_hi
-#undef UUID_C_100NS_PER_SEC
-#undef UUID_C_100NS_PER_USEC
-#undef UADD_UVLW_2_UVLW
-#undef UADD_UW_2_UVLW
-
-#endif // __WIN32__