Here's my solution to this problem.  (I've used this solution for a while.)

Icon code:
----------

# Dynamically-loaded procedure to do C's "sprintf(format,x)".
procedure sprintf1(a[])
  return (sprintf1 := pathload("libCutils.so","isprintf"))!a
end

  
C code (really, RTL, has to be run through "rtt")
--------------------
#include "Icon2C.h"
int isprintf(int argc, struct descrip argv[]) {
  char cs[32];
  ArgString(1);  ArgReal(2);
  sprintf(cs, StringVal(argv[1]), RealVal(argv[2]));
  /* RTL hiding inside this macro: */
  RetString(cs);
}

The whole "trick" is in the Icon2c.h file, which is my replacement of the
standard "icall.h".  I append this file below.


                            Kostas


============================================================================

/*
              ===================================
              ICON PROCEDURES CALLING C FUNCTIONS
              ===================================

              0. Declaration of the C function.
              1. Entering the C function:
                   a. Checking and converting arguments
                   b. Getting the C values
              2. Allocations of Icon structures
              3. Returning to Icon


              NOTE: a C routine *must* contain code for *all* of the above
              steps, as some macros assume that others have been called before
              them.  In particular, 1b depends on 1a, and 2 on 1.
*/



/*
  0. Declaration of the C function.
  =================================

  To allow dynamic loading by Icon, the C function *must* be declared as
      int func(int argc, dptr argv)
   or like
      int func(int argc, struct descrip argv[])
   See src/runtime/fload.r.
   
   The call of this in Icon looks like "func(x,y,z,...)".

*/



/*  
  1a. Entering the C function: checking and converting arguments
  =============================================================

  This is the most conceptually difficult part.  Familiarity with the
  implementation book is necessary!  Also some familiarity with RTL.

  We have to check the types of the Icon descriptors and "convert" them.
  To understand the details, see the functions cnv_int(), cnv_real(), cnv_str()
  in runtime/cnv.r.  They convert a source descriptor "s" to a destination
  descriptor "d", and return 1 on success and 0 on failure.
  Instead of the following macros one could have used the functions cnv_c_int(),
  cnv_c_dbl(), cnv_c_str() (see runtime/cnv.r), plus error checking.
    
*/

#define ArgInteger(i) do { if (argc < (i)) FailCode(101); \
if (!cnv_int(&argv[i],&argv[i])) ArgError(i,101); } while(0)

#define ArgReal(i) \
do {if (argc < (i))  FailCode(102); \
    if (!cnv_real(&argv[i],&argv[i])) ArgError(i,102); \
   } while(0);

#define ArgString(i) \
do {if (argc < (i))  FailCode(103); \
    if (!cnv_str(&argv[i],&argv[i])) ArgError(i,103); \
   } while(0);

#define ArgList(i) \
do {if (argc < (i))  FailCode(101); \
    if (argv[i].dword != D_List) ArgError(i,108); \
   } while(0);

#define ListLen(d)      ((d).vword.bptr->list.size)



/*  
  1b. Entering the C function: getting the C values
  =============================================================

  Here we get C values out of Icon descriptors.
  The following macros *assume* that the descriptor conversions in 1a above have
  taken place.

*/

#define IntegerVal(d) ((d).vword.integr)
#define RealVal(d)    getdbl(&(d))
#define StringVal(d) \
(*(char*)((d).vword.sptr+(d).dword) ? cnv_c_str(&(d),&(d)) : 0, 
(char*)((d).vword.sptr))


/*
   Given an Icon list descrip "d", fill the C array of ints "a".
   Using cpslots() shortens the necessary code, and takes care of lists that
   have been constructed or modified by put() and get(), etc.
*/
#define IListVal(d,a) \
do {if (sizeof(a[0]) != sizeof(int))  FailCode(101); \
    register int n = ListLen(d); \
    register int i; \
    struct descrip slot[n]; \
    cpslots(&(d),&slot[0],1,n+1); \
    for(i=0; i<n; i++) a[i] = IntegerVal(slot[i]); \
   } while(0);

/* Given an Icon list descrip "d", fill the C array of doubles "a". */
#define RListVal(d,a) \
do {if (sizeof(a[0]) != sizeof(double))  FailCode(102); \
    register int n = ListLen(d); \
    register int i; \
    struct descrip slot[n]; \
    cpslots(&(d),&slot[0],1,n+1); \
    for (i=0; i<n; i++) a[i] = RealVal(slot[i]); \
   } while(0);





/*  
  2. Allocations of Icon structures.
  =============================================================

  The point here is this: if memory is allocated dynamically inside a C routine
  for an Icon structure, say for a block holding a real, the request for space
  to the Icon run-time system may trigger a garbage collection.  The garbage
  collector must be able to recognize and save all values that might be
  referenced after the collection.  Otherwise bugs that are virtually impossible
  to find will ensue.
  The garbage collector is informed by declaring pointers as "tended".  See
  section 4.2 of the RTL paper (The Run-Time Implemenation Language for Icon).

  E.g. if "d" is a C double,

            tended struct b_real *bp;
            Protect(bp = alcreal(d), ReturnErrNum(307,Error));

  The Protect() macro checks that the request for space succeeded.  It is
  defined in  h/grttin.h.

  If a C routine wants to return an Icon real or string, the allocation occurs
  inside the macros RetReal() and RetString() below.
  For allocating lists of integers and reals see
                 mkIlist() and mkRlist()
  in "mklist.r" here.
*/





/* 
  3. Returning from the C function to Icon.
  =============================================================
*/

/* A dynamically-loaded C function returns 0 on success, -1 on failure, 
   or a positive error code. */
#define FailCode(n) return n;
/* Return argv[i] as offending value for error code n */
#define ArgError(i,n) return (argv[0] = argv[i], n)

/* Integers, reals, strings, lists */
#define RetInteger(n) \
  return (argv->dword = D_Integer, argv->vword.integr = n, 0)

/* Given a C double "x", return an Icon real to the calling routine. */
#define RetReal(x) do {  \
  tended struct b_real *d;  \
  Protect(d = alcreal(x), ReturnErrNum(307,Error));  \
  return (argv->dword = D_Real, argv->vword.bptr = (union block *)d, 0);  \
} while(0);

/* Given a C string "s", return an Icon string to the calling routine. */
#define RetString(s) do {  \
  tended struct descrip d; \
  int len = strlen(s);  \
  Protect(StrLoc(d) = alcstr(s,len), ReturnErrNum(306,Error));  \
  StrLen(d) = len;  \
  return (argv->dword = StrLen(d), argv->vword.sptr = StrLoc(d), 0);  \
} while (0);

#define RetConstString(s) \
  return (argv->dword = strlen(s), argv->vword.sptr = s, 0)

/* Here L is supposed to be L = mkIlist(...) or L = mkRlist(...). */
#define RetList(L) \
  return (argv[0].dword = D_List, argv[0].vword.bptr = (union block *)L, 0)


-------------------------------------------------------
This SF.Net email is sponsored by: INetU
Attention Web Developers & Consultants: Become An INetU Hosting Partner.
Refer Dedicated Servers. We Manage Them. You Get 10% Monthly Commission!
INetU Dedicated Managed Hosting http://www.inetu.net/partner/index.php
_______________________________________________
Unicon-group mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/unicon-group

Reply via email to