comp.lang.ada
 help / color / mirror / Atom feed
* Wrapping / Interfacing to C macros
@ 2002-08-22 21:56 Le Snelson
  2002-08-22 22:42 ` Dale Stanbrough
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Le Snelson @ 2002-08-22 21:56 UTC (permalink / raw)


I'm hoping someone has seen a dialect or pattern for interfacing to C
macros.  I need to use the ioctl() mechanisms of VxWorks to control
some low level features of a couple of serial cards.  I've never seen
any Ada applications wrapping up linguistic attributes such as the
following from Tornado/target/h/sys/ioctl.h :

#define	_IO(x,y)	(IOC_VOID|((x)<<8)|y)
#define	_IOR(x,y,t)	(IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
#define	_IOW(x,y,t)	(IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
/* this should be _IORW, but stdio got there first */
#define	_IOWR(x,y,t)	(IOC_INOUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)


#define	SIOCSHIWAT	_IOW('s',  0, int)		/* set high watermark */
#define	SIOCGHIWAT	_IOR('s',  1, int)		/* get high watermark */
#define	SIOCSLOWAT	_IOW('s',  2, int)		/* set low watermark */
#define	SIOCGLOWAT	_IOR('s',  3, int)		/* get low watermark */
#define	SIOCATMARK	_IOR('s',  7, int)		/* at oob mark? */


I have one alternative in mind - create a C function to provide all of
these macros through a parameterized selection.

Any other ideas?



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Wrapping / Interfacing to C macros
  2002-08-22 21:56 Wrapping / Interfacing to C macros Le Snelson
@ 2002-08-22 22:42 ` Dale Stanbrough
  2002-08-22 23:29 ` tmoran
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Dale Stanbrough @ 2002-08-22 22:42 UTC (permalink / raw)


In article <ec0cf315.0208221356.7356d38a@posting.google.com>,
 le_snelson@juno.com (Le Snelson) wrote:

> I'm hoping someone has seen a dialect or pattern for interfacing to C
> macros.  I need to use the ioctl() mechanisms of VxWorks to control
> some low level features of a couple of serial cards.  I've never seen
> any Ada applications wrapping up linguistic attributes such as the
> following from Tornado/target/h/sys/ioctl.h :
> 
> #define	_IO(x,y)	(IOC_VOID|((x)<<8)|y)
> #define	_IOR(x,y,t)	(IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
> #define	_IOW(x,y,t)	(IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
> /* this should be _IORW, but stdio got there first */
> #define	_IOWR(x,y,t)	(IOC_INOUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
> 
> 
> #define	SIOCSHIWAT	_IOW('s',  0, int)		/* set high watermark */
> #define	SIOCGHIWAT	_IOR('s',  1, int)		/* get high watermark */
> #define	SIOCSLOWAT	_IOW('s',  2, int)		/* set low watermark */
> #define	SIOCGLOWAT	_IOR('s',  3, int)		/* get low watermark */
> #define	SIOCATMARK	_IOR('s',  7, int)		/* at oob mark? */



Given the fact that you have a type parameter, a generic would
seem the only solution for doing it in Ada.

The rest can be done in standard (type safe!) Ada.

Dale



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Wrapping / Interfacing to C macros
  2002-08-22 21:56 Wrapping / Interfacing to C macros Le Snelson
  2002-08-22 22:42 ` Dale Stanbrough
@ 2002-08-22 23:29 ` tmoran
  2002-08-23  8:26 ` Thierry Lelegard
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: tmoran @ 2002-08-22 23:29 UTC (permalink / raw)


What's wrong with:

  use type Interfaces.C.Unsigned;

  function Shift_Left(Value : Interfaces.C.Unsigned;
                      Amount: Natural) return Interfaces.C.Unsigned is
    -- Note: Here we assume Interfaces.C.Unsigned is 32 bits
    V : constant Interfaces.Unsigned_32 := Interfaces.Unsigned_32(Value);
  begin
    return Interfaces.C.Unsigned(Interfaces.Shift_Left(V, Amount));
  end Shift_Left;

  IOC_IN : constant Interfaces.C.Unsigned :=
  IOCPARM_MASK : constant Interfaces.C.Unsigned :=

- #define _IOW(x,y,t)     (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
  function IOW(x : Character;
               y : Interfaces.C.Unsigned;
               Size : Interfaces.C.Unsigned) return Interfaces.C.Unsigned is
  begin
    return IOC_IN or Shift_Left(Size and IOCPARM_MASK, 16)
           or Shift_Left(Character'pos(x), 8) or y;
  end IOW;

  -- other macros similarly

--#define SIOCSHIWAT      _IOW('s',  0, int)              /* set high watermark */
  SIOCSHIWAT : constant Interfaces.C.Unsigned
    := IOW('s', 0, Interfaces.C.Int'size/Interfaces.C.CHAR_BIT);



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Wrapping / Interfacing to C macros
  2002-08-22 21:56 Wrapping / Interfacing to C macros Le Snelson
  2002-08-22 22:42 ` Dale Stanbrough
  2002-08-22 23:29 ` tmoran
@ 2002-08-23  8:26 ` Thierry Lelegard
  2002-08-23 16:13   ` Warren W. Gay VE3WWG
  2002-08-23 10:18 ` Lutz Donnerhacke
  2002-08-31 15:03 ` Florian Weimer
  4 siblings, 1 reply; 7+ messages in thread
From: Thierry Lelegard @ 2002-08-23  8:26 UTC (permalink / raw)


> I'm hoping someone has seen a dialect or pattern for interfacing to C
> macros.  I need to use the ioctl() mechanisms of VxWorks to control
> some low level features of a couple of serial cards.  I've never seen
> any Ada applications wrapping up linguistic attributes such as the
> following from Tornado/target/h/sys/ioctl.h :
> 
> #define _IO(x,y)        (IOC_VOID|((x)<<8)|y)
> #define _IOR(x,y,t)     (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
> #define _IOW(x,y,t)     (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
> /* this should be _IORW, but stdio got there first */
> #define _IOWR(x,y,t)    (IOC_INOUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
> 
> #define SIOCSHIWAT      _IOW('s',  0, int)              /* set high watermark */
> #define SIOCGHIWAT      _IOR('s',  1, int)              /* get high watermark */
> #define SIOCSLOWAT      _IOW('s',  2, int)              /* set low watermark */
> #define SIOCGLOWAT      _IOR('s',  3, int)              /* get low watermark */
> #define SIOCATMARK      _IOR('s',  7, int)              /* at oob mark? */
> 
> I have one alternative in mind - create a C function to provide all of
> these macros through a parameterized selection.
> 
> Any other ideas?

Well, there is a tradeoff between theoretical-intellectual exercise and
practical-maintainabiliy-portability issue.

In the first case, you can mimic the macro definitions using plain Ada
features.

However, the API specification is C-oriented and only defines the name of
the C macro, not the way it is implemented (using nested macros like your
examples, plain values, etc). We have noticed that different flavors of
UNIX implement ioctl codes, for instance, in many different ways. So,
your plain Ada code which mimics the C macros will not be portable (even
between different versions of the same OS).

You will have the same problem with structures (like the stat/fstat structure).
The UNIX API (POSIX, XPG, etc) defines the name of the structure, the names
of _some_ fields in the structure and that's all. On different UNIXen, the
number of fields is different, contains different fields in addition to the
"standard" ones. Even the order and exact type (int, unsigned, short, etc)
of the standard fields are different.

So, to interface the C UNIX API in a portable, maintainable manner, we use
C jacket routines for each system routine which uses non basic types as
parameters or with parameter values which depend on C macros (like the
ioctl function code).

Thus, we have:
- Portable C jacket routines (they respect the standard C API for system calls).
- Portable interface between the C jacket routines and Ada (provided that
  we only use types which have a direct mapping in Interfaces.C in the interface
  of the jacket routine)
- Portable Ada code.

As a rule of thumb:
- If the information in C UNIX API standard (or man page) is sufficient to
  write an Ada interface using types from Interfaces.C, we write a direct 
  Ada interface.
- If we need to look at the content of some .h file to write an Ada interface,
  then we don't and we write a C jacket routine.

-Thierry Lelegard



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Wrapping / Interfacing to C macros
  2002-08-22 21:56 Wrapping / Interfacing to C macros Le Snelson
                   ` (2 preceding siblings ...)
  2002-08-23  8:26 ` Thierry Lelegard
@ 2002-08-23 10:18 ` Lutz Donnerhacke
  2002-08-31 15:03 ` Florian Weimer
  4 siblings, 0 replies; 7+ messages in thread
From: Lutz Donnerhacke @ 2002-08-23 10:18 UTC (permalink / raw)


* Le Snelson wrote:
>I'm hoping someone has seen a dialect or pattern for interfacing to C
>macros.  I need to use the ioctl() mechanisms of VxWorks to control
>some low level features of a couple of serial cards.  I've never seen
>any Ada applications wrapping up linguistic attributes such as the
>following from Tornado/target/h/sys/ioctl.h :
>
>#define  _IO(x,y)     (IOC_VOID|((x)<<8)|y)
>#define  _IOR(x,y,t)  (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
>#define  _IOW(x,y,t)  (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
>/* this should be _IORW, but stdio got there first */
>#define  _IOWR(x,y,t)  (IOC_INOUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
>
>#define  SIOCSHIWAT  _IOW('s',  0, int)    /* set high watermark */
>#define  SIOCGHIWAT  _IOR('s',  1, int)    /* get high watermark */
>#define  SIOCSLOWAT  _IOW('s',  2, int)    /* set low watermark */
>#define  SIOCGLOWAT  _IOR('s',  3, int)    /* get low watermark */
>#define  SIOCATMARK  _IOR('s',  7, int)    /* at oob mark? */

I usually prefer to define the type in Ada without looking at the C code.

type io_t (c : ioc_t) is record
   x : x_t;
   y : y_t;
   t : iocparam_t;
end record;
for io_t use record
   c at 0 range 24 .. 31;
   t at 0 range 16 .. 23;
   x at 0 range 7 .. 15;
   y at 0 range 0 .. 7;
end record;
for io_t'Bit_Order use ...;

procedure SIOCSHIWAT (level : ...);
function SIOCGHIWAT return ...;



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Wrapping / Interfacing to C macros
  2002-08-23  8:26 ` Thierry Lelegard
@ 2002-08-23 16:13   ` Warren W. Gay VE3WWG
  0 siblings, 0 replies; 7+ messages in thread
From: Warren W. Gay VE3WWG @ 2002-08-23 16:13 UTC (permalink / raw)


Thierry Lelegard wrote:
>>I'm hoping someone has seen a dialect or pattern for interfacing to C
>>macros.  I need to use the ioctl() mechanisms of VxWorks to control
>>some low level features of a couple of serial cards.  I've never seen
>>any Ada applications wrapping up linguistic attributes such as the
>>following from Tornado/target/h/sys/ioctl.h :
>>
>>#define _IO(x,y)        (IOC_VOID|((x)<<8)|y)
>>#define _IOR(x,y,t)     (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|y)
...
> 
> Well, there is a tradeoff between theoretical-intellectual exercise and
> practical-maintainabiliy-portability issue.
> 
> In the first case, you can mimic the macro definitions using plain Ada
> features.
> 
> However, the API specification is C-oriented and only defines the name of
> the C macro, not the way it is implemented (using nested macros like your
> examples, plain values, etc). We have noticed that different flavors of
> UNIX implement ioctl codes, for instance, in many different ways. So,
> your plain Ada code which mimics the C macros will not be portable (even
> between different versions of the same OS).
> 
> You will have the same problem with structures (like the stat/fstat structure).
> The UNIX API (POSIX, XPG, etc) defines the name of the structure, the names
> of _some_ fields in the structure and that's all. On different UNIXen, the
> number of fields is different, contains different fields in addition to the
> "standard" ones. Even the order and exact type (int, unsigned, short, etc)
> of the standard fields are different.
> 
> So, to interface the C UNIX API in a portable, maintainable manner, we use
> C jacket routines for each system routine which uses non basic types as
> parameters or with parameter values which depend on C macros (like the
> ioctl function code).
> 
> Thus, we have:
> - Portable C jacket routines (they respect the standard C API for system calls).
> - Portable interface between the C jacket routines and Ada (provided that
>   we only use types which have a direct mapping in Interfaces.C in the interface
>   of the jacket routine)
> - Portable Ada code.
> 
> As a rule of thumb:
> - If the information in C UNIX API standard (or man page) is sufficient to
>   write an Ada interface using types from Interfaces.C, we write a direct 
>   Ada interface.
> - If we need to look at the content of some .h file to write an Ada interface,
>   then we don't and we write a C jacket routine.
> 
> -Thierry Lelegard

I believe this is good advice, if you want portability. Any time
a macro is involved, it is simplest to deal with it in C terms,
and only provide the in/out parameters to "jacket routines" as
they were called above.

The only other alternative, when macros are used to produce
constants is to create a C main program to spit out Ada
source module(s) at make(1) time (you can produce enumerated
values for example).  This can be useful when
your goal is to arrive at only/mostly Ada95 code to be
included in the project.

There are two disadvantages with this approach however:

1. does not work well when variables are plugged into
    macros that evaluate to expression results.
2. enumerated type values must be sorted in ascending
    value order, requiring a bit more effort on the C
    code side. This is a requirement of the Ada "for"
    statement (at least it is for GNAT -- Ada language
    lawyers can advise on the rest ;-)
-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Wrapping / Interfacing to C macros
  2002-08-22 21:56 Wrapping / Interfacing to C macros Le Snelson
                   ` (3 preceding siblings ...)
  2002-08-23 10:18 ` Lutz Donnerhacke
@ 2002-08-31 15:03 ` Florian Weimer
  4 siblings, 0 replies; 7+ messages in thread
From: Florian Weimer @ 2002-08-31 15:03 UTC (permalink / raw)


le_snelson@juno.com (Le Snelson) writes:

> I have one alternative in mind - create a C function to provide all of
> these macros through a parameterized selection.
>
> Any other ideas?

I'm using autoconf for a similar purpose.  Add the following to
aclocal.m4:

| dnl Determine the value of an expression.
| dnl AC_CHECK_VALUE(NAME, EXPRESSION, [INCLUDES = DEFAULT-INCLUDES])
| AC_DEFUN([AC_CHECK_VALUE],
| [AS_LITERAL_IF([$1], [],
|                [AC_FATAL([$0: requires literal arguments])])dnl
| AC_CACHE_CHECK([value of $2], AS_TR_SH([ac_cv_value_$1]),
| [_AC_COMPUTE_INT([($2)],
|                   [AS_TR_SH([ac_cv_value_$1])],
|                   [AC_INCLUDES_DEFAULT([$3])],
|                   [AC_MSG_ERROR([cannot compute $2])])
| ])
| AC_SUBST(AS_TR_CPP(value_$1), $AS_TR_SH([ac_cv_value_$1]))
| ])# AC_CHECK_VALUE

In configure.ac, you can now say:

| AC_CHECK_VALUE(SIOCSHIWAT, SIOCSHIWAT,
| 			       [#include <sys/ioctl.h>])
| 
| ...
| 
| AC_OUTPUT(constants.ads.in)

constants.ads.in is a file you have to write.  It could look like
this:

| package Constants is
| 
|   SIOCSHIWAT : constant := @VALUE_SIOCSHIWAT@;
| 
| end Constants;

configure will replace "@VALUE_SIOCSHIWAT@" with the proper value for
your target.

This works even when cross-compiling.  (Yes, it's black magic!)  In
this case, it's quite slow, but the values are cached.



^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2002-08-31 15:03 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-08-22 21:56 Wrapping / Interfacing to C macros Le Snelson
2002-08-22 22:42 ` Dale Stanbrough
2002-08-22 23:29 ` tmoran
2002-08-23  8:26 ` Thierry Lelegard
2002-08-23 16:13   ` Warren W. Gay VE3WWG
2002-08-23 10:18 ` Lutz Donnerhacke
2002-08-31 15:03 ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox