prmjtime.c

来自「一个基于alice开发的机器人」· C语言 代码 · 共 647 行 · 第 1/2 页

C
647
字号
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Mozilla Communicator client code, released
 * March 31, 1998.
 *
 * The Initial Developer of the Original Code is
 * Netscape Communications Corporation.
 * Portions created by the Initial Developer are Copyright (C) 1998
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either of the GNU General Public License Version 2 or later (the "GPL"),
 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

/*
 * PR time code.
 */
#include "jsstddef.h"
#ifdef SOLARIS
#define _REENTRANT 1
#endif
#include <string.h>
#include <time.h>
#include "jstypes.h"
#include "jsutil.h"

#include "jsprf.h"
#include "prmjtime.h"

#define PRMJ_DO_MILLISECONDS 1

#ifdef XP_OS2
#include <sys/timeb.h>
#endif
#ifdef XP_WIN
#include <windef.h>
#include <winbase.h>
#endif

#ifdef XP_MAC
#include <OSUtils.h>
#include <TextUtils.h>
#include <Resources.h>
#include <Timer.h>
#include <UTCUtils.h>
#include <Power.h>
#include <CodeFragments.h>
#if !TARGET_CARBON
#include <Traps.h>
#endif
#endif

#if defined(XP_UNIX) || defined(XP_BEOS)

#ifdef _SVID_GETTOD   /* Defined only on Solaris, see Solaris <sys/types.h> */
extern int gettimeofday(struct timeval *tv);
#endif

#include <sys/time.h>

#endif /* XP_UNIX */

#ifdef XP_MAC
static uint64 			 dstLocalBaseMicroseconds;
static unsigned long	 gJanuaryFirst1970Seconds;

static void MacintoshInitializeTime(void)
{
    uint64					upTime;
    unsigned long			currentLocalTimeSeconds,
	   startupTimeSeconds;
    uint64				startupTimeMicroSeconds;
    uint32				upTimeSeconds;
    uint64				oneMillion, upTimeSecondsLong, microSecondsToSeconds;
    DateTimeRec				firstSecondOfUnixTime;

    /*
     * Figure out in local time what time the machine started up. This information can be added to
     * upTime to figure out the current local time as well as GMT.
     */

    Microseconds((UnsignedWide*)&upTime);

    GetDateTime(&currentLocalTimeSeconds);

    JSLL_I2L(microSecondsToSeconds, PRMJ_USEC_PER_SEC);
    JSLL_DIV(upTimeSecondsLong, upTime, microSecondsToSeconds);
    JSLL_L2I(upTimeSeconds, upTimeSecondsLong);

    startupTimeSeconds = currentLocalTimeSeconds - upTimeSeconds;

    /*  Make sure that we normalize the macintosh base seconds to the unix base of January 1, 1970.
     */

    firstSecondOfUnixTime.year = 1970;
    firstSecondOfUnixTime.month = 1;
    firstSecondOfUnixTime.day = 1;
    firstSecondOfUnixTime.hour = 0;
    firstSecondOfUnixTime.minute = 0;
    firstSecondOfUnixTime.second = 0;
    firstSecondOfUnixTime.dayOfWeek = 0;

    DateToSeconds(&firstSecondOfUnixTime, &gJanuaryFirst1970Seconds);

    startupTimeSeconds -= gJanuaryFirst1970Seconds;

    /*  Now convert the startup time into a wide so that we can figure out GMT and DST.
     */

    JSLL_I2L(startupTimeMicroSeconds, startupTimeSeconds);
    JSLL_I2L(oneMillion, PRMJ_USEC_PER_SEC);
    JSLL_MUL(dstLocalBaseMicroseconds, oneMillion, startupTimeMicroSeconds);
}

static SleepQRec  gSleepQEntry = { NULL, sleepQType, NULL, 0 };
static JSBool     gSleepQEntryInstalled = JS_FALSE;

static pascal long MySleepQProc(long message, SleepQRecPtr sleepQ)
{
    /* just woke up from sleeping, so must recompute dstLocalBaseMicroseconds. */
    if (message == kSleepWakeUp)
        MacintoshInitializeTime();
    return 0;
}

/* Because serial port and SLIP conflict with ReadXPram calls,
 * we cache the call here
 */

static void MyReadLocation(MachineLocation * loc)
{
    static MachineLocation storedLoc;	/* InsideMac, OSUtilities, page 4-20 */
    static JSBool didReadLocation = JS_FALSE;
    if (!didReadLocation)
    {
        MacintoshInitializeTime();
        ReadLocation(&storedLoc);
        /* install a sleep queue routine, so that when the machine wakes up, time can be recomputed. */
        if (&SleepQInstall != (void*)kUnresolvedCFragSymbolAddress
#if !TARGET_CARBON
            && NGetTrapAddress(0xA28A, OSTrap) != NGetTrapAddress(_Unimplemented, ToolTrap)
#endif
           ) {
            if ((gSleepQEntry.sleepQProc = NewSleepQUPP(MySleepQProc)) != NULL) {
                SleepQInstall(&gSleepQEntry);
                gSleepQEntryInstalled = JS_TRUE;
            }
        }
        didReadLocation = JS_TRUE;
     }
     *loc = storedLoc;
}


#ifndef XP_MACOSX

/* CFM library init and terminate routines. We'll use the terminate routine
   to clean up the sleep Q entry. On Mach-O, the sleep Q entry gets cleaned
   up for us, so nothing to do there.
*/

extern pascal OSErr __NSInitialize(const CFragInitBlock* initBlock);
extern pascal void __NSTerminate();

pascal OSErr __JSInitialize(const CFragInitBlock* initBlock);
pascal void __JSTerminate(void);

pascal OSErr __JSInitialize(const CFragInitBlock* initBlock)
{
	return __NSInitialize(initBlock);
}

pascal void __JSTerminate()
{
  /* clean up the sleepQ entry */
  if (gSleepQEntryInstalled)
    SleepQRemove(&gSleepQEntry);
  
	__NSTerminate();
}
#endif /* XP_MACOSX */

#endif /* XP_MAC */

#define IS_LEAP(year) \
   (year != 0 && ((((year & 0x3) == 0) &&  \
		   ((year - ((year/100) * 100)) != 0)) || \
		  (year - ((year/400) * 400)) == 0))

#define PRMJ_HOUR_SECONDS  3600L
#define PRMJ_DAY_SECONDS  (24L * PRMJ_HOUR_SECONDS)
#define PRMJ_YEAR_SECONDS (PRMJ_DAY_SECONDS * 365L)
#define PRMJ_MAX_UNIX_TIMET 2145859200L /*time_t value equiv. to 12/31/2037 */
/* function prototypes */
static void PRMJ_basetime(JSInt64 tsecs, PRMJTime *prtm);
/*
 * get the difference in seconds between this time zone and UTC (GMT)
 */
JSInt32
PRMJ_LocalGMTDifference()
{
#if defined(XP_UNIX) || defined(XP_WIN) || defined(XP_OS2) || defined(XP_BEOS)
    struct tm ltime;

    /* get the difference between this time zone and GMT */
    memset((char *)&ltime,0,sizeof(ltime));
    ltime.tm_mday = 2;
    ltime.tm_year = 70;
#ifdef SUNOS4
    ltime.tm_zone = 0;
    ltime.tm_gmtoff = 0;
    return timelocal(&ltime) - (24 * 3600);
#else
    return mktime(&ltime) - (24L * 3600L);
#endif
#endif
#if defined(XP_MAC)
    static JSInt32   zone = -1L;
    MachineLocation  machineLocation;
    JSInt32 	     gmtOffsetSeconds;

    /* difference has been set no need to recalculate */
    if (zone != -1)
        return zone;

    /* Get the information about the local machine, including
     * its GMT offset and its daylight savings time info.
     * Convert each into wides that we can add to
     * startupTimeMicroSeconds.
     */

    MyReadLocation(&machineLocation);

    /* Mask off top eight bits of gmtDelta, sign extend lower three. */
    gmtOffsetSeconds = (machineLocation.u.gmtDelta << 8);
    gmtOffsetSeconds >>= 8;

    /* Backout OS adjustment for DST, to give consistent GMT offset. */
    if (machineLocation.u.dlsDelta != 0)
        gmtOffsetSeconds -= PRMJ_HOUR_SECONDS;
    return (zone = -gmtOffsetSeconds);
#endif
}

/* Constants for GMT offset from 1970 */
#define G1970GMTMICROHI        0x00dcdcad /* micro secs to 1970 hi */
#define G1970GMTMICROLOW       0x8b3fa000 /* micro secs to 1970 low */

#define G2037GMTMICROHI        0x00e45fab /* micro secs to 2037 high */
#define G2037GMTMICROLOW       0x7a238000 /* micro secs to 2037 low */

/* Convert from base time to extended time */
static JSInt64
PRMJ_ToExtendedTime(JSInt32 base_time)
{
    JSInt64 exttime;
    JSInt64 g1970GMTMicroSeconds;
    JSInt64 low;
    JSInt32 diff;
    JSInt64  tmp;
    JSInt64  tmp1;

    diff = PRMJ_LocalGMTDifference();
    JSLL_UI2L(tmp, PRMJ_USEC_PER_SEC);
    JSLL_I2L(tmp1,diff);
    JSLL_MUL(tmp,tmp,tmp1);

    JSLL_UI2L(g1970GMTMicroSeconds,G1970GMTMICROHI);
    JSLL_UI2L(low,G1970GMTMICROLOW);
#ifndef JS_HAVE_LONG_LONG
    JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16);
    JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,16);
#else
    JSLL_SHL(g1970GMTMicroSeconds,g1970GMTMicroSeconds,32);
#endif
    JSLL_ADD(g1970GMTMicroSeconds,g1970GMTMicroSeconds,low);

    JSLL_I2L(exttime,base_time);
    JSLL_ADD(exttime,exttime,g1970GMTMicroSeconds);
    JSLL_SUB(exttime,exttime,tmp);
    return exttime;
}

JSInt64
PRMJ_Now(void)
{
#ifdef XP_OS2
    JSInt64 s, us, ms2us, s2us;
    struct timeb b;
#endif
#ifdef XP_WIN
    JSInt64 s, us,
    win2un = JSLL_INIT(0x19DB1DE, 0xD53E8000),
    ten = JSLL_INIT(0, 10);
    FILETIME time, midnight;
#endif
#if defined(XP_UNIX) || defined(XP_BEOS)
    struct timeval tv;
    JSInt64 s, us, s2us;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?