📄 mal_io.mx
字号:
@' The contents of this file are subject to the MonetDB Public License@' Version 1.1 (the "License"); you may not use this file except in@' compliance with the License. You may obtain a copy of the License at@' http://monetdb.cwi.nl/Legal/MonetDBLicense-1.1.html@'@' Software distributed under the License is distributed on an "AS IS"@' basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the@' License for the specific language governing rights and limitations@' under the License.@'@' The Original Code is the MonetDB Database System.@'@' The Initial Developer of the Original Code is CWI.@' Portions created by CWI are Copyright (C) 1997-2007 CWI.@' All Rights Reserved.@f mal_io@a N.J. Nes, M.L. Kersten@d 01/07/1996, 31/01/2002@+ Input/Output moduleThe IO module provides simple ASCII-io rendering options.It is modeled after the tuple formats, but does notattempt to outline the results. Instead, it is geared at speed,which also means that some functionality regarding the built-intypes is duplicated from the atoms definitions.A functional limited form of formatted printf is also provided.It accepts at most one variable.A more complete approach is the tablet module.The commands to load and save a BAT from/to an ASCII dumpare efficient, but work only for binary tables. @malmodule io;command stdin():bstreamaddress io_stdincomment "return the input stream to the database client";command stderr():streamsaddress io_stderrcomment "return the error stream for the database console";command stdout():streamsaddress io_stdoutcomment "return the output stream for the database client";pattern print(val:any_1,lst:any...):void address IOprint_valcomment "Print a MAL value tuple .";pattern print(b1:bat[:any_1,:any]...):void address IOtablecomment "BATs are printed with '#' for legend lines, and the BUNs on seperate lines between brackets, containing each to comma separated values (head and tail). If multiple BATs are passed for printing, print() performs an implicit natural join, producing a multi attribute table.";pattern ftable( filep:streams, b1:bat[:any_1,:any], b:bat[:any_1,:any]... ):voidaddress IOftable comment "Print an n-ary table to a file.";pattern print(order:int,b:bat[:any_1,:any], b2:bat[:any_1,:any]...):voidaddress IOotablecomment "The same as normal table print, but enforces to use the order of BAT number [1..argc] to do the printing.";pattern table(b1:bat[:any_1,:any], b2:bat[:any_1,:any]...):void address IOttablecomment "Print an n-ary table. Like print, but does not print oid column";pattern table(order:int, b1:bat[:any_1,:any], b2:bat[:any_1,:any]...):void address IOtotablecomment "Print an n-ary table.";pattern ftable(fp:streams, order:int, b1:bat[:any_1,:any], b:bat[:any_1,:any]...):voidaddress IOfotable comment "Print an n-ary table to a file.";pattern print(val:any_1):void address IOprint_valcomment "Print a MAL value tuple .";pattern print(val:bat[:any_1,:any_2]):void address IOprint_valcomment "Print a MAL value tuple .";pattern prompt(val:any_1):void address IOprompt_valcomment "Print a MAL value without brackets.";pattern printft(val:any_1):void address IOprint_ftcomment "Select default format ";command printf(format:str,val:bit):voidaddress IOprint_formatted_bit;command printf(format:str,val:chr):voidaddress IOprint_formatted_chr;command printf(format:str,val:int):voidaddress IOprint_formatted_int;command printf(format:str,val:sht):voidaddress IOprint_formatted_sht;command printf(format:str,val:oid):voidaddress IOprint_oid;command printf(format:str,val:lng):voidaddress IOprint_formatted_lng;command printf(format:str,val:flt):voidaddress IOprint_formatted_flt;command printf(format:str,val:dbl):voidaddress IOprint_formatted_dbl;command printf(val:str):voidaddress IOprint_str;command printf(format:str,val:str):voidaddress IOprint_formatted_str;command export(b:bat[:any_1,:any_2], filepath:str):bit address IOexportcomment "Export a BAT as ASCII to a file. If the 'filepath' is not absolute, it is put into the .../dbfarm/$DB directory. Success of failure is indicated.";command import(b:bat[:any_1,:any_2], filepath:str) :bat[:any_1,:any_2] address IOimportcomment "Import a BAT from an ASCII dump. The new tuples are *inserted* into the parameter BAT. You have to create it! Its signature must match the dump, else parsing errors will occur and FALSE is returned.";@-@{@* Implementation CodeThe polymorphic print commands are collected here.Watch out, the order of definitions is crucial, because the mostspecific should be introduced last.@h#ifndef _PRINT_H_#define _PRINT_H_#include <mal.h>#include <mal_interpreter.h>#include <blob.h>typedef struct { int up, down;} bipipe;typedef FILE *fstream;#define fileCheck(fp) if (!fp) \ throw(MAL, "io.@1","Incorrect file pointer");#ifdef WIN32#ifndef LIBMAL_IO#define io_export extern __declspec(dllimport)#else#define io_export extern __declspec(dllexport)#endif#else#define io_export extern#endifio_export str IOprint_tables(MalBlkPtr mb, MalStkPtr stk, InstrPtr p);io_export str IOtableAll(stream *f, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci,int i, int order, int printhead, int printorderby);io_export str IOprintBoth(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int indx,str hd, str tl, int nobat);io_export str IOprint_formatted_nil(stream *fd, str format, char last);io_export str IOprintBoth(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int indx,str hd, str tl, int nobat);io_export str IOprint_val(MalBlkPtr mb, MalStkPtr stk, InstrPtr p);io_export str IOprint_tables(MalBlkPtr mb, MalStkPtr stk, InstrPtr p);io_export str IOprompt_val(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);io_export str IOprint_ft(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);io_export str IOtableAll(stream *f, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci,int i, int order, int printhead, int printorder);io_export str IOotable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);io_export str IOtable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);io_export str IOfotable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);io_export str IOftable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);io_export str IOttable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);io_export str IOtotable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);io_export str IOprint_str(int *ret, str *s);io_export str IOprint_formatted_nil(stream *fd, str format, char last);io_export str IOprint_formatted_lng(int *ret, str *format, lng *val);io_export str IOprint_formatted_str(int *ret, ptr fmt, str *s);io_export str IOprint_oid(int *ret, ptr fmt, oid *s);io_export str IOprint_formatted_bit(int *ret, ptr fmt, bit *s);io_export str IOexport(int *ret, int *bid, str *fnme);io_export str IOimport(int *ret, int *bid, str *fnme);io_export str io_stdin(bstream **ret);io_export str io_stdout(stream **ret);io_export str io_stderr(stream **ret);#endif /* _PRINT_H_ */@+ PrintingThe print commands are implemented as single instruction rules,because they need access to the calling context.At a later stage we can look into the issues related toparsing the format string as part of the initialization phase.The old method in V4 essentially causes a lot of overheadbecause you have to prepare for the worst (e.g. mismatch formatidentifier and argument value)Beware, the types of the objects to be printed should beobtained from the stack, because the symbol table may actuallyallow for any type to be assigned.@c#include "mal_config.h"#include "mal_io.h"strio_stdin(bstream **ret){ *ret = (bstream*)GDKin; return MAL_SUCCEED;}strio_stdout(stream **ret){ *ret = GDKout; return MAL_SUCCEED;}strio_stderr(stream **ret){ *ret = GDKerr; return MAL_SUCCEED;}strIOprintBoth(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int indx, str hd, str tl, int nobat){ int tpe = getArgType(mb, pci, indx); ptr val = (ptr) getArgReference(stk, pci, indx); stream *fp = GDKout; (void) mb; if (tpe == TYPE_any) tpe = stk->stk[pci->argv[indx]].vtype; if (val == NULL || tpe == TYPE_void) { if (hd) stream_printf(fp, "%s", hd); stream_printf(fp, "nil"); if (tl) stream_printf(fp, "%s", tl); return MAL_SUCCEED; } if (isaBatType(tpe) ) { BAT *b; if (*(int *) val == 0) { if (hd) stream_printf(fp, "%s", hd); stream_printf(fp,"nil"); if (tl) stream_printf(fp, "%s", tl); return MAL_SUCCEED; } b = BATdescriptor(*(int *) val); if (b == NULL) { throw(MAL, "io.print", "Could not access descriptor"); } if (nobat) { if (hd) stream_printf(fp, "%s", hd); stream_printf(fp, "<%s>", BBPname(b->batCacheid)); if (tl) stream_printf(fp, "%s", tl); } else BATmultiprintf(GDKout, 2, &b, TRUE, 0, TRUE); BBPunfix(b->batCacheid); return MAL_SUCCEED; } if (hd) stream_printf(fp, "%s", hd); if (ATOMvarsized(tpe)) ATOMprint(tpe, *(str *) val, fp); else ATOMprint(tpe, val, fp); if (tl) stream_printf(fp, "%s", tl); return MAL_SUCCEED;}strIOprint_val(MalBlkPtr mb, MalStkPtr stk, InstrPtr p){ int i; if (p->argc == 2) IOprintBoth(mb, stk, p, 1, "[ ", " ]\n", 0); else { IOprintBoth(mb, stk, p, 1, "[ ", 0, 1); for (i = 2; i < p->argc - 1; i++) IOprintBoth(mb, stk, p, i, ", ", 0, 1); IOprintBoth(mb, stk, p, i, ", ", "]\n", 1); } return MAL_SUCCEED;}strIOprint_tables(MalBlkPtr mb, MalStkPtr stk, InstrPtr p){ IOtableAll(GDKout, mb, stk, p, 1, 0, FALSE, TRUE); return MAL_SUCCEED;}strIOprompt_val(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){ return IOprintBoth(mb, stk, pci, 1, 0, 0, 1);}strIOprint_ft(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){ int tpe = getArgType(mb, pci, 1); ptr val = (ptr) getArgReference(stk, pci, 1); if (val == NULL) { ATOMprint(TYPE_str, "nil", GDKout); return MAL_SUCCEED; } if (tpe == TYPE_str) ATOMprint(TYPE_str, *(str *) val, GDKout); else ATOMprint(tpe, val, GDKout); return MAL_SUCCEED;}@-The table printing routine implementations rely on the multiprintf.They merely differ in destination and order prerequisite@cstrIOtableAll(stream *f, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci, int i, int order, int printhead, int printorder){ BAT *piv[MAXPARAMS], *b; int nbats = 0; int tpe, k = i; ptr val; for (; i < pci->argc; i++) { tpe = getArgType(mb, pci, i); val = (ptr) getArgReference(stk, pci, i); if (!isaBatType(tpe)) throw(MAL, "io.table", "BAT expected"); b = BATdescriptor(*(int *) val); if (b == NULL) { for (k = 0; k < nbats; k++) BBPunfix(piv[k]->batCacheid); throw(MAL, "io.table", "Could not access descriptor"); } piv[nbats++] = b; } /*if(printhead) */ nbats++; BATmultiprintf(f, nbats, piv, printhead, order, printorder); for (k = 0; k < nbats - 1; k++) BBPunfix(piv[k]->batCacheid); return MAL_SUCCEED;}strIOotable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){ int order; order = *(int *) getArgReference(stk, pci, 1); return IOtableAll(GDKout, mb, stk, pci, 2, order, TRUE, TRUE);}strIOtable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){ return IOtableAll(GDKout, mb, stk, pci, 1, 0, TRUE, TRUE);}strIOfotable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){ stream *fp; int order; fp = *(stream **) getArgReference(stk, pci, 1); order = *(int *) getArgReference(stk, pci, 2); (void) order; /* fool compiler */ return IOtableAll(fp, mb, stk, pci, 3, 1, TRUE, TRUE);}strIOftable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){ stream *fp; fp = *(stream **) getArgReference(stk, pci, 1); return IOtableAll(fp, mb, stk, pci, 2, 0, TRUE, TRUE);}strIOttable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){ return IOtableAll(GDKout, mb, stk, pci, 1, 0, FALSE, TRUE);}strIOtotable(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){ int order; order = *(int *) getArgReference(stk, pci, 1); (void) order; /* fool compiler */ return IOtableAll(GDKout, mb, stk, pci, 2, order, FALSE, TRUE);}@- Formatter printThe format string is scrutinized using VALsprintf in the GDK libraryto avoid that passing a wrong argument (e.g. NULL pointer) kills the server.The generic printf function is rather expensive. Ideally it should bereplaced by a squeezer into a type-specific function calls.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -