summaryrefslogtreecommitdiff
path: root/dlperl/dlperl.c
diff options
context:
space:
mode:
Diffstat (limited to 'dlperl/dlperl.c')
-rw-r--r--dlperl/dlperl.c1037
1 files changed, 0 insertions, 1037 deletions
diff --git a/dlperl/dlperl.c b/dlperl/dlperl.c
deleted file mode 100644
index 49d48bb197..0000000000
--- a/dlperl/dlperl.c
+++ /dev/null
@@ -1,1037 +0,0 @@
-static char sccsid[] = "@(#)dlperl.c 1.2 10/12/92 (DLPERL)";
-
-/*
- * name: dlperl.c
- * synopsis: dlperl - perl interface to dynamically linked usubs
- * sccsid: @(#)dlperl.c 1.2 10/12/92
- */
-
-/*
- * NOTE: this code is *not* portable
- * - uses SPARC assembler with gcc asm extensions
- * - is SPARC ABI specific
- * - uses SunOS 4.x dlopen
- *
- * NOTE: not all types are currently implemented
- * - multiple indirections (pointers to pointers, etc.)
- * - structures
- * - quad-precison (long double)
- */
-
-#include <dlfcn.h>
-#include <alloca.h>
-#include <ctype.h>
-
-/* perl */
-#include "EXTERN.h"
-#include "perl.h"
-
-/* globals */
-int Dl_warn = 1;
-int Dl_errno;
-#define DL_ERRSTR_SIZ 256
-char Dl_errstr[DL_ERRSTR_SIZ];
-#define WORD_SIZE (sizeof(int))
-
-static int userval();
-static int userset();
-static int usersub();
-
-
-/*
- * glue perl subroutines and variables to dlperl functions
- */
-enum usersubs {
- US_dl_open,
- US_dl_sym,
- US_dl_call,
- US_dl_close,
-};
-
-enum uservars {
- UV_DL_VERSION,
- UV_DL_WARN,
- UV_dl_errno,
- UV_dl_errstr,
-};
-
-
-int
-dlperl_init()
-{
- struct ufuncs uf;
- char *file = "dlperl.c";
-
- uf.uf_val = userval;
- uf.uf_set = userset;
-
-#define MAGICVAR(name, ix) uf.uf_index = ix, magicname(name, &uf, sizeof uf)
-
- /* subroutines */
- make_usub("dl_open", US_dl_open, usersub, file);
- make_usub("dl_sym", US_dl_sym, usersub, file);
- make_usub("dl_call", US_dl_call, usersub, file);
- make_usub("dl_close", US_dl_close, usersub, file);
-
- /* variables */
- MAGICVAR("DL_VERSION", (int) UV_DL_VERSION);
- MAGICVAR("DL_WARN", (int) UV_DL_WARN);
- MAGICVAR("dl_errno", (int) UV_dl_errno);
- MAGICVAR("dl_errstr", (int) UV_dl_errstr);
-
- return 0;
-}
-
-
-/*
- * USERVAL AND USERSET
- */
-
-/*
- * assign dlperl variables to perl variables
- */
-/*ARGSUSED*/
-static int
-userval(ix, str)
-int ix;
-STR *str;
-{
- switch(ix) {
- case UV_DL_VERSION:
- str_set(str, sccsid);
- break;
- case UV_DL_WARN:
- str_numset(str, (double) Dl_warn);
- break;
- case UV_dl_errno:
- str_numset(str, (double) Dl_errno);
- break;
- case UV_dl_errstr:
- str_set(str, Dl_errstr);
- break;
- default:
- fatal("dlperl: unimplemented userval");
- break;
- }
- return 0;
-}
-
-/*
- * assign perl variables to dlperl variables
- */
-static int
-userset(ix, str)
-int ix;
-STR *str;
-{
- switch(ix) {
- case UV_DL_WARN:
- Dl_warn = (int) str_gnum(str);
- break;
- default:
- fatal("dlperl: unimplemented userset");
- break;
- }
- return 0;
-}
-
-
-/*
- * USERSUBS
- */
-static int
-usersub(ix, sp, items)
-int ix;
-register int sp;
-register int items;
-{
- int oldsp = sp;
- STR **st = stack->ary_array + sp;
- register STR *Str; /* used in str_get and str_gnum macros */
-
- Dl_errno = 0;
- *Dl_errstr = '\0';
-
- switch(ix) {
- case US_dl_open:
- {
- char *file;
- void *dl_so;
-
- if(items != 1) {
- fatal("Usage: $dl_so = &dl_open($file)");
- return oldsp;
- }
-
- file = str_get(st[1]);
- dl_so = dlopen(file, 1);
-
- --sp;
- if(dl_so == NULL) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr, "&dl_open: %s", dlerror());
- if(Dl_warn) warn(Dl_errstr);
-
- astore(stack, ++sp, str_mortal(&str_undef));
- } else {
- astore(stack, ++sp, str_2mortal(str_make(
- (char *) &dl_so, sizeof(void *))));
- }
- break;
- }
- case US_dl_sym:
- {
- void *dl_so;
- char *symbol;
- void *dl_func;
-
- if(items != 2) {
- fatal("Usage: $dl_func = &dl_sym($dl_so, $symbol)");
- return oldsp;
- }
-
- dl_so = *(void **) str_get(st[1]);
- symbol = str_get(st[2]);
- dl_func = dlsym(dl_so, symbol);
-
- --sp;
- if(dl_func == NULL) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr, "&dl_sym: %s", dlerror());
- if(Dl_warn) warn(Dl_errstr);
-
- astore(stack, ++sp, str_mortal(&str_undef));
- } else {
- astore(stack, ++sp, str_2mortal(str_make(
- (char *) &dl_func, sizeof(void *))));
- }
- break;
- }
- case US_dl_call:
- {
- void *dl_func;
- char *parms_desc, *return_desc;
- int nstack, nparm, narr, nlen, nrep;
- int f_indirect, f_no_parm, f_result;
- char c, *c_p; int c_pn = 0;
- unsigned char C, *C_p; int C_pn = 0;
- short s, *s_p; int s_pn = 0;
- unsigned short S, *S_p; int S_pn = 0;
- int i, *i_p; int i_pn = 0;
- unsigned int I, *I_p; int I_pn = 0;
- long l, *l_p; int l_pn = 0;
- unsigned long L, *L_p; int L_pn = 0;
- float f, *f_p; int f_pn = 0;
- double d, *d_p; int d_pn = 0;
- char *a, **a_p; int a_pn = 0;
- char *p, **p_p; int p_pn = 0;
- unsigned int *stack_base, *stack_p;
- unsigned int *xp;
- void (*func)();
- unsigned int ret_o;
- double ret_fd;
- float ret_f;
- char *c1;
- int n1, n2;
-
- if(items < 3) {
-fatal("Usage: @vals = &dl_call($dl_func, $parms_desc, $return_desc, @parms)");
- return oldsp;
- }
- dl_func = *(void **) str_get(st[1]);
- parms_desc = str_get(st[2]);
- return_desc = str_get(st[3]);
-
- /* determine size of stack and temporaries */
-# define CNT_STK_TMP(PN, SN) \
- n2 = 0; do { \
- if(f_indirect) { \
- PN += narr; \
- ++nstack; \
- if(!f_no_parm) \
- nparm += narr; \
- } else { \
- nstack += SN; \
- if(!f_no_parm) \
- ++nparm; \
- } \
- } while(++n2 < nrep); \
- f_indirect = f_no_parm = narr = nrep = 0;
-
- nstack = 0;
- nparm = 0;
- f_indirect = f_no_parm = narr = nrep = 0;
- for(c1 = parms_desc;*c1;++c1) {
- switch(*c1) {
- case ' ':
- case '\t':
- break;
-
- case 'c': /* signed char */
- CNT_STK_TMP(c_pn, 1);
- break;
- case 'C': /* unsigned char */
- CNT_STK_TMP(C_pn, 1);
- break;
- case 's': /* signed short */
- CNT_STK_TMP(s_pn, 1);
- break;
- case 'S': /* unsigned short */
- CNT_STK_TMP(S_pn, 1);
- break;
- case 'i': /* signed int */
- CNT_STK_TMP(i_pn, 1);
- break;
- case 'I': /* unsigned int */
- CNT_STK_TMP(I_pn, 1);
- break;
- case 'l': /* signed long */
- CNT_STK_TMP(l_pn, 1);
- break;
- case 'L': /* unsigned long */
- CNT_STK_TMP(L_pn, 1);
- break;
- case 'f': /* float */
- CNT_STK_TMP(f_pn, 1);
- break;
- case 'd': /* double */
- CNT_STK_TMP(d_pn, 2);
- break;
- case 'a': /* ascii (null-terminated) string */
- CNT_STK_TMP(a_pn, 1);
- break;
- case 'p': /* pointer to <nlen> buffer */
- CNT_STK_TMP(p_pn, 1);
- break;
-
- case '&': /* pointer = [1] */
- if(f_indirect) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: too many indirections, with char %c",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- f_indirect = 1;
- narr = 1;
- break;
- case '[': /* array */
- if(f_indirect) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: too many indirections, with char %c",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- f_indirect = 1;
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- while(isdigit(*c1)) {
- narr = narr * 10 + (*c1 - '0');
- ++c1;
- }
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- if(*c1 != ']') {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: bad char %c, expected ]",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- break;
- case '<': /* length */
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- while(isdigit(*c1))
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- if(*c1 != '>') {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: bad char %c, expected >",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- break;
- case '+':
- break;
- case '-':
- f_no_parm = 1;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if(nrep) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: too many repeats");
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- while(isdigit(*c1)) {
- nrep = nrep * 10 + (*c1 - '0');
- ++c1;
- }
- --c1;
- break;
- default:
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: bad char %c",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- }
- /* trailing &[]<>+-0-9 is ignored */
- if(nparm != items - 3) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: bad parameter count %d, expected %d",
- items - 3, nparm);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- nparm = 4;
-
- /* allocate temporaries */
- if((c_pn && (c_p = (char *)
- alloca(c_pn * sizeof(char))) == NULL) ||
- (C_pn && (C_p = (unsigned char *)
- alloca(C_pn * sizeof(unsigned char))) == NULL) ||
- (s_pn && (s_p = (short *)
- alloca(s_pn * sizeof(short))) == NULL) ||
- (S_pn && (S_p = (unsigned short *)
- alloca(S_pn * sizeof(unsigned short))) == NULL) ||
- (i_pn && (i_p = (int *)
- alloca(i_pn * sizeof(int))) == NULL) ||
- (I_pn && (I_p = (unsigned int *)
- alloca(I_pn * sizeof(unsigned int))) == NULL) ||
- (l_pn && (l_p = (long *)
- alloca(l_pn * sizeof(long))) == NULL) ||
- (L_pn && (L_p = (unsigned long *)
- alloca(L_pn * sizeof(unsigned long))) == NULL) ||
- (f_pn && (f_p = (float *)
- alloca(f_pn * sizeof(float))) == NULL) ||
- (d_pn && (d_p = (double *)
- alloca(d_pn * sizeof(double))) == NULL) ||
- (a_pn && (a_p = (char **)
- alloca(a_pn * sizeof(char *))) == NULL) ||
- (p_pn && (p_p = (char **)
- alloca(p_pn * sizeof(char *))) == NULL)) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr, "&dl_call: bad alloca");
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
-
- /* grow stack - maintains stack alignment (double word) */
- /* NOTE: no functions should be called otherwise the stack */
- /* that is being built will be corrupted */
- /* NOTE: some of the stack is pre-allocated, but is not */
- /* reused here */
- if(alloca(nstack * WORD_SIZE) == NULL) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr, "&dl_call: bad alloca");
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
-
- /* stack base */
-#if !defined(lint)
- asm("add %%sp,68,%%o0;st %%o0,%0" :
- "=g" (stack_base) : /* input */ : "%%o0");
-#else
- stack_base = 0;
-#endif
- stack_p = stack_base;
-
- /* layout stack */
-# define LAY_STK_NUM(T, P, PN) \
- n2 = 0; do { \
- if(f_indirect) { \
- *stack_p++ = (unsigned int) &P[PN]; \
- if(f_no_parm) { \
- PN += narr; \
- } else { \
- for(n1 = 0;n1 < narr;++n1) { \
- P[PN++] = (T) \
- str_gnum(st[nparm++]); \
- } \
- } \
- } else { \
- if(f_no_parm) { \
- ++stack_p; \
- } else { \
- *stack_p++ = (T) \
- str_gnum(st[nparm++]); \
- } \
- } \
- } while(++n2 < nrep); \
- f_indirect = f_no_parm = narr = nrep = 0;
-
-# define LAY_STK_DOUBLE(T, P, PN) \
- n2 = 0; do { \
- if(f_indirect) { \
- *stack_p++ = (unsigned int) &P[PN]; \
- if(f_no_parm) { \
- PN += narr; \
- } else { \
- for(n1 = 0;n1 < narr;++n1) { \
- P[PN++] = (T) \
- str_gnum(st[nparm++]); \
- } \
- } \
- } else { \
- if(f_no_parm) { \
- stack_p += 2; \
- } else { \
- d = (T) str_gnum(st[nparm++]); \
- xp = (unsigned int *) &d; \
- *stack_p++ = *xp++; \
- *stack_p++ = *xp; \
- } \
- } \
- } while(++n2 < nrep); \
- f_indirect = f_no_parm = narr = nrep = 0;
-
-# define LAY_STK_STR(P, PN) \
- n2 = 0; do { \
- if(f_indirect) { \
- *stack_p++ = (unsigned int) &P[PN]; \
- if(f_no_parm) { \
- PN += narr; \
- } else { \
- for(n1 = 0;n1 < narr;++n1) { \
- P[PN++] = \
- str_get(st[nparm++]); \
- } \
- } \
- } else { \
- if(f_no_parm) { \
- ++stack_p; \
- } else { \
- *stack_p++ = (unsigned int) \
- str_get(st[nparm++]); \
- } \
- } \
- } while(++n2 < nrep); \
- f_indirect = f_no_parm = narr = nrep = 0;
-
- c_pn = C_pn = s_pn = S_pn = i_pn = I_pn = l_pn = L_pn = 0;
- f_pn = d_pn = a_pn = p_pn = 0;
- f_indirect = f_no_parm = narr = nrep = 0;
- for(c1 = parms_desc;*c1;++c1) {
- switch(*c1) {
- case ' ':
- case '\t':
- break;
-
- case 'c': /* signed char */
- LAY_STK_NUM(char, c_p, c_pn);
- break;
- case 'C': /* unsigned char */
- LAY_STK_NUM(unsigned char, C_p, C_pn);
- break;
- case 's': /* signed short */
- LAY_STK_NUM(short, s_p, s_pn);
- break;
- case 'S': /* unsigned short */
- LAY_STK_NUM(unsigned short, S_p, S_pn);
- break;
- case 'i': /* signed int */
- LAY_STK_NUM(int, i_p, i_pn);
- break;
- case 'I': /* unsigned int */
- LAY_STK_NUM(unsigned int, I_p, I_pn);
- break;
- case 'l': /* signed long */
- LAY_STK_NUM(long, l_p, l_pn);
- break;
- case 'L': /* unsigned long */
- LAY_STK_NUM(unsigned long, L_p, L_pn);
- break;
- case 'f': /* float */
- LAY_STK_NUM(float, f_p, f_pn);
- break;
- case 'd': /* double */
- LAY_STK_DOUBLE(double, d_p, d_pn);
- break;
- case 'a': /* ascii (null-terminated) string */
- LAY_STK_STR(a_p, a_pn);
- break;
- case 'p': /* pointer to <nlen> buffer */
- LAY_STK_STR(p_p, p_pn);
- break;
-
- case '&': /* pointer = [1] */
- if(f_indirect) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: too many indirections, with char %c",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- f_indirect = 1;
- narr = 1;
- break;
- case '[': /* array */
- if(f_indirect) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: too many indirections, with char %c",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- f_indirect = 1;
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- while(isdigit(*c1)) {
- narr = narr * 10 + (*c1 - '0');
- ++c1;
- }
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- if(*c1 != ']') {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: bad char %c, expected ]",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- break;
- case '<': /* length */
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- while(isdigit(*c1))
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- if(*c1 != '>') {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: bad char %c, expected >",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- break;
- case '+':
- break;
- case '-':
- f_no_parm = 1;
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if(nrep) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: too many repeats");
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- while(isdigit(*c1)) {
- nrep = nrep * 10 + (*c1 - '0');
- ++c1;
- }
- --c1;
- break;
- default:
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: bad char %c",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- }
- /* trailing &[]<>+-0-9 is ignored */
-
- /* call function */
- /* NOTE: the first 6 words are passed in registers %o0 - %o5 */
- /* %sp+68 to %sp+92 are vacant, but allocated */
- /* and shadow %o0 - %o5 */
- /* above stack_base starts at %sp+68 and the function */
- /* call below sets up %o0 - %o5 from stack_base */
- func = (void (*)()) dl_func;
- (*func)(stack_base[0], stack_base[1], stack_base[2],
- stack_base[3], stack_base[4], stack_base[5]);
-
- /* save return value */
- /* NOTE: return values are either in %o0 or %f0 */
-#if !defined(lint)
- asm("st %%o0,%0" : "=g" (ret_o) : /* input */);
- asm("std %%f0,%0" : "=g" (ret_fd) : /* input */);
- asm("st %%f0,%0" : "=g" (ret_f) : /* input */);
-#else
- ret_o = 0; ret_fd = 0.0; ret_f = 0.0;
-#endif
-
- /* parameter results */
-# define RES_NUM(P, PN, SN) \
- n2 = 0; do { \
- if(f_indirect) { \
- ++nstack; \
- if(f_result) { \
- for(n1 = 0;n1 < narr;++n1) { \
- astore(stack, ++sp, str_2mortal( \
- str_nmake((double) P[PN++]))); \
- } \
- } else { \
- PN += narr; \
- } \
- } else { \
- nstack += SN; \
- if(f_result) { \
- astore(stack, ++sp, \
- str_mortal(&str_undef));\
- } \
- } \
- } while(++n2 < nrep); \
- f_indirect = f_result = narr = nlen = nrep = 0;
-
-# define RES_STR(P, PN, L, SN) \
- n2 = 0; do { \
- if(f_indirect) { \
- ++nstack; \
- if(f_result) { \
- for(n1 = 0;n1 < narr;++n1) { \
- astore(stack, ++sp, str_2mortal( \
- str_make(P[PN++], L))); \
- } \
- } else { \
- PN += narr; \
- } \
- } else { \
- if(f_result) { \
- astore(stack, ++sp, str_2mortal(\
- str_make((char *) \
- stack_base[nstack], L))); \
- } \
- nstack += SN; \
- } \
- } while(++n2 < nrep); \
- f_indirect = f_result = narr = nlen = nrep = 0;
-
- --sp;
- nstack = 0;
- c_pn = C_pn = s_pn = S_pn = i_pn = I_pn = l_pn = L_pn = 0;
- f_pn = d_pn = a_pn = p_pn = 0;
- f_indirect = f_result = narr = nlen = nrep = 0;
- for(c1 = parms_desc;*c1;++c1) {
- switch(*c1) {
- case ' ':
- case '\t':
- break;
-
- case 'c': /* signed char */
- RES_NUM(c_p, c_pn, 1);
- break;
- case 'C': /* unsigned char */
- RES_NUM(C_p, C_pn, 1);
- break;
- case 's': /* signed short */
- RES_NUM(s_p, s_pn, 1);
- break;
- case 'S': /* unsigned short */
- RES_NUM(S_p, S_pn, 1);
- break;
- case 'i': /* signed int */
- RES_NUM(i_p, i_pn, 1);
- break;
- case 'I': /* unsigned int */
- RES_NUM(I_p, I_pn, 1);
- break;
- case 'l': /* signed long */
- RES_NUM(l_p, l_pn, 1);
- break;
- case 'L': /* unsigned long */
- RES_NUM(L_p, L_pn, 1);
- break;
- case 'f': /* float */
- RES_NUM(f_p, f_pn, 1);
- break;
- case 'd': /* double */
- RES_NUM(d_p, d_pn, 2);
- break;
- case 'a': /* ascii (null-terminated) string */
- RES_STR(a_p, a_pn, 0, 1);
- break;
- case 'p': /* pointer to <nlen> buffer */
- RES_STR(p_p, p_pn, nlen, 1);
- break;
-
- case '&': /* pointer = [1] */
- if(f_indirect) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: too many indirections, with char %c",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- f_indirect = 1;
- narr = 1;
- break;
- case '[': /* array */
- if(f_indirect) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: too many indirections, with char %c",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- f_indirect = 1;
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- while(isdigit(*c1)) {
- narr = narr * 10 + (*c1 - '0');
- ++c1;
- }
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- if(*c1 != ']') {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: bad char %c, expected ]",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- break;
- case '<': /* length */
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- while(isdigit(*c1)) {
- nlen = nlen * 10 + (*c1 - '0');
- ++c1;
- }
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- if(*c1 != '>') {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: bad char %c, expected >",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- break;
- case '+':
- f_result = 1;
- break;
- case '-':
- break;
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- if(nrep) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: too many repeats");
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- while(isdigit(*c1)) {
- nrep = nrep * 10 + (*c1 - '0');
- ++c1;
- }
- --c1;
- break;
- default:
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: parms_desc %s: bad char %c",
- parms_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- }
- /* trailing &[]<>+-0-9 is ignored */
-
- /* return value */
-# define RET_NUM(T, S, P, R) \
- if(f_indirect) { \
- P = (T *) ret_o; \
- for(n1 = 0;n1 < narr;++n1) { \
- S = *P++; \
- astore(stack, ++sp, str_2mortal( \
- str_nmake((double) S))); \
- } \
- } else { \
- S = (T) R; \
- astore(stack, ++sp, str_2mortal( \
- str_nmake((double) S))); \
- }
-
-# define RET_STR(S, P, L) \
- if(f_indirect) { \
- P = (char **) ret_o; \
- for(n1 = 0;n1 < narr;++n1) { \
- S = *P++; \
- astore(stack, ++sp, str_2mortal( \
- str_make((char *) S, L))); \
- } \
- } else { \
- S = (char *) ret_o; \
- astore(stack, ++sp, str_2mortal( \
- str_make((char *) S, L))); \
- }
-
- f_indirect = nlen = narr = 0;
- for(c1 = return_desc;*c1;++c1) {
- switch(*c1) {
- case ' ':
- case '\t':
- break;
-
- case 'c': /* signed char */
- RET_NUM(char, c, c_p, ret_o);
- goto ret_exit;
- case 'C': /* unsigned char */
- RET_NUM(unsigned char, C, C_p, ret_o);
- goto ret_exit;
- case 's': /* signed short */
- RET_NUM(short, s, s_p, ret_o);
- goto ret_exit;
- case 'S': /* unsigned short */
- RET_NUM(unsigned short, S, S_p, ret_o);
- goto ret_exit;
- case 'i': /* signed int */
- RET_NUM(int, i, i_p, ret_o);
- goto ret_exit;
- case 'I': /* unsigned int */
- RET_NUM(unsigned int, I, I_p, ret_o);
- goto ret_exit;
- case 'l': /* signed long */
- RET_NUM(long, l, l_p, ret_o);
- goto ret_exit;
- case 'L': /* unsigned long */
- RET_NUM(unsigned long, L, L_p, ret_o);
- goto ret_exit;
- case 'f': /* float */
- RET_NUM(float, f, f_p, ret_f);
- break;
- case 'd': /* double */
- RET_NUM(double, d, d_p, ret_fd);
- goto ret_exit;
- case 'a': /* ascii (null-terminated) string */
- RET_STR(a, a_p, 0);
- goto ret_exit;
- case 'p': /* pointer to <nlen> buffer */
- RET_STR(p, p_p, nlen);
- goto ret_exit;
-
- case '&': /* pointer = [1] */
- if(f_indirect) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: return_desc %s: too many indirections, with char %c",
- return_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- f_indirect = 1;
- narr = 1;
- break;
- case '[': /* array */
- if(f_indirect) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: return_desc %s: too many indirections, with char %c",
- return_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- f_indirect = 1;
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- while(isdigit(*c1)) {
- narr = narr * 10 + (*c1 - '0');
- ++c1;
- }
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- if(*c1 != ']') {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: return_desc %s: bad char %c, expected ]",
- return_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- break;
- case '<': /* length */
- ++c1;
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- while(isdigit(*c1)) {
- nlen = nlen * 10 + (*c1 - '0');
- ++c1;
- }
- while(*c1 == ' ' && *c1 == '\t')
- ++c1;
- if(*c1 != '>') {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: return_desc %s: bad char %c, expected >",
- return_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- break;
- default:
- Dl_errno = 1;
- (void) sprintf(Dl_errstr,
- "&dl_call: return_desc %s: bad char %c",
- return_desc, *c1);
- if(Dl_warn) warn(Dl_errstr);
- return oldsp;
- }
- }
-ret_exit: /* anything beyond first [cCsSiIlLdfap] is ignored */
- break;
- }
- case US_dl_close:
- {
- void *dl_so;
- int dl_err;
-
- if(items != 1) {
- fatal("Usage: $dl_err = &dl_close($dl_so)");
- return oldsp;
- }
-
- dl_so = *(void **) str_get(st[1]);
- dl_err = dlclose(dl_so);
-
- --sp;
- if(dl_err) {
- Dl_errno = 1;
- (void) sprintf(Dl_errstr, "&dl_close: %s", dlerror());
- if(Dl_warn) warn(Dl_errstr);
- }
- astore(stack, ++sp, str_2mortal(str_nmake((double) dl_err)));
- break;
- }
- default:
- fatal("dlperl: unimplemented usersub");
- break;
- }
- return sp;
-}