classpath
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Removing the TARGET_* layer or not ?


From: Ingo Prötel
Subject: Re: Removing the TARGET_* layer or not ?
Date: Wed, 04 Aug 2004 10:15:42 +0200
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040113

[I'm sending this again since I did not get it back via the list]

Hi Michael,

Michael Koch wrote:
Am Dienstag, 3. August 2004 15:39 schrieb Ingo Prötel:

Hi Michael,

Michael Koch wrote:

Hi list, hi Ingo,



I just started porting/testing GNU classpath to solaris (2.6).
Its not really different to other unices (we currently support
linux and *BSD) but some things are. When I wanted to do the
needed changes I stumbled over the TARGET_* layer which adds (in
my eyes) some unneeded complexity. It makes it more hard to read
the code and all the stuff seem to be implemented either in
target/generic or target/Linux with no real rule what have to go
where. It's just difficult to understand. In fact I try to
understand it since a long time and always fail because of its
"indirectness". Personally I think some AUTOCONF checks would be
more appropriate and would make the code much more readable and
bugfixable. There are some known bugs in it but noone attacked
them because none understands the code it seems.

Ingo: Now my question are you really using the TARGET_* system or
is it only rotting around in GNU classpath ? I really wonder if
some AUTOCONF macros would be more helpful for you ?

Yes, the TARGET-layer is in active use here.

The TARGET-layer has two advantages:
1. It makes JNI-code more readable,
2. It makes porting simple.

It makes JNI-code more readable because whenever a native function
is called there is only one macro call. The other possibility would
be that one has ifdefs for every system (possibly for every
system+architecture) that one wants to support with this code. This
would make the JNI-code difficult to read.


The MACRO names are really long and they dont really make the code more readable for me. Perhaps for the compiler ... I dont know.


It makes porting easier in that one can reuse generic macros and
only needs to override specific macros that differ for a given new
system. And this all can happen without modifing the actual
JNI-code. So the main step in porting is creating a new
subdirectory in tartget name it Solaris. Copy over all the files in
the Linux target. Add this to the include path. Then just work on
the error that the compiler will find and where necessary create
Solaris specific macros.


I tried to port to Solaris and you system just made it hard for me (and I know mjw had problems with it too when he dbugged some filesystem stuff).


If there is interest we could provide our Solaris, Darwin, and
MinGW TARGET-layer. This would probably help to understand how this
layer is helpful. In any case we can help if anyone needs help
understanding the code.


I don't get the benefit of the whole system. BSD's are already suppored by the "Linux" layer. I guess Darwin (as its a BSD too) is supported too and if not its easy to do so. I tried to support solaris in the "Linux" layer and I needed to add around 10 lines for it. So why add a lot oc code duplication to support an additional OS when its enough to add 10 lines that are much more easy to understand, adds no bloat and is more easy to maintain ? I haven't tried mingw yet but I guess its similar easy.

Sorry, but I'm currently upset because this layer made it hard for me to do something normally really simple. Autoconf was created to make it easy to write portable apps. We use it already in GNU classpath. Why not use it to write portable apps in it ?


Michael

You are quite right. Solaris is still pretty close to Linux. So the only 
difference is in the target_native_network.h file.
The difference to Darwin is even less. But we have been able to port to those 
platforms without having to modify the actual JNI-code.
If the TRAGET-layer would be removed all changes would need to be done in the 
JNI-file. We try to support embedded targets which use at least seven
different operating systems, which often have no native support for 64-bit 
values, or have weired endianess. If we would need to add all these
differences as as ifdefs in the JNI-code it would make this code difficult to 
read.
Debugging the macros is actually a hard thing. But once a macro works correctly 
it normally does not need to be changed any more. Much more often the
code around the macro must be changed and that is easier if it is not cluttered 
with ifdefs.

I have attached the target_native_network.h files for Solaris and Darwin. I 
hope that helps you a bit.

Ingo


--
Ingo Prötel                                          address@hidden
aicas GmbH                                        http://www.aicas.com
Haid-und-Neu-Str. 18                        phone   +49 721 663 968-32
76131 Karlsruhe                             fax     +49 721 663 968-93
Germany

/* ???.h - ???
   Copyright (C) 1998 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

/*
Description: Darwin/Mac OS-X target defintions of network functions
Systems    : Darwin/Mac OS-X

*/

#ifndef __TARGET_NATIVE_NETWORK__
#define __TARGET_NATIVE_NETWORK__

/****************************** Includes *******************************/
/* do not move; needed here because of some macro definitions */
#include <config.h>

#include <stdlib.h>

/****************** Conditional compilation switches *******************/

/***************************** Constants *******************************/

/***************************** Datatypes *******************************/

/***************************** Variables *******************************/

/****************************** Macros *********************************/

#define 
TARGET_NATIVE_NETWORK_SOCKET_SEND(socketDescriptor,buffer,length,bytesSent) \
  do { \
    bytesSent=send(socketDescriptor,buffer,length,0); \
  } while (0)

#define 
TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT(socketDescriptor,buffer,length,address,port,bytesSent)
 \
  do { \
    struct sockaddr_in __socketAddress; \
    \
    memset(&__socketAddress,0,sizeof(__socketAddress)); \
    __socketAddress.sin_family      = AF_INET; \
    __socketAddress.sin_addr.s_addr = htonl(address); \
    __socketAddress.sin_port        = htons((short)port); \
    bytesSent=sendto(socketDescriptor,buffer,length,0,(struct 
sockaddr*)&__socketAddress,sizeof(__socketAddress)); \
  } while (0)

/***************************** Functions *******************************/

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

/* include rest of definitions from generic file (do not move it to 
   another position!) */
#include "target_generic_network.h"

#endif /* __TARGET_NATIVE_NETWORK__ */

/* end of file */


/* ???.h - ???
   Copyright (C) 1998 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
 
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

/*
Description: SunOS/Solaris target defintions of network functions
Systems    : all
*/

#ifndef __TARGET_NATIVE_NETWORK__
#define __TARGET_NATIVE_NETWORK__

/****************************** Includes *******************************/
/* do not move; needed here because of some macro definitions */
#include <config.h>

#include <stdlib.h>
#include <stropts.h>
#include <sys/conf.h>
#include <netinet/in_systm.h>
#include <sys/ioctl.h>

/****************** Conditional compilation switches *******************/

/***************************** Constants *******************************/

/***************************** Datatypes *******************************/

/***************************** Variables *******************************/

/****************************** Macros *********************************/

/***********************************************************************\
* Name       : TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_NAME
* Purpose    : get hostname by name
* Input      : name           - hostname
*              maxAddressSize - max. size of address array
* Output     : addresses    - host addresses (array, in host byte
*                             order!)
*              addressCount - number of entries in address array
*              result       - TARGET_NATIVE_OK if no error occurred,
*                             TARGET_NATIVE_ERROR otherwise
* Return     : -
* Side-effect: unknown
* Notes      : -
\***********************************************************************/

#ifndef TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_NAME
  #include <netdb.h>
  #define 
TARGET_NATIVE_NETWORK_GET_HOSTNAME_BY_NAME(name,addresses,maxAddressSize,addressCount,result)
 \
    do { \
      struct hostent __hostEntry; \
      char           __buffer[5000]; \
      int            __h_errno; \
      \
      addressCount = 0; \
      \
      if (gethostbyname_r(name, &__hostEntry, __buffer, sizeof(__buffer), 
&__h_errno) != NULL) \
        { \
          while ((addressCount < maxAddressSize) && 
(__hostEntry.h_addr_list[addressCount] != NULL)) \
            { \
              addresses[addressCount] = 
ntohl(*(int*)(__hostEntry.h_addr_list[addressCount])); \
              addressCount++; \
            } \
          result = TARGET_NATIVE_OK; \
        } \
      else \
        { \
          result = TARGET_NATIVE_ERROR; \
        } \
    } while (0)
#endif

/***********************************************************************\
* Name       : TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_AVAILABLE
* Purpose    : get number of available bytes for receive
* Input      : socketDescriptor - socket descriptor
* Output     : bytesAvailable - available bytes for receive
*            : result         - TARGET_NATIVE_OK if no error occurred,
*                               TARGET_NATIVE_ERROR otherwise
* Return     : -
* Side-effect: unknown
* Notes      : -
\***********************************************************************/

#define 
TARGET_NATIVE_NETWORK_SOCKET_RECEIVE_AVAILABLE(socketDescriptor,bytesAvailable,result)
 \
  do { \
    int __value; \
    \
    bytesAvailable=0; \
    \
    result = (ioctl(socketDescriptor, I_NREAD, &__value) == 
0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \
    if (result == TARGET_NATIVE_OK) \
      { \
        bytesAvailable = __value; \
      } \
  } while (0)

#if 1
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#define 
TARGET_NATIVE_NETWORK_SOCKET_CONNECT(socketDescriptor,address,port,result) \
  do { \
    struct sockaddr_in __socketAddress; \
    int nnn; \
    \
fprintf(stderr, "address %08x %d\n", address, (int)port); \
    memset(&__socketAddress,0,sizeof(__socketAddress)); \
    __socketAddress.sin_family      = AF_INET; \
    __socketAddress.sin_addr.s_addr = htonl(address); \
    __socketAddress.sin_port        = htons(((short)port)); \
    \
    nnn=connect(socketDescriptor,(struct 
sockaddr*)&__socketAddress,sizeof(__socketAddress)); \
    result=(nnn==0)?TARGET_NATIVE_OK:TARGET_NATIVE_ERROR; \
fprintf(stderr,"%s,%d: connect: %d %d 
%d\n",__FILE__,__LINE__,socketDescriptor,nnn,errno); \
  } while (0)
#endif /* 0 */

/***********************************************************************\
* Name       : TARGET_NATIVE_NETWORK_SOCKET_SEND
* Purpose    : send data to socket
* Input      : socketDescriptor - socket descriptor
*            : buffer  - data to send
*              length  - length of data to send
* Output     : bytesSent - number of bytes sent, -1 otherwise
* Side-effect: unknown
* Notes      : -
\***********************************************************************/

#ifndef TARGET_NATIVE_NETWORK_SOCKET_SEND
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #define TARGET_NATIVE_NETWORK_SOCKET_SEND(socketDescriptor, buffer, length, 
bytesSent) \
    do { \
      bytesSent = send(socketDescriptor, \
                       buffer, \
                       length, \
                       0 /* MSG_NOSIGNAL not supported by Solaris */ \
                      ); \
    } while (0)
#endif

/***********************************************************************\
* Name       : TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT
* Purpose    : send data to socket
* Input      : socketDescriptor - socket descriptor
*            : buffer  - data to send
*              length  - length of data to send
*              Address - to address (NOT in network byte order!)
*              Port    - to port (NOT in network byte order!)
* Output     : bytesSent - number of bytes sent, -1 otherwise
* Side-effect: unknown
* Notes      : -
\***********************************************************************/

#ifndef TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT
  #include <sys/types.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #define TARGET_NATIVE_NETWORK_SOCKET_SEND_WITH_ADDRESS_PORT(socketDescriptor, 
buffer, length, address, port, bytesSent) \
    do { \
      struct sockaddr_in __socketAddress; \
      \
      memset(&__socketAddress,0,sizeof(__socketAddress)); \
      __socketAddress.sin_family      = AF_INET; \
      __socketAddress.sin_addr.s_addr = htonl(address); \
      __socketAddress.sin_port        = htons((short)port); \
      bytesSent = sendto(socketDescriptor, \
                         buffer, \
                         length, \
                         0 /* MSG_NOSIGNAL not supported by solaris */, \
                         (struct sockaddr*)&__socketAddress, \
                         sizeof(__socketAddress) \
                        ); \
    } while (0)
#endif

/***************************** Functions *******************************/

#ifdef __cplusplus
extern "C" {
#endif

#ifdef __cplusplus
}
#endif

/* include rest of definitions from generic file (do not move it to 
   another position!) */
#include "target_generic_network.h"

#endif /* __TARGET_NATIVE_NETWORK__ */

/* end of file */


reply via email to

[Prev in Thread] Current Thread [Next in Thread]