📄 mal_import.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.@a M. Kersten@v 0.0@+ Module importThe import statement simple switches the parser to a new input file, whichtakes precedence. The context for which the file should be interpretedis determined by the module name supplied.Typically this involves a module, whose definitions are stored at a known location.@{@h#ifndef _MAL_IMPORT_H#define _MAL_IMPORT_H#include "mal_exception.h"#include "mal_client.h"#include "mal_session.h"#include "mal_utils.h"mal_export void slash_2_dir_sep(str fname);@-The import context is located. If the module already exists, we should silently skip parsing the file. This is handled at the parser level.The files are extracted from a default location,namely the DBHOME/modules directory.If the string starts with '/' or '~' the context is not changed.Every IMPORT statement denotes a possible dynamic load library.Make sure it is loaded as well.@c#include "mal_config.h"#include "mal_import.h"#include "mal_interpreter.h" /* for showErrors() */#include "mal_linker.h" /* for loadModuleLibrary() */#include "mal_parser.h"voidslash_2_dir_sep(str fname){ char *s; for (s = fname; *s; s++) if (*s == '/') *s = DIR_SEP;}static stream *malOpenSource(str fname){ stream *fd = NULL; char path[PATHLENGTH]; str fullname; snprintf(path,PATHLENGTH,"%s",fname); slash_2_dir_sep(path); fullname = MSP_locate_script(path); if (fullname) { fd = open_rastream(fullname); GDKfree(fullname); } else { fd = open_rastream(path); } return fd;}@-The malLoadScript routine merely reads the contents of a file intothe input buffer of the client. It is typically used in situationswhere an intermediate file is used to pass commands around.Since the parser needs access to the complete block, we first haveto find out how long the input is.For the time being, we assume at most 1Mb.@hmal_export str malLoadScript(str name, bstream **fdin);@cstrmalLoadScript(str name, bstream **fdin){ stream *fd; fd = malOpenSource(name); if (stream_errnr(fd) == OPEN_ERROR) { stream_destroy(fd); throw(MAL, "malInclude", "could not open file: %s", name); } *fdin = bstream_create(fd, 128 * BLOCK); if( bstream_next(*fdin) < 0) stream_printf(GDKout,"!WARNING: could not read %s\n",name); return MAL_SUCCEED;}@-Beware that we have to isolate the execution of the source filein its own environment. E.g. we have to removed the executionstate until we are finished.The script being read my contain errors, such as non-balancedbrackets as indicated by blkmode.It should be reset before continuing.@-@= restoreState bstream *oldfdin = c->fdin; int oldyycur = c->yycur; int oldlisting = c->listing; int oldmode = c->mode; int oldblkmode = c->blkmode; str oldsrcFile = c->srcFile; ClientInput *oldbak = c->bak; str oldprompt = c->prompt; Module oldnspace = c->nspace; Symbol oldprg = c->curprg; MalStkPtr oldglb = c->glb;@= restoreClient1 if (c->fdin) { (void) stream_close(c->fdin->s); (void) stream_destroy(c->fdin->s); (void) bstream_destroy(c->fdin); } c->fdin = oldfdin; c->yycur = oldyycur; c->listing = oldlisting; c->mode = oldmode; c->blkmode = oldblkmode; c->bak = oldbak; c->srcFile = oldsrcFile; if(c->prompt) GDKfree(c->prompt); c->prompt = oldprompt; c->promptlength= strlen(c->prompt);@= restoreClient2 c->glb = oldglb; c->nspace = oldnspace; c->curprg = oldprg;@= restoreClient @:restoreClient1()@ @:restoreClient2()@@= runPhase if(msg== MAL_SUCCEED && c->phase[@1] && (msg= (str) (*c->phase[@1])(c)) ){ /* error occurred and ignored */ /* stream_printf(GDKout,"%s",msg);*/ GDKfree(msg); msg=MAL_SUCCEED; @:@2()@ return; }@-The include operation parses the file indentified and leaves the MAL code behind in the 'main' function.@hmal_export void malInclude(Client c, str name, int listing);@cvoidmalInclude(Client c, str name, int listing){ str s; bstream *oldfdin = c->fdin; int oldyycur = c->yycur; int oldlisting = c->listing; int oldmode = c->mode; int oldblkmode = c->blkmode; ClientInput *oldbak = c->bak; str oldprompt = c->prompt; str oldsrcFile = c->srcFile; MalStkPtr oldglb = c->glb; Module oldnspace = c->nspace; Symbol oldprg = c->curprg; c->yycur = 0; c->prompt = GDKstrdup(""); /* do not produce visible prompts */ c->promptlength = strlen(c->prompt); c->listing = listing; c->bak = NULL; c->fdin = NULL; c->srcFile = name; if ((s = malLoadScript(name, &c->fdin))) stream_printf(c->fdout, "!%s\n", s); else parseMAL(c,c->curprg); @:restoreClient()@}@+ File and input processingA recurring situation is to execute a stream of simple MAL instructionsstored on a file or comes from standard input. We parse one MAL instruction line at a time and attempt to execute it immediately.Note, this precludes entereing complex MAL structures on the primaryinput channel, because 1) this requires complex code to keep trackthat we are in 'definition mode' 2) this requires (too) carefulltyping by the user, because he can not make an typeing errorTherefore, all compound code fragments should be loaded and executedusing the evalFile and callString command. It will parse the completefile into a MAL program block and execute it.Running looks much like an Import operation, except for the executionphase. This is performed in the context of an a priori definedstack frame. Life becomes a little complicated when the script containsa definition.@hmal_export str evalFile(Client c, str fname, int listing);@cstrevalFile(Client c, str fname, int listing){ @:restoreState@ stream *fd; str msg= MAL_SUCCEED; c->yycur = 0; c->prompt = GDKstrdup(""); /* do not produce visible prompts */ c->promptlength = strlen(c->prompt); c->listing = listing; c->bak = NULL; c->fdin = NULL; c->srcFile= fname; fd = malOpenSource(fname); if (stream_errnr(fd) == OPEN_ERROR) { stream_destroy(fd); stream_printf(c->fdout, "#WARNING: could not open file: %s", fname); } else { c->fdin = bstream_create(fd, 128 * BLOCK); MSinitClientPrg(c,"user","main"); /* re-initialize context */ msg= runScenario(c); } @:restoreClient()@ return msg;}@hmal_export str compileString(Symbol *fcn, Client c, str s);@cstrcompileString(Symbol *fcn, Client c, str s){ @:restoreState@ int len = strlen(s); buffer *b; str msg = MAL_SUCCEED; str qry; c->yycur = 0; c->prompt = GDKstrdup(""); /* do not produce visible prompts */ c->promptlength = strlen(c->prompt); c->listing = 0; c->bak = NULL; c->fdin = NULL; c->srcFile= NULL; b = (buffer *) GDKmalloc(sizeof(buffer)); if (s[len - 1] != '\n') { char *n = GDKmalloc(len + 1 + 1); strncpy(n, s, len); n[len] = '\n'; n[len + 1] = 0; s = n; len++; } mal_unquote(qry = GDKstrdup(s)); buffer_init(b, qry, len); MCpushClientInput(c, bstream_create(buffer_rastream(b, "compileString"), b->len), 0, ""); MSinitClientPrg(c,"user", "main"); /* create new context */ /* runPhase(READER,restoreClient1) */ if(msg== MAL_SUCCEED && c->phase[READER] && (msg= (str) (*c->phase[READER])(c)) ){ @:restoreClient1()@ return msg; } /* runPhase(PARSER,restoreClient1) */ if(msg== MAL_SUCCEED && c->phase[PARSER] && (msg= (str) (*c->phase[PARSER])(c)) ){ /* error occurred and ignored */ /* stream_printf(GDKout,"%s",msg);*/ @:restoreClient1()@ return msg; } *fcn= c->curprg; /* restore IO channel */ @:restoreClient1()@ c->listing = oldlisting; c->glb = oldglb; c->nspace = oldnspace; c->curprg = oldprg; GDKfree(qry); return MAL_SUCCEED;}@hmal_export void callString(Client c, str s, int listing);@cvoidcallString(Client c, str s, int listing){ @:restoreState@ int len = strlen(s); buffer *b; str msg = MAL_SUCCEED,qry; c->yycur = 0; c->prompt = GDKstrdup(""); /* do not produce visible prompts */ c->promptlength = strlen(c->prompt); c->listing = listing; c->bak = NULL; c->fdin = NULL; c->srcFile= NULL; b = (buffer *) GDKmalloc(sizeof(buffer)); if (s[len - 1] != '\n') { char *n = GDKmalloc(len + 1 + 1); strncpy(n, s, len); n[len] = '\n'; n[len + 1] = 0; s = n; len++; } mal_unquote(qry = GDKstrdup(s)); buffer_init(b, qry, len); MCpushClientInput(c, bstream_create(buffer_rastream(b, "callString"), b->len), listing, ""); MSinitClientPrg(c,"user", "main"); /* create new context */ @:runPhase(READER,restoreClient1)@ @:runPhase(PARSER,restoreClient1)@ /* restore IO channel */ @:restoreClient1()@ @:runPhase(OPTIMIZE,restoreClient2)@ @:runPhase(SCHEDULER,restoreClient2)@ @:runPhase(ENGINE,restoreClient2)@ @:restoreClient2()@ GDKfree(qry);}@h#endif /* _MAL_IMPORT_H */@}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -