1 | /* |
2 | * This Source Code Form is subject to the terms of the Mozilla Public |
3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
5 | * |
6 | * Copyright 1997 - July 2008 CWI, August 2008 - 2019 MonetDB B.V. |
7 | */ |
8 | |
9 | /* |
10 | * (author) M.L.Kersten |
11 | * Every MAL command introduced in an atom module should be checked |
12 | * to detect overloading of a predefined function. |
13 | * Subsequently, we update the GDK atom structure. |
14 | * The function signatures should be parameter-less, which |
15 | * enables additional functions with the same name to appear |
16 | * as ordinary mal operators. |
17 | * |
18 | * A few fields are set only once, at creation time. |
19 | * They should be implemented with parameter-less functions. |
20 | */ |
21 | #include "monetdb_config.h" |
22 | #include "mal_instruction.h" |
23 | #include "mal_atom.h" |
24 | #include "mal_namespace.h" |
25 | #include "mal_exception.h" |
26 | #include "mal_private.h" |
27 | |
28 | static void setAtomName(InstrPtr pci) |
29 | { |
30 | char buf[FILENAME_MAX]; |
31 | snprintf(buf, FILENAME_MAX, "#%s" , getFunctionId(pci)); |
32 | setFunctionId(pci, putName(buf)); |
33 | } |
34 | |
35 | str |
36 | malAtomProperty(MalBlkPtr mb, InstrPtr pci) |
37 | { |
38 | str name; |
39 | int tpe; |
40 | (void)mb; /* fool compilers */ |
41 | assert(pci != 0); |
42 | name = getFunctionId(pci); |
43 | tpe = getAtomIndex(getModuleId(pci), strlen(getModuleId(pci)), TYPE_any); |
44 | if (tpe < 0 || tpe >= GDKatomcnt || tpe >= MAXATOMS) |
45 | return MAL_SUCCEED; |
46 | assert(pci->fcn != NULL); |
47 | switch (name[0]) { |
48 | case 'd': |
49 | if (idcmp("del" , name) == 0 && pci->argc == 1) { |
50 | BATatoms[tpe].atomDel = (void (*)(Heap *, var_t *))pci->fcn; |
51 | setAtomName(pci); |
52 | return MAL_SUCCEED; |
53 | } |
54 | break; |
55 | case 'c': |
56 | if (idcmp("cmp" , name) == 0 && pci->argc == 1) { |
57 | BATatoms[tpe].atomCmp = (int (*)(const void *, const void *))pci->fcn; |
58 | BATatoms[tpe].linear = true; |
59 | setAtomName(pci); |
60 | return MAL_SUCCEED; |
61 | } |
62 | break; |
63 | case 'f': |
64 | if (idcmp("fromstr" , name) == 0 && pci->argc == 1) { |
65 | BATatoms[tpe].atomFromStr = (ssize_t (*)(const char *, size_t *, ptr *, bool))pci->fcn; |
66 | setAtomName(pci); |
67 | return MAL_SUCCEED; |
68 | } |
69 | if (idcmp("fix" , name) == 0 && pci->argc == 1) { |
70 | BATatoms[tpe].atomFix = (int (*)(const void *))pci->fcn; |
71 | setAtomName(pci); |
72 | return MAL_SUCCEED; |
73 | } |
74 | break; |
75 | case 'h': |
76 | if (idcmp("heap" , name) == 0 && pci->argc == 1) { |
77 | /* heap function makes an atom varsized */ |
78 | BATatoms[tpe].size = sizeof(var_t); |
79 | assert_shift_width(ATOMelmshift(ATOMsize(tpe)), ATOMsize(tpe)); |
80 | BATatoms[tpe].atomHeap = (void (*)(Heap *, size_t))pci->fcn; |
81 | setAtomName(pci); |
82 | return MAL_SUCCEED; |
83 | } |
84 | if (idcmp("hash" , name) == 0 && pci->argc == 1) { |
85 | BATatoms[tpe].atomHash = (BUN (*)(const void *))pci->fcn; |
86 | setAtomName(pci); |
87 | return MAL_SUCCEED; |
88 | } |
89 | break; |
90 | case 'l': |
91 | if (idcmp("length" , name) == 0 && pci->argc == 1) { |
92 | BATatoms[tpe].atomLen = (size_t (*)(const void *))pci->fcn; |
93 | setAtomName(pci); |
94 | return MAL_SUCCEED; |
95 | } |
96 | break; |
97 | case 'n': |
98 | if (idcmp("null" , name) == 0 && pci->argc == 1) { |
99 | const void *atmnull = ((const void *(*)(void))pci->fcn)(); |
100 | |
101 | BATatoms[tpe].atomNull = atmnull; |
102 | setAtomName(pci); |
103 | return MAL_SUCCEED; |
104 | } |
105 | if (idcmp("nequal" , name) == 0 && pci->argc == 1) { |
106 | BATatoms[tpe].atomCmp = (int (*)(const void *, const void *))pci->fcn; |
107 | setAtomName(pci); |
108 | return MAL_SUCCEED; |
109 | } |
110 | break; |
111 | case 'p': |
112 | if (idcmp("put" , name) == 0 && pci->argc == 1) { |
113 | BATatoms[tpe].atomPut = (var_t (*)(Heap *, var_t *, const void *))pci->fcn; |
114 | setAtomName(pci); |
115 | return MAL_SUCCEED; |
116 | } |
117 | break; |
118 | case 's': |
119 | if (idcmp("storage" , name) == 0 && pci->argc == 1) { |
120 | BATatoms[tpe].storage = (*(int (*)(void))pci->fcn)(); |
121 | setAtomName(pci); |
122 | return MAL_SUCCEED; |
123 | } |
124 | break; |
125 | case 't': |
126 | if (idcmp("tostr" , name) == 0 && pci->argc == 1) { |
127 | BATatoms[tpe].atomToStr = (ssize_t (*)(str *, size_t *, const void *, bool))pci->fcn; |
128 | setAtomName(pci); |
129 | return MAL_SUCCEED; |
130 | } |
131 | break; |
132 | case 'u': |
133 | if (idcmp("unfix" , name) == 0 && pci->argc == 1) { |
134 | BATatoms[tpe].atomUnfix = (int (*)(const void *))pci->fcn; |
135 | setAtomName(pci); |
136 | return MAL_SUCCEED; |
137 | } |
138 | break; |
139 | case 'r': |
140 | if (idcmp("read" , name) == 0 && pci->argc == 1) { |
141 | BATatoms[tpe].atomRead = (void *(*)(void *, stream *, size_t))pci->fcn; |
142 | setAtomName(pci); |
143 | return MAL_SUCCEED; |
144 | } |
145 | break; |
146 | case 'w': |
147 | if (idcmp("write" , name) == 0 && pci->argc == 1) { |
148 | BATatoms[tpe].atomWrite = (gdk_return (*)(const void *, stream *, size_t))pci->fcn; |
149 | setAtomName(pci); |
150 | return MAL_SUCCEED; |
151 | } |
152 | break; |
153 | } |
154 | return MAL_SUCCEED; |
155 | } |
156 | /* |
157 | * Atoms are constructed incrementally in the kernel using the |
158 | * ATOMallocate function. It takes an existing type as a base |
159 | * to derive a new one. |
160 | * The most tedisous work is to check the signature types of the functions |
161 | * acceptable for the kernel. |
162 | */ |
163 | |
164 | str |
165 | malAtomDefinition(str name, int tpe) |
166 | { |
167 | int i; |
168 | |
169 | if (strlen(name) >= IDLENGTH) { |
170 | throw (SYNTAX, "atomDefinition" , "Atom name '%s' too long" , name); |
171 | } |
172 | if (ATOMindex(name) >= 0) { |
173 | #ifndef HAVE_EMBEDDED /* we can restart embedded MonetDB, making this an expected error */ |
174 | throw(TYPE, "atomDefinition" , "Redefinition of atom '%s'" , name); |
175 | #endif |
176 | } |
177 | if (tpe < 0 || tpe >= GDKatomcnt) { |
178 | throw(TYPE, "atomDefinition" , "Undefined atom inheritance '%s'" , name); |
179 | } |
180 | if (strlen(name) >= sizeof(BATatoms[0].name)) |
181 | throw(TYPE, "atomDefinition" , "Atom name too long '%s'" , name); |
182 | |
183 | i = ATOMallocate(name); |
184 | if (is_int_nil(i)) |
185 | throw(TYPE,"atomDefinition" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
186 | /* overload atom ? */ |
187 | if (tpe) { |
188 | BATatoms[i] = BATatoms[tpe]; |
189 | strcpy_len(BATatoms[i].name, name, sizeof(BATatoms[i].name)); |
190 | BATatoms[i].storage = ATOMstorage(tpe); |
191 | } else { /* cannot overload void atoms */ |
192 | BATatoms[i].storage = i; |
193 | BATatoms[i].linear = false; |
194 | } |
195 | return MAL_SUCCEED; |
196 | } |
197 | /* |
198 | * User defined modules may introduce fixed sized types |
199 | * to store information in BATs. |
200 | */ |
201 | int malAtomSize(int size, const char *name) |
202 | { |
203 | int i = 0; |
204 | |
205 | i = ATOMindex(name); |
206 | BATatoms[i].storage = i; |
207 | BATatoms[i].size = size; |
208 | assert_shift_width(ATOMelmshift(ATOMsize(i)), ATOMsize(i)); |
209 | return i; |
210 | } |
211 | |
212 | void |
213 | mal_atom_reset(void) |
214 | { |
215 | int i; |
216 | for( i = 0; i < GDKatomcnt; i++) |
217 | if( BATatoms[i].atomNull){ |
218 | // TBD |
219 | } |
220 | } |
221 | |