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 - 2019 MonetDB B.V.
7 */
8
9/*
10 * author Martin Kersten
11 * Inspection
12 * This module introduces a series of commands that provide access
13 * to information stored within the interpreter data structures.
14 * It's primary use is debugging.
15 * In all cases, the pseudo BAT operation is returned that
16 * should be garbage collected after being used.
17 *
18 * The main performance drain would be to use a pseudo BAT directly to
19 * successively access it components. This can be avoided by first assigning
20 * the pseudo BAT to a variable.
21 */
22#include "monetdb_config.h"
23#include "inspect.h"
24
25static int
26pseudo(bat *ret, BAT *b, str X1,str X2, str X3) {
27 char buf[BUFSIZ];
28 snprintf(buf,BUFSIZ,"%s_%s_%s", X1,X2,X3);
29 if (BBPindex(buf) <= 0 && BBPrename(b->batCacheid, buf) != 0)
30 return -1;
31 if (BATroles(b,X2) != GDK_SUCCEED)
32 return -1;
33 *ret = b->batCacheid;
34 BBPkeepref(*ret);
35 return 0;
36}
37
38/*
39 * Symbol table
40 * Mal symbol table and environment analysis.
41 *
42 * Collect symbol table information in a series of BATs for analysis
43 * and display. Note, the elements are aligned using a counter,
44 * which makes it susceptable for intermediate updates
45 */
46
47str
48INSPECTgetAllFunctions(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
49{
50 Module s;
51 Symbol t;
52 int i, j;
53 Module* moduleList;
54 int length;
55 BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
56 bat *ret = getArgReference_bat(stk,pci,0);
57
58 (void) mb;
59 if (b == 0)
60 throw(MAL, "inspect.getgetFunctionId", SQLSTATE(HY001) MAL_MALLOC_FAIL);
61
62 getModuleList(&moduleList, &length);
63 if (moduleList == NULL)
64 goto bailout;
65 for(j = -1; j < length; j++) {
66 s = j < 0 ? cntxt->usermodule : moduleList[j];
67 for (i = 0; s && i < MAXSCOPE; i++) {
68 if (s->space[i]) {
69 for (t = s->space[i]; t; t = t->peer) {
70 InstrPtr sig = getSignature(t);
71 if (BUNappend(b, getFunctionId(sig), false) != GDK_SUCCEED)
72 goto bailout;
73 }
74 }
75 }
76 }
77 if (pseudo(ret,b,"view","symbol","function"))
78 goto bailout;
79 freeModuleList(moduleList);
80
81 return MAL_SUCCEED;
82 bailout:
83 BBPreclaim(b);
84 freeModuleList(moduleList);
85 throw(MAL, "inspect.getgetFunctionId", SQLSTATE(HY001) MAL_MALLOC_FAIL);
86}
87
88str
89INSPECTgetAllModules(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
90{
91 Module s;
92 Symbol t;
93 int i, j;
94 Module* moduleList;
95 int length;
96 BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
97 bat *ret = getArgReference_bat(stk,pci,0);
98
99 (void) mb;
100 if (b == 0)
101 throw(MAL, "inspect.getmodule", SQLSTATE(HY001) MAL_MALLOC_FAIL);
102
103 getModuleList(&moduleList, &length);
104 if (moduleList == NULL)
105 goto bailout;
106 for(j = -1; j < length; j++) {
107 s = j < 0 ? cntxt->usermodule : moduleList[j];
108 for (i = 0; s && i < MAXSCOPE; i++) {
109 if (s->space[i]) {
110 for (t = s->space[i]; t; t = t->peer) {
111 InstrPtr sig = getSignature(t);
112
113 if (BUNappend(b, getModuleId(sig), false) != GDK_SUCCEED)
114 goto bailout;
115 }
116 }
117 }
118 }
119 if (pseudo(ret,b,"view","symbol","module"))
120 goto bailout;
121 freeModuleList(moduleList);
122
123 return MAL_SUCCEED;
124 bailout:
125 freeModuleList(moduleList);
126 BBPreclaim(b);
127 throw(MAL, "inspect.getmodule", SQLSTATE(HY001) MAL_MALLOC_FAIL);
128}
129
130str
131INSPECTgetkind(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
132{
133 Module s;
134 Symbol t;
135 int i, j;
136 Module* moduleList;
137 int length;
138 BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
139 bat *ret = getArgReference_bat(stk,pci,0);
140
141 (void)mb;
142 if (b == 0)
143 throw(MAL, "inspect.get", SQLSTATE(HY001) MAL_MALLOC_FAIL);
144
145 getModuleList(&moduleList, &length);
146 if (moduleList == NULL)
147 goto bailout;
148 for(j = -1; j < length; j++) {
149 s = j < 0 ? cntxt->usermodule : moduleList[j];
150 for (i = 0; s && i < MAXSCOPE; i++) {
151 if (s->space[i]) {
152 for (t = s->space[i]; t; t = t->peer) {
153 InstrPtr sig = getSignature(t);
154 str kind = operatorName(sig->token);
155 if (BUNappend(b, kind, false) != GDK_SUCCEED)
156 goto bailout;
157 }
158 }
159 }
160 }
161 if (pseudo(ret,b,"view","symbol","kind"))
162 goto bailout;
163 freeModuleList(moduleList);
164
165 return MAL_SUCCEED;
166 bailout:
167 BBPreclaim(b);
168 freeModuleList(moduleList);
169 throw(MAL, "inspect.get", SQLSTATE(HY001) MAL_MALLOC_FAIL);
170}
171
172
173str
174INSPECTgetAllSignatures(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
175{
176 Module s;
177 Symbol t;
178 int i, j;
179 Module* moduleList;
180 int length;
181 BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
182 char sig[BLOCK],*a;
183 bat *ret = getArgReference_bat(stk,pci,0);
184
185 (void)mb;
186 if (b == 0)
187 throw(MAL, "inspect.get", SQLSTATE(HY001) MAL_MALLOC_FAIL);
188
189 getModuleList(&moduleList, &length);
190 if (moduleList == NULL)
191 goto bailout;
192 for(j = -1; j < length; j++) {
193 s = j < 0 ? cntxt->usermodule : moduleList[j];
194 for (i = 0; s && i < MAXSCOPE; i++)
195 if (s->space[i]) {
196 for (t = s->space[i]; t; t = t->peer) {
197 fcnDefinition(t->def, getSignature(t), sig, 0,sig,BLOCK);
198 a= strstr(sig,"address");
199 if(a) *a = 0;
200 if (BUNappend(b, (a = strchr(sig, '(')) ? a : "", false) != GDK_SUCCEED)
201 goto bailout;
202 }
203 }
204 }
205 if (pseudo(ret,b,"view"," symbol","address"))
206 goto bailout;
207 freeModuleList(moduleList);
208
209 return MAL_SUCCEED;
210 bailout:
211 BBPreclaim(b);
212 freeModuleList(moduleList);
213 throw(MAL, "inspect.get", SQLSTATE(HY001) MAL_MALLOC_FAIL);
214}
215str
216INSPECTgetAllAddresses(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
217{
218 Module s;
219 Symbol t;
220 int i, j;
221 Module* moduleList;
222 int length;
223 BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
224 char sig[BLOCK],*a;
225 bat *ret = getArgReference_bat(stk,pci,0);
226
227 (void)mb;
228
229 if (b == 0)
230 throw(MAL, "inspect.get", SQLSTATE(HY001) MAL_MALLOC_FAIL);
231
232 getModuleList(&moduleList, &length);
233 if (moduleList == NULL)
234 goto bailout;
235 for(j = -1; j < length; j++) {
236 s = j < 0 ? cntxt->usermodule : moduleList[j];
237 for (i = 0; s && i < MAXSCOPE; i++)
238 if (s->space[i]) {
239 for (t = s->space[i]; t; t = t->peer) {
240 fcnDefinition(t->def, getSignature(t), sig, 0,sig,BLOCK);
241 a= strstr(sig,"address");
242 if( a)
243 for( a=a+7; isspace((unsigned char) *a); a++)
244 ;
245 if (BUNappend(b, (a? a: "nil"), false) != GDK_SUCCEED)
246 goto bailout;
247 }
248 }
249 }
250 if (pseudo(ret,b,"view"," symbol","address"))
251 goto bailout;
252 freeModuleList(moduleList);
253
254 return MAL_SUCCEED;
255 bailout:
256 BBPreclaim(b);
257 freeModuleList(moduleList);
258 throw(MAL, "inspect.get", SQLSTATE(HY001) MAL_MALLOC_FAIL);
259}
260
261str
262INSPECTgetDefinition(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
263{
264 bat *ret = getArgReference_bat(stk,pci,0);
265 str *mod = getArgReference_str(stk,pci,1);
266 str *fcn = getArgReference_str(stk,pci,2);
267 Symbol s;
268 BAT *b;
269 (void)mb;
270
271 s = findSymbol(cntxt->usermodule, putName(*mod), putName(*fcn));
272 if (s == 0)
273 throw(MAL, "inspect.getDefinition", RUNTIME_SIGNATURE_MISSING);
274
275 b = COLnew(0, TYPE_str, 256, TRANSIENT);
276 if (b == 0)
277 throw(MAL, "inspect.getDefinition", SQLSTATE(HY001) MAL_MALLOC_FAIL);
278
279 while (s) {
280 int i;
281 str ps;
282
283 for (i = 0; i < s->def->stop; i++) {
284 if((ps = instruction2str(s->def,0, getInstrPtr(s->def, i), 0)) == NULL)
285 goto bailout;
286 if (BUNappend(b, ps + 1, false) != GDK_SUCCEED) {
287 GDKfree(ps);
288 goto bailout;
289 }
290 GDKfree(ps);
291 }
292 s = s->peer;
293 }
294 if (pseudo(ret,b,"view","fcn","stmt"))
295 goto bailout;
296
297 return MAL_SUCCEED;
298 bailout:
299 BBPreclaim(b);
300 throw(MAL, "inspect.getDefinition", SQLSTATE(HY001) MAL_MALLOC_FAIL);
301}
302
303str
304INSPECTgetSignature(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
305{
306 bat *ret = getArgReference_bat(stk,pci,0);
307 str *mod = getArgReference_str(stk,pci,1);
308 str *fcn = getArgReference_str(stk,pci,2);
309 Symbol s;
310 str ps, tail;
311 BAT *b;
312 (void) mb;
313
314 s = findSymbol(cntxt->usermodule, getName(*mod), putName(*fcn));
315 if (s == 0)
316 throw(MAL, "inspect.getSignature", RUNTIME_SIGNATURE_MISSING);
317 b = COLnew(0, TYPE_str, 12, TRANSIENT);
318 if (b == 0)
319 throw(MAL, "inspect.getSignature", SQLSTATE(HY001) MAL_MALLOC_FAIL);
320
321 while (s != NULL) {
322 if (idcmp(s->name, *fcn) == 0) {
323 char *c, *w;
324
325 ps = instruction2str(s->def, 0, getSignature(s), 0);
326 if (ps == 0) {
327 continue;
328 }
329 c = strchr(ps, '(');
330 if (c == 0) {
331 GDKfree(ps);
332 continue;
333 }
334 tail= strstr(c,"address");
335 if( tail)
336 *tail = 0;
337 if (tail && (w=strchr(tail, ';')) )
338 *w = 0;
339 if (BUNappend(b, c, false) != GDK_SUCCEED) {
340 GDKfree(ps);
341 goto bailout;
342 }
343 GDKfree(ps);
344 }
345 s = s->peer;
346 }
347
348 if (pseudo(ret,b,"view","input","result"))
349 goto bailout;
350 return MAL_SUCCEED;
351 bailout:
352 BBPreclaim(b);
353 throw(MAL, "inspect.getSignature", SQLSTATE(HY001) MAL_MALLOC_FAIL);
354}
355
356str
357INSPECTgetAddress(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
358{
359 bat *ret = getArgReference_bat(stk,pci,0);
360 str *mod = getArgReference_str(stk,pci,1);
361 str *fcn = getArgReference_str(stk,pci,2);
362 Symbol s;
363 str ps, tail;
364 BAT *b;
365 (void) mb;
366
367 s = findSymbol(cntxt->usermodule, getName(*mod), putName(*fcn));
368 if (s == 0)
369 throw(MAL, "inspect.getAddress", RUNTIME_SIGNATURE_MISSING);
370 b = COLnew(0, TYPE_str, 12, TRANSIENT);
371 if (b == 0)
372 throw(MAL, "inspect.getAddress", SQLSTATE(HY001) MAL_MALLOC_FAIL);
373
374 while (s != NULL) {
375 if (idcmp(s->name, *fcn) == 0) {
376 char *c,*w;
377
378 ps = instruction2str(s->def, 0, getSignature(s), 0);
379 if(ps == NULL)
380 continue;
381 c = strchr(ps, '(');
382 if (c == 0) {
383 GDKfree(ps);
384 continue;
385 }
386 tail= strstr(c,"address");
387 if( tail){
388 *tail = 0;
389 for( tail=tail+7; isspace((unsigned char) *tail); tail++) ;
390 }
391 if (tail && (w=strchr(tail, ';')) )
392 *w = 0;
393 if (BUNappend(b, (tail? tail: "nil"), false) != GDK_SUCCEED) {
394 GDKfree(ps);
395 goto bailout;
396 }
397 GDKfree(ps);
398 }
399 s = s->peer;
400 }
401
402 if (pseudo(ret,b,"view","input","result"))
403 goto bailout;
404 return MAL_SUCCEED;
405 bailout:
406 BBPreclaim(b);
407 throw(MAL, "inspect.getAddress", SQLSTATE(HY001) MAL_MALLOC_FAIL);
408}
409str
410INSPECTgetComment(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
411{
412 bat *ret = getArgReference_bat(stk,pci,0);
413 str *mod = getArgReference_str(stk,pci,1);
414 str *fcn = getArgReference_str(stk,pci,2);
415 Symbol s;
416 BAT *b;
417 (void) mb;
418
419 s = findSymbol(cntxt->usermodule, getName(*mod), putName(*fcn));
420 if (s == 0)
421 throw(MAL, "inspect.getComment", RUNTIME_SIGNATURE_MISSING);
422 b = COLnew(0, TYPE_str, 12, TRANSIENT);
423 if (b == 0)
424 throw(MAL, "inspect.getComment", SQLSTATE(HY001) MAL_MALLOC_FAIL);
425
426 while (s != NULL) {
427 if (idcmp(s->name, *fcn) == 0 &&
428 BUNappend(b, s->def->help, false) != GDK_SUCCEED)
429 goto bailout;
430 s = s->peer;
431 }
432
433 if (pseudo(ret,b,"view","input","result"))
434 goto bailout;
435 return MAL_SUCCEED;
436 bailout:
437 BBPreclaim(b);
438 throw(MAL, "inspect.getComment", SQLSTATE(HY001) MAL_MALLOC_FAIL);
439}
440
441str
442INSPECTgetSource(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
443{
444 str *ret = getArgReference_str(stk,pci,0);
445 str *mod = getArgReference_str(stk,pci,1);
446 str *fcn = getArgReference_str(stk,pci,2);
447 Symbol s;
448 char *buf;
449 size_t len,lim;
450 (void) mb;
451
452 s = findSymbol( cntxt->usermodule, getName(*mod), putName(*fcn));
453 if (s == 0)
454 throw(MAL, "inspect.getSource", RUNTIME_SIGNATURE_MISSING);
455
456 buf= (char*) GDKmalloc(BUFSIZ);
457 if ( buf == NULL)
458 throw(MAL, "inspect.getSource", SQLSTATE(HY001) MAL_MALLOC_FAIL);
459 snprintf(buf,BUFSIZ,"%s.%s",*mod,*fcn);
460 buf[0]=0;
461 len= 0;
462 lim= BUFSIZ;
463
464 while (s) {
465 int i;
466 str ps;
467
468 for (i = 0; i < s->def->stop; i++) {
469 if((ps = instruction2str(s->def, 0, getInstrPtr(s->def, i), LIST_MAL_NAME )) == NULL) {
470 GDKfree(buf);
471 throw(MAL, "inspect.getSource", SQLSTATE(HY001) MAL_MALLOC_FAIL);
472 }
473 if( strlen(ps) >= lim-len){
474 /* expand the buffer */
475 char *bn;
476 bn= GDKrealloc(buf, lim+BUFSIZ);
477 if ( bn == NULL) {
478 GDKfree(ps);
479 GDKfree(buf);
480 throw(MAL, "inspect.getSource", SQLSTATE(HY001) MAL_MALLOC_FAIL);
481 }
482 buf=bn;
483 lim+= BUFSIZ;
484 }
485 strcat(buf+len,ps);
486 len+= strlen(ps);
487 buf[len++]='\n';
488 buf[len]=0;
489 GDKfree(ps);
490 }
491 s = s->peer;
492 }
493 *ret= buf;
494 return MAL_SUCCEED;
495}
496
497str
498INSPECTatom_names(bat *ret)
499{
500 int i;
501 BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
502
503 if (b == 0)
504 throw(MAL, "inspect.getAtomNames", SQLSTATE(HY001) MAL_MALLOC_FAIL);
505
506 for (i = 0; i < GDKatomcnt; i++)
507 if (BUNappend(b, ATOMname(i), false) != GDK_SUCCEED)
508 goto bailout;
509
510 if (pseudo(ret,b,"view","atom","name"))
511 goto bailout;
512
513 return MAL_SUCCEED;
514 bailout:
515 BBPreclaim(b);
516 throw(MAL, "inspect.getAtomNames", SQLSTATE(HY001) MAL_MALLOC_FAIL);
517}
518str
519INSPECTgetEnvironment(bat *ret, bat *ret2)
520{
521 BAT *k, *v;
522
523 if (GDKcopyenv(&k, &v, false) != GDK_SUCCEED)
524 throw(MAL, "inspect.getEnvironment", GDK_EXCEPTION);
525
526 BBPkeepref(*ret = k->batCacheid);
527 BBPkeepref(*ret2 = v->batCacheid);
528 return MAL_SUCCEED;
529}
530
531str
532INSPECTgetEnvironmentKey(str *ret, str *key)
533{
534 const char *s;
535 *ret = 0;
536
537 s= GDKgetenv(*key);
538 if (s == 0)
539 s= getenv(*key);
540 if (s == 0)
541 throw(MAL, "inspect.getEnvironment", "environment variable '%s' not found", *key);
542 *ret = GDKstrdup(s);
543 if (*ret == NULL)
544 throw(MAL, "inspect.getEnvironment", SQLSTATE(HY001) MAL_MALLOC_FAIL);
545 return MAL_SUCCEED;
546}
547
548str
549INSPECTatom_sup_names(bat *ret)
550{
551 int i, k;
552 BAT *b = COLnew(0, TYPE_str, 256, TRANSIENT);
553
554 if (b == 0)
555 throw(MAL, "inspect.getAtomSuper", SQLSTATE(HY001) MAL_MALLOC_FAIL);
556
557 for (i = 0; i < GDKatomcnt; i++) {
558 for (k = ATOMstorage(i); k > TYPE_str; k = ATOMstorage(k))
559 ;
560 if (BUNappend(b, ATOMname(k), false) != GDK_SUCCEED)
561 goto bailout;
562 }
563
564 if (pseudo(ret,b,"view","atom","sup_name"))
565 goto bailout;
566
567 return MAL_SUCCEED;
568 bailout:
569 BBPreclaim(b);
570 throw(MAL, "inspect.getAtomSuper", SQLSTATE(HY001) MAL_MALLOC_FAIL);
571}
572
573str
574INSPECTatom_sizes(bat *ret)
575{
576 int i;
577 int s;
578 BAT *b = COLnew(0, TYPE_int, 256, TRANSIENT);
579
580 if (b == 0)
581 throw(MAL, "inspect.getAtomSizes", SQLSTATE(HY001) MAL_MALLOC_FAIL);
582
583 for (i = 0; i < GDKatomcnt; i++) {
584 s = ATOMsize(i);
585 if (BUNappend(b, &s, false) != GDK_SUCCEED)
586 goto bailout;
587 }
588
589 if (pseudo(ret,b,"view","atom","size"))
590 goto bailout;
591
592 return MAL_SUCCEED;
593 bailout:
594 BBPreclaim(b);
595 throw(MAL, "inspect.getAtomSizes", SQLSTATE(HY001) MAL_MALLOC_FAIL);
596}
597
598/* calculate to trimmed storage space */
599static lng
600INSPECTcalcSize(MalBlkPtr mb){
601 lng size,args=0,i;
602 InstrPtr p;
603
604 for(i=0;i<mb->stop; i++){
605 p= getInstrPtr(mb,i);
606 args += (p->argc-1)* sizeof(*p->argv);
607 }
608 size = (offsetof(InstrRecord, argv) +sizeof(InstrPtr)) * mb->stop;
609 size += sizeof(VarRecord) * mb->vtop;
610 size += args;
611 return size;
612}
613
614str
615INSPECTgetSize(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p){
616 lng *ret = getArgReference_lng(stk,p,0);
617
618
619 *ret= INSPECTcalcSize(mb);
620 (void) cntxt;
621 (void) mb;
622 return MAL_SUCCEED;
623}
624
625str
626INSPECTgetFunctionSize(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
627{
628 lng *ret = getArgReference_lng(stk,pci,0);
629 str *mod = getArgReference_str(stk,pci,1);
630 str *fcn = getArgReference_str(stk,pci,2);
631 Symbol s;
632 (void) mb;
633
634 s = findSymbol(cntxt->usermodule, getName(*mod), putName(*fcn));
635 if (s == 0)
636 throw(MAL, "inspect.getSize", RUNTIME_SIGNATURE_MISSING);
637 *ret= INSPECTcalcSize(s->def);
638 return MAL_SUCCEED;
639}
640/*
641 * Display routines
642 */
643str
644INSPECTshowFunction(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
645{
646 (void) p;
647 printFunction(cntxt->fdout, mb, stk, LIST_INPUT);
648 return MAL_SUCCEED;
649}
650
651str
652INSPECTshowFunction3(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
653{
654 str modnme = getArgName(mb, p, 1);
655 str fcnnme = getArgName(mb, p, 2);
656 Symbol s = NULL;
657
658 s = findSymbol(cntxt->usermodule,getName(modnme), putName(fcnnme));
659
660 if (s == NULL){
661 char buf[BUFSIZ];
662 snprintf(buf,BUFSIZ,"%s.%s", modnme, fcnnme);
663 throw(MAL, "inspect.showSource",RUNTIME_SIGNATURE_MISSING "%s",buf);
664 } else
665 printFunction(cntxt->fdout, s->def, stk, LIST_INPUT);
666 return MAL_SUCCEED;
667}
668
669str
670INSPECTequalType(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
671{
672 bit *ret;
673 (void) stk;
674 (void) cntxt;
675 ret = getArgReference_bit(stk, pci, 0);
676 *ret = getArgType(mb,pci,1)== getArgType(mb,pci,2);
677 return MAL_SUCCEED;
678}
679
680str
681INSPECTtypeName(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
682{
683 str *hn, *tn =0;
684
685 hn = getArgReference_str(stk, pci, 0);
686
687 (void) cntxt;
688 if( pci->retc== 2){
689 tn = getArgReference_str(stk, pci, 1);
690 *hn = getTypeName(TYPE_oid);
691 *tn = getTypeName(getBatType(getArgType(mb, pci, 2)));
692 } else if (isaBatType(getArgType(mb,pci,1) ) ){
693 bat *bid= getArgReference_bat(stk,pci,1);
694 BAT *b;
695 if ((b = BATdescriptor(*bid)) ) {
696 *hn = getTypeName(newBatType(b->ttype));
697 BBPunfix(b->batCacheid);
698 } else
699 *hn = getTypeName(getArgType(mb, pci, 1));
700 } else
701 *hn = getTypeName(getArgType(mb, pci, 1));
702 return MAL_SUCCEED;
703}
704