pyscriptc 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyscriptc/__init__.py +3 -0
- pyscriptc/__main__.py +3 -0
- pyscriptc/_posthog_token.py +1 -0
- pyscriptc/builtins.py +156 -0
- pyscriptc/canonical.py +167 -0
- pyscriptc/check.py +49 -0
- pyscriptc/cli.py +271 -0
- pyscriptc/coverage.py +388 -0
- pyscriptc/debug.py +120 -0
- pyscriptc/diagnostics.py +179 -0
- pyscriptc/errors.py +56 -0
- pyscriptc/ir.py +365 -0
- pyscriptc/llvm.py +2129 -0
- pyscriptc/log.py +127 -0
- pyscriptc/lower/__init__.py +1071 -0
- pyscriptc/lower/_calls.py +1499 -0
- pyscriptc/lower/_classes.py +969 -0
- pyscriptc/lower/_core.py +301 -0
- pyscriptc/lower/_expr.py +886 -0
- pyscriptc/lower/_stdlib.py +491 -0
- pyscriptc/lower/_stdlib_shared.py +93 -0
- pyscriptc/lower/_stmt.py +1173 -0
- pyscriptc/package.py +249 -0
- pyscriptc/restlower.py +1008 -0
- pyscriptc/runtime/ps_argv.c +28 -0
- pyscriptc/runtime/ps_b64.c +168 -0
- pyscriptc/runtime/ps_coll.c +133 -0
- pyscriptc/runtime/ps_dt.c +388 -0
- pyscriptc/runtime/ps_hash.c +411 -0
- pyscriptc/runtime/ps_help.c +219 -0
- pyscriptc/runtime/ps_hmac.c +120 -0
- pyscriptc/runtime/ps_io.c +198 -0
- pyscriptc/runtime/ps_island.c +272 -0
- pyscriptc/runtime/ps_json.c +402 -0
- pyscriptc/runtime/ps_mix.c +47 -0
- pyscriptc/runtime/ps_more.c +1089 -0
- pyscriptc/runtime/ps_osmore.c +447 -0
- pyscriptc/runtime/ps_path.c +547 -0
- pyscriptc/runtime/ps_re.c +1102 -0
- pyscriptc/runtime/ps_rt.c +1175 -0
- pyscriptc/runtime/ps_rt.h +189 -0
- pyscriptc/runtime/ps_struct.c +291 -0
- pyscriptc/runtime/ps_time.c +207 -0
- pyscriptc/runtime/ps_unicode.c +1521 -0
- pyscriptc/runtime/ps_url.c +327 -0
- pyscriptc/stdlib_queue.py +191 -0
- pyscriptc/stdmore.py +1596 -0
- pyscriptc/telemetry.py +219 -0
- pyscriptc-0.1.0.dist-info/METADATA +187 -0
- pyscriptc-0.1.0.dist-info/RECORD +54 -0
- pyscriptc-0.1.0.dist-info/WHEEL +5 -0
- pyscriptc-0.1.0.dist-info/entry_points.txt +2 -0
- pyscriptc-0.1.0.dist-info/licenses/LICENSE +201 -0
- pyscriptc-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/* Shared layout for the runtime linked beside emitted LLVM.
|
|
2
|
+
|
|
3
|
+
%ps.str is { i64, ptr }. PsBuf must stay 16 bytes. PsSeq keeps len, elem, and
|
|
4
|
+
data in that order; cap is appended so existing stores still line up.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#ifndef PYSCRIPTC_PS_RT_H
|
|
8
|
+
#define PYSCRIPTC_PS_RT_H
|
|
9
|
+
|
|
10
|
+
#include <stdint.h>
|
|
11
|
+
|
|
12
|
+
enum {
|
|
13
|
+
PS_VALUE = 1,
|
|
14
|
+
PS_INDEX = 2,
|
|
15
|
+
PS_KEY = 3,
|
|
16
|
+
PS_OVERFLOW = 4,
|
|
17
|
+
PS_ZERO_DIV = 5,
|
|
18
|
+
PS_RUNTIME = 6,
|
|
19
|
+
PS_EXCEPTION = 7,
|
|
20
|
+
PS_USER_BASE = 8
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/* longjmp payload once an exception is pending; the class code lives on the
|
|
24
|
+
PsExc record, not on the wire. */
|
|
25
|
+
enum { PS_RAISED = -1 };
|
|
26
|
+
|
|
27
|
+
enum {
|
|
28
|
+
PS_JSON_INT = 1,
|
|
29
|
+
PS_JSON_BOOL = 2,
|
|
30
|
+
PS_JSON_STR = 3,
|
|
31
|
+
PS_JSON_LIST = 4,
|
|
32
|
+
PS_JSON_DICT = 5
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
typedef struct PsBuf {
|
|
36
|
+
int64_t len;
|
|
37
|
+
char *data;
|
|
38
|
+
} PsBuf;
|
|
39
|
+
|
|
40
|
+
typedef struct PsSeq {
|
|
41
|
+
int64_t len;
|
|
42
|
+
int64_t elem;
|
|
43
|
+
void *data;
|
|
44
|
+
int64_t cap;
|
|
45
|
+
} PsSeq;
|
|
46
|
+
|
|
47
|
+
typedef struct PsMap {
|
|
48
|
+
int64_t len;
|
|
49
|
+
int64_t cap;
|
|
50
|
+
int32_t key_kind;
|
|
51
|
+
int64_t key_size;
|
|
52
|
+
int64_t val_size;
|
|
53
|
+
void *keys;
|
|
54
|
+
void *vals;
|
|
55
|
+
} PsMap;
|
|
56
|
+
|
|
57
|
+
typedef struct PsType {
|
|
58
|
+
int32_t kind;
|
|
59
|
+
int32_t child;
|
|
60
|
+
} PsType;
|
|
61
|
+
|
|
62
|
+
typedef struct PsArg {
|
|
63
|
+
int32_t kind;
|
|
64
|
+
int32_t pad;
|
|
65
|
+
int64_t i;
|
|
66
|
+
double f;
|
|
67
|
+
PsBuf b;
|
|
68
|
+
} PsArg;
|
|
69
|
+
|
|
70
|
+
typedef struct PsGrow {
|
|
71
|
+
char *data;
|
|
72
|
+
int64_t len;
|
|
73
|
+
int64_t cap;
|
|
74
|
+
} PsGrow;
|
|
75
|
+
|
|
76
|
+
/* Raised exception. name and message are borrowed storage: name points at the
|
|
77
|
+
static class-name table, message at a 256-byte owned buffer like the old
|
|
78
|
+
ps_msg channel. cause and args stay NULL until M3/E3. */
|
|
79
|
+
typedef struct PsExc {
|
|
80
|
+
int32_t code;
|
|
81
|
+
int32_t flags;
|
|
82
|
+
PsBuf name;
|
|
83
|
+
PsBuf message;
|
|
84
|
+
struct PsExc *cause;
|
|
85
|
+
PsSeq *args;
|
|
86
|
+
} PsExc;
|
|
87
|
+
|
|
88
|
+
extern char ps_empty_byte;
|
|
89
|
+
|
|
90
|
+
__attribute__((noreturn)) void ps_raise_cstr(int32_t code, const char *msg);
|
|
91
|
+
__attribute__((noreturn)) void ps_raise_code(int32_t code);
|
|
92
|
+
__attribute__((noreturn)) void ps_reraise(void);
|
|
93
|
+
int32_t ps_exc_code(void);
|
|
94
|
+
int32_t ps_exc_isa(int32_t raised, int32_t wanted);
|
|
95
|
+
void *ps_alloc(int64_t n);
|
|
96
|
+
|
|
97
|
+
PsSeq *ps_seq_new(int64_t elem, int64_t n);
|
|
98
|
+
int64_t ps_seq_len(PsSeq *s);
|
|
99
|
+
void ps_seq_get(PsSeq *s, int64_t i, void *out);
|
|
100
|
+
void ps_seq_set(PsSeq *s, int64_t i, void *src);
|
|
101
|
+
void ps_seq_push(PsSeq *s, const void *src);
|
|
102
|
+
|
|
103
|
+
PsMap *ps_map_new(int32_t key_kind, int64_t key_size, int64_t val_size, int64_t cap);
|
|
104
|
+
void ps_map_put(PsMap *m, void *key, void *val);
|
|
105
|
+
int64_t ps_map_len(PsMap *m);
|
|
106
|
+
void ps_map_key_at(PsMap *m, int64_t i, void *out);
|
|
107
|
+
PsSeq *ps_dict_keys(PsMap *m);
|
|
108
|
+
void ps_map_val_at(PsMap *m, int64_t i, void *out);
|
|
109
|
+
|
|
110
|
+
void ps_buf_view(PsBuf *out, const char *p, int64_t n);
|
|
111
|
+
void ps_buf_copy(PsBuf *out, const char *p, int64_t n);
|
|
112
|
+
|
|
113
|
+
void ps_grow_init(PsGrow *g);
|
|
114
|
+
void ps_grow_add(PsGrow *g, const char *p, int64_t n);
|
|
115
|
+
void ps_grow_byte(PsGrow *g, unsigned char c);
|
|
116
|
+
void ps_grow_finish(PsGrow *g, PsBuf *out);
|
|
117
|
+
|
|
118
|
+
void ps_str_slice(
|
|
119
|
+
int64_t n, const char *p, int64_t start, int64_t stop, int64_t has_start, int64_t has_stop, int64_t step, PsBuf *out
|
|
120
|
+
);
|
|
121
|
+
PsSeq *ps_seq_slice(PsSeq *s, int64_t start, int64_t stop, int64_t has_start, int64_t has_stop, int64_t step);
|
|
122
|
+
PsSeq *ps_str_split(int64_t n, const char *p, int64_t sn, const char *sp, int64_t mode);
|
|
123
|
+
void ps_str_join(int64_t n, const char *sep, PsSeq *parts, PsBuf *out);
|
|
124
|
+
void ps_utf8_encode(int64_t n, const char *p, PsBuf *out);
|
|
125
|
+
void ps_utf8_decode(int64_t n, const char *p, PsBuf *out);
|
|
126
|
+
void ps_i64_str(int64_t v, PsBuf *out);
|
|
127
|
+
void ps_f64_str(double v, PsBuf *out);
|
|
128
|
+
int64_t ps_bisect_left(PsSeq *s, int64_t key);
|
|
129
|
+
int64_t ps_bisect_right(PsSeq *s, int64_t key);
|
|
130
|
+
int64_t ps_int_from_bytes(int64_t n, const char *s);
|
|
131
|
+
|
|
132
|
+
/* ps_more.c: R1-R5 helpers */
|
|
133
|
+
PsSeq *ps_seq_concat(PsSeq *a, PsSeq *b);
|
|
134
|
+
PsSeq *ps_seq_repeat(PsSeq *s, int64_t n);
|
|
135
|
+
void ps_seq_extend(PsSeq *dst, PsSeq *src);
|
|
136
|
+
void ps_seq_insert(PsSeq *s, int64_t i, void *src);
|
|
137
|
+
void ps_seq_reverse(PsSeq *s);
|
|
138
|
+
void ps_seq_sort_i64(PsSeq *s, int64_t desc);
|
|
139
|
+
void ps_seq_sort_f64(PsSeq *s, int64_t desc);
|
|
140
|
+
void ps_seq_sort_buf(PsSeq *s, int64_t desc);
|
|
141
|
+
int64_t ps_seq_index_i64(PsSeq *s, int64_t needle);
|
|
142
|
+
int64_t ps_seq_index_f64(PsSeq *s, double needle);
|
|
143
|
+
int64_t ps_seq_index_buf(PsSeq *s, int64_t n, char *p);
|
|
144
|
+
int64_t ps_seq_count_i64(PsSeq *s, int64_t needle);
|
|
145
|
+
int64_t ps_seq_count_f64(PsSeq *s, double needle);
|
|
146
|
+
int64_t ps_seq_count_buf(PsSeq *s, int64_t n, char *p);
|
|
147
|
+
void ps_seq_remove_i64(PsSeq *s, int64_t needle);
|
|
148
|
+
void ps_seq_remove_f64(PsSeq *s, double needle);
|
|
149
|
+
void ps_seq_remove_buf(PsSeq *s, int64_t n, char *p);
|
|
150
|
+
void ps_seq_insert_i64(PsSeq *s, int64_t i, int64_t v);
|
|
151
|
+
void ps_seq_insert_f64(PsSeq *s, int64_t i, double v);
|
|
152
|
+
void ps_seq_insert_buf(PsSeq *s, int64_t i, int64_t n, char *p);
|
|
153
|
+
int64_t ps_seq_pop_i64(PsSeq *s, int64_t i);
|
|
154
|
+
double ps_seq_pop_f64(PsSeq *s, int64_t i);
|
|
155
|
+
void ps_seq_pop_buf(PsSeq *s, int64_t i, PsBuf *out);
|
|
156
|
+
void ps_map_del(PsMap *m, void *key);
|
|
157
|
+
void ps_map_clear(PsMap *m);
|
|
158
|
+
void ps_map_update(PsMap *dst, PsMap *src);
|
|
159
|
+
PsSeq *ps_dict_values(PsMap *m);
|
|
160
|
+
PsSeq *ps_dict_items(PsMap *m, int64_t voff, int64_t esz);
|
|
161
|
+
PsSeq *ps_str_split_m(
|
|
162
|
+
int64_t n, const char *p, int64_t sn, const char *sp, int64_t mode, int64_t maxsplit, int64_t right
|
|
163
|
+
);
|
|
164
|
+
PsSeq *ps_str_splitlines(int64_t n, const char *p, int64_t keepends);
|
|
165
|
+
int64_t ps_str_count(int64_t n, const char *p, int64_t sn, const char *sp);
|
|
166
|
+
int64_t ps_str_index(int64_t n, const char *p, int64_t sn, const char *sp);
|
|
167
|
+
int64_t ps_str_rfind(int64_t n, const char *p, int64_t sn, const char *sp);
|
|
168
|
+
int64_t ps_str_isdigit(int64_t n, const char *p);
|
|
169
|
+
int64_t ps_str_isalpha(int64_t n, const char *p);
|
|
170
|
+
int64_t ps_str_isalnum(int64_t n, const char *p);
|
|
171
|
+
int64_t ps_str_isspace(int64_t n, const char *p);
|
|
172
|
+
int64_t ps_str_isupper(int64_t n, const char *p);
|
|
173
|
+
int64_t ps_str_islower(int64_t n, const char *p);
|
|
174
|
+
void ps_str_title(int64_t n, const char *p, PsBuf *out);
|
|
175
|
+
void ps_str_capitalize(int64_t n, const char *p, PsBuf *out);
|
|
176
|
+
void ps_str_casefold(int64_t n, const char *p, PsBuf *out);
|
|
177
|
+
void ps_str_swapcase(int64_t n, const char *p, PsBuf *out);
|
|
178
|
+
void ps_str_zfill(int64_t n, const char *p, int64_t width, PsBuf *out);
|
|
179
|
+
void ps_str_justify(
|
|
180
|
+
int64_t n, const char *p, int64_t width, int64_t fn, const char *fc, int64_t side, PsBuf *out
|
|
181
|
+
);
|
|
182
|
+
void ps_str_removeprefix(int64_t n, const char *p, int64_t sn, const char *sp, PsBuf *out);
|
|
183
|
+
void ps_str_removesuffix(int64_t n, const char *p, int64_t sn, const char *sp, PsBuf *out);
|
|
184
|
+
void ps_str_expandtabs(int64_t n, const char *p, int64_t tabsize, PsBuf *out);
|
|
185
|
+
void ps_str_partition(int64_t n, const char *p, int64_t sn, const char *sp, int64_t right, PsBuf *out);
|
|
186
|
+
void ps_repr_bytes(int64_t n, const char *p, PsBuf *out);
|
|
187
|
+
double ps_float_from_str(int64_t n, const char *p);
|
|
188
|
+
|
|
189
|
+
#endif
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
/* struct.pack / struct.unpack for a literal format. Standard sizes.
|
|
2
|
+
'@' is refused by the lowerer. Out of range values are ValueError. */
|
|
3
|
+
|
|
4
|
+
#include "ps_rt.h"
|
|
5
|
+
|
|
6
|
+
#include <stdlib.h>
|
|
7
|
+
#include <string.h>
|
|
8
|
+
|
|
9
|
+
static int ps_little(void) {
|
|
10
|
+
uint16_t x = 1;
|
|
11
|
+
return *(unsigned char *)&x == 1;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
static int ps_code_size(char code) {
|
|
15
|
+
switch (code) {
|
|
16
|
+
case 'x':
|
|
17
|
+
case 'b':
|
|
18
|
+
case 'B':
|
|
19
|
+
case 's':
|
|
20
|
+
return 1;
|
|
21
|
+
case 'h':
|
|
22
|
+
case 'H':
|
|
23
|
+
return 2;
|
|
24
|
+
case 'i':
|
|
25
|
+
case 'I':
|
|
26
|
+
case 'l':
|
|
27
|
+
case 'L':
|
|
28
|
+
case 'f':
|
|
29
|
+
return 4;
|
|
30
|
+
case 'q':
|
|
31
|
+
case 'Q':
|
|
32
|
+
case 'd':
|
|
33
|
+
return 8;
|
|
34
|
+
default:
|
|
35
|
+
return -1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static int ps_code_kind(char code) {
|
|
40
|
+
if (code == 'x') {
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
if (code == 'f' || code == 'd') {
|
|
44
|
+
return 2;
|
|
45
|
+
}
|
|
46
|
+
if (code == 's') {
|
|
47
|
+
return 3;
|
|
48
|
+
}
|
|
49
|
+
return 1;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static void ps_put_bytes(unsigned char *dst, uint64_t v, int size, int le) {
|
|
53
|
+
for (int i = 0; i < size; i++) {
|
|
54
|
+
int shift = le ? i : (size - 1 - i);
|
|
55
|
+
dst[i] = (unsigned char)((v >> (8 * shift)) & 0xff);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static uint64_t ps_get_bytes(const unsigned char *src, int size, int le) {
|
|
60
|
+
uint64_t v = 0;
|
|
61
|
+
for (int i = 0; i < size; i++) {
|
|
62
|
+
int shift = le ? i : (size - 1 - i);
|
|
63
|
+
v |= (uint64_t)src[i] << (8 * shift);
|
|
64
|
+
}
|
|
65
|
+
return v;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
static int ps_in_range(char code, int64_t v) {
|
|
69
|
+
switch (code) {
|
|
70
|
+
case 'b':
|
|
71
|
+
return v >= -128 && v <= 127;
|
|
72
|
+
case 'B':
|
|
73
|
+
return v >= 0 && v <= 255;
|
|
74
|
+
case 'h':
|
|
75
|
+
return v >= -32768 && v <= 32767;
|
|
76
|
+
case 'H':
|
|
77
|
+
return v >= 0 && v <= 65535;
|
|
78
|
+
case 'i':
|
|
79
|
+
case 'l':
|
|
80
|
+
return v >= -2147483648LL && v <= 2147483647LL;
|
|
81
|
+
case 'I':
|
|
82
|
+
case 'L':
|
|
83
|
+
return v >= 0 && v <= 4294967295LL;
|
|
84
|
+
case 'q':
|
|
85
|
+
return 1;
|
|
86
|
+
case 'Q':
|
|
87
|
+
return v >= 0;
|
|
88
|
+
default:
|
|
89
|
+
return 0;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
static void ps_walk(const char *fmt, int64_t fn, int pack, PsArg *args, int64_t nargs, const char *data, int64_t dn,
|
|
94
|
+
PsBuf *packed, PsSeq **unpacked, int want) {
|
|
95
|
+
int le = ps_little();
|
|
96
|
+
int64_t i = 0;
|
|
97
|
+
int64_t argi = 0;
|
|
98
|
+
int64_t cursor = 0;
|
|
99
|
+
PsGrow g;
|
|
100
|
+
PsSeq *seq = NULL;
|
|
101
|
+
if (pack) {
|
|
102
|
+
ps_grow_init(&g);
|
|
103
|
+
} else {
|
|
104
|
+
int64_t elem = want == 2 ? 8 : want == 3 ? 16 : 8;
|
|
105
|
+
seq = ps_seq_new(elem, 0);
|
|
106
|
+
}
|
|
107
|
+
while (i < fn) {
|
|
108
|
+
char c = fmt[i];
|
|
109
|
+
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
|
110
|
+
i++;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (c == '<' ) {
|
|
114
|
+
le = 1;
|
|
115
|
+
i++;
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (c == '>' || c == '!') {
|
|
119
|
+
le = 0;
|
|
120
|
+
i++;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
if (c == '=') {
|
|
124
|
+
le = ps_little();
|
|
125
|
+
i++;
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (c == '@') {
|
|
129
|
+
ps_raise_cstr(PS_VALUE, "struct native alignment is not lowered");
|
|
130
|
+
}
|
|
131
|
+
int64_t count = 1;
|
|
132
|
+
if (c >= '0' && c <= '9') {
|
|
133
|
+
count = 0;
|
|
134
|
+
while (i < fn && fmt[i] >= '0' && fmt[i] <= '9') {
|
|
135
|
+
count = count * 10 + (fmt[i] - '0');
|
|
136
|
+
i++;
|
|
137
|
+
}
|
|
138
|
+
if (i >= fn) {
|
|
139
|
+
ps_raise_cstr(PS_VALUE, "bad struct format");
|
|
140
|
+
}
|
|
141
|
+
c = fmt[i];
|
|
142
|
+
}
|
|
143
|
+
i++;
|
|
144
|
+
int size = ps_code_size(c);
|
|
145
|
+
if (size < 0) {
|
|
146
|
+
ps_raise_cstr(PS_VALUE, "bad struct format");
|
|
147
|
+
}
|
|
148
|
+
int kind = ps_code_kind(c);
|
|
149
|
+
if (!pack && kind != 0 && want != 0 && kind != want) {
|
|
150
|
+
ps_raise_cstr(PS_VALUE, "struct.unpack result types are mixed");
|
|
151
|
+
}
|
|
152
|
+
if (c == 's') {
|
|
153
|
+
int64_t nbytes = count;
|
|
154
|
+
if (pack) {
|
|
155
|
+
if (argi >= nargs || args[argi].kind != 3) {
|
|
156
|
+
ps_raise_cstr(PS_VALUE, "struct.pack expected bytes");
|
|
157
|
+
}
|
|
158
|
+
PsBuf b = args[argi++].b;
|
|
159
|
+
int64_t take = b.len < nbytes ? b.len : nbytes;
|
|
160
|
+
if (take > 0) {
|
|
161
|
+
ps_grow_add(&g, b.data, take);
|
|
162
|
+
}
|
|
163
|
+
for (int64_t z = take; z < nbytes; z++) {
|
|
164
|
+
ps_grow_byte(&g, 0);
|
|
165
|
+
}
|
|
166
|
+
} else {
|
|
167
|
+
if (cursor + nbytes > dn) {
|
|
168
|
+
ps_raise_cstr(PS_VALUE, "struct.unpack buffer is too small");
|
|
169
|
+
}
|
|
170
|
+
PsBuf piece;
|
|
171
|
+
ps_buf_copy(&piece, data + cursor, nbytes);
|
|
172
|
+
ps_seq_push(seq, &piece);
|
|
173
|
+
cursor += nbytes;
|
|
174
|
+
}
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
for (int64_t k = 0; k < count; k++) {
|
|
178
|
+
if (c == 'x') {
|
|
179
|
+
if (pack) {
|
|
180
|
+
ps_grow_byte(&g, 0);
|
|
181
|
+
} else {
|
|
182
|
+
if (cursor + 1 > dn) {
|
|
183
|
+
ps_raise_cstr(PS_VALUE, "struct.unpack buffer is too small");
|
|
184
|
+
}
|
|
185
|
+
cursor += 1;
|
|
186
|
+
}
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (pack) {
|
|
190
|
+
if (argi >= nargs) {
|
|
191
|
+
ps_raise_cstr(PS_VALUE, "struct.pack is missing an argument");
|
|
192
|
+
}
|
|
193
|
+
unsigned char tmp[8];
|
|
194
|
+
if (kind == 1) {
|
|
195
|
+
if (args[argi].kind != 1) {
|
|
196
|
+
ps_raise_cstr(PS_VALUE, "struct.pack expected an int");
|
|
197
|
+
}
|
|
198
|
+
int64_t v = args[argi++].i;
|
|
199
|
+
if (!ps_in_range(c, v)) {
|
|
200
|
+
ps_raise_cstr(PS_VALUE, "struct format argument out of range");
|
|
201
|
+
}
|
|
202
|
+
ps_put_bytes(tmp, (uint64_t)v, size, le);
|
|
203
|
+
ps_grow_add(&g, (char *)tmp, size);
|
|
204
|
+
} else {
|
|
205
|
+
double dv;
|
|
206
|
+
if (args[argi].kind == 2) {
|
|
207
|
+
dv = args[argi++].f;
|
|
208
|
+
} else if (args[argi].kind == 1) {
|
|
209
|
+
dv = (double)args[argi++].i;
|
|
210
|
+
} else {
|
|
211
|
+
ps_raise_cstr(PS_VALUE, "struct.pack expected a float");
|
|
212
|
+
}
|
|
213
|
+
if (c == 'f') {
|
|
214
|
+
float f = (float)dv;
|
|
215
|
+
uint32_t bits = 0;
|
|
216
|
+
memcpy(&bits, &f, 4);
|
|
217
|
+
ps_put_bytes(tmp, bits, 4, le);
|
|
218
|
+
ps_grow_add(&g, (char *)tmp, 4);
|
|
219
|
+
} else {
|
|
220
|
+
uint64_t bits = 0;
|
|
221
|
+
memcpy(&bits, &dv, 8);
|
|
222
|
+
ps_put_bytes(tmp, bits, 8, le);
|
|
223
|
+
ps_grow_add(&g, (char *)tmp, 8);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
} else {
|
|
227
|
+
if (cursor + size > dn) {
|
|
228
|
+
ps_raise_cstr(PS_VALUE, "struct.unpack buffer is too small");
|
|
229
|
+
}
|
|
230
|
+
uint64_t bits = ps_get_bytes((const unsigned char *)data + cursor, size, le);
|
|
231
|
+
cursor += size;
|
|
232
|
+
if (kind == 1) {
|
|
233
|
+
int64_t v = 0;
|
|
234
|
+
if (c == 'b') {
|
|
235
|
+
v = (int8_t)bits;
|
|
236
|
+
} else if (c == 'B') {
|
|
237
|
+
v = (uint8_t)bits;
|
|
238
|
+
} else if (c == 'h') {
|
|
239
|
+
v = (int16_t)bits;
|
|
240
|
+
} else if (c == 'H') {
|
|
241
|
+
v = (uint16_t)bits;
|
|
242
|
+
} else if (c == 'i' || c == 'l') {
|
|
243
|
+
v = (int32_t)bits;
|
|
244
|
+
} else if (c == 'I' || c == 'L') {
|
|
245
|
+
v = (uint32_t)bits;
|
|
246
|
+
} else if (c == 'q') {
|
|
247
|
+
v = (int64_t)bits;
|
|
248
|
+
} else {
|
|
249
|
+
if (bits > (uint64_t)INT64_MAX) {
|
|
250
|
+
ps_raise_cstr(PS_VALUE, "struct Q result does not fit in i64");
|
|
251
|
+
}
|
|
252
|
+
v = (int64_t)bits;
|
|
253
|
+
}
|
|
254
|
+
ps_seq_push(seq, &v);
|
|
255
|
+
} else if (c == 'f') {
|
|
256
|
+
uint32_t u = (uint32_t)bits;
|
|
257
|
+
float f = 0;
|
|
258
|
+
memcpy(&f, &u, 4);
|
|
259
|
+
double d = (double)f;
|
|
260
|
+
ps_seq_push(seq, &d);
|
|
261
|
+
} else {
|
|
262
|
+
double d = 0;
|
|
263
|
+
memcpy(&d, &bits, 8);
|
|
264
|
+
ps_seq_push(seq, &d);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
if (pack) {
|
|
270
|
+
if (argi != nargs) {
|
|
271
|
+
free(g.data);
|
|
272
|
+
ps_raise_cstr(PS_VALUE, "struct.pack has too many arguments");
|
|
273
|
+
}
|
|
274
|
+
ps_grow_finish(&g, packed);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (cursor != dn) {
|
|
278
|
+
ps_raise_cstr(PS_VALUE, "struct.unpack buffer has trailing bytes");
|
|
279
|
+
}
|
|
280
|
+
*unpacked = seq;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
void ps_struct_pack(int64_t fn, char *fmt, PsArg *args, int64_t nargs, PsBuf *out) {
|
|
284
|
+
ps_walk(fmt, fn, 1, args, nargs, NULL, 0, out, NULL, 0);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
PsSeq *ps_struct_unpack(int64_t fn, char *fmt, int64_t dn, char *data, int32_t want) {
|
|
288
|
+
PsSeq *seq = NULL;
|
|
289
|
+
ps_walk(fmt, fn, 0, NULL, 0, data, dn, NULL, &seq, want);
|
|
290
|
+
return seq;
|
|
291
|
+
}
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/* time.time, sleep, gmtime, localtime, strftime, and mktime.
|
|
2
|
+
|
|
3
|
+
struct_time fields match CPython: tm_mon is 1-12, tm_wday is Monday 0,
|
|
4
|
+
tm_yday is 1-366. C's tm_* is converted at the boundary.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include "ps_rt.h"
|
|
8
|
+
|
|
9
|
+
#include <errno.h>
|
|
10
|
+
#include <math.h>
|
|
11
|
+
#include <stdlib.h>
|
|
12
|
+
#include <string.h>
|
|
13
|
+
#include <time.h>
|
|
14
|
+
|
|
15
|
+
typedef struct {
|
|
16
|
+
int64_t year;
|
|
17
|
+
int64_t month;
|
|
18
|
+
int64_t day;
|
|
19
|
+
} PsDate;
|
|
20
|
+
|
|
21
|
+
typedef struct {
|
|
22
|
+
int64_t year;
|
|
23
|
+
int64_t month;
|
|
24
|
+
int64_t day;
|
|
25
|
+
int64_t hour;
|
|
26
|
+
int64_t minute;
|
|
27
|
+
int64_t second;
|
|
28
|
+
int64_t microsecond;
|
|
29
|
+
} PsDateTime;
|
|
30
|
+
|
|
31
|
+
typedef struct {
|
|
32
|
+
int64_t tm_year;
|
|
33
|
+
int64_t tm_mon;
|
|
34
|
+
int64_t tm_mday;
|
|
35
|
+
int64_t tm_hour;
|
|
36
|
+
int64_t tm_min;
|
|
37
|
+
int64_t tm_sec;
|
|
38
|
+
int64_t tm_wday;
|
|
39
|
+
int64_t tm_yday;
|
|
40
|
+
int64_t tm_isdst;
|
|
41
|
+
} PsStructTime;
|
|
42
|
+
|
|
43
|
+
static void ps_fill_stm(const struct tm *tm, PsStructTime *out) {
|
|
44
|
+
out->tm_year = (int64_t)tm->tm_year + 1900;
|
|
45
|
+
out->tm_mon = (int64_t)tm->tm_mon + 1;
|
|
46
|
+
out->tm_mday = tm->tm_mday;
|
|
47
|
+
out->tm_hour = tm->tm_hour;
|
|
48
|
+
out->tm_min = tm->tm_min;
|
|
49
|
+
out->tm_sec = tm->tm_sec;
|
|
50
|
+
out->tm_wday = (tm->tm_wday + 6) % 7;
|
|
51
|
+
out->tm_yday = (int64_t)tm->tm_yday + 1;
|
|
52
|
+
out->tm_isdst = tm->tm_isdst;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static int ps_read_stm(const PsStructTime *in, struct tm *tm) {
|
|
56
|
+
if (in->tm_year < 1900 || in->tm_mon < 1 || in->tm_mon > 12 || in->tm_mday < 1 || in->tm_mday > 31 ||
|
|
57
|
+
in->tm_hour < 0 || in->tm_hour > 23 || in->tm_min < 0 || in->tm_min > 59 || in->tm_sec < 0 ||
|
|
58
|
+
in->tm_sec > 60) {
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
tm->tm_year = (int)(in->tm_year - 1900);
|
|
62
|
+
tm->tm_mon = (int)(in->tm_mon - 1);
|
|
63
|
+
tm->tm_mday = (int)in->tm_mday;
|
|
64
|
+
tm->tm_hour = (int)in->tm_hour;
|
|
65
|
+
tm->tm_min = (int)in->tm_min;
|
|
66
|
+
tm->tm_sec = (int)in->tm_sec;
|
|
67
|
+
tm->tm_wday = (int)((in->tm_wday + 1) % 7);
|
|
68
|
+
tm->tm_yday = (int)(in->tm_yday - 1);
|
|
69
|
+
tm->tm_isdst = (int)in->tm_isdst;
|
|
70
|
+
return 1;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
static time_t ps_as_time(double ts) {
|
|
74
|
+
if (!isfinite(ts) || ts >= 9223372036854775808.0 || ts < -9223372036854775808.0) {
|
|
75
|
+
ps_raise_cstr(PS_VALUE, "timestamp out of range");
|
|
76
|
+
}
|
|
77
|
+
return (time_t)ts;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
static double ps_clock(clockid_t id) {
|
|
81
|
+
struct timespec ts;
|
|
82
|
+
if (clock_gettime(id, &ts) != 0) {
|
|
83
|
+
ps_raise_cstr(PS_RUNTIME, "clock_gettime failed");
|
|
84
|
+
}
|
|
85
|
+
return (double)ts.tv_sec + (double)ts.tv_nsec / 1000000000.0;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
double ps_time_time(void) { return ps_clock(CLOCK_REALTIME); }
|
|
89
|
+
|
|
90
|
+
double ps_time_monotonic(void) { return ps_clock(CLOCK_MONOTONIC); }
|
|
91
|
+
|
|
92
|
+
void ps_time_sleep(double seconds) {
|
|
93
|
+
struct timespec req;
|
|
94
|
+
if (!isfinite(seconds) || seconds < 0) {
|
|
95
|
+
ps_raise_cstr(PS_VALUE, "sleep length must be non-negative");
|
|
96
|
+
}
|
|
97
|
+
req.tv_sec = (time_t)seconds;
|
|
98
|
+
req.tv_nsec = (long)((seconds - (double)req.tv_sec) * 1000000000.0);
|
|
99
|
+
if (req.tv_nsec < 0) {
|
|
100
|
+
req.tv_nsec = 0;
|
|
101
|
+
}
|
|
102
|
+
if (req.tv_nsec > 999999999) {
|
|
103
|
+
req.tv_nsec = 999999999;
|
|
104
|
+
}
|
|
105
|
+
while (nanosleep(&req, &req) != 0) {
|
|
106
|
+
if (errno != EINTR) {
|
|
107
|
+
ps_raise_cstr(PS_RUNTIME, "sleep failed");
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
static void ps_gm(double ts, PsStructTime *out) {
|
|
113
|
+
time_t t = ps_as_time(ts);
|
|
114
|
+
struct tm tm;
|
|
115
|
+
if (gmtime_r(&t, &tm) == NULL) {
|
|
116
|
+
ps_raise_cstr(PS_VALUE, "timestamp out of range");
|
|
117
|
+
}
|
|
118
|
+
ps_fill_stm(&tm, out);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
static void ps_local(double ts, PsStructTime *out) {
|
|
122
|
+
time_t t = ps_as_time(ts);
|
|
123
|
+
struct tm tm;
|
|
124
|
+
if (localtime_r(&t, &tm) == NULL) {
|
|
125
|
+
ps_raise_cstr(PS_VALUE, "timestamp out of range");
|
|
126
|
+
}
|
|
127
|
+
ps_fill_stm(&tm, out);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
void ps_time_gm(double ts, PsStructTime *out) { ps_gm(ts, out); }
|
|
131
|
+
|
|
132
|
+
void ps_time_local(double ts, PsStructTime *out) { ps_local(ts, out); }
|
|
133
|
+
|
|
134
|
+
void ps_time_strftime(int64_t n, const char *fmt, PsStructTime *st, PsBuf *out) {
|
|
135
|
+
struct tm tm;
|
|
136
|
+
char buf[1024];
|
|
137
|
+
size_t wrote;
|
|
138
|
+
char *text;
|
|
139
|
+
if (n < 0 || n > 200) {
|
|
140
|
+
ps_raise_cstr(PS_VALUE, "strftime format is too long");
|
|
141
|
+
}
|
|
142
|
+
text = malloc((size_t)n + 1);
|
|
143
|
+
if (text == NULL) {
|
|
144
|
+
abort();
|
|
145
|
+
}
|
|
146
|
+
if (n > 0) {
|
|
147
|
+
memcpy(text, fmt, (size_t)n);
|
|
148
|
+
}
|
|
149
|
+
text[n] = '\0';
|
|
150
|
+
if (!ps_read_stm(st, &tm)) {
|
|
151
|
+
free(text);
|
|
152
|
+
ps_raise_cstr(PS_VALUE, "struct_time out of range");
|
|
153
|
+
}
|
|
154
|
+
wrote = strftime(buf, sizeof buf, text, &tm);
|
|
155
|
+
free(text);
|
|
156
|
+
if (wrote == 0) {
|
|
157
|
+
ps_raise_cstr(PS_VALUE, "strftime failed");
|
|
158
|
+
}
|
|
159
|
+
ps_buf_copy(out, buf, (int64_t)wrote);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
double ps_time_mktime(PsStructTime *st) {
|
|
163
|
+
struct tm tm;
|
|
164
|
+
time_t t;
|
|
165
|
+
if (!ps_read_stm(st, &tm)) {
|
|
166
|
+
ps_raise_cstr(PS_VALUE, "struct_time out of range");
|
|
167
|
+
}
|
|
168
|
+
t = mktime(&tm);
|
|
169
|
+
if (t == (time_t)-1) {
|
|
170
|
+
ps_raise_cstr(PS_VALUE, "mktime failed");
|
|
171
|
+
}
|
|
172
|
+
return (double)t;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
void ps_date_today_fill(PsDate *out) {
|
|
176
|
+
PsStructTime st;
|
|
177
|
+
ps_local(ps_time_time(), &st);
|
|
178
|
+
out->year = st.tm_year;
|
|
179
|
+
out->month = st.tm_mon;
|
|
180
|
+
out->day = st.tm_mday;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
void ps_dt_now_fill(PsDateTime *out) {
|
|
184
|
+
double now = ps_time_time();
|
|
185
|
+
double whole = floor(now);
|
|
186
|
+
double frac = now - whole;
|
|
187
|
+
PsStructTime st;
|
|
188
|
+
int64_t us;
|
|
189
|
+
if (frac < 0) {
|
|
190
|
+
frac = 0;
|
|
191
|
+
}
|
|
192
|
+
us = (int64_t)(frac * 1000000.0);
|
|
193
|
+
if (us < 0) {
|
|
194
|
+
us = 0;
|
|
195
|
+
}
|
|
196
|
+
if (us > 999999) {
|
|
197
|
+
us = 999999;
|
|
198
|
+
}
|
|
199
|
+
ps_local(whole, &st);
|
|
200
|
+
out->year = st.tm_year;
|
|
201
|
+
out->month = st.tm_mon;
|
|
202
|
+
out->day = st.tm_mday;
|
|
203
|
+
out->hour = st.tm_hour;
|
|
204
|
+
out->minute = st.tm_min;
|
|
205
|
+
out->second = st.tm_sec;
|
|
206
|
+
out->microsecond = us;
|
|
207
|
+
}
|