home *** CD-ROM | disk | FTP | other *** search
/ ftp.cs.arizona.edu / ftp.cs.arizona.edu.tar / ftp.cs.arizona.edu / icon / historic / v92.tgz / v92.tar / v92 / src / runtime / fload.r < prev    next >
Text File  |  1996-03-22  |  5KB  |  207 lines

  1. /*
  2.  * File: fload.r
  3.  *  Contents: loadfunc.
  4.  *
  5.  *  This file contains loadfunc(), the dynamic loading function for
  6.  *  Unix systems having the <dlfcn.h> interface.
  7.  *
  8.  *  from Icon:
  9.  *     p := loadfunc(filename, funcname)
  10.  *     p(arg1, arg2, ...)
  11.  *
  12.  *  in C:
  13.  *     int func(int argc, dptr argv)
  14.  *        return -1 for failure, 0 for success, >0 for error
  15.  *        argc is number of true args not including argv[0]
  16.  *        argv[0] is for return value; others are true args
  17.  */
  18.  
  19. #ifdef LoadFunc
  20.  
  21. #ifndef RTLD_LAZY    /* normally from <dlfcn.h> */
  22. #define RTLD_LAZY 1
  23. #endif                    /* RTLD_LAZY */
  24.  
  25. #ifdef FreeBSD
  26.  
  27. /* Sorry, no dlerror() on FreeBSD. Fake it. */
  28. char *dlerror(void)
  29. {
  30.     int no;
  31.  
  32.     if (0 == dlctl(NULL, DL_GETERRNO, &no))
  33.         return(strerror(no));
  34.     else
  35.         return(NULL);
  36. }
  37.  
  38. #endif                    /* __FreeBSD__ */
  39.  
  40. int glue();
  41. int makefunc    Params((dptr d, char *name, int (*func)()));
  42.  
  43. "loadfunc(filename,funcname) - load C function dynamically."
  44.  
  45. function{0,1} loadfunc(filename,funcname)
  46.  
  47.    if !cnv:C_string(filename) then
  48.       runerr(103, filename)
  49.    if !cnv:C_string(funcname) then
  50.       runerr(103, funcname)
  51.  
  52.    abstract {
  53.       return proc
  54.       }
  55.    body
  56.       {
  57.       int (*func)();
  58.       static char *curfile;
  59.       static void *handle;
  60.       char errbuf[1000];
  61.    
  62.       /*
  63.        * Get a library handle, reusing it over successive calls.
  64.        */
  65.       if (!handle || !curfile || strcmp(filename, curfile) != 0) {
  66.          if (curfile)
  67.             free((pointer)curfile);    /* free the old file name */
  68.          curfile = salloc(filename);    /* save the new name */
  69.          handle = dlopen(filename, RTLD_LAZY);    /* get the handle */
  70.          }
  71.       /*
  72.        * Load the function.  Diagnose both library and function errors here.
  73.        */
  74.       if (handle)
  75.          func = (int (*)())dlsym(handle, funcname);
  76.       if (!handle || !func) {
  77.          fprintf(stderr, "\nloadfunc(\"%s\",\"%s\"): %s\n",
  78.             filename, funcname, dlerror());
  79.          runerr(216);
  80.          }
  81.       /*
  82.        * Build and return a proc descriptor.
  83.        */
  84.       if (!makefunc(&result, funcname, func))
  85.          runerr(305);
  86.       return result;
  87.       }
  88. end
  89.  
  90. /*
  91.  * makefunc(d, name, func) -- make function descriptor in d.
  92.  *
  93.  *  Returns 0 if memory could not be allocated.
  94.  */
  95. int makefunc(d, name, func)
  96. dptr d;
  97. char *name;
  98. int (*func)();
  99.    {
  100.    struct b_proc *blk;
  101.  
  102.    blk = (struct b_proc *)malloc(sizeof(struct b_proc));
  103.    if (!blk)
  104.       return 0;
  105.    blk->title = T_Proc;
  106.    blk->blksize = sizeof(struct b_proc);
  107.  
  108. #if COMPILER
  109.    blk->ccode = glue;        /* set code addr to glue routine */
  110. #else                    /* COMPILER */
  111.    blk->entryp.ccode = glue;    /* set code addr to glue routine */
  112. #endif                    /* COMPILER */
  113.  
  114.    blk->nparam = -1;        /* varargs flag */
  115.    blk->ndynam = -1;        /* treat as built-in function */
  116.    blk->nstatic = 0;
  117.    blk->fstatic = 0;
  118.    blk->pname.dword = strlen(name);
  119.    blk->pname.vword.sptr = salloc(name);
  120.    blk->lnames[0].dword = 0;
  121.    blk->lnames[0].vword.sptr = (char *)func;
  122.                 /* save func addr in lnames[0] vword */
  123.    d->dword = D_Proc;        /* build proc descriptor */
  124.    d->vword.bptr = (union block *)blk;
  125.    return 1;
  126.    }
  127.  
  128. /*
  129.  * This glue routine is called when a loaded function is invoked.
  130.  * It digs the actual C code address out of the proc block, and calls that.
  131.  */
  132.  
  133. #if COMPILER
  134.  
  135. int glue(argc, dargv, rslt, succ_cont)
  136. int argc;
  137. dptr dargv;
  138. dptr rslt;
  139. continuation succ_cont;
  140.    {
  141.    int i, status, (*func)();
  142.    struct b_proc *blk;
  143.    struct descrip r;
  144.    tended struct descrip p;
  145.  
  146.    dargv--;                /* reset pointer to proc entry */
  147.    for (i = 0; i <= argc; i++)
  148.       deref(&dargv[i], &dargv[i]);    /* dereference args including proc */
  149.  
  150.    blk = (struct b_proc *)dargv[0].vword.bptr;    /* proc block address */
  151.    func = (int (*)())blk->lnames[0].vword.sptr;    /* entry point address */
  152.  
  153.    p = dargv[0];            /* save proc for traceback */
  154.    dargv[0] = nulldesc;            /* set default return value */
  155.    status = (*func)(argc, dargv);    /* call func */
  156.  
  157.    if (status == 0) {
  158.       *rslt = dargv[0];
  159.       Return;                /* success */
  160.       }
  161.  
  162.    if (status < 0)
  163.       Fail;                /* failure */
  164.  
  165.    r = dargv[0];            /* save result value */
  166.    dargv[0] = p;            /* restore proc for traceback */
  167.    if (is:null(r))
  168.       RunErr(status, NULL);        /* error, no value */
  169.    RunErr(status, &r);            /* error, with value */
  170.    }
  171.  
  172. #else                        /* COMPILER */
  173.  
  174. int glue(argc, dargv)
  175. int argc;
  176. dptr dargv;
  177.    {
  178.    int status, (*func)();
  179.    struct b_proc *blk;
  180.    struct descrip r;
  181.    tended struct descrip p;
  182.  
  183.    blk = (struct b_proc *)dargv[0].vword.bptr;    /* proc block address */
  184.    func = (int (*)())blk->lnames[0].vword.sptr;    /* entry point address */
  185.  
  186.    p = dargv[0];            /* save proc for traceback */
  187.    dargv[0] = nulldesc;            /* set default return value */
  188.    status = (*func)(argc, dargv);    /* call func */
  189.  
  190.    if (status == 0)
  191.       Return;                /* success */
  192.    if (status < 0)
  193.       Fail;                /* failure */
  194.  
  195.    r = dargv[0];            /* save result value */
  196.    dargv[0] = p;            /* restore proc for traceback */
  197.    if (is:null(r))
  198.       RunErr(status, NULL);        /* error, no value */
  199.    RunErr(status, &r);            /* error, with value */
  200.    }
  201.  
  202. #endif                        /* COMPILER */
  203.  
  204. #else                        /* LoadFunc */
  205. static char junk;            /* avoid empty module */
  206. #endif                        /* LoadFunc */
  207.