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
|
/*
* LSPIPAT - LUA SPIPAT WRAPPER
* Copyright (C) 2010, Robin Haberkorn
* License: LGPL
*
* CORE: STRING PRIMITIVES/CONSTRUCTORS
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include "lspipat.h"
static VString
stringFncHandler(void *global __attribute__((unused)), void *local)
{
struct retfncRefs *retfnc = local;
lua_State *L = retfnc->cb.L;
VString ret;
lua_rawgeti(L, LUA_REGISTRYINDEX, retfnc->cb.function);
lua_rawgeti(L, LUA_REGISTRYINDEX, retfnc->cb.cookie);
#if 0
lua_rawgeti(L, LUA_REGISTRYINDEX, *(int *)global);
#endif
lua_call(L, 1, 1);
if (!lua_isstring(L, -1)) {
lua_pop(L, 1);
L_ERROR(L_RETURN); /* FIXME: is it safe to raise errors? */
}
ret.ptr = lua_tolstring(L, -1, (size_t *)&ret.len);
ret.release = retfncUnrefRet;
ret.cookie = retfnc;
/*
* Register value so Lua doesn't free it until spipat
* doesn't need it anymore (value has to be popped now)
*/
retfnc->ret = luaL_ref(L, LUA_REGISTRYINDEX);
return ret;
}
struct stringPrimitive {
struct pat *(*chr)(Character);
struct pat *(*str)(VString);
struct pat *(*fnc)(VString (*)(void *, void*), void *);
};
static int
genericStringPrimitive(lua_State *L, struct stringPrimitive spipat)
{
int top = lua_gettop(L);
VString str = VSTRING_INITIALIZER;
PATTERN_WRAPPER *new;
luaL_argcheck(L, top, top, L_NUMBER);
if (!(new = lua_newuserdata(L, sizeof(PATTERN_WRAPPER))))
L_ERROR(L_ALLOC);
memset(new, 0, sizeof(PATTERN_WRAPPER));
switch (lua_type(L, 1)) {
case LUA_TNUMBER:
case LUA_TSTRING:
luaL_argcheck(L, top == 1, top, L_NUMBER);
str.ptr = lua_tolstring(L, 1, (size_t *)&str.len);
new->pattern = str.len == 1 ? spipat.chr(*str.ptr)
: spipat.str(str);
break;
case LUA_TFUNCTION: {
struct retfncRefs *retfnc;
luaL_argcheck(L, top == 1 || top == 2, top, L_NUMBER);
lua_insert(L, 1); /* move wrapper to bottom */
if (top == 1)
lua_pushnil(L); /* cookie will be LUA_REFNIL */
new->type = PATTERN_RETFNC;
retfnc = &new->u.retfnc;
retfnc->cb.L = L;
retfnc->cb.cookie = luaL_ref(L, LUA_REGISTRYINDEX);
retfnc->cb.function = luaL_ref(L, LUA_REGISTRYINDEX);
/* wrapper at top again */
new->pattern = spipat.fnc(stringFncHandler, retfnc);
break;
}
default:
return luaL_argerror(L, 1, L_TYPE);
}
if (!new->pattern)
L_ERROR(L_ALLOC);
luaL_getmetatable(L, PATTERN_MT);
lua_setmetatable(L, -2);
return 1;
}
#define STDSTRPRIM(LFNC, SPIFNC) \
LUA_SIG(LFNC) \
{ \
return genericStringPrimitive(L, (struct stringPrimitive) { \
.chr = SPIFNC##_chr, \
.str = SPIFNC##_str, \
.fnc = SPIFNC##_fnc \
}); \
}
STDSTRPRIM(l_primitive_any, spipat_any)
STDSTRPRIM(l_primitive_break, spipat_break)
STDSTRPRIM(l_primitive_breakx, spipat_breakx)
STDSTRPRIM(l_primitive_notany, spipat_notany)
STDSTRPRIM(l_primitive_nspan, spipat_nspan)
STDSTRPRIM(l_primitive_span, spipat_span)
#undef STDSTRPRIM
|