home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d3xx / d386 / xlispstat.lha / XLispStat / src3.lzh / Mac / macdynload.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-30  |  5.8 KB  |  213 lines

  1. /* macdynload - Dynamic loading and C function calling routines.       */
  2. /* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney                  */
  3. /* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz    */
  4. /* You may give out copies of this software; for conditions see the    */
  5. /* file COPYING included with this distribution.                       */
  6.  
  7. /* Calling conventions are based on the conventions given in the New S */
  8. /* book.                                                               */
  9.  
  10. #ifdef MPWC
  11. #include <Memory.h>
  12. #include <Resources.h>
  13. #else
  14. #include <MenuMgr.h>
  15. #include <ResourceMgr.h>
  16. #endif MPWC
  17.  
  18. #include "xlisp.h"
  19. #include "xlsx.h"
  20.  
  21. #define nil 0L
  22.  
  23. #define seqlen(x) ((vectorp(x)) ? getsize(x) : llength(x))
  24.  
  25. extern char buf[];
  26. extern LVAL s_true;
  27.  
  28. extern LVAL newvector(), make_string(), mklist(), getnextelement();
  29. extern double makedouble();
  30.  
  31. typedef void  (*pfv_t)();    /* pointer to function returning void. */
  32.  
  33. /************************************************************************/
  34. /**                                                                    **/
  35. /**                  Resource File Handling Functions                  **/
  36. /**                                                                    **/
  37. /************************************************************************/
  38.  
  39. LVAL xsopen_resfile()
  40.   char *name;
  41.   int fn;
  42.   
  43.   name = (char *) getstring(xlgastring());
  44.   xllastarg();
  45.   
  46.   CtoPstr(name);
  47.   fn = OpenResFile(name);
  48.   PtoCstr(name);
  49.   return((fn >= 0) ? cvfixnum((FIXTYPE) fn) : NIL);
  50. }
  51.  
  52. LVAL xsclose_resfile()
  53. {
  54.   int fn;
  55.   
  56.   fn = getfixnum(xlgafixnum());
  57.   xllastarg();
  58.   
  59.   CloseResFile(fn);
  60.   return(NIL);
  61. }
  62.  
  63. /************************************************************************/
  64. /**                                                                    **/
  65. /**               Allocation and Error Signalling Functions            **/
  66. /**                                                                    **/
  67. /************************************************************************/
  68.  
  69. static LVAL current_allocs;
  70.  
  71. /* allocate space that will be garbage collected after return */
  72. static char *xscall_alloc(n, m)
  73.      int n, m;
  74. {
  75.   LVAL adata;
  76.   char *p;
  77.  
  78.   adata = newadata(n, m, FALSE);
  79.   if (adata == NIL || (p = getadaddr(adata)) == nil)
  80.     xlfail("allocation failed");
  81.   current_allocs = cons(adata, current_allocs);
  82.   return(p);
  83. }
  84.  
  85. /* error routine for use within C functions */
  86. static xscall_fail(s) char *s; { xlfail(s); }
  87.  
  88. /************************************************************************/
  89. /**                                                                    **/
  90. /**                Lisp to C/FORTRAN Data Conversion                   **/
  91. /**                                                                    **/
  92. /************************************************************************/
  93.  
  94. #define IN 0
  95. #define RE 1
  96.  
  97. typedef struct {
  98.   int type, size;
  99.   char *addr;
  100. } call_arg;
  101.  
  102. /* convert lisp argument to allocated pointer */
  103. static call_arg lisp2arg(x)
  104.      LVAL x;
  105. {
  106.   call_arg a;
  107.   LVAL elem, data;
  108.   int i;
  109.  
  110.   xlprot1(x);
  111.  
  112.   /* make sure x is a sequence and find its length */
  113.   if (! sequencep(x)) x = consa(x);
  114.   a.size = seqlen(x);
  115.  
  116.   /* determine the mode of the data */
  117.   for (i = 0, a.type = IN, data = x; i < a.size; i++) {
  118.     elem = getnextelement(&data, i);
  119.     if (floatp(elem)) a.type = RE;
  120.     else if (! fixp(elem)) xlerror("not a real number", elem);
  121.   }
  122.  
  123.   /* allocate space for the data */
  124.   a.addr = xscall_alloc(a.size, (a.type == IN) ? sizeof(int) : sizeof(double));
  125.  
  126.   /* fill the space */
  127.   for (i = 0, data = x; i < a.size; i++) {
  128.     elem = getnextelement(&data, i);
  129.     if (a.type == IN) ((int *) a.addr)[i] = getfixnum(elem);
  130.     else ((double *) a.addr)[i] = makedouble(elem);
  131.   }
  132.   
  133.   xlpop();
  134.   return(a);
  135. }
  136.  
  137. /* copy allocated pointer back to new lisp list */
  138. static LVAL arg2lisp(a)
  139.      call_arg a;
  140. {
  141.   LVAL x, next;
  142.   int i;
  143.  
  144.   xlsave1(x);
  145.   x = mklist(a.size, NIL);
  146.   for (i = 0, next = x; i < a.size; i++, next = cdr(next)) {
  147.     if (a.type == IN) rplaca(next, cvfixnum((FIXTYPE) ((int *) a.addr)[i]));
  148.     else rplaca(next, cvflonum((FLOTYPE) ((double *) a.addr)[i]));
  149.   }
  150.   xlpop();
  151.   return(x);
  152. }
  153.  
  154. /************************************************************************/
  155. /**                                                                    **/
  156. /**                 Foreign Function Call Function                     **/
  157. /**                                                                    **/
  158. /************************************************************************/
  159.  
  160. LVAL xscall_cfun()
  161. {
  162.   LVAL result, Lname, old_allocs, next;
  163.   call_arg *args, *pargs;
  164.   int nargs, i;
  165.   Handle rhandle;
  166.   void (*routine)();
  167.   char *name;
  168.   XLSXblock params;
  169.  
  170.   xlstkcheck(3);
  171.   xlsave(old_allocs);
  172.   xlprotect(current_allocs);
  173.   xlsave(result);
  174.   old_allocs = current_allocs;
  175.   current_allocs = NIL;
  176.  
  177.   /* get the routine pointer */
  178.   Lname = xlgastring();
  179.   name = (char *) getstring(Lname);
  180.   CtoPstr(name);
  181.   rhandle = GetNamedResource('XLSX', name);
  182.   PtoCstr(name);
  183.   if (! rhandle) xlerror("can't load XLSX resource", Lname);
  184.  
  185.   /* convert the arguments to allocated pointers */
  186.   nargs = xlargc;
  187.   if (nargs == 0) xlfail("too few arguments");
  188.   args = (call_arg *) xscall_alloc(nargs, sizeof(call_arg));
  189.   params.argc = nargs;
  190.   params.argv = (char **) xscall_alloc(nargs, sizeof(char *));
  191.   for (i = 0; i < nargs; i++) {
  192.     args[i] = lisp2arg(xlgetarg());
  193.     params.argv[i] = args[i].addr;
  194.   }
  195.  
  196.   /* make the call */
  197.   HLock(rhandle);
  198.   routine = (pfv_t) *rhandle;
  199.   (*routine)(¶ms);
  200.   HUnlock(rhandle);
  201.   
  202.   /* convert the pointers back to lists, grouped in a list */
  203.   result = (nargs > 0) ? mklist(nargs, NIL) : NIL;
  204.   for (next = result, pargs = args; consp(next); next = cdr(next), pargs++)
  205.     rplaca(next, arg2lisp(*pargs));
  206.   
  207.   current_allocs = old_allocs;
  208.   xlpopn(3);
  209.  
  210.   return(result);
  211. }
  212.