LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_prelude.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 220 269 81.8 %
Date: 2021-09-14 22:17:06 Functions: 10 11 90.9 %

          Line data    Source code
       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 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /* Author(s) M.L. Kersten, N. Nes
      10             :  * This module takes the statically defined modules, atoms, commands and patterns
      11             :  * and populate the internal structures.
      12             :  *
      13             :  */
      14             : 
      15             : #include "monetdb_config.h"
      16             : #include "mal_import.h"
      17             : #include "mal_interpreter.h"  /* for showErrors() */
      18             : #include "mal_linker.h"               /* for loadModuleLibrary() */
      19             : #include "mal_scenario.h"
      20             : #include "mal_parser.h"
      21             : #include "mal_authorize.h"
      22             : #include "mal_private.h"
      23             : 
      24             : #include "mal_prelude.h"
      25             : 
      26             : #define MAX_MAL_MODULES 128
      27             : static int mel_modules = 0;
      28             : static struct mel_module {
      29             :         char *name;
      30             :         mel_atom *atoms;
      31             :         mel_func *funcs;
      32             :         mel_init inits;
      33             :         const char *code;
      34             : } mel_module[MAX_MAL_MODULES];
      35             : 
      36             : int
      37           0 : mal_startup(void)
      38             : {
      39             :         /* clean up the MAL internal structures before restart */
      40           0 :         return 0;
      41             : }
      42             : 
      43             : /* all MAL related functions register themselves
      44             :  * the order in which these registrations happen is significant
      45             :  * because there may be dependencies among the definitions.
      46             :  * For example, you better know the atoms before you use them
      47             :  */
      48             : 
      49             : void
      50         513 : mal_module2(str name, mel_atom *atoms, mel_func *funcs, mel_init initfunc, const char *code)
      51             : {
      52         513 :         assert (mel_modules < MAX_MAL_MODULES);
      53         513 :         mel_module[mel_modules].name = name;
      54         513 :         mel_module[mel_modules].atoms = atoms;
      55         513 :         mel_module[mel_modules].funcs = funcs;
      56         513 :         mel_module[mel_modules].inits = initfunc;
      57         513 :         mel_module[mel_modules].code = code;
      58         513 :         mel_modules++;
      59         513 : }
      60             : 
      61             : void
      62       15315 : mal_module(str name, mel_atom *atoms, mel_func *funcs)
      63             : {
      64       15315 :         assert (mel_modules < MAX_MAL_MODULES);
      65       15315 :         mel_module[mel_modules].name = name;
      66       15315 :         mel_module[mel_modules].atoms = atoms;
      67       15315 :         mel_module[mel_modules].funcs = funcs;
      68       15315 :         mel_module[mel_modules].inits = NULL;
      69       15315 :         mel_module[mel_modules].code = NULL;
      70       15315 :         mel_modules++;
      71       15315 : }
      72             : 
      73             : static char *
      74       16211 : initModule(Client c, char *name)
      75             : {
      76             :         char *msg = MAL_SUCCEED;
      77             : 
      78       16211 :         if (!getName(name))
      79             :                 return msg;
      80       14349 :         Module m = getModule(putName(name));
      81       14349 :         if (m) { /* run prelude */
      82       13551 :                 Symbol s = findSymbolInModule(m, putName("prelude"));
      83             : 
      84       13551 :                 if (s) {
      85        3219 :                         InstrPtr pci = getInstrPtr(s->def, 0);
      86             : 
      87        5906 :                         if (pci && pci->token == COMMANDsymbol && pci->argc == 1) {
      88        2687 :                                 int ret = 0;
      89             : 
      90        2687 :                                 assert(pci->fcn != NULL);
      91        2687 :                                 msg = (*pci->fcn)(&ret);
      92             :                                 (void)ret;
      93         532 :                         } else if (pci && pci->token == PATTERNsymbol) {
      94         532 :                                 assert(pci->fcn != NULL);
      95         532 :                                 msg = (*pci->fcn)(c, NULL, NULL, NULL);
      96             :                         }
      97             :                 }
      98             :         }
      99             :         return msg;
     100             : }
     101             : 
     102             : /*
     103             :  * The statically description of the MAL structures call for a translation into
     104             :  * their underlying structure.
     105             :  */
     106             : static str
     107        2648 : addAtom( mel_atom *atoms)
     108             : {
     109        6070 :         for(; atoms && atoms->name[0]; atoms++) {
     110        3422 :                 int i = ATOMallocate(atoms->name);
     111        3422 :                 if (is_int_nil(i))
     112           0 :                         throw(TYPE,"addAtom", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     113        3422 :                 if (atoms->basetype[0]) {
     114        2382 :                         int tpe = ATOMindex(atoms->basetype);
     115        2382 :                         if (tpe < 0)
     116           0 :                                 throw(TYPE,"addAtom", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     117        2382 :                         BATatoms[i] = BATatoms[tpe];
     118        2382 :                         strcpy_len(BATatoms[i].name, atoms->name, sizeof(BATatoms[i].name));
     119        2382 :                         BATatoms[i].storage = ATOMstorage(tpe);
     120             :                 } else  { /* cannot overload void atoms */
     121        1040 :                         BATatoms[i].storage = i;
     122        1040 :                         BATatoms[i].linear = false;
     123             :                 }
     124        3422 :                 if (atoms->del)
     125         774 :                         BATatoms[i].atomDel = atoms->del;
     126        3422 :                 if (atoms->cmp) {
     127        1294 :                         BATatoms[i].atomCmp = atoms->cmp;
     128        1294 :                         BATatoms[i].linear = true;
     129             :                 }
     130        3422 :                 if (atoms->fromstr)
     131        2624 :                         BATatoms[i].atomFromStr = atoms->fromstr;
     132        3422 :                 if (atoms->tostr)
     133        2624 :                         BATatoms[i].atomToStr = atoms->tostr;
     134        3422 :                 if (atoms->fix)
     135           0 :                         BATatoms[i].atomFix = atoms->fix;
     136        3422 :                 if (atoms->unfix)
     137           0 :                         BATatoms[i].atomUnfix = atoms->unfix;
     138        3422 :                 if (atoms->heap) {
     139         774 :                         BATatoms[i].size = sizeof(var_t);
     140         774 :                         assert_shift_width(ATOMelmshift(ATOMsize(i)), ATOMsize(i));
     141         774 :                         BATatoms[i].atomHeap = atoms->heap;
     142             :                 }
     143        3422 :                 if (atoms->hash)
     144        1028 :                         BATatoms[i].atomHash = atoms->hash;
     145        3422 :                 if (atoms->length)
     146         774 :                         BATatoms[i].atomLen = atoms->length;
     147        3422 :                 if (atoms->null) {
     148        1294 :                         const void *atmnull = (*atoms->null)();
     149             : 
     150        1294 :                         BATatoms[i].atomNull = atmnull;
     151             :                 }
     152        3422 :                 if (atoms->nequal)
     153           0 :                         BATatoms[i].atomCmp = atoms->nequal;
     154        3422 :                 if (atoms->put)
     155         774 :                         BATatoms[i].atomPut = atoms->put;
     156        3422 :                 if (atoms->storage)
     157           0 :                         BATatoms[i].storage = (*atoms->storage)();
     158        3422 :                 if (atoms->read)
     159        1028 :                         BATatoms[i].atomRead = atoms->read;
     160        3422 :                 if (atoms->write)
     161        1028 :                         BATatoms[i].atomWrite = atoms->write;
     162             :         }
     163             :         return MAL_SUCCEED;
     164             : }
     165             : 
     166             : static str
     167     5473397 : makeArgument(MalBlkPtr mb, const mel_arg *a, int *idx)
     168             : {
     169             :         int tpe = TYPE_any;//, l;
     170             : 
     171     5473397 :         if (
     172             : #ifdef MEL_STR
     173     5473397 :                 !a->type[0]
     174             : #else
     175             :                 a->type == TYPE_any
     176             : #endif
     177             :                 ) {
     178      491851 :                 if (a->isbat)
     179             :                         tpe = newBatType(tpe);
     180      491851 :                 if (a->nr > 0)
     181      314944 :                         setTypeIndex(tpe, a->nr);
     182             :         } else {
     183             :                 int mask = 0;
     184             : #ifdef MEL_STR
     185     4981546 :                 tpe = getAtomIndex(a->type, strlen(a->type),-1);
     186             : #else
     187             :                 tpe = a->type ;
     188             : #endif
     189     4981546 :                 if (a->isbat)
     190     1431374 :                         tpe = newBatType(tpe) | mask;
     191             :         }
     192             :         /*
     193             :           if (a->name){
     194             :           *idx = findVariableLength(mb, a->name, l = strlen(a->name));
     195             :           if( *idx != -1)
     196             :           throw(LOADER, "addFunctions", "Duplicate argument name %s", a->name);
     197             :           *idx = newVariable(mb, a->name, l, tpe);
     198             :           } else
     199             :         */
     200     5473397 :         *idx = newTmpVariable(mb, tpe);
     201     5473397 :         return MAL_SUCCEED;
     202             : }
     203             : 
     204             : static str
     205       16223 : addFunctions(mel_func *fcn){
     206             :         str msg = MAL_SUCCEED;
     207             :         const char *mod;
     208             :         int idx;
     209             :         Module c;
     210             :         Symbol s;
     211             :         MalBlkPtr mb;
     212             :         InstrPtr sig;
     213             : 
     214     1546534 :         for(; fcn && fcn->mod[0]; fcn++) {
     215     1530311 :                 assert(fcn->mod);
     216     1530311 :                 mod = putName(fcn->mod);
     217     1530311 :                 c = getModule(mod);
     218     1530311 :                 if( c == NULL){
     219       18411 :                         if (globalModule(mod=putName(fcn->mod)) == NULL)
     220           0 :                                 throw(LOADER, "addFunctions", "Module %s can not be created", fcn->mod);
     221       18411 :                         c = getModule(mod);
     222             :                 }
     223             : 
     224     2648873 :                 s = newSymbol(fcn->fcn, fcn->command ? COMMANDsymbol: PATTERNsymbol );
     225     1530311 :                 if ( s == NULL)
     226           0 :                         throw(LOADER, "addFunctions", "Can not create symbol for %s.%s missing", fcn->mod, fcn->fcn);
     227     1530311 :                 mb = s->def;
     228     1530311 :                 if( mb == NULL)
     229           0 :                         throw(LOADER, "addFunctions", "Can not create program block for %s.%s missing", fcn->mod, fcn->fcn);
     230             : 
     231     1530311 :                 if (fcn->cname && fcn->cname[0])
     232     1530311 :                         strcpy(mb->binding, fcn->cname);
     233             :                 /* keep the comment around, setting the static avoid freeing the string accidentally , saving on duplicate documentation in the code. */
     234     1530311 :                 mb->statichelp = mb->help = fcn->comment;
     235             : 
     236     1530311 :                 sig= newInstructionArgs(mb, fcn->mod, fcn->fcn, fcn->argc + (fcn->retc == 0));
     237     1530311 :                 sig->retc = 0;
     238     1530311 :                 sig->argc = 0;
     239     1530311 :                 sig->token = fcn->command?COMMANDsymbol:PATTERNsymbol;
     240     1530311 :                 sig->fcn = (MALfcn)fcn->imp;
     241     1530311 :                 if( fcn->unsafe)
     242       26688 :                         mb->unsafeProp = 1;
     243             :                 
     244             :                 /* add the return variables */
     245     1530311 :                 if(fcn->retc == 0){
     246       56658 :                         int idx = newTmpVariable(mb, TYPE_void);
     247       56658 :                         sig = pushReturn(mb, sig, idx);
     248       56658 :                         if (sig == NULL)
     249           0 :                                 throw(LOADER, "addFunctions", "Failed to create void return");
     250             :                 }
     251             :                 int i;
     252     3095035 :                 for (i = 0; i<fcn->retc; i++ ){
     253     1564724 :                         const mel_arg *a = fcn->args+i;
     254     1564724 :                         msg = makeArgument(mb, a, &idx);
     255     1564724 :                         if( msg)
     256           0 :                                 return msg;
     257     1564724 :                         sig = pushReturn(mb, sig, idx);
     258     1564724 :                         if (sig == NULL)
     259             :                                 //throw(LOADER, "addFunctions", "Failed to keep argument name %s", a->name);
     260           0 :                                 throw(LOADER, "addFunctions", "Failed to keep argument %d", i);
     261             :                         int tpe = TYPE_any;
     262     1564724 :                         if (a->nr > 0) {
     263       50274 :                                 if (a->isbat)
     264             :                                         tpe = newBatType(tpe);
     265       50274 :                                 setPolymorphic(sig, tpe, TRUE);
     266             :                         }
     267     1564724 :                         if (a->vargs) {
     268        2514 :                                 sig->varargs |= VARRETS;
     269        2514 :                                 setPolymorphic(sig, TYPE_any, TRUE);
     270             :                         }
     271             :                 }
     272             :                 /* add the arguments */
     273     5438984 :                 for (i = fcn->retc; i<fcn->argc; i++ ){
     274     3908673 :                         const mel_arg *a = fcn->args+i;
     275     3908673 :                         msg = makeArgument(mb, a, &idx);
     276     3908673 :                         if( msg)
     277           0 :                                 return msg;
     278     3908673 :                         sig = pushArgument(mb, sig, idx);
     279     3908673 :                         if (sig == NULL)
     280             :                                 //throw(LOADER, "addFunctions", "Failed to keep argument name %s", a->name);
     281           0 :                                 throw(LOADER, "addFunctions", "Failed to keep argument %d", i);
     282             :                         int tpe = TYPE_any;
     283     3908673 :                         if (a->nr > 0) {
     284      264670 :                                 if (a->isbat)
     285             :                                         tpe = newBatType(tpe);
     286      264670 :                                 setPolymorphic(sig, tpe, TRUE);
     287             :                         }
     288     3908673 :                         if (a->vargs) {
     289       11542 :                                 sig->varargs |= VARARGS;
     290       11542 :                                 setPolymorphic(sig, TYPE_any, TRUE);
     291             :                         }
     292             :                 }
     293     1530311 :                 assert(sig->retc > 0);
     294     1530311 :                 pushInstruction(mb, sig);
     295     1530311 :                 insertSymbol(c, s);
     296             :         }
     297             :         return msg;
     298             : }
     299             : 
     300             : static int
     301     7765338 : makeFuncArgument(MalBlkPtr mb, mel_func_arg *a)
     302             : {
     303             :         int tpe = TYPE_any;
     304             : 
     305     7765338 :         if (a->type == TYPE_any) {
     306       26600 :                 if (a->isbat)
     307             :                         tpe = newBatType(tpe);
     308       26600 :                 if (a->nr > 0)
     309       25536 :                         setTypeIndex(tpe, a->nr);
     310             :         } else {
     311     7738738 :                 tpe = a->type;
     312     7738738 :                 if (a->isbat)
     313     6441190 :                         tpe = newBatType(tpe);
     314             :         }
     315     7765338 :         return newTmpVariable(mb, tpe);
     316             : }
     317             : 
     318             : int
     319     1923446 : melFunction(bool command, const char *mod, const char *fcn, fptr imp, const char *fname, bool unsafe, const char *comment, int retc, int argc, ... )
     320             : {
     321             :         int i, idx;
     322             :         Module c;
     323             :         Symbol s;
     324             :         MalBlkPtr mb;
     325             :         InstrPtr sig;
     326             :         va_list va;
     327             : 
     328     1923446 :         assert(mod);
     329     1923446 :         mod = putName(mod);
     330     1923446 :         c = getModule(mod);
     331     1923446 :         if (c == NULL) {
     332           0 :                 if (globalModule(mod) == NULL)
     333             :                         return MEL_ERR;
     334           0 :                 c = getModule(mod);
     335             :         }
     336             : 
     337     3846892 :         s = newSymbol(fcn, command ? COMMANDsymbol:PATTERNsymbol );
     338     1923446 :         if (s == NULL)
     339             :                 return MEL_ERR;
     340     1923446 :         mb = s->def;
     341             :         (void)comment;
     342     1923446 :         if (fname)
     343     1923446 :                 strcpy(mb->binding, fname);
     344     1923446 :         if (mb == NULL) {
     345           0 :                 freeSymbol(s);
     346           0 :                 return MEL_ERR;
     347             :         }
     348     1923446 :         sig = newInstructionArgs(mb, mod, fcn, argc + (retc == 0));
     349     1923446 :         sig->retc = 0;
     350     1923446 :         sig->argc = 0;
     351     1923446 :         sig->token = command ? COMMANDsymbol:PATTERNsymbol;
     352     1923446 :         sig->fcn = (MALfcn)imp;
     353     1923446 :         if (unsafe)
     354           0 :                 mb->unsafeProp = 1;
     355             :         /* add the return variables */
     356     1923446 :         if(retc == 0) {
     357           0 :                 idx = newTmpVariable(mb, TYPE_void);
     358           0 :                 sig = pushReturn(mb, sig, idx);
     359           0 :                 if (idx < 0 || sig == NULL) {
     360           0 :                         freeInstruction(sig);
     361           0 :                         freeSymbol(s);
     362           0 :                         return MEL_ERR;
     363             :                 }
     364             :         }
     365             : 
     366     1923446 :         va_start(va, argc);
     367     3854340 :         for (i = 0; i<retc; i++ ){
     368     1930894 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     369     1930894 :                 idx = makeFuncArgument(mb, &a);
     370     1930894 :                 sig = pushReturn(mb, sig, idx);
     371     1930894 :                 if (idx < 0 || sig == NULL) {
     372           0 :                         freeInstruction(sig);
     373           0 :                         freeSymbol(s);
     374           0 :                         va_end(va);
     375           0 :                         return MEL_ERR;
     376             :                 }
     377             :                 int tpe = TYPE_any;
     378     1930894 :                 if (a.nr > 0) {
     379           0 :                         if (a.isbat)
     380             :                                 tpe = newBatType(tpe);
     381           0 :                         setPolymorphic(sig, tpe, TRUE);
     382             :                 }
     383     1930894 :                 if (a.vargs) {
     384           0 :                         sig->varargs |= VARRETS;
     385           0 :                         setPolymorphic(sig, TYPE_any, TRUE);
     386             :                 }
     387             :         }
     388             :         /* add the arguments */
     389     7757890 :         for (i = retc; i<argc; i++ ){
     390     5834444 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     391     5834444 :                 idx = makeFuncArgument(mb, &a);
     392     5834444 :                 sig = pushArgument(mb, sig, idx);
     393     5834444 :                 if (idx < 0 || sig == NULL) {
     394           0 :                         freeInstruction(sig);
     395           0 :                         freeSymbol(s);
     396           0 :                         va_end(va);
     397           0 :                         return MEL_ERR;
     398             :                 }
     399             :                 int tpe = TYPE_any;
     400     5834444 :                 if (a.nr > 0) {
     401      178752 :                         if (a.isbat)
     402             :                                 tpe = newBatType(tpe);
     403      178752 :                         setPolymorphic(sig, tpe, TRUE);
     404             :                 }
     405     5834444 :                 if (a.vargs) {
     406           0 :                         sig->varargs |= VARARGS;
     407           0 :                         setPolymorphic(sig, TYPE_any, TRUE);
     408             :                 }
     409             :         }
     410     1923446 :         assert(sig->retc > 0);
     411     1923446 :         pushInstruction(mb, sig);
     412     1923446 :         insertSymbol(c, s);
     413     1923446 :         va_end(va);
     414     1923446 :         return MEL_OK;
     415             : }
     416             : 
     417             : static str
     418         266 : malPrelude(Client c, int listing, int no_mapi_server)
     419             : {
     420             :         int i;
     421             :         str msg = MAL_SUCCEED;
     422             : 
     423             :         (void) listing;
     424             :         /* Add all atom definitions */
     425       16489 :         for(i = 0; i<mel_modules; i++) {
     426       16223 :                 if (mel_module[i].atoms) {
     427        2648 :                         msg = addAtom(mel_module[i].atoms);
     428        2648 :                         if (msg)
     429           0 :                                 return msg;
     430             :                 }
     431             :         }
     432             : 
     433             :         /* Add the signatures, where we now have access to all atoms */
     434       16489 :         for(i = 0; i<mel_modules; i++) {
     435       16223 :                 if (!malLibraryEnabled(mel_module[i].name))
     436           0 :                         continue;
     437       16223 :                 if (mel_module[i].funcs) {
     438       16223 :                         msg = addFunctions(mel_module[i].funcs);
     439       16223 :                         if (!msg && mel_module[i].code) /* some modules may also have some function definitions */
     440         254 :                                 msg = malIncludeString(c, mel_module[i].name, (str)mel_module[i].code, listing, NULL);
     441       16223 :                         if (msg)
     442           0 :                                 return msg;
     443             : 
     444             :                         /* skip sql should be last to startup and mapi if configured without mapi server */
     445       16223 :                         if (strcmp(mel_module[i].name, "sql") == 0 || (no_mapi_server && strcmp(mel_module[i].name, "mapi") == 0))
     446         278 :                                 continue;
     447       15945 :                         if (!mel_module[i].inits) {
     448       15679 :                                 msg = initModule(c, mel_module[i].name);
     449       15679 :                                 if (msg)
     450           0 :                                         return msg;
     451             :                         }
     452             :                 }
     453       15945 :                 if (mel_module[i].inits) {
     454         266 :                         msg = mel_module[i].inits();
     455         266 :                         if (msg)
     456           0 :                                 return msg;
     457             :                         /* skip sql should be last to startup and mapi if configured without mapi server */
     458         266 :                         if (strcmp(mel_module[i].name, "sql") == 0 || (no_mapi_server && strcmp(mel_module[i].name, "mapi") == 0))
     459           0 :                                 continue;
     460         266 :                         msg = initModule(c, mel_module[i].name);
     461         266 :                         if (msg)
     462           0 :                                 return msg;
     463             :                 }
     464             :         }
     465             :         return MAL_SUCCEED;
     466             : }
     467             : 
     468             : str
     469         266 : malIncludeModules(Client c, char *modules[], int listing, int no_mapi_server)
     470             : {
     471             :         int i;
     472             :         str msg;
     473             : 
     474        2571 :         for(i = 0; modules[i]; i++) {
     475             :                 /* load library */
     476        2305 :                 if (!malLibraryEnabled(modules[i]))
     477         711 :                         continue;
     478        1594 :                 if ((msg = loadLibrary(modules[i], listing)) != NULL)
     479           0 :                         return msg;
     480             :         }
     481             :         /* load the mal code for these modules and execute preludes */
     482         266 :         if ((msg = malPrelude(c, listing, no_mapi_server)) != NULL)
     483             :                 return msg;
     484         267 :         for(int i = 0; modules[i]; i++) {
     485         267 :                 if (strcmp(modules[i], "sql") == 0) { /* start now */
     486         266 :                         initModule(c, modules[i]);
     487         265 :                         break;
     488             :                 }
     489             :         }
     490             :         return MAL_SUCCEED;
     491             : }

Generated by: LCOV version 1.14