forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjulia_extensions.c
118 lines (108 loc) · 3.38 KB
/
julia_extensions.c
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
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "flisp.h"
#include "utf8proc.h"
#ifdef __cplusplus
extern "C" {
#endif
static int is_uws(uint32_t wc)
{
return (wc==9 || wc==10 || wc==11 || wc==12 || wc==13 || wc==32 ||
wc==133 || wc==160 || wc==5760 || wc==6158 || wc==8192 ||
wc==8193 || wc==8194 || wc==8195 || wc==8196 || wc==8197 ||
wc==8198 || wc==8199 || wc==8200 || wc==8201 || wc==8202 ||
wc==8232 || wc==8233 || wc==8239 || wc==8287 || wc==12288);
}
static int is_bom(uint32_t wc)
{
return wc == 0xFEFF;
}
value_t fl_skipws(value_t *args, u_int32_t nargs)
{
argcount("skip-ws", nargs, 2);
ios_t *s = fl_toiostream(args[0], "skip-ws");
int newlines = (args[1]!=FL_F);
uint32_t wc=0;
if (ios_peekutf8(s, &wc) == IOS_EOF)
return FL_EOF;
value_t skipped = FL_F;
while (!ios_eof(s) && (is_uws(wc) || is_bom(wc)) && (newlines || wc!=10)) {
skipped = FL_T;
ios_getutf8(s, &wc);
ios_peekutf8(s, &wc);
}
return skipped;
}
static int jl_id_char(uint32_t wc)
{
return ((wc >= 'A' && wc <= 'Z') || (wc >= 'a' && wc <= 'z') ||
(wc >= '0' && wc <= '9') || (wc >= 0xA1) ||
wc == '!' || wc == '_');
}
// return NFC-normalized UTF8-encoded version of s
static char *normalize(char *s)
{
static size_t buflen = 0;
static void *buf = NULL; // persistent buffer (avoid repeated malloc/free)
// options equivalent to utf8proc_NFC:
const int options = UTF8PROC_NULLTERM|UTF8PROC_STABLE|UTF8PROC_COMPOSE;
ssize_t result;
size_t newlen;
result = utf8proc_decompose((uint8_t*) s, 0, NULL, 0, options);
if (result < 0) goto error;
newlen = result * sizeof(int32_t) + 1;
if (newlen > buflen) {
buflen = newlen * 2;
buf = realloc(buf, buflen);
if (!buf) lerror(MemoryError, "error allocating UTF8 buffer");
}
result = utf8proc_decompose((uint8_t*)s,0, (int32_t*)buf,result, options);
if (result < 0) goto error;
result = utf8proc_reencode((int32_t*)buf,result, options);
if (result < 0) goto error;
return (char*) buf;
error:
lerrorf(symbol("error"), "error normalizing identifier %s: %s", s,
utf8proc_errmsg(result));
}
value_t fl_accum_julia_symbol(value_t *args, u_int32_t nargs)
{
argcount("accum-julia-symbol", nargs, 2);
ios_t *s = fl_toiostream(args[1], "accum-julia-symbol");
if (!iscprim(args[0]) || ((cprim_t*)ptr(args[0]))->type != wchartype)
type_error("accum-julia-symbol", "wchar", args[0]);
uint32_t wc = *(uint32_t*)cp_data((cprim_t*)ptr(args[0]));
ios_t str;
ios_mem(&str, 0);
while (jl_id_char(wc)) {
ios_getutf8(s, &wc);
if (wc == '!') {
uint32_t nwc;
ios_peekutf8(s, &nwc);
// make sure != is always an operator
if (nwc == '=') {
ios_ungetc('!', s);
break;
}
}
ios_pututf8(&str, wc);
if (ios_peekutf8(s, &wc) == IOS_EOF)
break;
}
ios_pututf8(&str, 0);
return symbol(normalize(str.buf));
}
static builtinspec_t julia_flisp_func_info[] = {
{ "skip-ws", fl_skipws },
{ "accum-julia-symbol", fl_accum_julia_symbol },
{ NULL, NULL }
};
void fl_init_julia_extensions(void)
{
assign_global_builtins(julia_flisp_func_info);
}
#ifdef __cplusplus
}
#endif