LCOV - code coverage report
Current view: top level - monetdb5/modules/mal - inspect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 60 382 15.7 %
Date: 2024-11-14 20:04:02 Functions: 6 21 28.6 %

          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          64 : INSPECTgetEnvironment(bat *ret, bat *ret2)
     488             : {
     489          64 :         BAT *k, *v;
     490             : 
     491          64 :         if (GDKcopyenv(&k, &v, false) != GDK_SUCCEED)
     492           0 :                 throw(MAL, "inspect.getEnvironment", GDK_EXCEPTION);
     493             : 
     494          64 :         *ret = k->batCacheid;
     495          64 :         BBPkeepref(k);
     496          64 :         *ret2 = v->batCacheid;
     497          64 :         BBPkeepref(v);
     498          64 :         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         321 : LIB_STARTUP_FUNC(init_inspect_mal)
     682         321 : { mal_module("inspect", NULL, inspect_init_funcs); }

Generated by: LCOV version 1.14