LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_listing.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 215 337 63.8 %
Date: 2021-09-14 22:17:06 Functions: 7 10 70.0 %

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

Generated by: LCOV version 1.14