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

Generated by: LCOV version 1.14