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

Generated by: LCOV version 1.14