home *** CD-ROM | disk | FTP | other *** search
- static char SccsId[] = "@(#)sybperl.c 1.9 12/20/91";
- /************************************************************************/
- /* Copyright 1991 by Michael Peppler and ITF Management SA */
- /* */
- /* Full ownership of this software, and all rights pertaining to */
- /* the for-profit distribution of this software, are retained by */
- /* Michael Peppler and ITF Management SA. You are permitted to */
- /* use this software without fee. This software is provided "as */
- /* is" without express or implied warranty. You may redistribute */
- /* this software, provided that this copyright notice is retained, */
- /* and that the software is not distributed for profit. If you */
- /* wish to use this software in a profit-making venture, you must */
- /* first license this code and its underlying technology from */
- /* ITF Management SA. */
- /* */
- /* Bottom line: you can have this software, you can use it, you */
- /* can give it away. You just can't sell any or all parts of it */
- /* without prior permission from ITF Management SA. */
- /************************************************************************/
-
- /* sybperl.c
- *
- * Call Sybase DB-Library functions from Perl.
- * Written by Michael Peppler (mpeppler@itf.ch)
- * ITF Management SA, 13 rue de la Fontaine
- * CH-1204 Geneva, Switzerland
- * Tel: (+4122) 312 1311 Fax: (+4122) 312 1322
- */
-
-
- /*
- * The Perl/Sybase savestr() conflict.
- * Both Perl and Sybase DB-Library have a function called savestr().
- * This creates a problem when calling dbcmd() and dbuse(). There are
- * several ways to work around this, one of which is to #define
- * BROKEN_DBCMD, which enables some code that I've written to simulate
- * dbcmd() locally. See Makefile and BUGS for details.
- */
- #include "EXTERN.h"
- #include "perl.h"
- #undef MAX
- #undef MIN
-
- #if !defined(VERSION3)
- #define str_2static(s) str_2mortal(s)
- #endif
-
- #include <sybfront.h>
- #include <sybdb.h>
- #include <syberror.h>
-
- #include "patchlevel.h"
-
- extern int wantarray;
-
- /*
- * The variables that the Sybase routines set, and that you may want
- * to test in your Perl script. These variables are READ-ONLY.
- */
- static enum uservars
- {
- UV_SUCCEED, /* Returns SUCCEED */
- UV_FAIL, /* Returns FAIL */
- UV_NO_MORE_ROWS, /* Returns NO_MORE_ROWS */
- UV_NO_MORE_RESULTS, /* Returns NO_MORE_RESULTS */
- UV_ComputeId, /* Returns the compute id of the row (in dbnextrow()) */
- UV_SybperlVer, /* Returns Sybperl Version/Patchlevel */
- UV_DBstatus, /* The value status value of the last dbnextrow() call */
- };
-
- /*
- * User subroutines that we have implemented. I've found that I can do
- * all the stuff I want to with this subset of DB-Library. Let me know
- * if you implement further routines.
- * The names are self-explanatory.
- */
- static enum usersubs
- {
- US_dblogin, /* This also performs the first dbopen() */
- US_dbopen,
- US_dbclose,
- US_dbcmd,
- US_dbsqlexec,
- US_dbresults,
- US_dbnextrow,
- US_dbcancel,
- US_dbcanquery,
- US_dbexit,
- US_dbuse,
- #ifdef HAS_CALLBACK
- US_dberrhandle,
- US_dbmsghandle,
- #endif
- US_dbstrcpy,
- };
-
- #ifndef MAX_DBPROCS
- #define MAX_DBPROCS 25 /* Change this if you really want your perl script to talk to */
- /* more than 25 dataserver connections at a time ...*/
- #endif
-
- static LOGINREC *login;
- static DBPROCESS *dbproc[MAX_DBPROCS];
- static int exitCalled = 0; /* Set to 1 if dbexit() has been called. */
- static int ComputeId;
- static int DBstatus; /* Set by dbnextrow() */
-
- /* Stack pointer for the error routines. This is set to the stack pointer
- when entering into the sybase subroutines. Error and message
- handling needs this. */
-
- static int perl_sp;
-
- /* Current error handler name. */
-
- static char *err_handler_sub;
-
- /* Current message handler subroutine name */
-
- static char *msg_handler_sub;
-
- /* Macro to access the stack. This is necessary since error handlers may
- call perl routines and thus the stack may change. I hope most compilers
- will optimize this reasonably. */
-
- #define STACK(SP) (stack->ary_array + (SP))
-
-
- static int usersub();
- static int userset();
- static int userval();
- static int err_handler(), msg_handler();
-
- int userinit()
- {
- init_sybase();
- }
-
- int
- init_sybase()
- {
- struct ufuncs uf;
- char *filename = "sybase.c";
-
- if (dbinit() == FAIL) /* initialize dblibrary */
- exit(ERREXIT);
- /*
- * Install the user-supplied error-handling and message-handling routines.
- * They are defined at the bottom of this source file.
- */
- dberrhandle(err_handler);
- dbmsghandle(msg_handler);
-
- if(MAX_DBPROCS > 25)
- dbsetmaxprocs(MAX_DBPROCS);
-
- uf.uf_set = userset;
- uf.uf_val = userval;
-
- #define MAGICVAR(name, ix) uf.uf_index = ix, magicname(name, &uf, sizeof uf)
-
- MAGICVAR("SUCCEED", UV_SUCCEED);
- MAGICVAR("FAIL",UV_FAIL);
- MAGICVAR("NO_MORE_ROWS", UV_NO_MORE_ROWS);
- MAGICVAR("NO_MORE_RESULTS", UV_NO_MORE_RESULTS);
- MAGICVAR("ComputeId", UV_ComputeId);
- MAGICVAR("SybperlVer", UV_SybperlVer);
-
- make_usub("dblogin", US_dblogin, usersub, filename);
- make_usub("dbopen", US_dbopen, usersub, filename);
- make_usub("dbclose", US_dbclose, usersub, filename);
- make_usub("dbcmd", US_dbcmd, usersub, filename);
- make_usub("dbsqlexec", US_dbsqlexec, usersub, filename);
- make_usub("dbresults", US_dbresults, usersub, filename);
- make_usub("dbnextrow", US_dbnextrow, usersub, filename);
- make_usub("dbcancel", US_dbcancel, usersub, filename);
- make_usub("dbcanquery", US_dbcanquery, usersub, filename);
- make_usub("dbexit", US_dbexit, usersub, filename);
- make_usub("dbuse", US_dbuse, usersub, filename);
- #ifdef HAS_CALLBACK
- make_usub("dberrhandle", US_dberrhandle, usersub, filename);
- make_usub("dbmsghandle", US_dbmsghandle, usersub, filename);
- #endif
- make_usub("dbstrcpy", US_dbstrcpy, usersub, filename);
-
- }
-
- static int
- usersub(ix, sp, items)
- int ix;
- register int sp;
- register int items;
- {
- STR **st = stack->ary_array + sp;
- ARRAY *ary = stack;
- register int i;
- register STR *Str; /* used in str_get and str_gnum macros */
- int inx = -1; /* Index into dbproc[] array. Passed as first parameter to nearly all &dbxxx() calls */
-
-
- if(exitCalled)
- fatal("&dbexit() has been called. Access to Sybase impossible.");
-
- perl_sp = sp + items;
-
- /*
- * We're calling some dblib function, but dblogin has not been
- * called. Two actions are possible: either fail the call, or call
- * dblogin/dbopen with the default info. The second option is used
- * to keep backwards compatibility with an older version of
- * sybperl. A call to fatal(msg) is probably better.
- */
- if(!login && (ix != US_dblogin) && (ix != US_dbmsghandle) && (ix != US_dberrhandle))
- { /* You can call &dbmsghandle/errhandle before calling &dblogin */
- #ifdef OLD_SYBPERL
- login = dblogin();
- dbproc[0] = dbopen(login, NULL);
- #else
- fatal("&dblogin has not been called yet!");
- #endif
- }
-
- switch (ix)
- {
- case US_dblogin:
- if (items > 2)
- fatal("Usage: &dblogin([user[,pwd]])");
- if (login)
- fatal("&dblogin() called twice.");
- else
- {
- int retval;
-
- login = dblogin();
- if(items)
- {
- DBSETLUSER(login, (char *)str_get(STACK(sp)[1]));
- if(items > 1)
- DBSETLPWD(login, (char *)str_get(STACK(sp)[2]));
- }
-
- dbproc[0] = dbopen(login, NULL);
- str_numset(STACK(sp)[0], (double) 0);
- }
- break;
- case US_dbopen:
- if (items != 0)
- fatal("Usage: $dbproc = &dbopen;");
- else
- {
- int j;
- for(j = 0; j < MAX_DBPROCS; ++j)
- if(dbproc[j] == NULL)
- break;
- if(j == MAX_DBPROCS)
- fatal("&dbopen: No more dbprocs available.");
- dbproc[j] = dbopen(login, NULL);
- str_numset(STACK(sp)[0], (double) j);
- }
- break;
- case US_dbclose:
- if (items != 1)
- fatal("Usage: $ret = &dbclose($dbproc);");
- else
- {
- inx = getDbProc(STACK(sp)[1]);
-
- dbclose(dbproc[inx]);
- dbproc[inx] = (DBPROCESS *)NULL;
- }
- break;
- case US_dbcancel:
- if (items > 1)
- fatal("Usage: &dbcancel($dbproc)");
- else
- {
- int retval;
- #if defined(BROKEN_DBCMD)
- DBSTRING *ptr;
- DBSTRING *old;
- #endif
- if(items)
- inx = getDbProc(STACK(sp)[1]);
- else
- inx = 0;
-
- retval = dbcancel(dbproc[inx]);
- str_numset(STACK(sp)[0], (double) retval);
- #if defined(BROKEN_DBCMD)
- ptr = dbproc[inx]->dbcmdbuf;
- while(ptr)
- {
- old = ptr;
- ptr = ptr->strnext;
- free(old->strtext);
- free(old);
- }
- dbproc[inx]->dbcmdbuf = NULL;
- #endif
- }
- break;
-
- case US_dbcanquery:
- if (items > 1)
- fatal("Usage: &dbcanquery($dbproc)");
- else
- {
- int retval;
-
- if(items)
- inx = getDbProc(STACK(sp)[1]);
- else
- inx = 0;
-
- retval = dbcanquery(dbproc[inx]);
- str_numset(STACK(sp)[0], (double) retval);
- }
- break;
-
- case US_dbexit:
- if (items != 0)
- fatal("Usage: &dbexit()");
- else
- {
- dbexit(dbproc[0]);
- exitCalled++;
- str_numset(STACK(sp)[0], (double) 1);
- }
- break;
-
- case US_dbuse:
- if (items > 2)
- fatal("Usage: &dbuse($dbproc, $database)");
- else
- {
- #if defined(BROKEN_DBCMD)
- /*
- * Why doesn't this $@#! dbuse() call not work from within
- * Perl????? (So we emulate it here, but I sure can't
- * guarantee anything about portability to future versions
- * of DB-Library!
- */
- DBSTRING *new;
- DBSTRING *sav;
- char buff[256];
- int ret, off;
-
- if(items == 2)
- {
- inx = getDbProc(STACK(sp)[1]);
- off = 2;
- }
- else
- inx = 0, off = 1;
-
- strcpy(buff, "use ");
- strcat(buff, (char *)str_get(STACK(sp)[off]));
- sav = dbproc[inx]->dbcmdbuf;
-
- Newz(902, new, 1, DBSTRING);
- New(902, new->strtext, strlen(buff) + 1, BYTE);
- strcpy(new->strtext, buff);
- new->strtotlen = strlen(new->strtext)+1;
- dbproc[inx]->dbcmdbuf = new;
-
- ret = dbsqlexec(dbproc[inx]);
- ret = dbresults(dbproc[inx]);
- while((ret = dbnextrow(dbproc[inx])) != NO_MORE_ROWS)
- ;
-
- Safefree(new->strtext);
- Safefree(new);
-
- dbproc[inx]->dbcmdbuf = sav;
- str_numset(STACK(sp)[0], (double) SUCCEED);
- #else
- int retval, off;
- char str[255];
-
- if(items == 2)
- {
- inx = getDbProc(STACK(sp)[1]);
- off = 2;
- }
- else
- inx = 0, off = 1;
-
- strcpy(str, (char *)str_get(STACK(sp)[off]));
-
-
- retval = dbuse(dbproc[inx], str);
- str_numset(STACK(sp)[0], (double) retval);
- #endif
- }
- break;
-
- case US_dbsqlexec:
- if (items > 1)
- fatal("Usage: &dbsqlexec($dbproc)");
- else
- {
- int retval;
- if(items)
- inx = getDbProc(STACK(sp)[1]);
- else
- inx = 0;
-
- retval = dbsqlexec(dbproc[inx]);
- str_numset(STACK(sp)[0], (double) retval);
- }
- break;
-
- case US_dbresults:
- if (items > 1)
- fatal("Usage: &dbresults($dbproc)");
- else
- {
- int retval;
-
- if(items)
- inx = getDbProc(STACK(sp)[1]);
- else
- inx = 0;
-
- retval = dbresults(dbproc[inx]);
- str_numset(STACK(sp)[0], (double) retval);
- #if defined(BROKEN_DBCMD)
- if(retval==NO_MORE_RESULTS)
- {
- DBSTRING *ptr = dbproc[inx]->dbcmdbuf;
- DBSTRING *old;
-
- while(ptr)
- {
- old = ptr;
- ptr = ptr->strnext;
- Safefree(old->strtext);
- Safefree(old);
- }
- dbproc[inx]->dbcmdbuf = NULL;
- }
- #endif
- }
- break;
-
- case US_dbcmd:
- if (items > 2)
- fatal("Usage: &dbcmd($dbproc, $str)");
- else
- {
- int retval, off;
- #if defined(BROKEN_DBCMD)
- DBSTRING *ptr;
- DBSTRING *new, *old;
- char *strdup();
- #endif
- if(items == 2)
- {
- inx = getDbProc(STACK(sp)[1]);
- off = 2;
- }
- else
- inx = 0, off = 1;
-
- #if defined(BROKEN_DBCMD)
- ptr = dbproc[inx]->dbcmdbuf;
-
- Newz(902, new, 1, DBSTRING);
- New(902, new->strtext, strlen((char *)str_get(STACK(sp)[off])) + 1, BYTE);
- strcpy(new->strtext, (char *)str_get(STACK(sp)[off]));
- new->strtotlen = strlen(new->strtext)+1;
- if(!ptr)
- dbproc[inx]->dbcmdbuf = new;
- else
- {
- while(ptr->strnext)
- ptr = ptr->strnext;
- ptr->strnext = new;
- }
- #else
- retval = dbcmd(dbproc[inx], (char *)str_get(STACK(sp)[off]));
- #endif
- str_numset(STACK(sp)[0], (double) retval);
- }
- break;
-
- case US_dbnextrow:
- if (items > 1)
- fatal("Usage: @arr = &dbnextrow($dbproc)");
- else
- {
- int retval;
- if(items)
- inx = getDbProc(STACK(sp)[1]);
- else
- inx = 0;
-
- --sp; /* otherwise you get an empty element at the beginning of the results array! */
-
- DBstatus = retval = dbnextrow(dbproc[inx]);
- if(retval == REG_ROW)
- {
- char buff[1024], *p = NULL, *t;
- BYTE *data;
- int col, type, numcols = dbnumcols(dbproc[inx]);
- int len;
- DBFLT8 tmp;
-
- ComputeId = 0;
-
- for(col = 1, buff[0] = 0; col <= numcols; ++col)
- {
- type = dbcoltype(dbproc[inx], col);
- len = dbdatlen(dbproc[inx],col);
- data = (BYTE *)dbdata(dbproc[inx],col);
- t = &buff[0];
- if(!data && !len)
- {
- strcpy(buff,"NULL");
- }
- else
- {
- switch(type)
- {
- case SYBCHAR:
- strncpy(buff,data,len);
- buff[len] = 0;
- break;
- case SYBTEXT:
- New(902, p, len + 1, char);
- strncpy(p, data, len);
- p[len] = 0;
- t = p;
- break;
- case SYBINT1:
- case SYBBIT: /* a bit is at least a byte long... */
- sprintf(buff,"%u",*(unsigned char *)data);
- break;
- case SYBINT2:
- sprintf(buff,"%d",*(short *)data);
- break;
- case SYBINT4:
- sprintf(buff,"%d",*(long *)data);
- break;
- case SYBFLT8:
- sprintf(buff,"%.6f",*(double *)data);
- break;
- case SYBMONEY:
- dbconvert(dbproc[inx], SYBMONEY, data, len, SYBFLT8, &tmp, -1);
- sprintf(buff,"%.6f",tmp);
- break;
- case SYBDATETIME:
- dbconvert(dbproc[inx], SYBDATETIME, data, len, SYBCHAR, buff, -1);
- break;
- case SYBBINARY:
- dbconvert(dbproc[inx], type, data, len, SYBCHAR, buff, -1);
- break;
- default:
- /* ignored for the moment */
- break;
- }
- }
- (void)astore(ary,++sp,str_2static(str_make(t, 0)));
- /*
- * If we've allocated some space to retrieve a
- * SYBTEXT field, then free it now.
- */
- if(t == p)
- {
- Safefree(p);
- p = NULL;
- }
- }
- }
- if (retval > 0)
- {
- char buff[1024], *p = NULL, *t;
- BYTE *data;
- int col, type, numcols;
- int len;
- DBFLT8 tmp;
-
- ComputeId = retval;
- numcols = dbnumalts(dbproc[inx], ComputeId);
-
- for(col = 1, buff[0] = 0; col <= numcols; ++col)
- {
- type = dbalttype(dbproc[inx], ComputeId, col);
- len = dbadlen(dbproc[inx], ComputeId, col);
- data = (BYTE *)dbadata(dbproc[inx], ComputeId, col);
- t = &buff[0];
- if(!data && !len)
- {
- strcpy(buff,"NULL");
- }
- else
- {
- switch(type)
- {
- case SYBCHAR:
- strncpy(buff,data,len);
- buff[len] = 0;
- break;
- case SYBTEXT:
- New(902, p, len + 1, char);
- strncpy(p, data, len);
- p[len] = 0;
- t = p;
- break;
- case SYBINT1:
- case SYBBIT: /* a bit is at least a byte long... */
- sprintf(buff,"%d",*(char *)data);
- break;
- case SYBINT2:
- sprintf(buff,"%d",*(short *)data);
- break;
- case SYBINT4:
- sprintf(buff,"%d",*(long *)data);
- break;
- case SYBFLT8:
- sprintf(buff,"%.6f",*(double *)data);
- break;
- case SYBMONEY:
- dbconvert(dbproc[inx], SYBMONEY, data, len, SYBFLT8, &tmp, -1);
- sprintf(buff,"%.6f",tmp);
- break;
- case SYBDATETIME:
- dbconvert(dbproc[inx], SYBDATETIME, data, len, SYBCHAR, buff, -1);
- break;
- case SYBBINARY:
- dbconvert(dbproc[inx], type, data, len, SYBCHAR, buff, -1);
- break;
- default:
- /* ignored at the moment... */
- break;
- }
- }
- (void)astore(ary,++sp,str_2static(str_make(t, 0)));
- /*
- * If we've allocated some space because the field
- * was a text field, then free it now:
- */
- if(t == p)
- {
- Safefree(p);
- p = NULL;
- }
-
- }
- }
- #if defined(BROKEN_DBCMD)
- /*
- * We can't rely on dbcmd(),dbresults() etc. to clean up
- * the dbcmdbuf linked list, so we have to it ourselves...
- */
- if(retval == NO_MORE_ROWS && !DBMORECMDS(dbproc[inx]))
- {
- DBSTRING *ptr = dbproc[inx]->dbcmdbuf;
- DBSTRING *new, *old;
-
- while(ptr)
- {
- old = ptr;
- ptr = ptr->strnext;
- Safefree(old->strtext);
- Safefree(old);
- }
- dbproc[inx]->dbcmdbuf = NULL;
- }
- #endif
- }
- break;
- #ifdef HAS_CALLBACK
- case US_dberrhandle:
- if (items > 1)
- fatal ("Usage: &dberrhandle($handler)");
- else
- {
- char *old = err_handler_sub;
- if (items == 1)
- {
- if (STACK (sp)[1] == &str_undef)
- err_handler_sub = 0;
- else
- {
- char *sub = (char *) str_get (STACK (sp)[1]);
- New (902, err_handler_sub, strlen (sub) + 1, char);
- strcpy (err_handler_sub, sub);
- }
- }
-
- if (old)
- {
- STACK (sp)[0] = str_2mortal (str_make (old, strlen (old)));
- if (items == 1)
- Safefree (old);
- }
- else
- STACK (sp)[0] = &str_undef;
- }
- break;
- case US_dbmsghandle:
- if (items > 1)
- fatal ("Usage: &dbmsghandle($handler)");
- else
- {
- char *old = msg_handler_sub;
- if (items == 1)
- {
- if (STACK (sp)[1] == &str_undef)
- msg_handler_sub = 0;
- else
- {
- char *sub = (char *) str_get (STACK (sp)[1]);
- New (902, msg_handler_sub, strlen (sub) + 1, char);
- strcpy (msg_handler_sub, sub);
- }
- }
-
- if (old)
- {
- STACK (sp)[0] = str_2mortal (str_make (old, strlen (old)));
- if (items == 1)
- Safefree (old);
- }
- else
- STACK (sp)[0] = &str_undef;
- }
- break;
- #endif /* HAS_CALLBACK */
- case US_dbstrcpy:
- if (items > 1)
- fatal("Usage: $string = &dbstrcpy($dbproc)");
- else
- {
- int retval, len;
- char *buff;
-
- if(items)
- inx = getDbProc(STACK(sp)[1]);
- else
- inx = 0;
-
- if(dbproc[inx] && (len = dbstrlen(dbproc[inx])))
- {
- New(902, buff, len+1, char);
- retval = dbstrcpy(dbproc[inx], 0, -1, buff);
- str_set(STACK(sp)[0], buff);
- Safefree(buff);
- }
- else
- str_set(STACK(sp)[0], "");
- }
- break;
-
- default:
- fatal("Unimplemented user-defined subroutine");
- }
- return sp;
- }
-
- /*
- * Return the value of a userdefined variable. These variables are all
- * READ-ONLY in Perl.
- */
- static int
- userval(ix, str)
- int ix;
- STR *str;
- {
- char buff[24];
-
- switch (ix)
- {
- case UV_SUCCEED:
- str_numset(str, (double)SUCCEED);
- break;
- case UV_FAIL:
- str_numset(str, (double)FAIL);
- break;
- case UV_NO_MORE_ROWS:
- str_numset(str, (double)NO_MORE_ROWS);
- break;
- case UV_NO_MORE_RESULTS:
- str_numset(str, (double)NO_MORE_RESULTS);
- break;
- case UV_ComputeId:
- str_numset(str, (double)ComputeId);
- break;
- case UV_SybperlVer:
- sprintf(buff, "%d.%3.3d", VERSION, PATCHLEVEL);
- str_set(str, buff);
- break;
- case UV_DBstatus:
- str_numset(str, (double)DBstatus);
- break;
- }
- return 0;
- }
-
- static int
- userset(ix, str) /* Not used. None of these variables are user-settable */
- int ix;
- STR *str;
- {
- return 0;
- }
-
-
- /*ARGSUSED*/
- static int err_handler(db, severity, dberr, oserr, dberrstring, oserrstr)
- DBPROCESS *db;
- int severity;
- int dberr;
- int oserr;
- char *dberrstring;
- char *oserrstr;
- {
- #ifdef HAS_CALLBACK
- /* If we have error handler subroutine, use it. */
- if (err_handler_sub)
- {
- int sp = perl_sp;
- int j;
-
- for(j = 0; j < MAX_DBPROCS; ++j)
- if(db == dbproc[j])
- break;
- if(j == MAX_DBPROCS)
- j = 0;
-
- /* Reserve spot for return value. */
- astore (stack, ++ sp, Nullstr);
-
- /* Set up arguments. */
- astore (stack, ++ sp,
- str_2mortal (str_nmake ((double) j)));
- astore (stack, ++ sp, str_2mortal (str_nmake ((double) severity)));
- astore (stack, ++ sp, str_2mortal (str_nmake ((double) dberr)));
- astore (stack, ++ sp, str_2mortal (str_nmake ((double) oserr)));
- if (dberrstring && *dberrstring)
- astore (stack, ++ sp, str_2mortal (str_make (dberrstring, 0)));
- else
- astore (stack, ++ sp, &str_undef);
- if (oserrstr && *oserrstr)
- astore (stack, ++ sp, str_2mortal (str_make (oserrstr, 0)));
- else
- astore (stack, ++ sp, &str_undef);
-
- /* Call it. */
- sp = callback (err_handler_sub, sp, 0, 1, 6);
-
- /* Return whatever it returned. */
- return (int) str_gnum (STACK (sp)[0]);
- }
- #endif /* HAS_CALLBACK */
- if ((db == NULL) || (DBDEAD(db)))
- return(INT_EXIT);
- else
- {
- fprintf(stderr,"DB-Library error:\n\t%s\n", dberrstring);
-
- if (oserr != DBNOERR)
- fprintf(stderr,"Operating-system error:\n\t%s\n", oserrstr);
-
- return(INT_CANCEL);
- }
- }
-
- /*ARGSUSED*/
-
- static int msg_handler(db, msgno, msgstate, severity, msgtext, srvname, procname, line)
- DBPROCESS *db;
- DBINT msgno;
- int msgstate;
- int severity;
- char *msgtext;
- char *srvname;
- char *procname;
- DBUSMALLINT line;
- {
- #ifdef HAS_CALLBACK
- /* If we have message handler subroutine, use it. */
- if (msg_handler_sub)
- {
- int sp = perl_sp;
- int j;
-
- for(j = 0; j < MAX_DBPROCS; ++j)
- if(db == dbproc[j])
- break;
- if(j == MAX_DBPROCS)
- j = 0;
-
- /* Reserve spot for return value. */
- astore (stack, ++ sp, Nullstr);
-
- /* Set up arguments. */
- astore (stack, ++ sp,
- str_2mortal (str_nmake ((double) j)));
- astore (stack, ++ sp, str_2mortal (str_nmake ((double) msgno)));
- astore (stack, ++ sp, str_2mortal (str_nmake ((double) msgstate)));
- astore (stack, ++ sp, str_2mortal (str_nmake ((double) severity)));
- if (msgtext && *msgtext)
- astore (stack, ++ sp, str_2mortal (str_make (msgtext, 0)));
- else
- astore (stack, ++ sp, &str_undef);
- if (srvname && *srvname)
- astore (stack, ++ sp, str_2mortal (str_make (srvname, 0)));
- else
- astore (stack, ++ sp, &str_undef);
- if (procname && *procname)
- astore (stack, ++ sp, str_2mortal (str_make (procname, 0)));
- else
- astore (stack, ++ sp, &str_undef);
- astore (stack, ++ sp, str_2mortal (str_nmake ((double) line)));
-
- /* Call it. */
- sp = callback (msg_handler_sub, sp, 0, 1, 8);
-
- /* Return whatever it returned. */
- return (int) str_gnum (STACK (sp)[0]);
- }
- #endif /* HAS_CALLBACK */
- #ifdef OLD_SYBPERL
- if(!severity)
- return 0;
- #endif
- fprintf (stderr,"Msg %ld, Level %d, State %d\n",
- msgno, severity, msgstate);
- if (strlen(srvname) > 0)
- fprintf (stderr,"Server '%s', ", srvname);
- if (strlen(procname) > 0)
- fprintf (stderr,"Procedure '%s', ", procname);
- if (line > 0)
- fprintf (stderr,"Line %d", line);
-
- fprintf(stderr,"\n\t%s\n", msgtext);
-
- return(0);
- }
-
- /*
- * Get the index into the dbproc[] array from a Perl STR datatype.
- * Check that the index is reasonably valid...
- */
- int getDbProc(Str)
- STR *Str;
- {
- int ix = (int)str_gnum(Str);
-
- if(ix < 0 || ix >= MAX_DBPROCS)
- fatal("$dbproc parameter is out of range.");
- return ix;
- }
-
- #ifdef HAS_CALLBACK
-
- /* Taken from Perl 4.018 usub/usersub.c. mp. */
-
- /* Be sure to refetch the stack pointer after calling these routines. */
-
- int
- callback(subname, sp, gimme, hasargs, numargs)
- char *subname;
- int sp; /* stack pointer after args are pushed */
- int gimme; /* called in array or scalar context */
- int hasargs; /* whether to create a @_ array for routine */
- int numargs; /* how many args are pushed on the stack */
- {
- static ARG myarg[3]; /* fake syntax tree node */
- int arglast[3];
-
- arglast[2] = sp;
- sp -= numargs;
- arglast[1] = sp--;
- arglast[0] = sp;
-
- if (!myarg[0].arg_ptr.arg_str)
- myarg[0].arg_ptr.arg_str = str_make("",0);
-
- myarg[1].arg_type = A_WORD;
- myarg[1].arg_ptr.arg_stab = stabent(subname, FALSE);
-
- myarg[2].arg_type = hasargs ? A_EXPR : A_NULL;
-
- return do_subr(myarg, gimme, arglast);
- }
-
- #endif /* HAS_CALLBACK */
-
-