LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_listing.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 299 417 71.7 %
Date: 2025-03-26 20:06:40 Functions: 9 11 81.8 %

          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, 2025 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     3406049 : copystring(char **dstp, const char *src, size_t *lenp)
      46             : {
      47     3406049 :         size_t len = *lenp;
      48     3406049 :         char *dst = *dstp;
      49             : 
      50     3406049 :         if (src == NULL)
      51             :                 return true;
      52     3406049 :         if (len > 0) {
      53    14501225 :                 while (*src && len > 1) {
      54    11095169 :                         *dst++ = *src++;
      55    11095169 :                         len--;
      56             :                 }
      57     3406056 :                 *dst = 0;
      58     3406056 :                 *dstp = dst;
      59     3406056 :                 *lenp = len;
      60             :         }
      61     3406049 :         return *src == 0;
      62             : }
      63             : 
      64             : static void
      65       29675 : renderTerm(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int idx, int flg, char *buf, size_t max_len)
      66             : {
      67       29675 :         char *bufend = buf;
      68       29675 :         int nameused = 0;
      69       29675 :         ValRecord *val = 0;
      70       29675 :         char *cv = 0;
      71       29675 :         str tpe;
      72       29675 :         int showtype = 0, closequote = 0;
      73       29675 :         int varid = getArg(p, idx);
      74             : 
      75             :         // show the name when required or is used
      76       29675 :         if ((flg & LIST_MAL_NAME) && !isVarConstant(mb, varid)
      77       13397 :                 && !isVarTypedef(mb, varid)) {
      78       13395 :                 (void) getVarNameIntoBuffer(mb, varid, bufend);
      79       13396 :                 bufend += strlen(bufend);
      80       13396 :                 nameused = 1;
      81             :         }
      82             :         // show the value when required or being a constant
      83       29676 :         if (((flg & LIST_MAL_VALUE) && stk != 0) || isVarConstant(mb, varid)) {
      84       18051 :                 if (nameused)
      85        1778 :                         bufend = stpcpy(bufend, "=");
      86             :                 // locate value record
      87       18051 :                 if (isVarConstant(mb, varid)) {
      88       16273 :                         val = &getVarConstant(mb, varid);
      89       16273 :                         showtype = getVarType(mb, varid) != TYPE_str
      90       16273 :                                         && getVarType(mb, varid) != TYPE_bit;
      91        1778 :                 } else if (stk) {
      92        1778 :                         val = &stk->stk[varid];
      93             :                 }
      94       18051 :                 cv = VALformat(val);
      95       18052 :                 if (cv == NULL) {
      96           0 :                         bufend = stpcpy(bufend, "<alloc failed...>");
      97       18052 :                 } else if (!val->bat && strcmp(cv, "nil") == 0) {
      98         200 :                         bufend = stpcpy(bufend, cv);
      99         209 :                         showtype = showtype ||
     100           9 :                                 (getBatType(getVarType(mb, varid)) >= TYPE_date
     101           9 :                                  && getBatType(getVarType(mb, varid)) != TYPE_str) ||
     102         208 :                                 ((isVarTypedef(mb, varid)) && isVarConstant(mb, varid)) ||
     103           8 :                                 isaBatType(getVarType(mb, varid));
     104             :                 } else {
     105       17852 :                         if (!isaBatType(getVarType(mb, varid))
     106       16016 :                                 && getBatType(getVarType(mb, varid)) >= TYPE_date
     107        7241 :                                 && getBatType(getVarType(mb, varid)) != TYPE_str) {
     108         280 :                                 closequote = 1;
     109         280 :                                 bufend = stpcpy(bufend, "\"");
     110             :                         }
     111       17852 :                         size_t cv_len = strlen(cv);
     112       17852 :                         if (cv_len > 100) {
     113          25 :                                 cv_len = 100;
     114          25 :                                 if (cv_len > (size_t) ((buf + max_len) - bufend))
     115           0 :                                         cv_len = (buf + max_len) - bufend - 1;
     116          25 :                                 strcpy_len(bufend, cv, cv_len + 1); /* 1 for null termination */
     117          25 :                                 bufend += cv_len;
     118          25 :                                 cv_len = strconcat_len(bufend, (buf + max_len) - bufend, "\" ..... ", NULL);
     119          25 :                                 bufend += cv_len;
     120             :                         } else {
     121       17827 :                                 bufend = stpcpy(bufend, cv);
     122             :                         }
     123       17852 :                         if (closequote) {
     124         280 :                                 bufend = stpcpy(bufend, "\"");
     125             :                         }
     126       45413 :                         showtype = showtype || closequote > TYPE_str ||
     127        9709 :                                 ((isVarTypedef(mb, varid) ||
     128       27561 :                                   (flg & (LIST_MAL_REMOTE | LIST_MAL_TYPE))) && isVarConstant(mb, varid)) ||
     129        1788 :                                 (isaBatType(getVarType(mb, varid)) && idx < p->retc);
     130             : 
     131       17852 :                         if (stk && isaBatType(getVarType(mb, varid))
     132        1665 :                                 && stk->stk[varid].val.bval) {
     133        1663 :                                 BAT *d = BBPquickdesc(stk->stk[varid].val.bval);
     134        1663 :                                 if (d)
     135        1500 :                                         bufend += snprintf(bufend, (buf + max_len) - bufend, "[" BUNFMT "]", BATcount(d));
     136             :                         }
     137             :                 }
     138       18052 :                 GDKfree(cv);
     139             :         }
     140       29677 :         *bufend = 0;
     141             :         // show the type when required or frozen by the user
     142             :         // special care should be taken with constants, they may have been casted
     143       29677 :         if ((flg & LIST_MAL_TYPE) || (idx < p->retc) || isVarTypedef(mb, varid)
     144          16 :                 || showtype) {
     145       29661 :                 tpe = getTypeName(getVarType(mb, varid));
     146       29658 :                 if (tpe) {
     147       29658 :                         strconcat_len(bufend, (buf + max_len) - bufend, ":", tpe, NULL);
     148       29657 :                         GDKfree(tpe);
     149             :                 }
     150             :         }
     151       29677 : }
     152             : 
     153             : /*
     154             : It receives the space to store the definition
     155             : The MAL profiler dumps some performance data at the
     156             : beginning of each line.
     157             : */
     158             : 
     159             : str
     160      162427 : cfcnDefinition(Symbol s, str base, size_t len)
     161             : {
     162      162427 :         unsigned int i;
     163      162427 :         str arg, tpe;
     164      162427 :         mel_func *f = s->func;
     165      162427 :         str t = base;
     166             : 
     167      162427 :         if (f->unsafe && !copystring(&t, "unsafe ", &len))
     168             :                 return base;
     169      324854 :         if (!copystring(&t, operatorName(s->kind), &len) ||
     170      324854 :                 !copystring(&t, " ", &len) ||
     171      487281 :                 !copystring(&t, f->mod ? f->mod : userRef, &len) ||
     172      324854 :                 !copystring(&t, ".", &len) ||
     173      324854 :                 !copystring(&t, f->fcn, &len) || !copystring(&t, "(", &len))
     174           0 :                 return base;
     175             : 
     176      162427 :         char var[16];
     177      617542 :         for (i = f->retc; i < f->argc; i++) {
     178      455115 :                 if (snprintf(var, 16, "X_%d:", i-f->retc) >= 16 || !copystring(&t, var, &len))
     179           0 :                         return base;
     180      714011 :                 if ((f->args[i].isbat || (f->args[i].opt == 1)) && !copystring(&t, (f->args[i].opt == 1)?"bat?[:":"bat[:", &len))
     181             :                         return base;
     182      455115 :                 arg = f->args[i].type;
     183      455115 :                 if (arg[0] && !copystring(&t, arg, &len))
     184             :                         return base;
     185      455115 :                 if (!arg[0]) {
     186       17314 :                         if (f->args[i].nr) {
     187       15904 :                                 if (snprintf(var, 16, "any_%d", f->args[i].nr ) >= 16 || !copystring(&t, var, &len))
     188           0 :                                         return base;
     189        1410 :                         } else if (!copystring(&t, "any", &len))
     190             :                                 return base;
     191             :                 }
     192      455115 :                 if ((f->args[i].isbat || f->args[i].opt == 1) && !copystring(&t, "]", &len))
     193             :                         return base;
     194      455115 :                 if (i+1 < f->argc && !copystring(&t, ", ", &len))
     195             :                         return base;
     196             :         }
     197             : 
     198      162427 :         advance(t, base, len);
     199      162427 :         if (f->vargs && !copystring(&t, "...", &len))
     200             :                 return base;
     201             : 
     202      162427 :         if (f->retc == 0) {
     203        1586 :                 if (!copystring(&t, "):void", &len))
     204             :                         return base;
     205      160841 :         } else if (f->retc == 1) {
     206      157401 :                 if (!copystring(&t, "):", &len))
     207             :                         return base;
     208      265723 :                 if ((f->args[0].isbat || f->args[0].opt == 1) && !copystring(&t, (f->args[0].opt == 1)?"bat?[:":"bat[:", &len))
     209             :                         return base;
     210      157401 :                 tpe = f->args[0].type;
     211      157401 :                 if (tpe[0] && !copystring(&t, tpe, &len))
     212             :                         return base;
     213      157401 :                 if (!tpe[0]) {
     214        2633 :                         if (f->args[0].nr) {
     215        2450 :                                 if (snprintf(var, 16, "any_%d", f->args[0].nr ) >= 16 || !copystring(&t, var, &len))
     216           0 :                                         return base;
     217         183 :                         } else if (!copystring(&t, "any", &len))
     218             :                                 return base;
     219             :                 }
     220      157401 :                 if ((f->args[0].isbat || f->args[0].opt == 1) && !copystring(&t, "]", &len))
     221             :                         return base;
     222      157401 :                 if (f->vrets && !copystring(&t, "...", &len))
     223             :                         return base;
     224             :         } else {
     225        3440 :                 if (!copystring(&t, ") (", &len))
     226             :                         return base;
     227       14000 :                 for (i = 0; i < f->retc; i++) {
     228       10560 :                         if (snprintf(var, 16, "X_%d:", i+(f->argc-f->retc)) >= 16 || !copystring(&t, var, &len))
     229           0 :                                 return base;
     230       19648 :                         if ((f->args[i].isbat || (f->args[i].opt == 1)) && !copystring(&t, (f->args[i].opt == 1)?"bat?[:":"bat[:", &len))
     231             :                                 return base;
     232       10560 :                         arg = f->args[i].type;
     233       10560 :                         if (arg[0] && !copystring(&t, arg, &len))
     234             :                                 return base;
     235       10560 :                         if (!arg[0]) {
     236         352 :                                 if (f->args[i].nr) {
     237         304 :                                         if (snprintf(var, 16, "any_%d", f->args[i].nr ) >= 16 || !copystring(&t, var, &len))
     238           0 :                                                 return base;
     239          48 :                                 } else if (!copystring(&t, "any", &len))
     240             :                                 return base;
     241             :                         }
     242       10560 :                         if ((f->args[i].isbat || f->args[i].opt == 1) && !copystring(&t, "]", &len))
     243             :                                 return base;
     244       10560 :                         if (i+1 < f->retc && !copystring(&t, ", ", &len))
     245             :                                 return base;
     246             :                 }
     247        3440 :                 if (f->vrets && !copystring(&t, "...", &len))
     248             :                         return base;
     249        3440 :                 if (!copystring(&t, ")", &len))
     250             :                         return base;
     251             :         }
     252             : 
     253             :         return base;
     254             : }
     255             : 
     256             : str
     257         171 : fcnDefinition(MalBlkPtr mb, InstrPtr p, str t, int flg, str base, size_t len)
     258             : {
     259         171 :         int i, j;
     260         171 :         char arg[256];
     261         171 :         str tpe;
     262             : 
     263         171 :         len -= t - base;
     264         171 :         if (!flg && !copystring(&t, "#", &len))
     265             :                 return base;
     266         171 :         if (mb->inlineProp && !copystring(&t, "inline ", &len))
     267             :                 return base;
     268         171 :         if (mb->unsafeProp && !copystring(&t, "unsafe ", &len))
     269             :                 return base;
     270         342 :         if (!copystring(&t, operatorName(p->token), &len) ||
     271         342 :                 !copystring(&t, " ", &len) ||
     272         513 :                 !copystring(&t, getModuleId(p) ? getModuleId(p) : userRef, &len) ||
     273         342 :                 !copystring(&t, ".", &len) ||
     274         342 :                 !copystring(&t, getFunctionId(p), &len) || !copystring(&t, "(", &len))
     275           0 :                 return base;
     276             : 
     277         175 :         for (i = p->retc; i < p->argc; i++) {
     278           4 :                 renderTerm(mb, 0, p, i,
     279             :                                    (LIST_MAL_NAME | LIST_MAL_TYPE | LIST_MAL_PROPS),
     280             :                                    arg, sizeof(arg));
     281           4 :                 if (!copystring(&t, arg, &len))
     282             :                         return base;
     283           4 :                 if (i < p->argc - 1 && !copystring(&t, ", ", &len))
     284             :                         return base;
     285             :         }
     286             : 
     287         171 :         advance(t, base, len);
     288         171 :         if (p->varargs & VARARGS && !copystring(&t, "...", &len))
     289             :                 return base;
     290             : 
     291         171 :         if (p->retc == 1) {
     292         171 :                 if (!copystring(&t, "):", &len))
     293             :                         return base;
     294         171 :                 tpe = getTypeName(getVarType(mb, getArg(p, 0)));
     295         171 :                 if (!copystring(&t, tpe, &len)) {
     296           0 :                         GDKfree(tpe);
     297           0 :                         return base;
     298             :                 }
     299         171 :                 GDKfree(tpe);
     300         171 :                 if (p->varargs & VARRETS && !copystring(&t, "...", &len))
     301             :                         return base;
     302             :         } else {
     303           0 :                 if (!copystring(&t, ") (", &len))
     304             :                         return base;
     305           0 :                 for (i = 0; i < p->retc; i++) {
     306           0 :                         renderTerm(mb, 0, p, i,
     307             :                                            (LIST_MAL_NAME | LIST_MAL_TYPE | LIST_MAL_PROPS),
     308             :                                            arg, sizeof(arg));
     309           0 :                         if (!copystring(&t, arg, &len))
     310             :                                 return base;
     311           0 :                         if (i < p->retc - 1 && !copystring(&t, ", ", &len))
     312             :                                 return base;
     313             :                 }
     314           0 :                 if (p->varargs & VARRETS && !copystring(&t, "...", &len))
     315             :                         return base;
     316           0 :                 if (!copystring(&t, ")", &len))
     317             :                         return base;
     318             :         }
     319             : 
     320         171 :         if ((flg & LIST_MAL_NOCFUNC) == 0) {
     321         155 :                 if (mb->binding[0]) {
     322           0 :                         if (!copystring(&t, " address ", &len) ||
     323           0 :                                 !copystring(&t, mb->binding, &len))
     324           0 :                                 return base;
     325             :                 }
     326         155 :                 (void) copystring(&t, ";", &len);
     327             :         }
     328             :         /* add the extra properties for debugging */
     329         171 :         if (flg & LIST_MAL_PROPS) {
     330           1 :                 char extra[256];
     331           1 :                 if (p->token == REMsymbol) {
     332             :                 } else {
     333           0 :                         snprintf(extra, 256, "\t#[%d] (" BUNFMT ") %s ", getPC(mb, p),
     334           1 :                                          getRowCnt(mb, getArg(p, 0)),
     335           1 :                                          (p->blk ? p->blk->binding : ""));
     336           1 :                         if (!copystring(&t, extra, &len))
     337           0 :                                 return base;
     338           2 :                         for (j = 0; j < p->retc; j++) {
     339           1 :                                 snprintf(extra, 256, "%d ", getArg(p, j));
     340           1 :                                 if (!copystring(&t, extra, &len))
     341             :                                         return base;
     342             :                         }
     343           1 :                         if (p->argc - p->retc > 0) {
     344           0 :                                 if (!copystring(&t, "<- ", &len))
     345             :                                         return base;
     346             :                         }
     347           1 :                         for (; j < p->argc; j++) {
     348           0 :                                 snprintf(extra, 256, "%d ", getArg(p, j));
     349           0 :                                 if (!copystring(&t, extra, &len))
     350             :                                         return base;
     351             :                         }
     352           1 :                         if (!p->typeresolved) {
     353           0 :                                 if (!copystring(&t, " type check needed", &len))
     354             :                                         return base;
     355             :                         }
     356             :                 }
     357             :         }
     358             :         return base;
     359             : }
     360             : 
     361             : static str
     362        3160 : fmtRemark(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, str t, int flg, str base,
     363             :                   size_t len)
     364             : {
     365        3160 :         char aux[128];
     366             : 
     367        3160 :         if (!copystring(&t, "# ", &len))
     368             :                 return base;
     369             : 
     370        3160 :         if (pci->argc == 3) {
     371        3156 :                 if (getFunctionId(pci)) {
     372        3156 :                         char arg[256];
     373        3156 :                         renderTerm(mb, stk, pci, 1, flg, arg, sizeof(arg));
     374        3156 :                         int a1 = atoi(arg);
     375        3156 :                         renderTerm(mb, stk, pci, 2, flg, arg, sizeof(arg));
     376        3156 :                         long a2 = atol(arg);
     377        3156 :                         const char *f = getFunctionId(pci);
     378        3156 :                         if (strcmp(f, "total") == 0)
     379         108 :                                 snprintf(aux, 128, "%d optimizers %ld usecs", a1, a2);
     380             :                         else
     381        3048 :                                 snprintf(aux, 128, "%-36s %d actions %ld usecs", f, a1, a2);
     382        3156 :                         (void) copystring(&t, aux, &len);
     383             :                 }
     384           4 :         } else if (pci->argc == 1) {
     385           4 :                 if (getFunctionId(pci)) {
     386           4 :                         if (!copystring(&t, getFunctionId(pci), &len))
     387             :                                 return base;
     388             :                 }
     389           0 :         } else if (getVar(mb, getArg(pci, 0))->value.val.sval &&
     390           0 :                            getVar(mb, getArg(pci, 0))->value.len > 0 &&
     391           0 :                            !copystring(&t, getVar(mb, getArg(pci, 0))->value.val.sval,
     392             :                                                    &len))
     393             :                 return base;
     394             : 
     395             :         return base;
     396             : }
     397             : 
     398             : str
     399      162707 : operatorName(int i)
     400             : {
     401      162707 :         switch (i) {
     402             :         case ASSIGNsymbol:
     403             :                 return ":=";
     404          20 :         case BARRIERsymbol:
     405          20 :                 return "barrier";
     406           0 :         case REDOsymbol:
     407           0 :                 return "redo";
     408           0 :         case LEAVEsymbol:
     409           0 :                 return "leave";
     410          12 :         case EXITsymbol:
     411          12 :                 return "exit";
     412           0 :         case RETURNsymbol:
     413           0 :                 return "return";
     414           0 :         case CATCHsymbol:
     415           0 :                 return "catch";
     416           0 :         case RAISEsymbol:
     417           0 :                 return "raise";
     418          36 :         case ENDsymbol:
     419          36 :                 return "end";
     420         212 :         case FUNCTIONsymbol:
     421         212 :                 return "function";
     422       25313 :         case COMMANDsymbol:
     423       25313 :                 return "command";
     424      137114 :         case PATTERNsymbol:
     425      137114 :                 return "pattern";
     426             : 
     427             :                 /* internal symbols */
     428             :         case FCNcall:
     429           0 :                 assert(0);
     430             :                 return "FCNcall";
     431             :         case CMDcall:
     432           0 :                 assert(0);
     433             :                 return "CMDcall";
     434             :         case PATcall:
     435           0 :                 assert(0);
     436             :                 return "PATcall";
     437             :         }
     438           0 :         return "";
     439             : }
     440             : 
     441             : str
     442        8603 : instruction2str(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int flg)
     443             : {
     444        8603 :         int i, j;
     445        8603 :         str base, t;
     446        8603 :         size_t len = 512 + (p->argc * 128);  /* max realistic line length estimate */
     447             : 
     448        8603 :         t = base = GDKmalloc(len);
     449        8606 :         if (base == NULL)
     450             :                 return NULL;
     451        8606 :         if (!flg) {
     452           1 :                 *t++ = '#';
     453           1 :                 len--;
     454           1 :                 if (!p->typeresolved) {
     455           0 :                         *t++ = '!';                     /* error */
     456           0 :                         len--;
     457             :                 }
     458             :         }
     459        8606 :         *t = 0;
     460        8606 :         if (p->token == REMsymbol
     461        3164 :                 && !(getModuleId(p) && strcmp(getModuleId(p), "querylog") == 0
     462           0 :                          && getFunctionId(p) && strcmp(getFunctionId(p), "define") == 0)) {
     463             :                 /* do nothing */
     464        5442 :         } else if (p->barrier) {
     465          28 :                 if (p->barrier == LEAVEsymbol ||
     466          28 :                         p->barrier == REDOsymbol ||
     467             :                         p->barrier == RETURNsymbol || p->barrier == RAISEsymbol) {
     468           0 :                         if (!copystring(&t, "    ", &len))
     469             :                                 return base;
     470             :                 }
     471          28 :                 if (!copystring(&t, operatorName(p->barrier), &len) || !copystring(&t, " ", &len))
     472           0 :                         return base;
     473        5414 :         } else if (functionStart(p) && flg != LIST_MAL_CALL) {
     474         150 :                 return fcnDefinition(mb, p, t, flg, base, len + (t - base));
     475        5264 :         } else if (!functionExit(p) && flg != LIST_MAL_CALL) {
     476             :                 // beautify with tabs
     477        5110 :                 if (!copystring(&t, "    ", &len))
     478             :                         return base;
     479             :         }
     480        8455 :         switch (p->token < 0 ? -p->token : p->token) {
     481        5138 :         case FCNcall:
     482             :         case PATcall:
     483             :         case CMDcall:
     484             :         case ASSIGNsymbol:
     485             :                 // is any variable explicit or used
     486             :                 /* this code was meant to make it easy to detect functions whose
     487             :                  * result variable was not used anywhere.
     488             :                  * It is not essential
     489             :                  for (i = 0; i < p->retc; i++)
     490             :                  if ( !isTmpVar(mb,getArg(p,i)) || isVarUsed(mb, getArg(p, i)))
     491             :                  break;
     492             : 
     493             :                  if (i == p->retc)
     494             :                  break;
     495             :                  */
     496             : 
     497             :                 /* display multi-assignment list */
     498        5138 :                 if (p->retc > 1 && !copystring(&t, "(", &len))
     499             :                         return base;
     500             : 
     501       10387 :                 for (i = 0; i < p->retc; i++) {
     502        5248 :                         char arg[256];
     503        5248 :                         renderTerm(mb, stk, p, i, flg, arg, sizeof(arg));
     504        5249 :                         if (!copystring(&t, arg, &len))
     505           0 :                                 return base;
     506        5249 :                         if (i < p->retc - 1 && !copystring(&t, ", ", &len))
     507             :                                 return base;
     508             :                 }
     509        5139 :                 if (p->retc > 1 && !copystring(&t, ")", &len))
     510             :                         return base;
     511             : 
     512        5139 :                 if (p->argc > p->retc || getFunctionId(p)) {
     513        5127 :                         if (!copystring(&t, " := ", &len))
     514             :                                 return base;
     515             :                 }
     516             :                 break;
     517         149 :         case ENDsymbol:
     518         298 :                 if (!copystring(&t, "end ", &len) ||
     519         298 :                         !copystring(&t, getModuleId(getInstrPtr(mb, 0)), &len) ||
     520         298 :                         !copystring(&t, ".", &len) ||
     521         149 :                         !copystring(&t, getFunctionId(getInstrPtr(mb, 0)), &len))
     522           0 :                         return base;
     523             :                 break;
     524           5 :         case COMMANDsymbol:
     525             :         case FUNCTIONsymbol:
     526             :         case PATTERNsymbol:
     527           5 :                 if (flg & LIST_MAL_VALUE) {
     528          10 :                         if (!copystring(&t, operatorName(p->token), &len) ||
     529           5 :                                 !copystring(&t, " ", &len))
     530           0 :                                 return base;
     531             :                 }
     532           5 :                 return fcnDefinition(mb, p, t, flg, base, len + (t - base));
     533        3160 :         case REMsymbol:
     534        3160 :                 return fmtRemark(mb, stk, p, t, flg, base, len);
     535           3 :         default:
     536           3 :                 i = snprintf(t, len, " unknown symbol ?%d? ", p->token);
     537           3 :                 if (i < 0 || (size_t) i >= len)
     538             :                         return base;
     539           3 :                 len -= (size_t) i;
     540           3 :                 t += i;
     541           3 :                 break;
     542             :         }
     543             : 
     544        5290 :         if (getModuleId(p)) {
     545        5127 :                 if (!copystring(&t, getModuleId(p), &len) || !copystring(&t, ".", &len))
     546           0 :                         return base;
     547             :         }
     548        5288 :         if (getFunctionId(p)) {
     549       10254 :                 if (!copystring(&t, getFunctionId(p), &len) ||
     550        5127 :                         !copystring(&t, "(", &len))
     551           0 :                         return base;
     552         161 :         } else if (p->argc > p->retc + 1) {
     553           0 :                 if (!copystring(&t, "(", &len))
     554             :                         return base;
     555             :         }
     556       23400 :         for (i = p->retc; i < p->argc; i++) {
     557       18112 :                 char arg[256];
     558       18112 :                 renderTerm(mb, stk, p, i, flg, arg, sizeof(arg));
     559       18112 :                 if (!copystring(&t, arg, &len))
     560           0 :                                 return base;
     561       18112 :                 if (i < p->argc - 1 && !copystring(&t, ", ", &len))
     562             :                         return base;
     563             :         }
     564        5288 :         if (getFunctionId(p) || p->argc > p->retc + 1) {
     565        5127 :                 if (!copystring(&t, ")", &len))
     566             :                         return base;
     567             :         }
     568        5288 :         if (p->token != REMsymbol) {
     569        5288 :                 if (!copystring(&t, ";", &len))
     570             :                         return base;
     571             :         }
     572             :         /* add the extra properties for debugging */
     573        5288 :         if (flg & LIST_MAL_PROPS) {
     574        2400 :                 char extra[256];
     575        2400 :                 if (p->token == REMsymbol) {
     576             :                 } else {
     577           1 :                         snprintf(extra, 256, "\t#[%d] (" BUNFMT ") %s ", p->pc,
     578        2400 :                                          getRowCnt(mb, getArg(p, 0)),
     579        2400 :                                          (p->blk ? p->blk->binding : ""));
     580        2400 :                         if (!copystring(&t, extra, &len))
     581           0 :                                 return base;
     582        4834 :                         for (j = 0; j < p->retc; j++) {
     583        2434 :                                 snprintf(extra, 256, "%d ", getArg(p, j));
     584        2434 :                                 if (!copystring(&t, extra, &len))
     585             :                                         return base;
     586             :                         }
     587        2400 :                         if (p->argc - p->retc > 0) {
     588        2397 :                                 if (!copystring(&t, "<- ", &len))
     589             :                                         return base;
     590             :                         }
     591       12061 :                         for (; j < p->argc; j++) {
     592        9661 :                                 snprintf(extra, 256, "%d ", getArg(p, j));
     593        9661 :                                 if (!copystring(&t, extra, &len))
     594             :                                         return base;
     595             :                         }
     596        2400 :                         if (!p->typeresolved) {
     597           0 :                                 if (!copystring(&t, " type check needed", &len))
     598             :                                         return base;
     599             :                         }
     600             :                 }
     601             :         }
     602        5288 :         if (flg & LIST_MAL_ALGO) {
     603         807 :                 const char *algo = MT_thread_getalgorithm();
     604         807 :                 if (algo) {
     605         122 :                         if (!copystring(&t, " # ", &len))
     606             :                                 return base;
     607         122 :                         if (!copystring(&t, algo, &len))
     608             :                                 return base;
     609             :                 }
     610             :         }
     611             :         return base;
     612             : }
     613             : 
     614             : /* the MAL beautifier is meant to simplify correlation of MAL variables and
     615             :  * the columns in the underlying database.
     616             :  * If the status is set, then we consider the instruction DONE and the result variables
     617             :  * should be shown as well.
     618             :  */
     619             : 
     620             : /* Remote execution of MAL calls for more type/property information to be exchanged */
     621             : str
     622           0 : mal2str(MalBlkPtr mb, int first, int last)
     623             : {
     624           0 :         str ps = NULL, *txt;
     625           0 :         int i, j;
     626           0 :         size_t *len, totlen = 0;
     627             : 
     628           0 :         txt = GDKmalloc(sizeof(str) * mb->stop);
     629           0 :         len = GDKmalloc(sizeof(size_t) * mb->stop);
     630             : 
     631           0 :         if (txt == NULL || len == NULL) {
     632           0 :                 addMalException(mb, "mal2str: " MAL_MALLOC_FAIL);
     633           0 :                 GDKfree(txt);
     634           0 :                 GDKfree(len);
     635           0 :                 return NULL;
     636             :         }
     637           0 :         for (i = first; i < last; i++) {
     638           0 :                 if (i == 0)
     639           0 :                         txt[i] = instruction2str(mb, 0, getInstrPtr(mb, i),
     640             :                                                                          LIST_MAL_NAME | LIST_MAL_TYPE |
     641             :                                                                          LIST_MAL_PROPS);
     642             :                 else
     643           0 :                         txt[i] = instruction2str(mb, 0, getInstrPtr(mb, i),
     644             :                                                                          LIST_MAL_CALL | LIST_MAL_PROPS |
     645             :                                                                          LIST_MAL_REMOTE);
     646             : 
     647           0 :                 if (txt[i])
     648           0 :                         totlen += len[i] = strlen(txt[i]);
     649             :                 else {
     650           0 :                         addMalException(mb, "mal2str: " MAL_MALLOC_FAIL);
     651           0 :                         GDKfree(len);
     652           0 :                         for (j = first; j < i; j++)
     653           0 :                                 GDKfree(txt[j]);
     654           0 :                         GDKfree(txt);
     655           0 :                         return NULL;
     656             :                 }
     657             :         }
     658           0 :         ps = GDKmalloc(totlen + mb->stop + 1);
     659           0 :         if (ps == NULL) {
     660           0 :                 addMalException(mb, "mal2str: " MAL_MALLOC_FAIL);
     661           0 :                 GDKfree(len);
     662           0 :                 for (i = first; i < last; i++)
     663           0 :                         GDKfree(txt[i]);
     664           0 :                 GDKfree(txt);
     665           0 :                 return NULL;
     666             :         }
     667             : 
     668             :         totlen = 0;
     669           0 :         for (i = first; i < last; i++) {
     670           0 :                 if (txt[i]) {
     671           0 :                         strncpy(ps + totlen, txt[i], len[i]);
     672           0 :                         ps[totlen + len[i]] = '\n';
     673           0 :                         ps[totlen + len[i] + 1] = 0;
     674           0 :                         totlen += len[i] + 1;
     675           0 :                         GDKfree(txt[i]);
     676             :                 }
     677             :         }
     678           0 :         GDKfree(len);
     679           0 :         GDKfree(txt);
     680           0 :         return ps;
     681             : }
     682             : 
     683             : void
     684        2689 : printInstruction(stream *fd, MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int flg)
     685             : {
     686        2689 :         str ps;
     687             : 
     688        2689 :         if (fd == 0)
     689             :                 return;
     690        2689 :         ps = instruction2str(mb, stk, p, flg);
     691             :         /* ps[strlen(ps)-1] = 0; remove '\n' */
     692        2689 :         if (ps) {
     693        2729 :                 mnstr_printf(fd, "%s%s", (flg & LIST_MAL_MAPI ? "=" : ""), ps);
     694        2689 :                 GDKfree(ps);
     695             :         } else {
     696           0 :                 mnstr_printf(fd, "#failed instruction2str()");
     697             :         }
     698        2689 :         mnstr_printf(fd, "\n");
     699             : }
     700             : 
     701             : void
     702    43899255 : traceInstruction(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int flg)
     703             : {
     704    43899255 :         str ps;
     705    43899255 :         TRC_DEBUG_IF(MAL_OPTIMIZER) {
     706           0 :                 ps = instruction2str(mb, stk, p, flg);
     707             :                 /* ps[strlen(ps)-1] = 0; remove '\n' */
     708           0 :                 if (ps) {
     709           0 :                         TRC_DEBUG_ENDIF(MAL_OPTIMIZER, "%s%s\n",
     710             :                                                         (flg & LIST_MAL_MAPI ? "=" : ""), ps);
     711           0 :                         GDKfree(ps);
     712             :                 } else {
     713           0 :                         TRC_DEBUG_ENDIF(MAL_OPTIMIZER, "Failed instruction2str()\n");
     714             :                 }
     715             :         }
     716    43899255 : }
     717             : 
     718             : void
     719           0 : printSignature(stream *fd, Symbol s, int flg)
     720             : {
     721           0 :         InstrPtr p;
     722           0 :         str txt;
     723             : 
     724           0 :         if (s->def == 0) {
     725           0 :                 mnstr_printf(fd, "missing definition of %s\n", s->name);
     726           0 :                 return;
     727             :         }
     728           0 :         txt = GDKzalloc(MAXLISTING);    /* some slack for large blocks */
     729           0 :         if (txt) {
     730           0 :                 p = getSignature(s);
     731           0 :                 (void) fcnDefinition(s->def, p, txt, flg, txt, MAXLISTING);
     732           0 :                 mnstr_printf(fd, "%s\n", txt);
     733           0 :                 GDKfree(txt);
     734             :         } else
     735           0 :                 mnstr_printf(fd, "printSignature: " MAL_MALLOC_FAIL);
     736             : }

Generated by: LCOV version 1.14