This is sybperl.c in view mode; [Download] [Up]
static char SccsId[] = "@(#)sybperl.c 1.14 4/6/93"; /************************************************************************/ /* Copyright 1991, 1992, 1993 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 */ #include "EXTERN.h" #include "perl.h" #undef MAX #undef MIN #if defined(VERSION3) #define str_2mortal(s) str_2static(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, US_DBMORECMDS, US_DBCMDROW, US_DBROWS, US_DBCOUNT, US_DBCURCMD, US_dbhasretstat, US_dbretstatus, #if defined(DBLIB42) US_dbsafestr, #endif US_dbwritetext, }; #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() */ static int DBReturnAssoc; /* If true, dbnextrow returns an associative array */ /* 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); make_usub("DBCURCMD", US_DBCURCMD, usersub, filename); make_usub("DBMORECMDS", US_DBMORECMDS, usersub, filename); make_usub("DBCMDROW", US_DBCMDROW, usersub, filename); make_usub("DBROWS", US_DBROWS, usersub, filename); make_usub("DBCOUNT", US_DBCOUNT, usersub, filename); make_usub("dbhasretstat", US_dbhasretstat, usersub, filename); make_usub("dbretstatus", US_dbretstatus, usersub, filename); #if defined(DBLIB42) make_usub("dbsafestr", US_dbsafestr, usersub, filename); #endif make_usub("dbwritetext", US_dbwritetext, 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 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 > 3) fatal("Usage: &dblogin([user[,pwd[,server]]])"); else { int j = 0; char *server = NULL, *user = NULL, *pwd = NULL; if (!login) login = dblogin(); switch(items) { case 3: server = (char *)str_get(STACK(sp)[3]); case 2: if(STACK(sp)[2] != &str_undef) { pwd = (char *)str_get(STACK(sp)[2]); if(pwd && strlen(pwd)) DBSETLPWD(login, pwd); } case 1: if(STACK(sp)[1] != &str_undef) { user = (char *)str_get(STACK(sp)[1]); if(user && strlen(user)) DBSETLUSER(login, user); } } for(j = 0; j < MAX_DBPROCS; ++j) if(dbproc[j] == NULL) break; if(j == MAX_DBPROCS) fatal ("&dblogin: No more dbprocs available."); if((dbproc[j] = dbopen(login, server)) == NULL) j = -1; str_numset(STACK(sp)[0], (double) j); } break; case US_dbopen: if (items > 1) fatal("Usage: $dbproc = &dbopen([server]);"); else { int j; char *server = NULL; for(j = 0; j < MAX_DBPROCS; ++j) if(dbproc[j] == NULL) break; if(j == MAX_DBPROCS) fatal("&dbopen: No more dbprocs available."); if(items == 1) server = (char *)str_get(STACK(sp)[1]); dbproc[j] = dbopen(login, server); 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(items) inx = getDbProc(STACK(sp)[1]); else inx = 0; retval = dbcancel(dbproc[inx]); str_numset(STACK(sp)[0], (double) retval); } 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 { 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); } 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); } break; case US_dbcmd: if (items > 2) fatal("Usage: &dbcmd($dbproc, $str)"); else { int retval, off; if(items == 2) { inx = getDbProc(STACK(sp)[1]); off = 2; } else inx = 0, off = 1; retval = dbcmd(dbproc[inx], (char *)str_get(STACK(sp)[off])); str_numset(STACK(sp)[0], (double) retval); } break; case US_dbnextrow: if (items > 2) fatal("Usage: @arr = &dbnextrow([$dbproc [, $returnAssoc]])"); else { int retval; char buff[1024], *p = NULL, *t; BYTE *data; int col, type, numcols; int len; int doAssoc = 0; DBFLT8 tmp; char *colname; char cname[64]; inx = 0; switch(items) { case 2: doAssoc = (int)str_gnum(STACK(sp)[2]); case 1: inx = getDbProc(STACK(sp)[1]); break; } --sp; /* otherwise you get an empty element at the beginning of the results array! */ DBstatus = retval = dbnextrow(dbproc[inx]); if(retval == REG_ROW) { ComputeId = 0; numcols = dbnumcols(dbproc[inx]); } else { ComputeId = retval; numcols = dbnumalts(dbproc[inx], ComputeId); } for(col = 1, buff[0] = 0; col <= numcols; ++col) { colname = NULL; if(!ComputeId) { type = dbcoltype(dbproc[inx], col); len = dbdatlen(dbproc[inx],col); data = (BYTE *)dbdata(dbproc[inx],col); colname = dbcolname(dbproc[inx], col); if(!colname || !colname[0]) { sprintf(cname, "Col %d", col); colname = cname; } } else { int colid = dbaltcolid(dbproc[inx], ComputeId, col); type = dbalttype(dbproc[inx], ComputeId, col); len = dbadlen(dbproc[inx], ComputeId, col); data = (BYTE *)dbadata(dbproc[inx], ComputeId, col); if(colid > 0) colname = dbcolname(dbproc[inx], colid); if(!colname || !colname[0]) { sprintf(cname, "Col %d", col); colname = cname; } } t = &buff[0]; if(!data && !len) { #if defined(NULL_IS_UNDEF) t = &str_undef; #else strcpy(buff,"NULL"); #endif } 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; #if defined(DBLIB42) case SYBREAL: sprintf(buff, "%.6f", *(float *)data); break; case SYBDATETIME4: dbconvert(dbproc[inx], SYBDATETIME4, data, len, SYBCHAR, buff, -1); break; #endif case SYBIMAGE: fatal ("&dbnextrow: SYBIMAGE datatypes are not handled at the moment!"); break; default: /* * WARNING! * * We convert unknown data types to SYBCHAR * without checking to see if the resulting * string will fit in the 'buff' variable. * This isn't very pretty... */ dbconvert(dbproc[inx], type, data, len, SYBCHAR, buff, -1); break; } } if(doAssoc) (void)astore(ary,++sp,str_2mortal(str_make(colname, 0))); (void)astore(ary,++sp,str_2mortal(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; } } } 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; case US_DBCURCMD: if (items > 1) fatal("Usage: $num = &DBCURCMD($dbproc)"); else { int retval = 0; if(items) inx = getDbProc(STACK(sp)[1]); else inx = 0; if(dbproc[inx]) retval = DBCURCMD(dbproc[inx]); str_numset(STACK(sp)[0], (double) retval); } break; case US_DBMORECMDS: if (items > 1) fatal("Usage: $rc = &DBMORECMDS($dbproc)"); else { int retval = 0; if(items) inx = getDbProc(STACK(sp)[1]); else inx = 0; if(dbproc[inx]) retval = DBMORECMDS(dbproc[inx]); str_numset(STACK(sp)[0], (double) retval); } break; case US_DBCMDROW: if (items > 1) fatal("Usage: $rc = &DBCMDROW($dbproc)"); else { int retval = 0; if(items) inx = getDbProc(STACK(sp)[1]); else inx = 0; if(dbproc[inx]) retval = DBCMDROW(dbproc[inx]); str_numset(STACK(sp)[0], (double) retval); } break; case US_DBROWS: if (items > 1) fatal("Usage: $rc = &DBROWS($dbproc)"); else { int retval = 0; if(items) inx = getDbProc(STACK(sp)[1]); else inx = 0; if(dbproc[inx]) retval = DBROWS(dbproc[inx]); str_numset(STACK(sp)[0], (double) retval); } break; case US_DBCOUNT: if (items > 1) fatal("Usage: $ret = &DBCOUNT($dbproc)"); else { int retval = 0; if(items) inx = getDbProc(STACK(sp)[1]); else inx = 0; if(dbproc[inx]) retval = DBCOUNT(dbproc[inx]); str_numset(STACK(sp)[0], (double) retval); } break; case US_dbhasretstat: if (items > 1) fatal("Usage: $rc = &dbhasretstat($dbproc)"); else { int retval = 0; if(items) inx = getDbProc(STACK(sp)[1]); else inx = 0; if(dbproc[inx]) retval = dbhasretstat(dbproc[inx]); str_numset(STACK(sp)[0], (double) retval); } break; case US_dbretstatus: if (items > 1) fatal("Usage: $rc = &dbretstatus($dbproc)"); else { int retval = 0; if(items) inx = getDbProc(STACK(sp)[1]); else inx = 0; if(dbproc[inx]) retval = dbretstatus(dbproc[inx]); str_numset(STACK(sp)[0], (double) retval); } break; #if defined(DBLIB42) case US_dbsafestr: if (items > 3 || items != 2) fatal ("Usage: $string = &dbsafestr($dbproc,$instring[,$quote_char])"); else { int retval, len, quote; char *buff, *instr; inx = getDbProc (STACK (sp)[1]); instr = (char *) str_get (STACK (sp)[2]); if (items != 3) quote = DBBOTH; else { char *quote_char = (char *) str_get (STACK (sp)[3]); if (*quote_char == '\"') quote = DBDOUBLE; else if (*quote_char == '\'') quote = DBSINGLE; else { /* invalid */ str_set (STACK (sp)[0], ""); break; } } if (dbproc[inx] && (len = strlen (instr))) { /* twice as much space needed worst case */ New (902, buff, len * 2 + 1, char); retval = dbsafestr (dbproc[inx], instr, -1, buff, -1, quote); str_set (STACK (sp)[0], buff); Safefree (buff); } } break; #endif case US_dbwritetext: if (items != 5) fatal ("Usage: dbwritetext($dbproc1,$column,$dbproc2,$col,$text"); else { int inx2, wcolnum; char *wcolname, *wtext; int ret; inx = getDbProc(STACK(sp)[1]); wcolname = str_get(STACK(sp)[2]); inx2 = getDbProc(STACK(sp)[3]); wcolnum = (int)str_gnum(STACK(sp)[4]); wtext = str_get(STACK(sp)[5]); ret = dbwritetext (dbproc[inx], wcolname, dbtxptr(dbproc[inx2], wcolnum), DBTXPLEN, dbtxtimestamp(dbproc[inx2], wcolnum), 0, strlen(wtext), wtext); str_numset(STACK(sp)[0], (double) ret); } 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) int ix; STR *str; { #if defined(USERVAL_SET_FATAL) fatal("sybperl: trying to write to a read-only variable."); #else return 0; #endif } /*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."); if(dbproc[ix] == NULL || DBDEAD(dbproc[ix])) fatal("$dbproc parameter is NULL or the connection to the server has been closed."); 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 */
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.