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