LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_listing.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 264 392 67.3 %
Date: 2024-04-25 20:03:45 Functions: 8 10 80.0 %

          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. Kersten 2015
      15             : */
      16             : 
      17             : #include "monetdb_config.h"
      18             : #include "mal_instruction.h"
      19             : #include "mal_function.h"             /* for getPC() */
      20             : #include "mal_utils.h"
      21             : #include "mal_exception.h"
      22             : #include "mal_listing.h"
      23             : 
      24             : /*
      25             :  * Since MAL programs can be created on the fly by linked-in query
      26             :  * compilers, or transformed by optimizers, it becomes
      27             :  * mandatory to be able to produce textual correct MAL programs
      28             :  * from its internal representation for several purposes.
      29             :  *
      30             :  * Whenever there is an overriding property it is applied.
      31             :  *
      32             :  * The hiddenInstruction operator assumes a sufficiently large block
      33             :  * to leave information on the signature behind.
      34             :  *
      35             :  * The protection against overflow is not tight.
      36             : */
      37             : #define advance(X,B,L)  while(*(X) && B+L>X)(X)++;
      38             : 
      39             : /* Copy string in src to *dstp which has *lenp space available and
      40             :  * terminate with a NULL byte.  *dstp and *lenp are adjusted for the
      41             :  * used space.  If there is not enough space to copy all of src,
      42             :  * return false, otherwise return true.  The resulting string is
      43             :  * always NULL-terminated. */
      44             : static inline bool
      45     2003055 : copystring(char **dstp, const char *src, size_t *lenp)
      46             : {
      47     2003055 :         size_t len = *lenp;
      48     2003055 :         char *dst = *dstp;
      49             : 
      50     2003055 :         if (src == NULL)
      51             :                 return true;
      52     2003055 :         if (len > 0) {
      53    13240861 :                 while (*src && len > 1) {
      54    11237806 :                         *dst++ = *src++;
      55    11237806 :                         len--;
      56             :                 }
      57     2003055 :                 *dst = 0;
      58     2003055 :                 *dstp = dst;
      59     2003055 :                 *lenp = len;
      60             :         }
      61     2003055 :         return *src == 0;
      62             : }
      63             : 
      64             : static str
      65      375380 : renderTerm(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int idx, int flg)
      66             : {
      67      375380 :         char *buf = 0;
      68      375380 :         char *nme = 0;
      69      375380 :         int nameused = 0;
      70      375380 :         size_t len = 0, maxlen = BUFSIZ;
      71      375380 :         ValRecord *val = 0;
      72      375380 :         char *cv = 0, *c;
      73      375380 :         str tpe;
      74      375380 :         int showtype = 0, closequote = 0;
      75      375380 :         int varid = getArg(p, idx);
      76             : 
      77      375380 :         buf = GDKzalloc(maxlen);
      78      375380 :         if (buf == NULL) {
      79           0 :                 addMalException(mb, "renderTerm:Failed to allocate");
      80           0 :                 return NULL;
      81             :         }
      82             :         // show the name when required or is used
      83      375380 :         if ((flg & LIST_MAL_NAME) && !isVarConstant(mb, varid)
      84      362162 :                 && !isVarTypedef(mb, varid)) {
      85      362155 :                 nme = getVarName(mb, varid);
      86      362155 :                 len += snprintf(buf, maxlen, "%s", nme);
      87      362155 :                 nameused = 1;
      88             :         }
      89             :         // show the value when required or being a constant
      90      375380 :         if (((flg & LIST_MAL_VALUE) && stk != 0) || isVarConstant(mb, varid)) {
      91       15033 :                 if (nameused) {
      92        1821 :                         strcat(buf + len, "=");
      93        1821 :                         len++;
      94             :                 }
      95             : 
      96             :                 // locate value record
      97       15033 :                 if (isVarConstant(mb, varid)) {
      98       13212 :                         val = &getVarConstant(mb, varid);
      99       13212 :                         showtype = getVarType(mb, varid) != TYPE_str
     100       13212 :                                         && getVarType(mb, varid) != TYPE_bit;
     101        1821 :                 } else if (stk)
     102        1821 :                         val = &stk->stk[varid];
     103             : 
     104       15033 :                 if ((cv = VALformat(val)) == NULL) {
     105           0 :                         addMalException(mb, "renderTerm:Failed to allocate");
     106           0 :                         GDKfree(buf);
     107           0 :                         return NULL;
     108             :                 }
     109       15033 :                 if (len + strlen(cv) >= maxlen) {
     110           0 :                         char *nbuf = GDKrealloc(buf, maxlen = len + strlen(cv) + BUFSIZ);
     111             : 
     112           0 :                         if (nbuf == 0) {
     113           0 :                                 GDKfree(buf);
     114           0 :                                 GDKfree(cv);
     115           0 :                                 addMalException(mb, "renderTerm:Failed to allocate");
     116           0 :                                 return NULL;
     117             :                         }
     118             :                         buf = nbuf;
     119             :                 }
     120             : 
     121       15033 :                 if (strcmp(cv, "nil") == 0) {
     122         539 :                         strcat(buf + len, cv);
     123         539 :                         len += strlen(buf + len);
     124         539 :                         GDKfree(cv);
     125         539 :                         showtype = showtype
     126          11 :                                         || (getBatType(getVarType(mb, varid)) >= TYPE_date
     127          11 :                                                 && getBatType(getVarType(mb, varid)) != TYPE_str)
     128          10 :                                         || ((isVarTypedef(mb, varid)) && isVarConstant(mb, varid))
     129         549 :                                         || isaBatType(getVarType(mb, varid));
     130             :                 } else {
     131       14494 :                         if (!isaBatType(getVarType(mb, varid))
     132       12949 :                                 && getBatType(getVarType(mb, varid)) >= TYPE_date
     133        3704 :                                 && getBatType(getVarType(mb, varid)) != TYPE_str) {
     134         280 :                                 closequote = 1;
     135         280 :                                 strcat(buf + len, "\"");
     136         280 :                                 len++;
     137             :                         }
     138       14494 :                         if (isaBatType(getVarType(mb, varid))) {
     139        1545 :                                 c = strchr(cv, '>');
     140        1545 :                                 strcat(buf + len, c + 1);
     141        1545 :                                 len += strlen(buf + len);
     142             :                         } else {
     143       12949 :                                 strcat(buf + len, cv);
     144       12949 :                                 len += strlen(buf + len);
     145             :                         }
     146       14494 :                         GDKfree(cv);
     147             : 
     148       14494 :                         if (closequote) {
     149         280 :                                 strcat(buf + len, "\"");
     150         280 :                                 len++;
     151             :                         }
     152       28988 :                         showtype = showtype || closequote > TYPE_str
     153        6254 :                                         ||
     154        6254 :                                         ((isVarTypedef(mb, varid)
     155        6254 :                                           || (flg & (LIST_MAL_REMOTE | LIST_MAL_TYPE)))
     156        6244 :                                          && isVarConstant(mb, varid))
     157       16322 :                                         || (isaBatType(getVarType(mb, varid)) && idx < p->retc);
     158             : 
     159       14494 :                         if (stk && isaBatType(getVarType(mb, varid))
     160        1545 :                                 && stk->stk[varid].val.bval) {
     161        1545 :                                 BAT *d = BBPquickdesc(stk->stk[varid].val.bval);
     162        1545 :                                 if (d)
     163        1545 :                                         len += snprintf(buf + len, maxlen - len, "[" BUNFMT "]",
     164             :                                                                         BATcount(d));
     165             :                         }
     166             :                 }
     167             :         }
     168             : 
     169             :         // show the type when required or frozen by the user
     170             :         // special care should be taken with constants, they may have been casted
     171      375380 :         if ((flg & LIST_MAL_TYPE) || (idx < p->retc) || isVarTypedef(mb, varid)
     172          16 :                 || showtype) {
     173      375364 :                 strcat(buf + len, ":");
     174      375364 :                 len++;
     175      375364 :                 tpe = getTypeName(getVarType(mb, varid));
     176      375362 :                 len += snprintf(buf + len, maxlen - len, "%s", tpe);
     177      375362 :                 GDKfree(tpe);
     178             :         }
     179             : 
     180      375380 :         if (len >= maxlen)
     181           0 :                 addMalException(mb, "renderTerm:Value representation too large");
     182             :         return buf;
     183             : }
     184             : 
     185             : /*
     186             : It receives the space to store the definition
     187             : The MAL profiler dumps some performance data at the
     188             : beginning of each line.
     189             : */
     190             : 
     191             : str
     192      123056 : fcnDefinition(MalBlkPtr mb, InstrPtr p, str t, int flg, str base, size_t len)
     193             : {
     194      123056 :         int i, j;
     195      123056 :         str arg, tpe;
     196             : 
     197      123056 :         len -= t - base;
     198      123056 :         if (!flg && !copystring(&t, "#", &len))
     199             :                 return base;
     200      123056 :         if (mb->inlineProp && !copystring(&t, "inline ", &len))
     201             :                 return base;
     202      123056 :         if (mb->unsafeProp && !copystring(&t, "unsafe ", &len))
     203             :                 return base;
     204      246112 :         if (!copystring(&t, operatorName(p->token), &len) ||
     205      246112 :                 !copystring(&t, " ", &len) ||
     206      369168 :                 !copystring(&t, getModuleId(p) ? getModuleId(p) : "user", &len) ||
     207      246112 :                 !copystring(&t, ".", &len) ||
     208      246112 :                 !copystring(&t, getFunctionId(p), &len) || !copystring(&t, "(", &len))
     209           0 :                 return base;
     210             : 
     211      468891 :         for (i = p->retc; i < p->argc; i++) {
     212      345835 :                 arg = renderTerm(mb, 0, p, i,
     213             :                                                  (LIST_MAL_NAME | LIST_MAL_TYPE | LIST_MAL_PROPS));
     214      345835 :                 if (arg && !copystring(&t, arg, &len)) {
     215           0 :                         GDKfree(arg);
     216           0 :                         return base;
     217             :                 }
     218      345835 :                 GDKfree(arg);
     219      345835 :                 if (i < p->argc - 1 && !copystring(&t, ", ", &len))
     220             :                         return base;
     221             :         }
     222             : 
     223      123056 :         advance(t, base, len);
     224      123056 :         if (p->varargs & VARARGS && !copystring(&t, "...", &len))
     225             :                 return base;
     226             : 
     227      123056 :         if (p->retc == 1) {
     228      120488 :                 if (!copystring(&t, "):", &len))
     229             :                         return base;
     230      120488 :                 tpe = getTypeName(getVarType(mb, getArg(p, 0)));
     231      120488 :                 if (!copystring(&t, tpe, &len)) {
     232           0 :                         GDKfree(tpe);
     233           0 :                         return base;
     234             :                 }
     235      120488 :                 GDKfree(tpe);
     236      120488 :                 if (p->varargs & VARRETS && !copystring(&t, "...", &len))
     237             :                         return base;
     238             :         } else {
     239        2568 :                 if (!copystring(&t, ") (", &len))
     240             :                         return base;
     241       10380 :                 for (i = 0; i < p->retc; i++) {
     242        7812 :                         arg = renderTerm(mb, 0, p, i,
     243             :                                                          (LIST_MAL_NAME | LIST_MAL_TYPE | LIST_MAL_PROPS));
     244        7812 :                         if (arg && !copystring(&t, arg, &len)) {
     245           0 :                                 GDKfree(arg);
     246           0 :                                 return base;
     247             :                         }
     248        7812 :                         GDKfree(arg);
     249        7812 :                         if (i < p->retc - 1 && !copystring(&t, ", ", &len))
     250             :                                 return base;
     251             :                 }
     252        2568 :                 if (p->varargs & VARRETS && !copystring(&t, "...", &len))
     253             :                         return base;
     254        2568 :                 if (!copystring(&t, ")", &len))
     255             :                         return base;
     256             :         }
     257             : 
     258      123056 :         if (mb->binding[0]) {
     259      245742 :                 if (!copystring(&t, " address ", &len) ||
     260      122871 :                         !copystring(&t, mb->binding, &len))
     261           0 :                         return base;
     262             :         }
     263      123056 :         (void) copystring(&t, ";", &len);
     264             :         /* add the extra properties for debugging */
     265      123056 :         if (flg & LIST_MAL_PROPS) {
     266           1 :                 char extra[256];
     267           1 :                 if (p->token == REMsymbol) {
     268             :                 } else {
     269           0 :                         snprintf(extra, 256, "\t#[%d] (" BUNFMT ") %s ", getPC(mb, p),
     270           1 :                                          getRowCnt(mb, getArg(p, 0)),
     271           1 :                                          (p->blk ? p->blk->binding : ""));
     272           1 :                         if (!copystring(&t, extra, &len))
     273           0 :                                 return base;
     274           2 :                         for (j = 0; j < p->retc; j++) {
     275           1 :                                 snprintf(extra, 256, "%d ", getArg(p, j));
     276           1 :                                 if (!copystring(&t, extra, &len))
     277             :                                         return base;
     278             :                         }
     279           1 :                         if (p->argc - p->retc > 0) {
     280           0 :                                 if (!copystring(&t, "<- ", &len))
     281             :                                         return base;
     282             :                         }
     283           1 :                         for (; j < p->argc; j++) {
     284           0 :                                 snprintf(extra, 256, "%d ", getArg(p, j));
     285           0 :                                 if (!copystring(&t, extra, &len))
     286             :                                         return base;
     287             :                         }
     288           1 :                         if (p->typechk == TYPE_UNKNOWN) {
     289           0 :                                 if (!copystring(&t, " type check needed", &len))
     290             :                                         return base;
     291             :                         }
     292             :                 }
     293             :         }
     294             :         return base;
     295             : }
     296             : 
     297             : static str
     298        3322 : fmtRemark(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, str t, int flg, str base,
     299             :                   size_t len)
     300             : {
     301        3322 :         char aux[128];
     302             : 
     303        3322 :         if (!copystring(&t, "# ", &len))
     304             :                 return base;
     305             : 
     306        3322 :         if (pci->argc == 3) {
     307        3318 :                 if (getFunctionId(pci)) {
     308        3318 :                         char *arg1 = renderTerm(mb, stk, pci, 1, flg);
     309        3318 :                         char *arg2 = renderTerm(mb, stk, pci, 2, flg);
     310        3318 :                         if (arg1 && arg2) {
     311        3318 :                                 const char *f = getFunctionId(pci);
     312        3318 :                                 if (strcmp(f, "total") == 0)
     313         126 :                                         snprintf(aux, 128, "%d optimizers %ld usecs", atoi(arg1), atol(arg2));
     314             :                                 else
     315        3192 :                                         snprintf(aux, 128, "%-36s %d actions %ld usecs", f, atoi(arg1), atol(arg2));
     316        3318 :                                 (void) copystring(&t, aux, &len);
     317             :                         }
     318        3318 :                         GDKfree(arg1);
     319        3318 :                         GDKfree(arg2);
     320             :                 }
     321           4 :         } else if (pci->argc == 1) {
     322           4 :                 if (getFunctionId(pci)) {
     323           4 :                         if (!copystring(&t, getFunctionId(pci), &len))
     324             :                                 return base;
     325             :                 }
     326           0 :         } else if (getVar(mb, getArg(pci, 0))->value.val.sval &&
     327           0 :                            getVar(mb, getArg(pci, 0))->value.len > 0 &&
     328           0 :                            !copystring(&t, getVar(mb, getArg(pci, 0))->value.val.sval,
     329             :                                                    &len))
     330             :                 return base;
     331             : 
     332             :         return base;
     333             : }
     334             : 
     335             : str
     336      123165 : operatorName(int i)
     337             : {
     338      123165 :         switch (i) {
     339             :         case ASSIGNsymbol:
     340             :                 return ":=";
     341          20 :         case BARRIERsymbol:
     342          20 :                 return "barrier";
     343           0 :         case REDOsymbol:
     344           0 :                 return "redo";
     345           0 :         case LEAVEsymbol:
     346           0 :                 return "leave";
     347          12 :         case EXITsymbol:
     348          12 :                 return "exit";
     349           0 :         case RETURNsymbol:
     350           0 :                 return "return";
     351           0 :         case CATCHsymbol:
     352           0 :                 return "catch";
     353           0 :         case RAISEsymbol:
     354           0 :                 return "raise";
     355          36 :         case ENDsymbol:
     356          36 :                 return "end";
     357         226 :         case FUNCTIONsymbol:
     358         226 :                 return "function";
     359       19537 :         case COMMANDsymbol:
     360       19537 :                 return "command";
     361      103334 :         case PATTERNsymbol:
     362      103334 :                 return "pattern";
     363             : 
     364             :                 /* internal symbols */
     365           0 :         case FCNcall:
     366           0 :                 return "FCNcall";
     367           0 :         case CMDcall:
     368           0 :                 return "CMDcall";
     369           0 :         case THRDcall:
     370           0 :                 return "THRcall";
     371           0 :         case PATcall:
     372           0 :                 return "PATcall";
     373             :         }
     374           0 :         return "";
     375             : }
     376             : 
     377             : str
     378        7290 : instruction2str(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int flg)
     379             : {
     380        7290 :         int i, j;
     381        7290 :         str base, t;
     382        7290 :         size_t len = 512 + (p->argc * 128);  /* max realistic line length estimate */
     383        7290 :         str arg;
     384             : 
     385        7290 :         t = base = GDKmalloc(len);
     386        7290 :         if (base == NULL)
     387             :                 return NULL;
     388        7290 :         if (!flg) {
     389           1 :                 *t++ = '#';
     390           1 :                 len--;
     391           1 :                 if (p->typechk == TYPE_UNKNOWN) {
     392           0 :                         *t++ = '!';                     /* error */
     393           0 :                         len--;
     394             :                 }
     395             :         }
     396        7290 :         *t = 0;
     397        7290 :         if (p->token == REMsymbol
     398        3322 :                 && !(getModuleId(p) && strcmp(getModuleId(p), "querylog") == 0
     399           0 :                          && getFunctionId(p) && strcmp(getFunctionId(p), "define") == 0)) {
     400             :                 /* do nothing */
     401        3968 :         } else if (p->barrier) {
     402          28 :                 if (p->barrier == LEAVEsymbol ||
     403          28 :                         p->barrier == REDOsymbol ||
     404             :                         p->barrier == RETURNsymbol || p->barrier == RAISEsymbol) {
     405           0 :                         if (!copystring(&t, "    ", &len))
     406             :                                 return base;
     407             :                 }
     408          28 :                 arg = operatorName(p->barrier);
     409          28 :                 if (!copystring(&t, arg, &len) || !copystring(&t, " ", &len))
     410           0 :                         return base;
     411        3940 :         } else if (functionStart(p) && flg != LIST_MAL_CALL) {
     412         168 :                 return fcnDefinition(mb, p, t, flg, base, len + (t - base));
     413        3772 :         } else if (!functionExit(p) && flg != LIST_MAL_CALL) {
     414             :                 // beautify with tabs
     415        3600 :                 if (!copystring(&t, "    ", &len))
     416             :                         return base;
     417             :         }
     418        7122 :         switch (p->token < 0 ? -p->token : p->token) {
     419        3628 :         case FCNcall:
     420             :         case PATcall:
     421             :         case CMDcall:
     422             :         case ASSIGNsymbol:
     423             :                 // is any variable explicit or used
     424             :                 /* this code was meant to make it easy to detect functions whose
     425             :                  * result variable was not used anywhere.
     426             :                  * It is not essential
     427             :                  for (i = 0; i < p->retc; i++)
     428             :                  if ( !isTmpVar(mb,getArg(p,i)) || isVarUsed(mb, getArg(p, i)))
     429             :                  break;
     430             : 
     431             :                  if (i == p->retc)
     432             :                  break;
     433             :                  */
     434             : 
     435             :                 /* display multi-assignment list */
     436        3628 :                 if (p->retc > 1 && !copystring(&t, "(", &len))
     437             :                         return base;
     438             : 
     439        7393 :                 for (i = 0; i < p->retc; i++) {
     440        3765 :                         arg = renderTerm(mb, stk, p, i, flg);
     441        3765 :                         if (arg) {
     442        3765 :                                 if (!copystring(&t, arg, &len)) {
     443           0 :                                         GDKfree(arg);
     444           0 :                                         return base;
     445             :                                 }
     446        3765 :                                 GDKfree(arg);
     447             :                         }
     448        3765 :                         if (i < p->retc - 1 && !copystring(&t, ", ", &len))
     449             :                                 return base;
     450             :                 }
     451        3628 :                 if (p->retc > 1 && !copystring(&t, ")", &len))
     452             :                         return base;
     453             : 
     454        3628 :                 if (p->argc > p->retc || getFunctionId(p)) {
     455        3616 :                         if (!copystring(&t, " := ", &len))
     456             :                                 return base;
     457             :                 }
     458             :                 break;
     459         167 :         case ENDsymbol:
     460         334 :                 if (!copystring(&t, "end ", &len) ||
     461         334 :                         !copystring(&t, getModuleId(getInstrPtr(mb, 0)), &len) ||
     462         334 :                         !copystring(&t, ".", &len) ||
     463         167 :                         !copystring(&t, getFunctionId(getInstrPtr(mb, 0)), &len))
     464           0 :                         return base;
     465             :                 break;
     466           5 :         case COMMANDsymbol:
     467             :         case FUNCTIONsymbol:
     468             :         case PATTERNsymbol:
     469           5 :                 if (flg & LIST_MAL_VALUE) {
     470          10 :                         if (!copystring(&t, operatorName(p->token), &len) ||
     471           5 :                                 !copystring(&t, " ", &len))
     472           0 :                                 return base;
     473             :                 }
     474           5 :                 return fcnDefinition(mb, p, t, flg, base, len + (t - base));
     475        3322 :         case REMsymbol:
     476        3322 :                 return fmtRemark(mb, stk, p, t, flg, base, len);
     477           0 :         default:
     478           0 :                 i = snprintf(t, len, " unknown symbol ?%d? ", p->token);
     479           0 :                 if (i < 0 || (size_t) i >= len)
     480             :                         return base;
     481           0 :                 len -= (size_t) i;
     482           0 :                 t += i;
     483           0 :                 break;
     484             :         }
     485             : 
     486        3795 :         if (getModuleId(p)) {
     487        3548 :                 if (!copystring(&t, getModuleId(p), &len) || !copystring(&t, ".", &len))
     488           0 :                         return base;
     489             :         }
     490        3795 :         if (getFunctionId(p)) {
     491        7095 :                 if (!copystring(&t, getFunctionId(p), &len) ||
     492        3548 :                         !copystring(&t, "(", &len))
     493           0 :                         return base;
     494         247 :         } else if (p->argc > p->retc + 1) {
     495           0 :                 if (!copystring(&t, "(", &len))
     496             :                         return base;
     497             :         }
     498       15125 :         for (i = p->retc; i < p->argc; i++) {
     499       11331 :                 arg = renderTerm(mb, stk, p, i, flg);
     500       11332 :                 if (arg) {
     501       11332 :                         if (!copystring(&t, arg, &len)) {
     502           1 :                                 GDKfree(arg);
     503           1 :                                 return base;
     504             :                         }
     505       11331 :                         GDKfree(arg);
     506             :                 }
     507             : 
     508       11331 :                 if (i < p->argc - 1 && !copystring(&t, ", ", &len))
     509             :                         return base;
     510             :         }
     511        3794 :         if (getFunctionId(p) || p->argc > p->retc + 1) {
     512        3547 :                 if (!copystring(&t, ")", &len))
     513             :                         return base;
     514             :         }
     515        3795 :         if (p->token != REMsymbol) {
     516        3794 :                 if (!copystring(&t, ";", &len))
     517             :                         return base;
     518             :         }
     519             :         /* add the extra properties for debugging */
     520        3794 :         if (flg & LIST_MAL_PROPS) {
     521         571 :                 char extra[256];
     522         571 :                 if (p->token == REMsymbol) {
     523             :                 } else {
     524         570 :                         snprintf(extra, 256, "\t#[%d] (" BUNFMT ") %s ", p->pc,
     525         571 :                                          getRowCnt(mb, getArg(p, 0)),
     526         571 :                                          (p->blk ? p->blk->binding : ""));
     527         571 :                         if (!copystring(&t, extra, &len))
     528           0 :                                 return base;
     529        1176 :                         for (j = 0; j < p->retc; j++) {
     530         605 :                                 snprintf(extra, 256, "%d ", getArg(p, j));
     531         605 :                                 if (!copystring(&t, extra, &len))
     532             :                                         return base;
     533             :                         }
     534         571 :                         if (p->argc - p->retc > 0) {
     535         568 :                                 if (!copystring(&t, "<- ", &len))
     536             :                                         return base;
     537             :                         }
     538        2863 :                         for (; j < p->argc; j++) {
     539        2292 :                                 snprintf(extra, 256, "%d ", getArg(p, j));
     540        2292 :                                 if (!copystring(&t, extra, &len))
     541             :                                         return base;
     542             :                         }
     543         571 :                         if (p->typechk == TYPE_UNKNOWN) {
     544           0 :                                 if (!copystring(&t, " type check needed", &len))
     545             :                                         return base;
     546             :                         }
     547             :                 }
     548             :         }
     549        3794 :         if (flg & LIST_MAL_ALGO) {
     550         821 :                 const char *algo = MT_thread_getalgorithm();
     551         821 :                 if (algo) {
     552         130 :                         if (!copystring(&t, " # ", &len))
     553             :                                 return base;
     554         130 :                         if (!copystring(&t, algo, &len))
     555             :                                 return base;
     556             :                 }
     557             :         }
     558             :         return base;
     559             : }
     560             : 
     561             : /* the MAL beautifier is meant to simplify correlation of MAL variables and
     562             :  * the columns in the underlying database.
     563             :  * If the status is set, then we consider the instruction DONE and the result variables
     564             :  * should be shown as well.
     565             :  */
     566             : 
     567             : /* Remote execution of MAL calls for more type/property information to be exchanged */
     568             : str
     569           0 : mal2str(MalBlkPtr mb, int first, int last)
     570             : {
     571           0 :         str ps = NULL, *txt;
     572           0 :         int i, j;
     573           0 :         size_t *len, totlen = 0;
     574             : 
     575           0 :         txt = GDKmalloc(sizeof(str) * mb->stop);
     576           0 :         len = GDKmalloc(sizeof(size_t) * mb->stop);
     577             : 
     578           0 :         if (txt == NULL || len == NULL) {
     579           0 :                 addMalException(mb, "mal2str: " MAL_MALLOC_FAIL);
     580           0 :                 GDKfree(txt);
     581           0 :                 GDKfree(len);
     582           0 :                 return NULL;
     583             :         }
     584           0 :         for (i = first; i < last; i++) {
     585           0 :                 if (i == 0)
     586           0 :                         txt[i] = instruction2str(mb, 0, getInstrPtr(mb, i),
     587             :                                                                          LIST_MAL_NAME | LIST_MAL_TYPE |
     588             :                                                                          LIST_MAL_PROPS);
     589             :                 else
     590           0 :                         txt[i] = instruction2str(mb, 0, getInstrPtr(mb, i),
     591             :                                                                          LIST_MAL_CALL | LIST_MAL_PROPS |
     592             :                                                                          LIST_MAL_REMOTE);
     593             : 
     594           0 :                 if (txt[i])
     595           0 :                         totlen += len[i] = strlen(txt[i]);
     596             :                 else {
     597           0 :                         addMalException(mb, "mal2str: " MAL_MALLOC_FAIL);
     598           0 :                         GDKfree(len);
     599           0 :                         for (j = first; j < i; j++)
     600           0 :                                 GDKfree(txt[j]);
     601           0 :                         GDKfree(txt);
     602           0 :                         return NULL;
     603             :                 }
     604             :         }
     605           0 :         ps = GDKmalloc(totlen + mb->stop + 1);
     606           0 :         if (ps == NULL) {
     607           0 :                 addMalException(mb, "mal2str: " MAL_MALLOC_FAIL);
     608           0 :                 GDKfree(len);
     609           0 :                 for (i = first; i < last; i++)
     610           0 :                         GDKfree(txt[i]);
     611           0 :                 GDKfree(txt);
     612           0 :                 return NULL;
     613             :         }
     614             : 
     615             :         totlen = 0;
     616           0 :         for (i = first; i < last; i++) {
     617           0 :                 if (txt[i]) {
     618           0 :                         strncpy(ps + totlen, txt[i], len[i]);
     619           0 :                         ps[totlen + len[i]] = '\n';
     620           0 :                         ps[totlen + len[i] + 1] = 0;
     621           0 :                         totlen += len[i] + 1;
     622           0 :                         GDKfree(txt[i]);
     623             :                 }
     624             :         }
     625           0 :         GDKfree(len);
     626           0 :         GDKfree(txt);
     627           0 :         return ps;
     628             : }
     629             : 
     630             : void
     631        2942 : printInstruction(stream *fd, MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int flg)
     632             : {
     633        2942 :         str ps;
     634             : 
     635        2942 :         if (fd == 0)
     636             :                 return;
     637        2942 :         ps = instruction2str(mb, stk, p, flg);
     638             :         /* ps[strlen(ps)-1] = 0; remove '\n' */
     639        2942 :         if (ps) {
     640        2982 :                 mnstr_printf(fd, "%s%s", (flg & LIST_MAL_MAPI ? "=" : ""), ps);
     641        2942 :                 GDKfree(ps);
     642             :         } else {
     643           0 :                 mnstr_printf(fd, "#failed instruction2str()");
     644             :         }
     645        2942 :         mnstr_printf(fd, "\n");
     646             : }
     647             : 
     648             : void
     649    40235263 : traceInstruction(component_t comp, MalBlkPtr mb, MalStkPtr stk, InstrPtr p,
     650             :                                  int flg)
     651             : {
     652    40235263 :         str ps;
     653    40235263 :         TRC_DEBUG_IF(comp) {
     654           0 :                 ps = instruction2str(mb, stk, p, flg);
     655             :                 /* ps[strlen(ps)-1] = 0; remove '\n' */
     656           0 :                 if (ps) {
     657           0 :                         TRC_DEBUG_ENDIF(comp, "%s%s\n", (flg & LIST_MAL_MAPI ? "=" : ""),
     658             :                                                         ps);
     659           0 :                         GDKfree(ps);
     660             :                 } else {
     661           0 :                         TRC_DEBUG_ENDIF(comp, "Failed instruction2str()\n");
     662             :                 }
     663             :         }
     664    40235263 : }
     665             : 
     666             : void
     667           0 : printSignature(stream *fd, Symbol s, int flg)
     668             : {
     669           0 :         InstrPtr p;
     670           0 :         str txt;
     671             : 
     672           0 :         if (s->def == 0) {
     673           0 :                 mnstr_printf(fd, "missing definition of %s\n", s->name);
     674           0 :                 return;
     675             :         }
     676           0 :         txt = GDKzalloc(MAXLISTING);    /* some slack for large blocks */
     677           0 :         if (txt) {
     678           0 :                 p = getSignature(s);
     679           0 :                 (void) fcnDefinition(s->def, p, txt, flg, txt, MAXLISTING);
     680           0 :                 mnstr_printf(fd, "%s\n", txt);
     681           0 :                 GDKfree(txt);
     682             :         } else
     683           0 :                 mnstr_printf(fd, "printSignature: " MAL_MALLOC_FAIL);
     684             : }

Generated by: LCOV version 1.14