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 N.J. Nes, M.L. Kersten
15 : * 01/07/1996, 31/01/2002
16 : *
17 : * Input/Output module
18 : * The IO module provides simple @sc{ascii-io} rendering options.
19 : * It is modeled after the tuple formats, but does not
20 : * attempt to outline the results. Instead, it is geared at speed,
21 : * which also means that some functionality regarding the built-in
22 : * types is duplicated from the atoms definitions.
23 : *
24 : * A functional limited form of formatted printf is also provided.
25 : * It accepts at most one variable.
26 : * A more complete approach is the tablet module.
27 : *
28 : * The commands to load and save a BAT from/to an ASCII dump
29 : * are efficient, but work only for binary tables.
30 : */
31 :
32 : /*
33 : * Printing
34 : * The print commands are implemented as single instruction rules,
35 : * because they need access to the calling context.
36 : * At a later stage we can look into the issues related to
37 : * parsing the format string as part of the initialization phase.
38 : * The old method in V4 essentially causes a lot of overhead
39 : * because you have to prepare for the worst (e.g. mismatch format
40 : * identifier and argument value)
41 : * Beware, the types of the objects to be printed should be
42 : * obtained from the stack, because the symbol table may actually
43 : * allow for any type to be assigned.
44 : */
45 : #include "monetdb_config.h"
46 : #include "mal.h"
47 : #include "mal_instruction.h"
48 : #include "mal_interpreter.h"
49 : #include "mutils.h"
50 : #include "mal_exception.h"
51 :
52 : #define MAXFORMAT 64*1024
53 :
54 : static str
55 0 : io_stdin(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
56 : {
57 0 : bstream **ret = (bstream **) getArgReference(stk, pci, 0);
58 0 : (void) mb;
59 0 : if (cntxt->fdin == NULL)
60 0 : throw(MAL, "io.print", SQLSTATE(HY002) "Input channel missing");
61 0 : *ret = cntxt->fdin;
62 0 : return MAL_SUCCEED;
63 : }
64 :
65 : static str
66 0 : io_stdout(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
67 : {
68 0 : stream **ret = (stream **) getArgReference(stk, pci, 0);
69 0 : (void) mb;
70 0 : if (cntxt->fdout == NULL)
71 0 : throw(MAL, "io.print", SQLSTATE(HY002) "Output channel missing");
72 0 : *ret = cntxt->fdout;
73 0 : return MAL_SUCCEED;
74 : }
75 :
76 : static str
77 1355 : IOprintBoth(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int indx,
78 : str hd, str tl, int nobat)
79 : {
80 1355 : int tpe = getArgType(mb, pci, indx);
81 1355 : ptr val = getArgReference(stk, pci, indx);
82 1355 : stream *fp = cntxt->fdout;
83 :
84 1355 : (void) mb;
85 1355 : if (cntxt->fdout == NULL)
86 0 : throw(MAL, "io.print", SQLSTATE(HY002) "Output channel missing");
87 :
88 1355 : if (tpe == TYPE_any)
89 1 : tpe = stk->stk[pci->argv[indx]].vtype;
90 1355 : if (val == NULL || tpe == TYPE_void) {
91 2 : if (hd)
92 2 : mnstr_printf(fp, "%s", hd);
93 2 : mnstr_printf(fp, "nil");
94 2 : if (tl)
95 2 : mnstr_printf(fp, "%s", tl);
96 2 : return MAL_SUCCEED;
97 : }
98 1353 : if (isaBatType(tpe)) {
99 636 : BAT *b;
100 :
101 636 : if (is_bat_nil(*(bat *) val)) {
102 2 : if (hd)
103 2 : mnstr_printf(fp, "%s", hd);
104 2 : mnstr_printf(fp, "nil");
105 2 : if (tl)
106 2 : mnstr_printf(fp, "%s", tl);
107 2 : return MAL_SUCCEED;
108 : }
109 634 : b = BATdescriptor(*(bat *) val);
110 634 : if (b == NULL) {
111 0 : throw(MAL, "io.print", SQLSTATE(HY002) RUNTIME_OBJECT_MISSING);
112 : }
113 634 : if (nobat) {
114 0 : if (hd)
115 0 : mnstr_printf(fp, "%s", hd);
116 0 : mnstr_printf(fp, "<%s>", BBP_logical(b->batCacheid));
117 0 : if (tl)
118 0 : mnstr_printf(fp, "%s", tl);
119 : } else {
120 634 : BATprint(cntxt->fdout, b);
121 : }
122 634 : BBPunfix(b->batCacheid);
123 634 : return MAL_SUCCEED;
124 : }
125 717 : if (hd)
126 717 : mnstr_printf(fp, "%s", hd);
127 :
128 717 : if (ATOMextern(tpe))
129 440 : ATOMprint(tpe, *(ptr *) val, fp);
130 : else
131 277 : ATOMprint(tpe, val, fp);
132 :
133 717 : if (tl)
134 716 : mnstr_printf(fp, "%s", tl);
135 : return MAL_SUCCEED;
136 : }
137 :
138 : static str
139 1354 : IOprint_val(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
140 : {
141 1354 : int i;
142 1354 : str msg;
143 :
144 1354 : (void) cntxt;
145 1354 : if (p->argc == 2)
146 1353 : msg = IOprintBoth(cntxt, mb, stk, p, 1, "[ ", " ]\n", 0);
147 : else {
148 1 : msg = IOprintBoth(cntxt, mb, stk, p, 1, "[ ", 0, 1);
149 1 : if (msg)
150 : return msg;
151 1 : for (i = 2; i < p->argc - 1; i++)
152 0 : if ((msg = IOprintBoth(cntxt, mb, stk, p, i, ", ", 0, 1)) != NULL)
153 0 : return msg;
154 1 : msg = IOprintBoth(cntxt, mb, stk, p, i, ", ", "]\n", 1);
155 : }
156 : return msg;
157 :
158 : }
159 :
160 : /*
161 : * The IOprintf_() gets a format str, and a sequence of (ptr,int) parameters
162 : * containing values and their type numbers. The printf() proved to be a
163 : * great risk; people formatting badly their "%s" format strings were crashing
164 : * the kernel. This function will prevent you from doing so.
165 : *
166 : * New implementation that repeatedly invokes sprintf => hacking the va_alist
167 : * for using vfsprintf proved to be too compiler-dependent (OLD approach).
168 : */
169 : #define writemem(X1) \
170 : do { \
171 : if (dst+X1 > buf+size) { \
172 : ptrdiff_t offset = dst - buf; \
173 : char *tmp; \
174 : do { \
175 : size *= 2; \
176 : } while (dst+X1 > buf+size); \
177 : tmp = GDKrealloc(buf, size); \
178 : if (tmp == NULL) { \
179 : va_end(ap); \
180 : GDKfree(buf); \
181 : GDKfree(add); \
182 : throw(MAL, "io.printf", SQLSTATE(HY013) MAL_MALLOC_FAIL); \
183 : } \
184 : buf = tmp; \
185 : dst = buf + offset; \
186 : } \
187 : } while (0)
188 :
189 : #define m5sprintf(X1)\
190 : if (width > adds) {\
191 : str newadd;\
192 : newadd = GDKrealloc(add, width + 10);\
193 : if (newadd != NULL) {\
194 : adds = width + 10;\
195 : add = newadd;\
196 : }\
197 : }\
198 : n = snprintf(add, adds, meta, X1);\
199 : while (n < 0 || (size_t) n >= adds) {\
200 : size_t newadds;\
201 : str newadd;\
202 : \
203 : if (n >= 0) /* glibc 2.1 */\
204 : newadds = n + 1; /* precisely what is needed */\
205 : else /* glibc 2.0 */\
206 : newadds = n * 2; /* twice the old size */\
207 : \
208 : newadd = GDKrealloc(add, newadds);\
209 : if (newadd == NULL)\
210 : break;\
211 : \
212 : adds = newadds;\
213 : add = newadd;\
214 : n = snprintf(add, adds, meta, X1);\
215 : }
216 :
217 :
218 : static const char toofew_error[80] =
219 : OPERATION_FAILED " At least %d parameter(s) expected.\n";
220 : static const char format_error[80] =
221 : OPERATION_FAILED " Error in format before param %d.\n";
222 : static const char type_error[80] =
223 : OPERATION_FAILED " Illegal type in param %d.\n";
224 :
225 : #define return_error(x) \
226 : do { \
227 : GDKfree(buf); \
228 : GDKfree(add); \
229 : throw(MAL,"io.printf", x,argc); \
230 : } while (0)
231 :
232 : static const char niltext[4] = "nil";
233 :
234 : static str
235 139 : IOprintf_(str *res, str format, ...)
236 : {
237 139 : va_list ap;
238 139 : int n;
239 :
240 139 : int prec = 0, dotseen = 0, escaped = 0, type, size, argc = 1;
241 139 : size_t adds = 100, width = 0;
242 139 : char *add, *dst, *buf, *cur, *paramseen = NULL;
243 139 : char *p;
244 :
245 139 : if (format == NULL) {
246 0 : throw(MAL, "io.printf",
247 : ILLEGAL_ARGUMENT " NULL pointer passed as format.\n");
248 139 : } else if (strchr(format, '%') == NULL) {
249 31 : *res = GDKstrdup(format);
250 31 : if (*res == NULL)
251 0 : throw(MAL, "io.printf", SQLSTATE(HY013) MAL_MALLOC_FAIL);
252 : return MAL_SUCCEED;
253 : }
254 108 : buf = dst = (str) GDKmalloc(size = 80);
255 108 : if (buf == NULL)
256 0 : throw(MAL, "io.printf", SQLSTATE(HY013) MAL_MALLOC_FAIL);
257 108 : *res = NULL;
258 :
259 108 : add = GDKmalloc(adds);
260 108 : if (add == NULL) {
261 0 : GDKfree(buf);
262 0 : throw(MAL, "io.printf", SQLSTATE(HY013) MAL_MALLOC_FAIL);
263 : }
264 :
265 108 : va_start(ap, format);
266 1383 : for (cur = format; *cur; cur++) {
267 1276 : if (paramseen) {
268 130 : char meta[100];
269 130 : ptrdiff_t extra = 0;
270 130 : ptrdiff_t len;
271 :
272 130 : if (GDKisdigit(*cur)) {
273 10 : if (dotseen) {
274 2 : prec = 10 * prec + (*cur - '0');
275 : } else {
276 8 : width = 10 * width + (*cur - '0');
277 : }
278 15 : continue;
279 120 : } else if (dotseen == 0 && *cur == '.') {
280 2 : dotseen = 1;
281 2 : continue;
282 118 : } else if (cur == paramseen + 1
283 110 : && (*cur == '+' || *cur == '-' || *cur == ' ')) {
284 3 : continue;
285 115 : } else if (*cur == 'l') {
286 0 : cur++;
287 0 : if (*cur == 'l') {
288 0 : cur++;
289 : /* start of ll */
290 0 : extra = (cur - paramseen) - 2;
291 : }
292 : }
293 115 : if ((p = va_arg(ap, char *)) == NULL) {
294 1 : va_end(ap);
295 1 : return_error(toofew_error);
296 : }
297 114 : type = va_arg(ap, int);
298 114 : type = ATOMbasetype(type);
299 :
300 114 : len = 1 + (cur - paramseen);
301 114 : memcpy(meta, paramseen, len);
302 114 : meta[len] = 0;
303 114 : if (ATOMcmp(type, ATOMnilptr(type), p) == 0) {
304 : /* value is nil; attempt to print formatted 'nil'
305 : without generating %ls etc. */
306 : char *csrc, *ctrg = meta;
307 :
308 39 : for (csrc = paramseen; csrc < cur; csrc++) {
309 23 : if (*csrc == '.')
310 : break;
311 22 : if (GDKisdigit(*csrc) || *csrc == '-')
312 4 : *(++ctrg) = *csrc;
313 : }
314 17 : *(++ctrg) = 's';
315 17 : *(++ctrg) = 0;
316 34 : m5sprintf(niltext);
317 97 : } else if (strchr("cdiouxX", *cur) && !extra) {
318 78 : int ival;
319 :
320 78 : if (dotseen) {
321 0 : va_end(ap);
322 0 : return_error(format_error);
323 78 : } else if (type == TYPE_bte) {
324 3 : ival = (int) *(bte *) p;
325 : } else if (type == TYPE_sht) {
326 0 : ival = (int) *(sht *) p;
327 : } else if (type == TYPE_flt) {
328 0 : ival = (int) *(flt *) p;
329 : } else if (type == TYPE_lng) {
330 23 : goto largetypes;
331 : #ifdef HAVE_HGE
332 : } else if (type == TYPE_hge) {
333 : /* Does this happen?
334 : * If so, what do we have TODO ? */
335 0 : va_end(ap);
336 0 : return_error(type_error);
337 : #endif
338 : } else if (type == TYPE_int) {
339 52 : ival = *(int *) p;
340 : } else {
341 0 : va_end(ap);
342 0 : return_error(type_error);
343 : }
344 110 : m5sprintf(ival);
345 19 : } else if (strchr("diouxX", *cur)) {
346 : #ifdef NATIVE_WIN32
347 : ptrdiff_t i;
348 : #endif
349 0 : lng lval;
350 :
351 0 : if (dotseen) {
352 0 : va_end(ap);
353 0 : return_error(format_error);
354 : }
355 0 : largetypes:
356 23 : if (type == TYPE_bte) {
357 0 : lval = (lng) *(bte *) p;
358 23 : } else if (type == TYPE_sht) {
359 0 : lval = (lng) *(sht *) p;
360 : } else if (type == TYPE_int) {
361 0 : lval = (lng) *(int *) p;
362 : } else if (type == TYPE_flt) {
363 0 : lval = (lng) *(flt *) p;
364 : } else if (type == TYPE_dbl) {
365 0 : lval = (lng) *(dbl *) p;
366 : } else if (type == TYPE_lng) {
367 23 : lval = *(lng *) p;
368 : #ifdef HAVE_HGE
369 0 : } else if (type == TYPE_hge) {
370 : /* Does this happen?
371 : * If so, what do we have TODO ? */
372 0 : va_end(ap);
373 0 : return_error(type_error);
374 : #endif
375 : } else {
376 0 : va_end(ap);
377 0 : return_error(type_error);
378 : }
379 23 : if (!extra) {
380 23 : meta[len + 2] = meta[len];
381 23 : meta[len + 1] = meta[len - 1];
382 23 : meta[len] = 'l';
383 23 : meta[len - 1] = 'l';
384 23 : len += 2;
385 23 : extra = len - 3;
386 : }
387 : #ifdef NATIVE_WIN32
388 : for (i = len; i >= (extra + 2); i--) {
389 : meta[i + 1] = meta[i];
390 : }
391 : meta[extra] = 'I';
392 : meta[extra + 1] = '6';
393 : meta[extra + 2] = '4';
394 : #endif
395 46 : m5sprintf(lval);
396 19 : } else if (strchr("feEgG", *cur)) {
397 2 : dbl dval;
398 :
399 2 : if (type == TYPE_flt) {
400 2 : dval = (dbl) *(flt *) p;
401 0 : } else if (type == TYPE_dbl) {
402 0 : dval = *(dbl *) p;
403 : } else {
404 0 : va_end(ap);
405 0 : return_error(type_error);
406 : }
407 2 : width += (1 + prec);
408 4 : m5sprintf(dval);
409 17 : } else if (*cur == 's') {
410 17 : size_t length;
411 :
412 17 : if (extra) {
413 0 : va_end(ap);
414 0 : return_error(format_error);
415 17 : } else if (type != TYPE_str) {
416 0 : va_end(ap);
417 0 : return_error(type_error);
418 : }
419 17 : length = strLen(p);
420 17 : width++;
421 17 : prec++; /* account for '\0' */
422 17 : if (dotseen && (size_t) prec < length)
423 17 : length = (size_t) prec;
424 17 : if (length > width)
425 : width = length;
426 34 : m5sprintf(p);
427 : } else {
428 0 : va_end(ap);
429 0 : return_error(format_error);
430 : }
431 114 : width = strlen(add);
432 114 : writemem(width);
433 114 : memcpy(dst, add, width);
434 114 : dst += width;
435 114 : paramseen = NULL;
436 114 : argc++;
437 1146 : } else if (!escaped) {
438 1146 : if (*cur == '\\' || (*cur == '%' && cur[1] == '%')) {
439 : escaped = 1;
440 1146 : } else if (*cur == '%') {
441 : paramseen = cur;
442 : dotseen = prec = 0;
443 : width = 0;
444 : } else {
445 1031 : writemem(1);
446 1031 : *dst++ = *cur;
447 : }
448 : } else {
449 0 : escaped = 0;
450 0 : writemem(1);
451 0 : *dst++ = *cur;
452 : }
453 : }
454 :
455 : /*
456 : if ( va_arg(ap, char *) != NULL){
457 : GDKfree(buf);
458 : throw(MAL,"io.printf", "params %d and beyond ignored %s.\n",argc);
459 : }
460 : */
461 :
462 107 : writemem(1);
463 107 : va_end(ap);
464 107 : *dst = 0;
465 107 : *res = buf;
466 107 : GDKfree(add);
467 107 : return MAL_SUCCEED;
468 : }
469 :
470 : #define getArgValue(s,p,k) VALptr(&(s)->stk[(p)->argv[k]])
471 :
472 : #define G(X) getArgValue(stk,pci,X), getArgType(mb,pci,X)
473 :
474 : static str
475 139 : IOprintf(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
476 : {
477 139 : str *fmt = getArgReference_str(stk, pci, 1);
478 139 : str fmt2 = NULL;
479 139 : str msg = MAL_SUCCEED;
480 :
481 139 : (void) cntxt;
482 139 : (void) mb;
483 139 : switch (pci->argc) {
484 31 : case 2:
485 31 : msg = IOprintf_(&fmt2, *fmt);
486 31 : break;
487 103 : case 3:
488 103 : msg = IOprintf_(&fmt2, *fmt, G(2));
489 103 : break;
490 4 : case 4:
491 4 : msg = IOprintf_(&fmt2, *fmt, G(2), G(3));
492 4 : break;
493 0 : case 5:
494 0 : msg = IOprintf_(&fmt2, *fmt, G(2), G(3), G(4));
495 0 : break;
496 1 : case 6:
497 1 : msg = IOprintf_(&fmt2, *fmt, G(2), G(3), G(4), G(5));
498 1 : break;
499 0 : case 7:
500 0 : msg = IOprintf_(&fmt2, *fmt, G(2), G(3), G(4), G(5), G(6));
501 0 : break;
502 0 : case 8:
503 0 : msg = IOprintf_(&fmt2, *fmt, G(2), G(3), G(4), G(5), G(6), G(7));
504 0 : break;
505 0 : case 9:
506 0 : msg = IOprintf_(&fmt2, *fmt, G(2), G(3), G(4), G(5), G(6), G(7), G(8));
507 0 : break;
508 0 : case 10:
509 0 : msg = IOprintf_(&fmt2, *fmt, G(2), G(3), G(4), G(5), G(6), G(7), G(8),
510 0 : G(9));
511 0 : break;
512 0 : default:
513 0 : throw(MAL, "io.printf", "Too many arguments to io.printf");
514 : }
515 139 : if (msg == MAL_SUCCEED) {
516 138 : mnstr_printf(cntxt->fdout, "%s", fmt2);
517 138 : GDKfree(fmt2);
518 : }
519 : return msg;
520 : }
521 :
522 : static str
523 0 : IOprintfStream(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
524 : {
525 0 : str *fmt = getArgReference_str(stk, pci, 2);
526 0 : str fmt2 = NULL;
527 0 : stream *f = (stream *) getArgReference(stk, pci, 1);
528 0 : str msg = MAL_SUCCEED;
529 :
530 0 : (void) cntxt;
531 0 : (void) mb;
532 0 : switch (pci->argc) {
533 0 : case 3:
534 0 : msg = IOprintf_(&fmt2, *fmt);
535 0 : break;
536 0 : case 4:
537 0 : msg = IOprintf_(&fmt2, *fmt, G(3));
538 0 : break;
539 0 : case 5:
540 0 : msg = IOprintf_(&fmt2, *fmt, G(3), G(4));
541 0 : break;
542 0 : case 6:
543 0 : msg = IOprintf_(&fmt2, *fmt, G(3), G(4), G(5));
544 0 : break;
545 0 : case 7:
546 0 : msg = IOprintf_(&fmt2, *fmt, G(3), G(4), G(5), G(6));
547 0 : break;
548 0 : case 8:
549 0 : msg = IOprintf_(&fmt2, *fmt, G(3), G(4), G(5), G(6), G(7));
550 0 : break;
551 0 : case 9:
552 0 : msg = IOprintf_(&fmt2, *fmt, G(3), G(4), G(5), G(6), G(7), G(8));
553 0 : break;
554 0 : case 10:
555 0 : msg = IOprintf_(&fmt2, *fmt, G(3), G(4), G(5), G(6), G(7), G(8), G(9));
556 0 : break;
557 0 : case 11:
558 0 : msg = IOprintf_(&fmt2, *fmt, G(3), G(4), G(5), G(6), G(7), G(8), G(9),
559 0 : G(10));
560 0 : break;
561 0 : default:
562 0 : throw(MAL, "io.printf", "Too many arguments to io.printf");
563 : }
564 0 : if (msg == MAL_SUCCEED) {
565 0 : mnstr_printf(f, "%s", fmt2);
566 0 : GDKfree(fmt2);
567 : }
568 : return msg;
569 : }
570 :
571 : /*
572 : * The table printing routine implementations.
573 : * They merely differ in destination and order prerequisite
574 : */
575 : static str
576 53 : IOtable(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
577 : {
578 53 : BAT *piv[MAXPARAMS];
579 53 : int i;
580 53 : int tpe;
581 53 : ptr val;
582 :
583 53 : (void) cntxt;
584 53 : if (pci->retc != 1 || pci->argc < 2 || pci->argc >= MAXPARAMS)
585 0 : throw(MAL, "io.table",
586 : "INTERNAL ERROR" " assertion error retc %d argc %d", pci->retc,
587 : pci->argc);
588 :
589 53 : memset(piv, 0, sizeof(BAT *) * MAXPARAMS);
590 177 : for (i = 1; i < pci->argc; i++) {
591 124 : tpe = getArgType(mb, pci, i);
592 124 : val = getArgReference(stk, pci, i);
593 124 : if (!isaBatType(tpe)) {
594 0 : while (--i >= 1)
595 0 : BBPreclaim(piv[i]);
596 0 : throw(MAL, "io.table", ILLEGAL_ARGUMENT " BAT expected");
597 : }
598 124 : if ((piv[i] = BATdescriptor(*(bat *) val)) == NULL) {
599 0 : while (--i >= 1)
600 0 : BBPunfix(piv[i]->batCacheid);
601 0 : throw(MAL, "io.table", ILLEGAL_ARGUMENT " null BAT encountered");
602 : }
603 : }
604 : /* add materialized void column */
605 53 : piv[0] = BATdense(piv[1]->hseqbase, 0, BATcount(piv[1]));
606 53 : if (piv[0] == NULL) {
607 0 : for (i = 1; i < pci->argc; i++)
608 0 : BBPunfix(piv[i]->batCacheid);
609 0 : throw(MAL, "io.table", SQLSTATE(HY013) MAL_MALLOC_FAIL);
610 : }
611 53 : BATprintcolumns(cntxt->fdout, pci->argc, piv);
612 283 : for (i = 0; i < pci->argc; i++)
613 177 : BBPunfix(piv[i]->batCacheid);
614 : return MAL_SUCCEED;
615 : }
616 :
617 : static str
618 0 : IOsetmallocsuccesscount(void *res, lng *count)
619 : {
620 0 : (void) res;
621 0 : GDKsetmallocsuccesscount(*count);
622 0 : return MAL_SUCCEED;
623 : }
624 :
625 : #include "mel.h"
626 : mel_func mal_io_init_funcs[] = {
627 : pattern("io", "stdin", io_stdin, false, "return the input stream to the database client", args(1,1, arg("",bstream))),
628 : pattern("io", "stdout", io_stdout, false, "return the output stream for the database client", args(1,1, arg("",streams))),
629 : pattern("io", "print", IOprint_val, false, "Print a MAL value tuple .", args(1,3, arg("",void),argany("val",1),varargany("lst",0))),
630 : pattern("io", "print", IOtable, false, "BATs are printed with '#' for legend \nlines, and the BUNs on seperate lines \nbetween brackets, containing each to \ncomma separated values (head and tail). \nIf multiple BATs are passed for printing, \nprint() performs an implicit natural \njoin on the void head, producing a multi attribute table.", args(1,2, arg("",void),batvarargany("b1",0))),
631 : pattern("io", "print", IOprint_val, false, "Print a MAL value.", args(1,2, arg("",void),argany("val",1))),
632 : pattern("io", "print", IOprint_val, false, "Print a MAL value column .", args(1,2, arg("",void),batargany("val",1))),
633 : pattern("io", "printf", IOprintf, false, "Select default format ", args(1,3, arg("",void),arg("fmt",str),varargany("val",0))),
634 : pattern("io", "printf", IOprintf, false, "Select default format ", args(1,2, arg("",void),arg("fmt",str))),
635 : pattern("io", "printf", IOprintfStream, false, "Select default format ", args(1,4, arg("",void),arg("filep",streams),arg("fmt",str),varargany("val",0))),
636 : pattern("io", "printf", IOprintfStream, false, "Select default format ", args(1,3, arg("",void),arg("filep",streams),arg("fmt",str))),
637 : command("io", "setmallocsuccesscount", IOsetmallocsuccesscount, false, "Set number of mallocs that are allowed to succeed.", args(1,2, arg("",void),arg("count",lng))),
638 : { .imp=NULL }
639 : };
640 : #include "mal_import.h"
641 : #ifdef _MSC_VER
642 : #undef read
643 : #pragma section(".CRT$XCU",read)
644 : #endif
645 329 : LIB_STARTUP_FUNC(init_mal_io_mal)
646 329 : { mal_module("mal_io", NULL, mal_io_init_funcs); }
|