summaryrefslogtreecommitdiff
path: root/source/luametatex/source/utilities/auxsystem.c
blob: d3d818a85e34c5998d0d908098c3461aa777ceeb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/*
    See license.txt in the root of this project.
*/

# include "luametatex.h"

/*tex This code is taken from the \LUA\ socket library: |timeout.c|. */

# ifdef _WIN32

    double aux_get_current_time(void) {
        FILETIME ft;
        double t;
        GetSystemTimeAsFileTime(&ft);
        /* Windows file time (time since January 1, 1601 (UTC)) */
        t  = ft.dwLowDateTime/1.0e7 + ft.dwHighDateTime*(4294967296.0/1.0e7);
        /* convert to Unix Epoch time (time since January 1, 1970 (UTC)) */
        return (t - 11644473600.0);
    }

# else

    double aux_get_current_time(void) {
        struct timeval v;
        gettimeofday(&v, (struct timezone *) NULL);
        /* Unix Epoch time (time since January 1, 1970 (UTC)) */
        return v.tv_sec + v.tv_usec/1.0e6;
    }

# endif

void aux_set_run_time(void)
{
    lmt_main_state.start_time = aux_get_current_time();
}

double aux_get_run_time(void)
{
    return aux_get_current_time() - lmt_main_state.start_time;
}

/*tex

    In order to avoid all kind of time code in the backend code we use a function. The start time
    can be overloaded in several ways:

    \startitemize[n]
        \startitem
            By setting the environmment variable |SOURCE_DATE_EPOCH|. This will influence the \PDF\
            timestamp and \PDF\ id that is derived from the time. This variable is consulted when
            the kpse library is enabled which is analogue to other properties.
        \stopitem
        \startitem
            By setting the |texconfig.start_time| variable (as with other variables we use the
            internal name there). This has the same effect as (1) and is provided for when kpse is
            not used to set these variables or when an overloaded is wanted. This is analogue to
            other properties.
        \stopitem
    \stopitemize

    To some extend a cleaner solution would be to have a flag that disables all variable data in
    one go (like filenames and so) but we just follow the method implemented in pdftex where
    primitives are used to disable it.

*/

static int start_time = -1; /*tex This will move to one of the structs. */

static int aux_get_start_time(void) {
    if (start_time < 0) {
        start_time = (int) time((time_t *) NULL);
    }
    return start_time;
}

/*tex

    This one is used to fetch a value from texconfig which can also be used to set properties.
    This might come in handy when one has other ways to get date info in the \PDF\ file.

*/

void aux_set_start_time(int s) {
    if (s >= 0) {
        start_time = s ;
    }
}

/*tex

    All our interrupt handler has to do is set \TEX's global variable |interrupt|; then they
    will do everything needed.

*/

# ifdef _WIN32

    /* Win32 doesn't set SIGINT ... */

    static BOOL WINAPI catch_interrupt(DWORD arg)
    {
        switch (arg) {
            case CTRL_C_EVENT:
            case CTRL_BREAK_EVENT:
                aux_quit_the_program();
                return 1;
            default:
                /*tex No need to set interrupt as we are exiting anyway. */
                return 0;
        }
    }

    void aux_set_interrupt_handler(void)
    {
        SetConsoleCtrlHandler(catch_interrupt, TRUE);
    }

# else

    /* static RETSIGTYPE catch_interrupt(int arg) */

    static void catch_interrupt(int arg)
    {
        (void) arg;
        aux_quit_the_program();
        (void) signal(SIGINT, catch_interrupt);
    }

    void aux_set_interrupt_handler(void)
    {
        /* RETSIGTYPE (*old_handler) (int); */
        void (*old_handler) (int);
        old_handler = signal(SIGINT, catch_interrupt);
        if (old_handler != SIG_DFL) {
            signal(SIGINT, old_handler);
        }
    }

# endif

void aux_get_date_and_time(int *minutes, int *day, int *month, int *year, int *utc)
{
    time_t myclock = aux_get_start_time();
    struct tm *tmptr ;
    if (*utc) {
        tmptr = gmtime(&myclock);
    } else {
        tmptr = localtime(&myclock);
    }
    *minutes = tmptr->tm_hour * 60 + tmptr->tm_min;
    *day = tmptr->tm_mday;
    *month = tmptr->tm_mon + 1;
    *year = tmptr->tm_year + 1900;
 /* set_interrupt_handler(); */
}