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 : str
33 3 : malAtomProperty(mel_func *f)
34 : {
35 3 : const char *name;
36 3 : int tpe;
37 3 : assert(f != 0);
38 3 : name = f->fcn;
39 3 : tpe = getAtomIndex(f->mod, strlen(f->mod), TYPE_any);
40 3 : if (tpe < 0 || tpe >= GDKatomcnt || tpe >= MAXATOMS)
41 : return MAL_SUCCEED;
42 3 : assert(f->imp != NULL);
43 3 : switch (name[0]) {
44 0 : case 'd':
45 0 : if (idcmp("del", name) == 0 && f->argc == 1) {
46 0 : BATatoms[tpe].atomDel = (void (*)(Heap *, var_t *)) f->imp;
47 0 : return MAL_SUCCEED;
48 : }
49 : break;
50 0 : case 'c':
51 0 : if (idcmp("cmp", name) == 0 && f->argc == 1) {
52 0 : BATatoms[tpe].atomCmp = (int (*)(const void *, const void *)) f->imp;
53 0 : BATatoms[tpe].linear = true;
54 0 : return MAL_SUCCEED;
55 : }
56 : break;
57 3 : case 'f':
58 3 : if (idcmp("fromstr", name) == 0 && f->argc == 1) {
59 0 : BATatoms[tpe].atomFromStr = (ssize_t (*)(const char *, size_t *, ptr *, bool)) f->imp;
60 0 : return MAL_SUCCEED;
61 : }
62 : break;
63 0 : case 'h':
64 0 : if (idcmp("heap", name) == 0 && f->argc == 1) {
65 : /* heap function makes an atom varsized */
66 0 : BATatoms[tpe].size = sizeof(var_t);
67 0 : assert_shift_width(ATOMelmshift(ATOMsize(tpe)), ATOMsize(tpe));
68 0 : BATatoms[tpe].atomHeap = (gdk_return (*)(Heap *, size_t)) f->imp;
69 0 : return MAL_SUCCEED;
70 : }
71 0 : if (idcmp("hash", name) == 0 && f->argc == 1) {
72 0 : BATatoms[tpe].atomHash = (BUN (*)(const void *)) f->imp;
73 0 : return MAL_SUCCEED;
74 : }
75 : break;
76 0 : case 'l':
77 0 : if (idcmp("length", name) == 0 && f->argc == 1) {
78 0 : BATatoms[tpe].atomLen = (size_t (*)(const void *)) f->imp;
79 0 : return MAL_SUCCEED;
80 : }
81 : break;
82 0 : case 'n':
83 0 : if (idcmp("null", name) == 0 && f->argc == 1) {
84 0 : const void *atmnull = ((const void *(*)(void)) f->imp)();
85 :
86 0 : BATatoms[tpe].atomNull = atmnull;
87 0 : return MAL_SUCCEED;
88 : }
89 0 : if (idcmp("nequal", name) == 0 && f->argc == 1) {
90 0 : BATatoms[tpe].atomCmp = (int (*)(const void *, const void *)) f->imp;
91 0 : return MAL_SUCCEED;
92 : }
93 : break;
94 0 : case 'p':
95 0 : if (idcmp("put", name) == 0 && f->argc == 1) {
96 0 : BATatoms[tpe].atomPut = (var_t (*)(BAT *, var_t *, const void *)) f->imp;
97 0 : return MAL_SUCCEED;
98 : }
99 : break;
100 0 : case 's':
101 0 : if (idcmp("storage", name) == 0 && f->argc == 1) {
102 0 : BATatoms[tpe].storage = (*(int (*)(void)) f->imp) ();
103 0 : return MAL_SUCCEED;
104 : }
105 : break;
106 0 : case 't':
107 0 : if (idcmp("tostr", name) == 0 && f->argc == 1) {
108 0 : BATatoms[tpe].atomToStr = (ssize_t (*)(str *, size_t *, const void *, bool)) f->imp;
109 0 : return MAL_SUCCEED;
110 : }
111 : break;
112 0 : case 'r':
113 0 : if (idcmp("read", name) == 0 && f->argc == 1) {
114 0 : BATatoms[tpe].atomRead = (void *(*)(void *, size_t *, stream *, size_t)) f->imp;
115 0 : return MAL_SUCCEED;
116 : }
117 : break;
118 0 : case 'w':
119 0 : if (idcmp("write", name) == 0 && f->argc == 1) {
120 0 : BATatoms[tpe].atomWrite = (gdk_return (*)(const void *, stream *, size_t)) f->imp;
121 0 : return MAL_SUCCEED;
122 : }
123 : break;
124 : }
125 : return MAL_SUCCEED;
126 : }
127 :
128 : /*
129 : * Atoms are constructed incrementally in the kernel using the
130 : * ATOMallocate function. It takes an existing type as a base
131 : * to derive a new one.
132 : * The most tedisous work is to check the signature types of the functions
133 : * acceptable for the kernel.
134 : */
135 :
136 : str
137 4 : malAtomDefinition(const char *name, int tpe)
138 : {
139 4 : int i;
140 :
141 4 : if (strlen(name) >= IDLENGTH) {
142 0 : throw(SYNTAX, "atomDefinition", "Atom name '%s' too long", name);
143 : }
144 4 : if (ATOMindex(name) >= 0) {
145 : return MAL_SUCCEED;
146 : }
147 4 : if (tpe < 0 || tpe >= GDKatomcnt) {
148 0 : throw(TYPE, "atomDefinition", "Undefined atom inheritance '%s'", name);
149 : }
150 4 : if (strlen(name) >= sizeof(BATatoms[0].name))
151 0 : throw(TYPE, "atomDefinition", "Atom name too long '%s'", name);
152 :
153 4 : i = ATOMallocate(name);
154 4 : if (is_int_nil(i))
155 0 : throw(TYPE, "atomDefinition", SQLSTATE(HY013) MAL_MALLOC_FAIL);
156 : /* overload atom ? */
157 4 : if (tpe) {
158 4 : BATatoms[i] = BATatoms[tpe];
159 4 : strcpy_len(BATatoms[i].name, name, sizeof(BATatoms[i].name));
160 4 : BATatoms[i].storage = ATOMstorage(tpe);
161 : } else { /* cannot overload void atoms */
162 0 : BATatoms[i].storage = i;
163 0 : BATatoms[i].linear = false;
164 : }
165 : return MAL_SUCCEED;
166 : }
167 :
168 : /*
169 : * User defined modules may introduce fixed sized types
170 : * to store information in BATs.
171 : */
172 : int
173 340 : malAtomSize(int size, const char *name)
174 : {
175 340 : int i = 0;
176 :
177 340 : i = ATOMindex(name);
178 340 : BATatoms[i].storage = i;
179 340 : BATatoms[i].size = size;
180 340 : assert_shift_width(ATOMelmshift(ATOMsize(i)), ATOMsize(i));
181 340 : return i;
182 : }
183 :
184 : void
185 350 : mal_atom_reset(void)
186 : {
187 350 : int i;
188 350 : for (i = 0; i < GDKatomcnt; i++)
189 : if (BATatoms[i].atomNull) {
190 : // TBD
191 : }
192 350 : }
|