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
|
/*
* LSPIPAT - LUA SPIPAT WRAPPER
* Copyright (C) 2010, Robin Haberkorn
* License: LGPL
*
* CORE: COMPOSITION OPERATIONS
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <string.h>
#include "lspipat.h"
struct composeOperator {
struct pat *(*str_pat)(VString, struct pat *);
struct pat *(*pat_str)(struct pat *, VString);
struct pat *(*chr_pat)(Character, struct pat *);
struct pat *(*pat_chr)(struct pat *, Character);
struct pat *(*pat_pat)(struct pat *, struct pat *);
};
/* at least one parameter must be a pattern, both are only allowed to be numbers, strings or patterns */
static int
genericComposeOperator(lua_State *L, struct composeOperator spipat)
{
VString str = VSTRING_INITIALIZER;
PATTERN_WRAPPER *new;
if (!(new = lua_newuserdata(L, sizeof(PATTERN_WRAPPER))))
L_ERROR(L_ALLOC);
memset(new, 0, sizeof(PATTERN_WRAPPER));
lua_insert(L, 1);
if (lua_isstring(L, 2)) { /* lvalue number/string, rvalue is pattern */
PATTERN_WRAPPER *rvalue = lua_touserdata(L, 3);
if (!rvalue->pattern)
L_ERROR(L_FREED);
str.ptr = lua_tolstring(L, 2, (size_t *)&str.len);
new->type = PATTERN_ONESUBPAT;
new->u.onesubpat.pattern = luaL_ref(L, LUA_REGISTRYINDEX);
new->pattern = str.len == 1 ? spipat.chr_pat(*str.ptr, rvalue->pattern)
: spipat.str_pat(str, rvalue->pattern);
lua_pop(L, 1); /* `new' at stack top */
} else { /* lvalue must be pattern */
PATTERN_WRAPPER *lvalue = luaL_checkudata(L, 2, PATTERN_MT);
if (!lvalue->pattern)
L_ERROR(L_FREED);
if (lua_isstring(L, 3)) { /* rvalue number/string */
str.ptr = lua_tolstring(L, 3, (size_t *)&str.len);
new->pattern = str.len == 1 ? spipat.pat_chr(lvalue->pattern, *str.ptr)
: spipat.pat_str(lvalue->pattern, str);
lua_pop(L, 1);
new->type = PATTERN_ONESUBPAT;
new->u.onesubpat.pattern = luaL_ref(L, LUA_REGISTRYINDEX);
} else { /* rvalue must be pattern */
PATTERN_WRAPPER *rvalue = luaL_checkudata(L, 3, PATTERN_MT);
if (!rvalue->pattern)
L_ERROR(L_FREED);
new->type = PATTERN_TWOSUBPAT;
new->u.twosubpat.pattern2 = luaL_ref(L, LUA_REGISTRYINDEX);
new->u.twosubpat.pattern1 = luaL_ref(L, LUA_REGISTRYINDEX);
new->pattern = spipat.pat_pat(lvalue->pattern, rvalue->pattern);
}
}
if (!new->pattern)
L_ERROR(L_ALLOC);
luaL_getmetatable(L, PATTERN_MT);
lua_setmetatable(L, -2);
return 1;
}
#define STDCOMPOSEOP(LFNC, SPIFNC) \
LUA_SIG(LFNC) \
{ \
return genericComposeOperator(L, (struct composeOperator) { \
.str_pat = SPIFNC##_str_pat, \
.pat_str = SPIFNC##_pat_str, \
.chr_pat = SPIFNC##_chr_pat, \
.pat_chr = SPIFNC##_pat_chr, \
.pat_pat = SPIFNC##_pat_pat \
}); \
}
STDCOMPOSEOP(l_op_and, spipat_and)
STDCOMPOSEOP(l_op_or, spipat_or)
#undef STDCOMPOSEOP
|