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 Martin Kersten
15 : * Inspection
16 : * This module introduces a series of commands that provide access
17 : * to information stored within the interpreter data structures.
18 : * It's primary use is debugging.
19 : * In all cases, the pseudo BAT operation is returned that
20 : * should be garbage collected after being used.
21 : *
22 : * The main performance drain would be to use a pseudo BAT directly to
23 : * successively access it components. This can be avoided by first assigning
24 : * the pseudo BAT to a variable.
25 : */
26 : #include "monetdb_config.h"
27 : #include "gdk.h"
28 : #include <time.h>
29 : #include "mal_resolve.h"
30 : #include "mal_client.h"
31 : #include "mal_exception.h"
32 : #include "mal_interpreter.h"
33 : #include "mal_listing.h"
34 : #include "mal_namespace.h"
35 :
36 : /*
37 : * Symbol table
38 : * Mal symbol table and environment analysis.
39 : *
40 : * Collect symbol table information in a series of BATs for analysis
41 : * and display. Note, the elements are aligned using a counter,
42 : * which makes it susceptable for intermediate updates
43 : */
44 :
45 : static str
46 0 : INSPECTgetAllFunctions(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
47 : {
48 0 : Module s;
49 0 : Symbol t;
50 0 : int i, j;
51 0 : Module *moduleList;
52 0 : int length;
53 0 : BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
54 0 : bat *ret = getArgReference_bat(stk, pci, 0);
55 :
56 0 : (void) mb;
57 0 : if (b == 0)
58 0 : throw(MAL, "inspect.getgetFunctionId", SQLSTATE(HY013) MAL_MALLOC_FAIL);
59 :
60 0 : getModuleList(&moduleList, &length);
61 0 : if (moduleList == NULL)
62 0 : goto bailout;
63 0 : for (j = -1; j < length; j++) {
64 0 : s = j < 0 ? cntxt->usermodule : moduleList[j];
65 0 : for (i = 0; s && i < MAXSCOPE; i++) {
66 0 : if (s->space[i]) {
67 0 : for (t = s->space[i]; t; t = t->peer) {
68 0 : InstrPtr sig = getSignature(t);
69 0 : if (BUNappend(b, getFunctionId(sig), false) != GDK_SUCCEED)
70 0 : goto bailout;
71 : }
72 : }
73 : }
74 : }
75 0 : *ret = b->batCacheid;
76 0 : BBPkeepref(b);
77 0 : freeModuleList(moduleList);
78 :
79 0 : return MAL_SUCCEED;
80 0 : bailout:
81 0 : BBPreclaim(b);
82 0 : freeModuleList(moduleList);
83 0 : throw(MAL, "inspect.getgetFunctionId", SQLSTATE(HY013) MAL_MALLOC_FAIL);
84 : }
85 :
86 : static str
87 0 : INSPECTgetAllModules(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
88 : {
89 0 : Module s;
90 0 : Symbol t;
91 0 : int i, j;
92 0 : Module *moduleList;
93 0 : int length;
94 0 : BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
95 0 : bat *ret = getArgReference_bat(stk, pci, 0);
96 :
97 0 : (void) mb;
98 0 : if (b == 0)
99 0 : throw(MAL, "inspect.getmodule", SQLSTATE(HY013) MAL_MALLOC_FAIL);
100 :
101 0 : getModuleList(&moduleList, &length);
102 0 : if (moduleList == NULL)
103 0 : goto bailout;
104 0 : for (j = -1; j < length; j++) {
105 0 : s = j < 0 ? cntxt->usermodule : moduleList[j];
106 0 : for (i = 0; s && i < MAXSCOPE; i++) {
107 0 : if (s->space[i]) {
108 0 : for (t = s->space[i]; t; t = t->peer) {
109 0 : InstrPtr sig = getSignature(t);
110 :
111 0 : if (BUNappend(b, getModuleId(sig), false) != GDK_SUCCEED)
112 0 : goto bailout;
113 : }
114 : }
115 : }
116 : }
117 0 : *ret = b->batCacheid;
118 0 : BBPkeepref(b);
119 0 : freeModuleList(moduleList);
120 :
121 0 : return MAL_SUCCEED;
122 0 : bailout:
123 0 : freeModuleList(moduleList);
124 0 : BBPreclaim(b);
125 0 : throw(MAL, "inspect.getmodule", SQLSTATE(HY013) MAL_MALLOC_FAIL);
126 : }
127 :
128 : static str
129 0 : INSPECTgetkind(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
130 : {
131 0 : Module s;
132 0 : Symbol t;
133 0 : int i, j;
134 0 : Module *moduleList;
135 0 : int length;
136 0 : BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
137 0 : bat *ret = getArgReference_bat(stk, pci, 0);
138 :
139 0 : (void) mb;
140 0 : if (b == 0)
141 0 : throw(MAL, "inspect.get", SQLSTATE(HY013) MAL_MALLOC_FAIL);
142 :
143 0 : getModuleList(&moduleList, &length);
144 0 : if (moduleList == NULL)
145 0 : goto bailout;
146 0 : for (j = -1; j < length; j++) {
147 0 : s = j < 0 ? cntxt->usermodule : moduleList[j];
148 0 : for (i = 0; s && i < MAXSCOPE; i++) {
149 0 : if (s->space[i]) {
150 0 : for (t = s->space[i]; t; t = t->peer) {
151 0 : InstrPtr sig = getSignature(t);
152 0 : str kind = operatorName(sig->token);
153 0 : if (BUNappend(b, kind, false) != GDK_SUCCEED)
154 0 : goto bailout;
155 : }
156 : }
157 : }
158 : }
159 0 : *ret = b->batCacheid;
160 0 : BBPkeepref(b);
161 0 : freeModuleList(moduleList);
162 :
163 0 : return MAL_SUCCEED;
164 0 : bailout:
165 0 : BBPreclaim(b);
166 0 : freeModuleList(moduleList);
167 0 : throw(MAL, "inspect.get", SQLSTATE(HY013) MAL_MALLOC_FAIL);
168 : }
169 :
170 : static str
171 0 : INSPECTgetAllSignatures(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
172 : {
173 0 : Module s;
174 0 : Symbol t;
175 0 : int i, j;
176 0 : Module *moduleList;
177 0 : int length;
178 0 : BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
179 0 : char sig[BLOCK], *a;
180 0 : bat *ret = getArgReference_bat(stk, pci, 0);
181 :
182 0 : (void) mb;
183 0 : if (b == 0)
184 0 : throw(MAL, "inspect.get", SQLSTATE(HY013) MAL_MALLOC_FAIL);
185 :
186 0 : getModuleList(&moduleList, &length);
187 0 : if (moduleList == NULL)
188 0 : goto bailout;
189 0 : for (j = -1; j < length; j++) {
190 0 : s = j < 0 ? cntxt->usermodule : moduleList[j];
191 0 : for (i = 0; s && i < MAXSCOPE; i++)
192 0 : if (s->space[i]) {
193 0 : for (t = s->space[i]; t; t = t->peer) {
194 0 : fcnDefinition(t->def, getSignature(t), sig, 0, sig, BLOCK);
195 0 : a = strstr(sig, "address");
196 0 : if (a)
197 0 : *a = 0;
198 0 : if (BUNappend(b, (a = strchr(sig, '(')) ? a : "", false) != GDK_SUCCEED)
199 0 : goto bailout;
200 : }
201 : }
202 : }
203 0 : *ret = b->batCacheid;
204 0 : BBPkeepref(b);
205 0 : freeModuleList(moduleList);
206 :
207 0 : return MAL_SUCCEED;
208 0 : bailout:
209 0 : BBPreclaim(b);
210 0 : freeModuleList(moduleList);
211 0 : throw(MAL, "inspect.get", SQLSTATE(HY013) MAL_MALLOC_FAIL);
212 : }
213 :
214 : #if 0
215 : static str
216 : INSPECTgetAllAddresses(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
217 : {
218 : Module s;
219 : Symbol t;
220 : int i, j;
221 : Module *moduleList;
222 : int length;
223 : BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
224 : char sig[BLOCK], *a;
225 : bat *ret = getArgReference_bat(stk, pci, 0);
226 :
227 : (void) mb;
228 :
229 : if (b == 0)
230 : throw(MAL, "inspect.get", SQLSTATE(HY013) MAL_MALLOC_FAIL);
231 :
232 : getModuleList(&moduleList, &length);
233 : if (moduleList == NULL)
234 : goto bailout;
235 : for (j = -1; j < length; j++) {
236 : s = j < 0 ? cntxt->usermodule : moduleList[j];
237 : for (i = 0; s && i < MAXSCOPE; i++)
238 : if (s->space[i]) {
239 : for (t = s->space[i]; t; t = t->peer) {
240 : fcnDefinition(t->def, getSignature(t), sig, 0, sig, BLOCK);
241 : a = strstr(sig, "address");
242 : if (a)
243 : for (a = a + 7; isspace((unsigned char) *a); a++) ;
244 : if (BUNappend(b, (a ? a : "nil"), false) != GDK_SUCCEED)
245 : goto bailout;
246 : }
247 : }
248 : }
249 : *ret = b->batCacheid;
250 : BBPkeepref(b);
251 : freeModuleList(moduleList);
252 :
253 : return MAL_SUCCEED;
254 : bailout:
255 : BBPreclaim(b);
256 : freeModuleList(moduleList);
257 : throw(MAL, "inspect.get", SQLSTATE(HY013) MAL_MALLOC_FAIL);
258 : }
259 : #endif
260 :
261 : static str
262 0 : INSPECTgetDefinition(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
263 : {
264 0 : bat *ret = getArgReference_bat(stk, pci, 0);
265 0 : str *mod = getArgReference_str(stk, pci, 1);
266 0 : str *fcn = getArgReference_str(stk, pci, 2);
267 0 : Symbol s;
268 0 : BAT *b;
269 0 : (void) mb;
270 :
271 0 : s = findSymbol(cntxt->usermodule, putName(*mod), putName(*fcn));
272 0 : if (s == 0)
273 0 : throw(MAL, "inspect.getDefinition", RUNTIME_SIGNATURE_MISSING);
274 :
275 0 : b = COLnew(0, TYPE_str, 256, TRANSIENT);
276 0 : if (b == 0)
277 0 : throw(MAL, "inspect.getDefinition", SQLSTATE(HY013) MAL_MALLOC_FAIL);
278 :
279 0 : while (s) {
280 : int i;
281 : str ps;
282 :
283 0 : for (i = 0; i < s->def->stop; i++) {
284 0 : if ((ps = instruction2str(s->def, 0, getInstrPtr(s->def, i), 0)) == NULL)
285 0 : goto bailout;
286 0 : if (BUNappend(b, ps + 1, false) != GDK_SUCCEED) {
287 0 : GDKfree(ps);
288 0 : goto bailout;
289 : }
290 0 : GDKfree(ps);
291 : }
292 0 : s = s->peer;
293 : }
294 0 : *ret = b->batCacheid;
295 0 : BBPkeepref(b);
296 :
297 0 : return MAL_SUCCEED;
298 0 : bailout:
299 0 : BBPreclaim(b);
300 0 : throw(MAL, "inspect.getDefinition", SQLSTATE(HY013) MAL_MALLOC_FAIL);
301 : }
302 :
303 : static str
304 0 : INSPECTgetExistence(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
305 : {
306 0 : (void) mb;
307 :
308 0 : bit *ret = getArgReference_bit(stk, pci, 0);
309 0 : str *mod = getArgReference_str(stk, pci, 1);
310 0 : str *fcn = getArgReference_str(stk, pci, 2);
311 :
312 0 : Symbol s = findSymbol(cntxt->usermodule, getName(*mod), putName(*fcn));
313 :
314 0 : *ret = (s != NULL);
315 :
316 0 : return MAL_SUCCEED;
317 : }
318 :
319 : static str
320 1 : INSPECTgetSignature(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
321 : {
322 1 : bat *ret = getArgReference_bat(stk, pci, 0);
323 1 : str *mod = getArgReference_str(stk, pci, 1);
324 1 : str *fcn = getArgReference_str(stk, pci, 2);
325 1 : Symbol s;
326 1 : str ps, tail;
327 1 : BAT *b;
328 1 : (void) mb;
329 :
330 1 : s = findSymbol(cntxt->usermodule, getName(*mod), putName(*fcn));
331 1 : if (s == 0)
332 0 : throw(MAL, "inspect.getSignature", RUNTIME_SIGNATURE_MISSING);
333 1 : b = COLnew(0, TYPE_str, 12, TRANSIENT);
334 1 : if (b == 0)
335 0 : throw(MAL, "inspect.getSignature", SQLSTATE(HY013) MAL_MALLOC_FAIL);
336 :
337 2 : while (s != NULL) {
338 1 : if (idcmp(s->name, *fcn) == 0) {
339 1 : InstrPtr p = getSignature(s);
340 1 : char *c, *w;
341 :
342 1 : ps = instruction2str(s->def, 0, p, 0);
343 1 : if (ps == 0) {
344 0 : continue;
345 : }
346 1 : c = strchr(ps, '(');
347 1 : if (c == 0) {
348 0 : GDKfree(ps);
349 0 : continue;
350 : }
351 1 : tail = strstr(c, "address");
352 1 : if (tail)
353 0 : *tail = 0;
354 0 : if (tail && (w = strchr(tail, ';')))
355 0 : *w = 0;
356 1 : if (BUNappend(b, c, false) != GDK_SUCCEED) {
357 0 : GDKfree(ps);
358 0 : goto bailout;
359 : }
360 1 : GDKfree(ps);
361 : }
362 1 : s = s->peer;
363 : }
364 :
365 1 : *ret = b->batCacheid;
366 1 : BBPkeepref(b);
367 1 : return MAL_SUCCEED;
368 0 : bailout:
369 0 : BBPreclaim(b);
370 0 : throw(MAL, "inspect.getSignature", SQLSTATE(HY013) MAL_MALLOC_FAIL);
371 : }
372 :
373 : static str
374 0 : INSPECTgetComment(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
375 : {
376 0 : bat *ret = getArgReference_bat(stk, pci, 0);
377 0 : str *mod = getArgReference_str(stk, pci, 1);
378 0 : str *fcn = getArgReference_str(stk, pci, 2);
379 0 : Symbol s;
380 0 : BAT *b;
381 0 : (void) mb;
382 :
383 0 : s = findSymbol(cntxt->usermodule, getName(*mod), putName(*fcn));
384 0 : if (s == 0)
385 0 : throw(MAL, "inspect.getComment", RUNTIME_SIGNATURE_MISSING);
386 0 : b = COLnew(0, TYPE_str, 12, TRANSIENT);
387 0 : if (b == 0)
388 0 : throw(MAL, "inspect.getComment", SQLSTATE(HY013) MAL_MALLOC_FAIL);
389 :
390 0 : while (s != NULL) {
391 0 : if (idcmp(s->name, *fcn) == 0 &&
392 0 : BUNappend(b, s->def->help, false) != GDK_SUCCEED)
393 0 : goto bailout;
394 0 : s = s->peer;
395 : }
396 :
397 0 : *ret = b->batCacheid;
398 0 : BBPkeepref(b);
399 0 : return MAL_SUCCEED;
400 0 : bailout:
401 0 : BBPreclaim(b);
402 0 : throw(MAL, "inspect.getComment", SQLSTATE(HY013) MAL_MALLOC_FAIL);
403 : }
404 :
405 : static str
406 0 : INSPECTgetSource(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
407 : {
408 0 : str *ret = getArgReference_str(stk, pci, 0);
409 0 : str *mod = getArgReference_str(stk, pci, 1);
410 0 : str *fcn = getArgReference_str(stk, pci, 2);
411 0 : Symbol s;
412 0 : char *buf;
413 0 : size_t len, lim;
414 0 : (void) mb;
415 :
416 0 : s = findSymbol(cntxt->usermodule, getName(*mod), putName(*fcn));
417 0 : if (s == 0)
418 0 : throw(MAL, "inspect.getSource", RUNTIME_SIGNATURE_MISSING);
419 :
420 0 : buf = (char *) GDKmalloc(BUFSIZ);
421 0 : if (buf == NULL)
422 0 : throw(MAL, "inspect.getSource", SQLSTATE(HY013) MAL_MALLOC_FAIL);
423 0 : snprintf(buf, BUFSIZ, "%s.%s", *mod, *fcn);
424 0 : buf[0] = 0;
425 0 : len = 0;
426 0 : lim = BUFSIZ;
427 :
428 0 : while (s) {
429 : int i;
430 : str ps;
431 :
432 0 : for (i = 0; i < s->def->stop; i++) {
433 0 : if ((ps = instruction2str(s->def, 0, getInstrPtr(s->def, i),
434 : LIST_MAL_NAME)) == NULL) {
435 0 : GDKfree(buf);
436 0 : throw(MAL, "inspect.getSource",
437 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
438 : }
439 0 : if (strlen(ps) >= lim - len) {
440 : /* expand the buffer */
441 0 : char *bn;
442 0 : bn = GDKrealloc(buf, lim + BUFSIZ);
443 0 : if (bn == NULL) {
444 0 : GDKfree(ps);
445 0 : GDKfree(buf);
446 0 : throw(MAL, "inspect.getSource",
447 : SQLSTATE(HY013) MAL_MALLOC_FAIL);
448 : }
449 : buf = bn;
450 : lim += BUFSIZ;
451 : }
452 0 : strcat(buf + len, ps);
453 0 : len += strlen(ps);
454 0 : buf[len++] = '\n';
455 0 : buf[len] = 0;
456 0 : GDKfree(ps);
457 : }
458 0 : s = s->peer;
459 : }
460 0 : *ret = buf;
461 0 : return MAL_SUCCEED;
462 : }
463 :
464 : static str
465 0 : INSPECTatom_names(bat *ret)
466 : {
467 0 : int i;
468 0 : BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
469 :
470 0 : if (b == 0)
471 0 : throw(MAL, "inspect.getAtomNames", SQLSTATE(HY013) MAL_MALLOC_FAIL);
472 :
473 0 : for (i = 0; i < GDKatomcnt; i++)
474 0 : if (BUNappend(b, ATOMname(i), false) != GDK_SUCCEED)
475 0 : goto bailout;
476 :
477 0 : *ret = b->batCacheid;
478 0 : BBPkeepref(b);
479 :
480 0 : return MAL_SUCCEED;
481 0 : bailout:
482 0 : BBPreclaim(b);
483 0 : throw(MAL, "inspect.getAtomNames", SQLSTATE(HY013) MAL_MALLOC_FAIL);
484 : }
485 :
486 : static str
487 65 : INSPECTgetEnvironment(bat *ret, bat *ret2)
488 : {
489 65 : BAT *k, *v;
490 :
491 65 : if (GDKcopyenv(&k, &v, false) != GDK_SUCCEED)
492 0 : throw(MAL, "inspect.getEnvironment", GDK_EXCEPTION);
493 :
494 65 : *ret = k->batCacheid;
495 65 : BBPkeepref(k);
496 65 : *ret2 = v->batCacheid;
497 65 : BBPkeepref(v);
498 65 : return MAL_SUCCEED;
499 : }
500 :
501 : static str
502 8 : INSPECTgetEnvironmentKey(str *ret, const char *const *key)
503 : {
504 8 : const char *s;
505 8 : *ret = 0;
506 :
507 8 : s = GDKgetenv(*key);
508 8 : if (s == 0)
509 0 : throw(MAL, "inspect.getEnvironment",
510 : "environment variable '%s' not found", *key);
511 8 : *ret = GDKstrdup(s);
512 8 : if (*ret == NULL)
513 0 : throw(MAL, "inspect.getEnvironment", SQLSTATE(HY013) MAL_MALLOC_FAIL);
514 : return MAL_SUCCEED;
515 : }
516 :
517 : static str
518 2 : INSPECTgetDatabaseName(str *ret)
519 : {
520 2 : const char *key = "gdk_dbname";
521 2 : return INSPECTgetEnvironmentKey(ret, &key);
522 : }
523 :
524 : static str
525 0 : INSPECTatom_sup_names(bat *ret)
526 : {
527 0 : int i, k;
528 0 : BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
529 :
530 0 : if (b == 0)
531 0 : throw(MAL, "inspect.getAtomSuper", SQLSTATE(HY013) MAL_MALLOC_FAIL);
532 :
533 0 : for (i = 0; i < GDKatomcnt; i++) {
534 0 : for (k = ATOMstorage(i); k > TYPE_str; k = ATOMstorage(k)) ;
535 0 : if (BUNappend(b, ATOMname(k), false) != GDK_SUCCEED)
536 0 : goto bailout;
537 : }
538 :
539 0 : *ret = b->batCacheid;
540 0 : BBPkeepref(b);
541 :
542 0 : return MAL_SUCCEED;
543 0 : bailout:
544 0 : BBPreclaim(b);
545 0 : throw(MAL, "inspect.getAtomSuper", SQLSTATE(HY013) MAL_MALLOC_FAIL);
546 : }
547 :
548 : static str
549 0 : INSPECTatom_sizes(bat *ret)
550 : {
551 0 : int i;
552 0 : int s;
553 0 : BAT *b = COLnew(0, TYPE_int, 256, TRANSIENT);
554 :
555 0 : if (b == 0)
556 0 : throw(MAL, "inspect.getAtomSizes", SQLSTATE(HY013) MAL_MALLOC_FAIL);
557 :
558 0 : for (i = 0; i < GDKatomcnt; i++) {
559 0 : s = ATOMsize(i);
560 0 : if (BUNappend(b, &s, false) != GDK_SUCCEED)
561 0 : goto bailout;
562 : }
563 :
564 0 : *ret = b->batCacheid;
565 0 : BBPkeepref(b);
566 :
567 0 : return MAL_SUCCEED;
568 0 : bailout:
569 0 : BBPreclaim(b);
570 0 : throw(MAL, "inspect.getAtomSizes", SQLSTATE(HY013) MAL_MALLOC_FAIL);
571 : }
572 :
573 : /* calculate to trimmed storage space */
574 : static lng
575 0 : INSPECTcalcSize(MalBlkPtr mb)
576 : {
577 0 : lng size, args = 0, i;
578 0 : InstrPtr p;
579 :
580 0 : for (i = 0; i < mb->stop; i++) {
581 0 : p = getInstrPtr(mb, i);
582 0 : args += (p->argc - 1) * sizeof(*p->argv);
583 : }
584 0 : size = (offsetof(InstrRecord, argv) + sizeof(InstrPtr)) * mb->stop;
585 0 : size += sizeof(VarRecord) * mb->vtop;
586 0 : size += args;
587 0 : return size;
588 : }
589 :
590 : static str
591 0 : INSPECTgetSize(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
592 : {
593 0 : lng *ret = getArgReference_lng(stk, p, 0);
594 :
595 :
596 0 : *ret = INSPECTcalcSize(mb);
597 0 : (void) cntxt;
598 0 : (void) mb;
599 0 : return MAL_SUCCEED;
600 : }
601 :
602 : static str
603 0 : INSPECTgetFunctionSize(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
604 : {
605 0 : lng *ret = getArgReference_lng(stk, pci, 0);
606 0 : const char *mod = *getArgReference_str(stk, pci, 1);
607 0 : const char *fcn = *getArgReference_str(stk, pci, 2);
608 0 : Symbol s;
609 0 : (void) mb;
610 :
611 0 : s = findSymbol(cntxt->usermodule, getName(mod), putName(fcn));
612 0 : if (s == 0)
613 0 : throw(MAL, "inspect.getSize", RUNTIME_SIGNATURE_MISSING);
614 0 : *ret = INSPECTcalcSize(s->def);
615 0 : return MAL_SUCCEED;
616 : }
617 :
618 : static str
619 0 : INSPECTequalType(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
620 : {
621 0 : bit *ret;
622 0 : (void) stk;
623 0 : (void) cntxt;
624 0 : ret = getArgReference_bit(stk, pci, 0);
625 0 : *ret = getArgType(mb, pci, 1) == getArgType(mb, pci, 2);
626 0 : return MAL_SUCCEED;
627 : }
628 :
629 : static str
630 7 : INSPECTtypeName(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
631 : {
632 7 : str *hn, *tn = 0;
633 :
634 7 : hn = getArgReference_str(stk, pci, 0);
635 :
636 7 : (void) cntxt;
637 7 : if (pci->retc == 2) {
638 0 : tn = getArgReference_str(stk, pci, 1);
639 0 : *hn = getTypeName(TYPE_oid);
640 0 : *tn = getTypeName(getBatType(getArgType(mb, pci, 2)));
641 7 : } else if (isaBatType(getArgType(mb, pci, 1))) {
642 1 : bat *bid = getArgReference_bat(stk, pci, 1);
643 1 : BAT *b;
644 1 : if ((b = BBPquickdesc(*bid)))
645 1 : *hn = getTypeName(newBatType(b->ttype));
646 : else
647 0 : *hn = getTypeName(getArgType(mb, pci, 1));
648 : } else
649 6 : *hn = getTypeName(getArgType(mb, pci, 1));
650 7 : return MAL_SUCCEED;
651 : }
652 :
653 : #include "mel.h"
654 : mel_func inspect_init_funcs[] = {
655 : pattern("inspect", "getDefinition", INSPECTgetDefinition, false, "Returns a string representation of a specific function.", args(1,3, batarg("",str),arg("mod",str),arg("fcn",str))),
656 : pattern("inspect", "getExistence", INSPECTgetExistence, false, "Returns a boolean indicating existence of a definition of a specific function.", args(1,3, arg("",bit),arg("mod",str),arg("fcn",str))),
657 : pattern("inspect", "getSignature", INSPECTgetSignature, false, "Returns the function signature(s).", args(1,3, batarg("",str),arg("mod",str),arg("fcn",str))),
658 : pattern("inspect", "getComment", INSPECTgetComment, false, "Returns the function help information.", args(1,3, batarg("",str),arg("mod",str),arg("fcn",str))),
659 : pattern("inspect", "getSource", INSPECTgetSource, false, "Return the original input for a function.", args(1,3, arg("",str),arg("mod",str),arg("fcn",str))),
660 : pattern("inspect", "getKind", INSPECTgetkind, false, "Obtain the instruction kind.", args(1,1, batarg("",str))),
661 : pattern("inspect", "getModule", INSPECTgetAllModules, false, "Obtain the function name.", args(1,1, batarg("",str))),
662 : pattern("inspect", "getFunction", INSPECTgetAllFunctions, false, "Obtain the function name.", args(1,1, batarg("",str))),
663 : pattern("inspect", "getSignatures", INSPECTgetAllSignatures, false, "Obtain the function signatures.", args(1,1, batarg("",str))),
664 : pattern("inspect", "getSize", INSPECTgetSize, false, "Return the storage size for the current function (in bytes).", args(1,1, arg("",lng))),
665 : pattern("inspect", "getSize", INSPECTgetFunctionSize, false, "Return the storage size for a function (in bytes).", args(1,3, arg("",lng),arg("mod",str),arg("fcn",str))),
666 : pattern("inspect", "getType", INSPECTtypeName, false, "Return the concrete type of a variable (expression).", args(1,2, arg("",str),argany("v",1))),
667 : pattern("inspect", "equalType", INSPECTequalType, false, "Return true if both operands are of the same type", args(1,3, arg("",bit),argany("l",0),argany("r",0))),
668 : command("inspect", "getAtomNames", INSPECTatom_names, false, "Collect a BAT with the atom names.", args(1,1, batarg("",str))),
669 : command("inspect", "getAtomSuper", INSPECTatom_sup_names, false, "Collect a BAT with the atom names.", args(1,1, batarg("",str))),
670 : command("inspect", "getAtomSizes", INSPECTatom_sizes, false, "Collect a BAT with the atom sizes.", args(1,1, batarg("",int))),
671 : command("inspect", "getEnvironment", INSPECTgetEnvironment, false, "Collect the environment variables.", args(2,2, batarg("k",str),batarg("v",str))),
672 : command("inspect", "getEnvironment", INSPECTgetEnvironmentKey, false, "Get the value of an environment variable", args(1,2, arg("",str),arg("k",str))),
673 : command("inspect", "getDatabaseName", INSPECTgetDatabaseName, false, "Return database name", args(1,1, arg("",str))),
674 : { .imp=NULL }
675 : };
676 : #include "mal_import.h"
677 : #ifdef _MSC_VER
678 : #undef read
679 : #pragma section(".CRT$XCU",read)
680 : #endif
681 323 : LIB_STARTUP_FUNC(init_inspect_mal)
682 323 : { mal_module("inspect", NULL, inspect_init_funcs); }
|