LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_prelude.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 266 343 77.6 %
Date: 2024-04-25 20:03:45 Functions: 10 11 90.9 %

          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             : /* Author(s) M.L. Kersten, N. Nes
      14             :  * This module takes the statically defined modules, atoms, commands and patterns
      15             :  * and populate the internal structures.
      16             :  *
      17             :  */
      18             : 
      19             : #include "monetdb_config.h"
      20             : #include "mal_import.h"
      21             : #include "mal_interpreter.h"  /* for showErrors() */
      22             : #include "mal_linker.h"                       /* for loadModuleLibrary() */
      23             : #include "mal_scenario.h"
      24             : #include "mal_parser.h"
      25             : #include "mal_authorize.h"
      26             : #include "mal_private.h"
      27             : #include "mutils.h"
      28             : 
      29             : #include "mal_prelude.h"
      30             : 
      31             : #define MAX_MAL_MODULES 128
      32             : static int mel_modules = 0;
      33             : static struct mel_module {
      34             :         const char *name;
      35             :         mel_atom *atoms;
      36             :         mel_func *funcs;
      37             :         mel_init inits;
      38             :         const char *code;
      39             : } mel_module[MAX_MAL_MODULES];
      40             : 
      41             : int
      42           0 : mal_startup(void)
      43             : {
      44             :         /* clean up the MAL internal structures before restart */
      45           0 :         return 0;
      46             : }
      47             : 
      48             : /* all MAL related functions register themselves
      49             :  * the order in which these registrations happen is significant
      50             :  * because there may be dependencies among the definitions.
      51             :  * For example, you better know the atoms before you use them
      52             :  */
      53             : 
      54             : void
      55        3296 : mal_module2(const char *name, mel_atom *atoms, mel_func *funcs,
      56             :                         mel_init initfunc, const char *code)
      57             : {
      58        3296 :         assert(mel_modules < MAX_MAL_MODULES);
      59        3296 :         mel_module[mel_modules].name = name;
      60        3296 :         mel_module[mel_modules].atoms = atoms;
      61        3296 :         mel_module[mel_modules].funcs = funcs;
      62        3296 :         mel_module[mel_modules].inits = initfunc;
      63        3296 :         mel_module[mel_modules].code = code;
      64        3296 :         mel_modules++;
      65        3296 : }
      66             : 
      67             : void
      68       15121 : mal_module(const char *name, mel_atom *atoms, mel_func *funcs)
      69             : {
      70       15121 :         assert(mel_modules < MAX_MAL_MODULES);
      71       15121 :         mel_module[mel_modules].name = name;
      72       15121 :         mel_module[mel_modules].atoms = atoms;
      73       15121 :         mel_module[mel_modules].funcs = funcs;
      74       15121 :         mel_module[mel_modules].inits = NULL;
      75       15121 :         mel_module[mel_modules].code = NULL;
      76       15121 :         mel_modules++;
      77       15121 : }
      78             : 
      79             : static char *
      80       15411 : initModule(Client c, const char *name, const char *initpasswd)
      81             : {
      82       15411 :         char *msg = MAL_SUCCEED;
      83             : 
      84       15411 :         if (!getName(name))
      85             :                 return msg;
      86       15411 :         if ((name = putName(name)) == NULL)
      87           0 :                 throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
      88       15411 :         Module m = getModule(name);
      89       15411 :         if (m) {                                        /* run prelude */
      90       12387 :                 const char *prelude = putName("prelude");
      91       12387 :                 if (prelude == NULL)
      92           0 :                         throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
      93       12387 :                 Symbol s = findSymbolInModule(m, prelude);
      94             : 
      95       12387 :                 if (s) {
      96         670 :                         InstrPtr pci = getInstrPtr(s->def, 0);
      97             : 
      98         670 :                         if (pci && pci->token == COMMANDsymbol && pci->argc == 1) {
      99           0 :                                 int ret = 0;
     100             : 
     101           0 :                                 assert(pci->fcn != NULL);
     102           0 :                                 msg = (*(str (*)(int *)) pci->fcn) (&ret);
     103           0 :                                 (void) ret;
     104         670 :                         } else if (pci && pci->token == PATTERNsymbol) {
     105         670 :                                 void *mb = NULL;
     106         670 :                                 assert(pci->fcn != NULL);
     107         670 :                                 if (strcmp(name, "sql") == 0) {
     108             :                                         /* HACK ALERT: temporarily use sqlcontext to pass
     109             :                                          * the initial password to the prelude function */
     110         336 :                                         assert(c->sqlcontext == NULL);
     111         336 :                                         c->sqlcontext = (void *) initpasswd;
     112             :                                         /* HACK ALERT: use mb (MalBlkPtr) to pass revision
     113             :                                          * string in order to check that in the callee */
     114         336 :                                         mb = (void *) mercurial_revision();
     115             :                                 }
     116         670 :                                 msg = (*(str (*)(Client, MalBlkPtr, MalStkPtr, InstrPtr)) pci->
     117             :                                            fcn) (c, mb, NULL, NULL);
     118             :                         }
     119             :                 }
     120             :         }
     121             :         return msg;
     122             : }
     123             : 
     124             : /*
     125             :  * The statically description of the MAL structures call for a translation into
     126             :  * their underlying structure.
     127             :  */
     128             : static str
     129        3012 : addAtom(mel_atom *atoms)
     130             : {
     131        7008 :         for (; atoms && atoms->name[0]; atoms++) {
     132        3996 :                 int i = ATOMallocate(atoms->name);
     133        3996 :                 if (is_int_nil(i))
     134           0 :                         throw(TYPE, __func__, GDK_EXCEPTION);
     135        3996 :                 if (atoms->basetype[0]) {
     136        3012 :                         int tpe = ATOMindex(atoms->basetype);
     137        3012 :                         if (tpe < 0)
     138           0 :                                 throw(TYPE, __func__, TYPE_NOT_SUPPORTED);
     139        3012 :                         BATatoms[i] = BATatoms[tpe];
     140        3012 :                         strcpy_len(BATatoms[i].name, atoms->name, sizeof(BATatoms[i].name));
     141        3012 :                         BATatoms[i].storage = ATOMstorage(tpe);
     142             :                 } else {                                /* cannot overload void atoms */
     143         984 :                         BATatoms[i].storage = i;
     144         984 :                         BATatoms[i].linear = false;
     145             :                 }
     146        3996 :                 if (atoms->del)
     147         648 :                         BATatoms[i].atomDel = atoms->del;
     148        3996 :                 if (atoms->cmp) {
     149        1308 :                         BATatoms[i].atomCmp = atoms->cmp;
     150        1308 :                         BATatoms[i].linear = true;
     151             :                 }
     152        3996 :                 if (atoms->fromstr)
     153        2988 :                         BATatoms[i].atomFromStr = atoms->fromstr;
     154        3996 :                 if (atoms->tostr)
     155        2988 :                         BATatoms[i].atomToStr = atoms->tostr;
     156        3996 :                 if (atoms->fix)
     157           0 :                         BATatoms[i].atomFix = atoms->fix;
     158        3996 :                 if (atoms->unfix)
     159           0 :                         BATatoms[i].atomUnfix = atoms->unfix;
     160        3996 :                 if (atoms->heap) {
     161         648 :                         BATatoms[i].size = sizeof(var_t);
     162         648 :                         assert_shift_width(ATOMelmshift(ATOMsize(i)), ATOMsize(i));
     163         648 :                         BATatoms[i].atomHeap = atoms->heap;
     164             :                 }
     165        3996 :                 if (atoms->hash)
     166         972 :                         BATatoms[i].atomHash = atoms->hash;
     167        3996 :                 if (atoms->length)
     168         648 :                         BATatoms[i].atomLen = atoms->length;
     169        3996 :                 if (atoms->null) {
     170        1308 :                         const void *atmnull = (*atoms->null) ();
     171             : 
     172        1308 :                         BATatoms[i].atomNull = atmnull;
     173             :                 }
     174        3996 :                 if (atoms->nequal)
     175           0 :                         BATatoms[i].atomCmp = atoms->nequal;
     176        3996 :                 if (atoms->put)
     177         648 :                         BATatoms[i].atomPut = atoms->put;
     178        3996 :                 if (atoms->storage)
     179           0 :                         BATatoms[i].storage = (*atoms->storage) ();
     180        3996 :                 if (atoms->read)
     181         972 :                         BATatoms[i].atomRead = atoms->read;
     182        3996 :                 if (atoms->write)
     183         972 :                         BATatoms[i].atomWrite = atoms->write;
     184             :         }
     185             :         return MAL_SUCCEED;
     186             : }
     187             : 
     188             : static str
     189     6513546 : makeArgument(MalBlkPtr mb, const mel_arg *a, int *idx)
     190             : {
     191     6513546 :         int tpe = TYPE_any;                     //, l;
     192             : 
     193     6513546 :         if (
     194             : #ifdef MEL_STR
     195     6513546 :                    !a->type[0]
     196             : #else
     197             :                    a->type == TYPE_any
     198             : #endif
     199             :                         ) {
     200      630305 :                 if (a->isbat)
     201      339356 :                         tpe = newBatType(tpe);
     202      630305 :                 if (a->nr > 0)
     203      402860 :                         setTypeIndex(tpe, a->nr);
     204             :         } else {
     205     5883241 :                 int mask = 0;
     206             : #ifdef MEL_STR
     207     5883241 :                 tpe = getAtomIndex(a->type, strlen(a->type), -1);
     208             : #else
     209             :                 tpe = a->type;
     210             : #endif
     211     5883241 :                 if (a->isbat)
     212     2102295 :                         tpe = newBatType(tpe) | mask;
     213             :         }
     214             :         /*
     215             :           if (a->name) {
     216             :           *idx = findVariableLength(mb, a->name, l = strlen(a->name));
     217             :           if (*idx != -1)
     218             :           throw(LOADER, __func__, "Duplicate argument name %s", a->name);
     219             :           *idx = newVariable(mb, a->name, l, tpe);
     220             :           } else
     221             :         */
     222     6513546 :         *idx = newTmpVariable(mb, tpe);
     223     6513546 :         if (*idx < 0) {
     224           0 :                 char *msg = mb->errors;
     225           0 :                 mb->errors = NULL;
     226           0 :                 if (msg)
     227             :                         return msg;
     228           0 :                 throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     229             :         }
     230             :         return MAL_SUCCEED;
     231             : }
     232             : 
     233             : static str
     234       18770 : addFunctions(mel_func *fcn)
     235             : {
     236       18770 :         str msg = MAL_SUCCEED;
     237       18770 :         const char *mod;
     238       18770 :         int idx;
     239       18770 :         Module c;
     240       18770 :         Symbol s;
     241       18770 :         MalBlkPtr mb;
     242       18770 :         InstrPtr sig;
     243             : 
     244     1781901 :         for (; fcn && fcn->mod[0]; fcn++) {
     245     1763131 :                 assert(fcn->mod);
     246     1763131 :                 mod = putName(fcn->mod);
     247     1763131 :                 if (mod == NULL)
     248           0 :                         throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     249     1763131 :                 c = getModule(mod);
     250     1763131 :                 if (c == NULL && (c = globalModule(mod)) == NULL)
     251           0 :                         throw(LOADER, __func__, "Module %s can not be created", fcn->mod);
     252             : 
     253     2981994 :                 s = newSymbol(fcn->fcn, fcn->command ? COMMANDsymbol : PATTERNsymbol);
     254     1763131 :                 if (s == NULL)
     255           0 :                         throw(LOADER, __func__,
     256             :                                   "Can not create symbol for %s.%s missing", fcn->mod,
     257             :                                   fcn->fcn);
     258     1763131 :                 mb = s->def;
     259     1763131 :                 assert(mb);                             /* if this is NULL, s should have been NULL */
     260             : 
     261     1763131 :                 if (fcn->cname && fcn->cname[0])
     262     1763131 :                         strcpy_len(mb->binding, fcn->cname, sizeof(mb->binding));
     263             :                 /* keep the comment around, setting the static avoids freeing
     264             :                  * the string accidentally, saving on duplicate documentation in
     265             :                  * the code. */
     266     1763131 :                 mb->statichelp = mb->help = fcn->comment;
     267             : 
     268     1763131 :                 sig = newInstructionArgs(mb, mod, putName(fcn->fcn),
     269     1763131 :                                                                  fcn->argc + (fcn->retc == 0));
     270     1763131 :                 if (sig == NULL) {
     271           0 :                         freeSymbol(s);
     272           0 :                         throw(LOADER, __func__, SQLSTATE(HY013) MAL_MALLOC_FAIL);
     273             :                 }
     274     1763131 :                 sig->retc = 0;
     275     1763131 :                 sig->argc = 0;
     276     1763131 :                 sig->token = fcn->command ? COMMANDsymbol : PATTERNsymbol;
     277     1763131 :                 sig->fcn = fcn->imp;
     278     1763131 :                 if (fcn->unsafe)
     279       49092 :                         mb->unsafeProp = 1;
     280             : 
     281             :                 /* add the return variables */
     282     1763131 :                 if (fcn->retc == 0) {
     283       31916 :                         int idx = newTmpVariable(mb, TYPE_void);
     284       31916 :                         if (idx < 0) {
     285           0 :                                 freeInstruction(sig);
     286           0 :                                 freeSymbol(s);
     287           0 :                                 throw(LOADER, __func__, MAL_MALLOC_FAIL);
     288             :                         }
     289       31916 :                         sig = pushReturn(mb, sig, idx);
     290             :                 }
     291             :                 int i;
     292     3631518 :                 for (i = 0; i < fcn->retc; i++) {
     293     1868387 :                         const mel_arg *a = fcn->args + i;
     294     1868387 :                         msg = makeArgument(mb, a, &idx);
     295     1868387 :                         if (msg) {
     296           0 :                                 freeInstruction(sig);
     297           0 :                                 freeSymbol(s);
     298           0 :                                 return msg;
     299             :                         }
     300     1868387 :                         sig = pushReturn(mb, sig, idx);
     301     1868387 :                         int tpe = TYPE_any;
     302     1868387 :                         if (a->nr > 0) {
     303       64868 :                                 if (a->isbat)
     304       53770 :                                         tpe = newBatType(tpe);
     305       64868 :                                 setPolymorphic(sig, tpe, TRUE);
     306             :                         }
     307     1868387 :                         if (a->vargs) {
     308        3186 :                                 sig->varargs |= VARRETS;
     309        3186 :                                 setPolymorphic(sig, TYPE_any, TRUE);
     310             :                         }
     311             :                 }
     312             :                 /* add the arguments */
     313     6408290 :                 for (i = fcn->retc; i < fcn->argc; i++) {
     314     4645159 :                         const mel_arg *a = fcn->args + i;
     315     4645159 :                         msg = makeArgument(mb, a, &idx);
     316     4645159 :                         if (msg) {
     317           0 :                                 freeInstruction(sig);
     318           0 :                                 freeSymbol(s);
     319           0 :                                 return msg;
     320             :                         }
     321     4645159 :                         sig = pushArgument(mb, sig, idx);
     322     4645159 :                         int tpe = TYPE_any;
     323     4645159 :                         if (a->nr > 0) {
     324      337992 :                                 if (a->isbat)
     325      264408 :                                         tpe = newBatType(tpe);
     326      337992 :                                 setPolymorphic(sig, tpe, TRUE);
     327             :                         }
     328     4645159 :                         if (a->vargs) {
     329       11896 :                                 sig->varargs |= VARARGS;
     330       11896 :                                 setPolymorphic(sig, TYPE_any, TRUE);
     331             :                         }
     332             :                 }
     333     1763131 :                 if (mb->errors) {
     334           0 :                         freeInstruction(sig);
     335           0 :                         freeSymbol(s);
     336           0 :                         msg = mb->errors;
     337           0 :                         mb->errors = NULL;
     338           0 :                         return msg;
     339             :                 }
     340     1763131 :                 assert(sig->retc > 0);
     341     1763131 :                 pushInstruction(mb, sig);
     342     1763131 :                 if (mb->errors) {
     343           0 :                         freeSymbol(s);
     344           0 :                         msg = mb->errors;
     345           0 :                         mb->errors = NULL;
     346           0 :                         return msg;
     347             :                 }
     348     1763131 :                 insertSymbol(c, s);
     349             :         }
     350             :         return msg;
     351             : }
     352             : 
     353             : static int
     354     6709248 : makeFuncArgument(MalBlkPtr mb, mel_func_arg *a)
     355             : {
     356     6709248 :         int tpe = TYPE_any;
     357             : 
     358     6709248 :         if (a->type == TYPE_any) {
     359       32928 :                 if (a->isbat)
     360       22176 :                         tpe = newBatType(tpe);
     361       32928 :                 if (a->nr > 0)
     362       32256 :                         setTypeIndex(tpe, a->nr);
     363             :         } else {
     364     6676320 :                 tpe = a->type;
     365     6676320 :                 if (a->isbat)
     366     5500992 :                         tpe = newBatType(tpe);
     367             :         }
     368     6709248 :         return newTmpVariable(mb, tpe);
     369             : }
     370             : 
     371             : int
     372     1672944 : melFunction(bool command, const char *mod, const char *fcn, MALfcn imp,
     373             :                         const char *fname, bool unsafe, const char *comment, int retc,
     374             :                         int argc, ...)
     375             : {
     376     1672944 :         int i, idx;
     377     1672944 :         Module c;
     378     1672944 :         Symbol s;
     379     1672944 :         MalBlkPtr mb;
     380     1672944 :         InstrPtr sig;
     381     1672944 :         va_list va;
     382             : 
     383     1672944 :         assert(mod);
     384     1672944 :         mod = putName(mod);
     385     1672944 :         c = getModule(mod);
     386     1672944 :         if (c == NULL && (c = globalModule(mod)) == NULL)
     387             :                 return MEL_ERR;
     388             : 
     389     3345888 :         s = newSymbol(fcn, command ? COMMANDsymbol : PATTERNsymbol);
     390     1672944 :         if (s == NULL)
     391             :                 return MEL_ERR;
     392     1672944 :         fcn = s->name;
     393     1672944 :         mb = s->def;
     394     1672944 :         (void) comment;
     395     1672944 :         if (fname)
     396     1672944 :                 strcpy_len(mb->binding, fname, sizeof(mb->binding));
     397     1672944 :         if (mb == NULL) {
     398           0 :                 freeSymbol(s);
     399           0 :                 return MEL_ERR;
     400             :         }
     401     1672944 :         sig = newInstructionArgs(mb, mod, fcn, argc + (retc == 0));
     402     1672944 :         if (sig == NULL) {
     403           0 :                 freeSymbol(s);
     404           0 :                 return MEL_ERR;
     405             :         }
     406     1672944 :         sig->retc = 0;
     407     1672944 :         sig->argc = 0;
     408     1672944 :         sig->token = command ? COMMANDsymbol : PATTERNsymbol;
     409     1672944 :         sig->fcn = imp;
     410     1672944 :         if (unsafe)
     411           0 :                 mb->unsafeProp = 1;
     412             :         /* add the return variables */
     413     1672944 :         if (retc == 0) {
     414           0 :                 idx = newTmpVariable(mb, TYPE_void);
     415           0 :                 if (idx < 0) {
     416           0 :                         freeInstruction(sig);
     417           0 :                         freeSymbol(s);
     418           0 :                         return MEL_ERR;
     419             :                 }
     420           0 :                 sig = pushReturn(mb, sig, idx);
     421             :         }
     422             : 
     423     1672944 :         va_start(va, argc);
     424     3355296 :         for (i = 0; i < retc; i++) {
     425     1682352 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     426     1682352 :                 idx = makeFuncArgument(mb, &a);
     427     1682352 :                 if (idx < 0) {
     428           0 :                         freeInstruction(sig);
     429           0 :                         freeSymbol(s);
     430           0 :                         va_end(va);
     431           0 :                         return MEL_ERR;
     432             :                 }
     433     1682352 :                 sig = pushReturn(mb, sig, idx);
     434     1682352 :                 int tpe = TYPE_any;
     435     1682352 :                 if (a.nr > 0) {
     436           0 :                         if (a.isbat)
     437           0 :                                 tpe = newBatType(tpe);
     438           0 :                         setPolymorphic(sig, tpe, TRUE);
     439             :                 }
     440     1682352 :                 if (a.vargs) {
     441           0 :                         sig->varargs |= VARRETS;
     442           0 :                         setPolymorphic(sig, TYPE_any, TRUE);
     443             :                 }
     444             :         }
     445             :         /* add the arguments */
     446     6699840 :         for (i = retc; i < argc; i++) {
     447     5026896 :                 mel_func_arg a = va_arg(va, mel_func_arg);
     448     5026896 :                 idx = makeFuncArgument(mb, &a);
     449     5026896 :                 if (idx < 0) {
     450           0 :                         freeInstruction(sig);
     451           0 :                         freeSymbol(s);
     452           0 :                         va_end(va);
     453           0 :                         return MEL_ERR;
     454             :                 }
     455     5026896 :                 sig = pushArgument(mb, sig, idx);
     456     5026896 :                 int tpe = TYPE_any;
     457     5026896 :                 if (a.nr > 0) {
     458      225792 :                         if (a.isbat)
     459      150528 :                                 tpe = newBatType(tpe);
     460      225792 :                         setPolymorphic(sig, tpe, TRUE);
     461             :                 }
     462     5026896 :                 if (a.vargs) {
     463           0 :                         sig->varargs |= VARARGS;
     464           0 :                         setPolymorphic(sig, TYPE_any, TRUE);
     465             :                 }
     466             :         }
     467     1672944 :         assert(sig->retc > 0);
     468     1672944 :         pushInstruction(mb, sig);
     469     1672944 :         insertSymbol(c, s);
     470     1672944 :         va_end(va);
     471     1672944 :         return MEL_OK;
     472             : }
     473             : 
     474             : static str
     475         336 : malPrelude(Client c, int listing, int *sql, int *mapi)
     476             : {
     477         336 :         int i;
     478         336 :         str msg = MAL_SUCCEED;
     479             : 
     480         336 :         (void) listing;
     481             :         /* Add all atom definitions */
     482       19106 :         for (i = 0; i < mel_modules; i++) {
     483       18770 :                 if (mel_module[i].atoms) {
     484        3012 :                         msg = addAtom(mel_module[i].atoms);
     485        3012 :                         if (msg)
     486           0 :                                 return msg;
     487             :                 }
     488             :         }
     489             : 
     490             :         /* Add the signatures, where we now have access to all atoms */
     491       19106 :         for (i = 0; i < mel_modules; i++) {
     492       18770 :                 const char *name = putName(mel_module[i].name);
     493       18770 :                 if (!malLibraryEnabled(name))
     494           0 :                         continue;
     495       18770 :                 if (mel_module[i].funcs) {
     496       18770 :                         msg = addFunctions(mel_module[i].funcs);
     497       18770 :                         if (!msg && mel_module[i].code) /* some modules may also have some function definitions */
     498           0 :                                 msg = malIncludeString(c, name, (str) mel_module[i].code, listing, NULL);
     499       18770 :                         if (msg)
     500           0 :                                 return msg;
     501             : 
     502             :                         /* mapi should be last, and sql last before mapi */
     503       18770 :                         if (strcmp(name, "sql") == 0) {
     504         336 :                                 *sql = i;
     505         336 :                                 continue;
     506             :                         }
     507       18434 :                         if (strcmp(name, "mapi") == 0) {
     508         336 :                                 *mapi = i;
     509         336 :                                 continue;
     510             :                         }
     511       18098 :                         if (!mel_module[i].inits) {
     512       15075 :                                 msg = initModule(c, name, NULL);
     513       15075 :                                 if (msg)
     514           0 :                                         return msg;
     515             :                         }
     516             :                 }
     517       18098 :                 if (mel_module[i].inits) {
     518             :                         /* mapi should be last, and sql last before mapi */
     519        3023 :                         if (strcmp(name, "sql") == 0 || strcmp(name, "mapi") == 0)
     520           0 :                                 continue;
     521        3023 :                         msg = mel_module[i].inits();
     522        3023 :                         if (msg)
     523           0 :                                 return msg;
     524             :                 }
     525             :         }
     526             :         return MAL_SUCCEED;
     527             : }
     528             : 
     529             : str
     530         336 : malIncludeModules(Client c, char *modules[], int listing, bool no_mapi_server,
     531             :                                   const char *initpasswd)
     532             : {
     533         336 :         str msg;
     534         336 :         int sql = -1, mapi = -1;
     535             : 
     536        3597 :         for (int i = 0; modules[i]; i++) {
     537             :                 /* load library */
     538        3261 :                 if (!malLibraryEnabled(modules[i]))
     539         951 :                         continue;
     540        2310 :                 if ((msg = loadLibrary(modules[i], listing)) != NULL)
     541           0 :                         return msg;
     542             :         }
     543             :         /* load the mal code for these modules and execute preludes */
     544         336 :         if ((msg = malPrelude(c, listing, &sql, &mapi)) != NULL)
     545             :                 return msg;
     546             :         /* mapi should be last, and sql last before mapi */
     547         336 :         if (sql >= 0) {
     548         336 :                 if (mel_module[sql].inits)
     549           0 :                         msg = mel_module[sql].inits();
     550             :                 else
     551         336 :                         msg = initModule(c, "sql", initpasswd);
     552         335 :                 if (msg)
     553             :                         return msg;
     554             :         }
     555         335 :         if (!no_mapi_server && mapi >= 0 && initpasswd == NULL) {
     556         323 :                 if (mel_module[mapi].inits)
     557         323 :                         msg = mel_module[mapi].inits();
     558             :                 else
     559           0 :                         msg = initModule(c, "mapi", NULL);
     560         323 :                 if (msg)
     561             :                         return msg;
     562             :         }
     563             :         return MAL_SUCCEED;
     564             : }

Generated by: LCOV version 1.14