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