bug-gnulib
[Top][All Lists]
Advanced

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

[bug-gnulib] new modules for C# interoperability


From: Bruno Haible
Subject: [bug-gnulib] new modules for C# interoperability
Date: Wed, 25 May 2005 20:23:18 +0200
User-agent: KMail/1.5

After the modules for Java, here come the modules for C# interoperability.
C# is a language which lies between C++ and Java, nearer to Java than to C++.
It is ECMA standardized and has at least 2 free implementations (pnet and
mono). Like Java, it allows to write conceptually simple tasks - that
would require complex C programs - as simple programs.

The support comes in two modules:

  - csharpexec   - Execute a C# program.
  - csharpcomp   - Compile a C# program.

Here comes the first one. In use by GNU gettext for more than a year.

============================= modules/csharpexec =============================
Description:
Execute a C# program.

Files:
lib/csharpexec.h
lib/csharpexec.c
lib/csharpexec.sh.in
m4/csharpexec.m4
m4/csharp.m4

Depends-on:
stdbool
execute
classpath
xsetenv
sh-quote
xalloc
xallocsa
error
gettext

configure.ac:
gt_CSHARPEXEC

Makefile.am:
DEFS += -DEXEEXT=\"$(EXEEXT)\"
lib_SOURCES += csharpexec.h csharpexec.c
EXTRA_DIST += csharpexec.sh.in

Include:
"csharpexec.h"

License:
GPL

Maintainer:
Bruno Haible

============================ lib/csharpexec.sh.in ============================
#!/bin/sh
# Execute a C# program.

# Copyright (C) 2003 Free Software Foundation, Inc.
# Written by Bruno Haible <address@hidden>, 2003.
#
# This program 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.
#
# This program 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 this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.

# This uses the same choices as csharpexec.c, but instead of relying on the
# environment settings at run time, it uses the environment variables
# present at configuration time.
#
# This is a separate shell script, because the various C# interpreters have
# different command line options.
#
# Usage: /bin/sh csharpexec.sh [OPTION] program.exe [ARGUMENTS]
# Options:
#   -L DIRECTORY      search for C# libraries also in DIRECTORY

sed_quote_subst='s/\([|&;<>()$`"'"'"'*?[#~=%    \\]\)/\\\1/g'
options_ilrun=
libdirs_mono=
prog=
while test $# != 0; do
  case "$1" in
    -L)
      options_ilrun="$options_ilrun -L "`echo "$2" | sed -e "$sed_quote_subst"`
      libdirs_mono="${libdirs_mono:address@hidden@}$2"
      shift
      ;;
    -*)
      echo "csharpexec: unknown option '$1'" 1>&2
      exit 1
      ;;
    *)
      prog="$1"
      break
      ;;
  esac
  shift
done
if test -z "$prog"; then
  echo "csharpexec: no program specified" 1>&2
  exit 1
fi
case "$prog" in
  *.exe) ;;
  *)
    echo "csharpexec: program is not a .exe" 1>&2
    exit 1
    ;;
esac

if test -n "@HAVE_ILRUN@"; then
  test -z "$CSHARP_VERBOSE" || echo ilrun $options_ilrun "$@"
  exec ilrun $options_ilrun "$@"
else
  if test -n "@HAVE_MONO@"; then
    CONF_MONO_PATH='@MONO_PATH@'
    if test -n "$libdirs_mono"; then
      MONO_PATH="$libdirs_mono${CONF_MONO_PATH:address@hidden@$CONF_MONO_PATH}"
    else
      MONO_PATH="$CONF_MONO_PATH"
    fi
    export MONO_PATH
    test -z "$CSHARP_VERBOSE" || echo mono "$@"
    exec mono "$@"
  else
    echo 'C# virtual machine not found, try installing pnet, then reconfigure' 
1>&2
    exit 1
  fi
fi
============================== lib/csharpexec.h ==============================
/* Execute a C# program.
   Copyright (C) 2003 Free Software Foundation, Inc.
   Written by Bruno Haible <address@hidden>, 2003.

   This program 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.

   This program 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 this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifndef _CSHARPEXEC_H
#define _CSHARPEXEC_H

#include <stdbool.h>

typedef bool execute_fn (const char *progname,
                         const char *prog_path, char **prog_argv,
                         void *private_data);

/* Execute a C# program.
   assembly_path is the assembly's pathname (= program name with .exe).
   libdirs is a list of directories to be searched for libraries.
   args is a NULL terminated list of arguments to be passed to the program.
   If verbose, the command to be executed will be printed.
   Then the command is passed to the execute function together with the
   private_data argument.  This function returns false if OK, true on error.
   Return false if OK, true on error.
   If quiet, error messages will not be printed.  */
extern bool execute_csharp_program (const char *assembly_path,
                                    const char * const *libdirs,
                                    unsigned int libdirs_count,
                                    const char * const *args,
                                    bool verbose, bool quiet,
                                    execute_fn *executer, void *private_data);

#endif /* _CSHARPEXEC_H */
============================== lib/csharpexec.c ==============================
/* Execute a C# program.
   Copyright (C) 2003-2004 Free Software Foundation, Inc.
   Written by Bruno Haible <address@hidden>, 2003.

   This program 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.

   This program 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 this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <alloca.h>

/* Specification.  */
#include "csharpexec.h"

#include <stdio.h>
#include <stdlib.h>

#include "execute.h"
#include "sh-quote.h"
#include "xallocsa.h"
#include "error.h"
#include "gettext.h"

/* Handling of MONO_PATH is just like Java CLASSPATH.  */
#define CLASSPATHVAR "MONO_PATH"
#define new_classpath new_monopath
#define set_classpath set_monopath
#define reset_classpath reset_monopath
#include "classpath.h"
#include "classpath.c"

#define _(str) gettext (str)


/* Survey of CIL interpreters.

   Program    from

   ilrun      pnet
   mono       mono

   With Mono, the MONO_PATH is a colon separated list of pathnames. (On
   Windows: semicolon separated list of pathnames.)

   We try the CIL interpreters in the following order:
     1. "ilrun", because it is a completely free system.
     2. "mono", because it is a partially free system but doesn't integrate
        well with Unix.
   But the order can be changed through the --enable-csharp configuration
   option.
 */

static int
execute_csharp_using_pnet (const char *assembly_path,
                           const char * const *libdirs,
                           unsigned int libdirs_count,
                           const char * const *args, unsigned int nargs,
                           bool verbose, bool quiet,
                           execute_fn *executer, void *private_data)
{
  static bool ilrun_tested;
  static bool ilrun_present;

  if (!ilrun_tested)
    {
      /* Test for presence of ilrun:
         "ilrun --version >/dev/null 2>/dev/null"  */
      char *argv[3];
      int exitstatus;

      argv[0] = "ilrun";
      argv[1] = "--version";
      argv[2] = NULL;
      exitstatus = execute ("ilrun", "ilrun", argv, false, false, true, true,
                            true, false);
      ilrun_present = (exitstatus == 0);
      ilrun_tested = true;
    }

  if (ilrun_present)
    {
      unsigned int argc;
      char **argv;
      char **argp;
      unsigned int i;
      bool err;

      argc = 1 + 2 * libdirs_count + 1 + nargs;
      argv = (char **) xallocsa ((argc + 1) * sizeof (char *));

      argp = argv;
      *argp++ = "ilrun";
      for (i = 0; i < libdirs_count; i++)
        {
          *argp++ = "-L";
          *argp++ = (char *) libdirs[i];
        }
      *argp++ = (char *) assembly_path;
      for (i = 0; i < nargs; i++)
        *argp++ = (char *) args[i];
      *argp = NULL;
      /* Ensure argv length was correctly calculated.  */
      if (argp - argv != argc)
        abort ();

      if (verbose)
        {
          char *command = shell_quote_argv (argv);
          printf ("%s\n", command);
          free (command);
        }

      err = executer ("ilrun", "ilrun", argv, private_data);

      freesa (argv);

      return err;
    }
  else
    return -1;
}

static int
execute_csharp_using_mono (const char *assembly_path,
                           const char * const *libdirs,
                           unsigned int libdirs_count,
                           const char * const *args, unsigned int nargs,
                           bool verbose, bool quiet,
                           execute_fn *executer, void *private_data)
{
  static bool mono_tested;
  static bool mono_present;

  if (!mono_tested)
    {
      /* Test for presence of mono:
         "mono --version >/dev/null 2>/dev/null"  */
      char *argv[3];
      int exitstatus;

      argv[0] = "mono";
      argv[1] = "--version";
      argv[2] = NULL;
      exitstatus = execute ("mono", "mono", argv, false, false, true, true,
                            true, false);
      mono_present = (exitstatus == 0);
      mono_tested = true;
    }

  if (mono_present)
    {
      char *old_monopath;
      char **argv = (char **) xallocsa ((2 + nargs + 1) * sizeof (char *));
      unsigned int i;
      bool err;

      /* Set MONO_PATH.  */
      old_monopath = set_monopath (libdirs, libdirs_count, false, verbose);

      argv[0] = "mono";
      argv[1] = (char *) assembly_path;
      for (i = 0; i <= nargs; i++)
        argv[2 + i] = (char *) args[i];

      if (verbose)
        {
          char *command = shell_quote_argv (argv);
          printf ("%s\n", command);
          free (command);
        }

      err = executer ("mono", "mono", argv, private_data);

      /* Reset MONO_PATH.  */
      reset_monopath (old_monopath);

      freesa (argv);

      return err;
    }
  else
    return -1;
}

bool
execute_csharp_program (const char *assembly_path,
                        const char * const *libdirs,
                        unsigned int libdirs_count,
                        const char * const *args,
                        bool verbose, bool quiet,
                        execute_fn *executer, void *private_data)
{
  unsigned int nargs;
  int result;

  /* Count args.  */
  {
    const char * const *arg;

    for (nargs = 0, arg = args; *arg != NULL; nargs++, arg++)
     ;
  }

  /* First try the C# implementation specified through --enable-csharp.  */
#if CSHARP_CHOICE_PNET
  result = execute_csharp_using_pnet (assembly_path, libdirs, libdirs_count,
                                      args, nargs, verbose, quiet,
                                      executer, private_data);
  if (result >= 0)
    return (bool) result;
#endif

#if CSHARP_CHOICE_MONO
  result = execute_csharp_using_mono (assembly_path, libdirs, libdirs_count,
                                      args, nargs, verbose, quiet,
                                      executer, private_data);
  if (result >= 0)
    return (bool) result;
#endif

  /* Then try the remaining C# implementations in our standard order.  */
#if !CSHARP_CHOICE_PNET
  result = execute_csharp_using_pnet (assembly_path, libdirs, libdirs_count,
                                      args, nargs, verbose, quiet,
                                      executer, private_data);
  if (result >= 0)
    return (bool) result;
#endif

#if !CSHARP_CHOICE_MONO
  result = execute_csharp_using_mono (assembly_path, libdirs, libdirs_count,
                                      args, nargs, verbose, quiet,
                                      executer, private_data);
  if (result >= 0)
    return (bool) result;
#endif

  if (!quiet)
    error (0, 0, _("C# virtual machine not found, try installing pnet"));
  return true;
}
============================== m4/csharpexec.m4 ==============================
# csharpexec.m4 serial 2 (gettext-0.15)
dnl Copyright (C) 2003-2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.

# Prerequisites of csharpexec.sh.
# gt_CSHARPEXEC or gt_CSHARPEXEC(testexecutable, its-directory)
# Sets HAVE_CSHARPEXEC to nonempty if csharpexec.sh will work.

AC_DEFUN([gt_CSHARPEXEC],
[
  AC_REQUIRE([gt_CSHARP_CHOICE])
  AC_MSG_CHECKING([for C[#] program execution engine])
  AC_EGREP_CPP(yes, [
#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__
  yes
#endif
], MONO_PATH_SEPARATOR=';', MONO_PATH_SEPARATOR=':')
  HAVE_CSHARPEXEC=1
  pushdef([AC_MSG_CHECKING],[:])dnl
  pushdef([AC_CHECKING],[:])dnl
  pushdef([AC_MSG_RESULT],[:])dnl
  AC_CHECK_PROG(HAVE_ILRUN_IN_PATH, ilrun, yes)
  AC_CHECK_PROG(HAVE_MONO_IN_PATH, mono, yes)
  popdef([AC_MSG_RESULT])dnl
  popdef([AC_CHECKING])dnl
  popdef([AC_MSG_CHECKING])dnl
  for impl in "$CSHARP_CHOICE" pnet mono no; do
    case "$impl" in
      pnet)
        if test -n "$HAVE_ILRUN_IN_PATH" \
           && ilrun --version >/dev/null 2>/dev/null \
           ifelse([$1], , , [&& ilrun $2/$1 >/dev/null 2>/dev/null]); then
          HAVE_ILRUN=1
          ac_result="ilrun"
          break
        fi
        ;;
      mono)
        if test -n "$HAVE_MONO_IN_PATH" \
           && mono --version >/dev/null 2>/dev/null \
           ifelse([$1], , , [&& mono $2/$1 >/dev/null 2>/dev/null]); then
          HAVE_MONO=1
          ac_result="mono"
          break
        fi
        ;;
      no)
        HAVE_CSHARPEXEC=
        ac_result="no"
        break
        ;;
    esac
  done
  AC_MSG_RESULT([$ac_result])
  AC_SUBST(MONO_PATH)
  AC_SUBST(MONO_PATH_SEPARATOR)
  AC_SUBST(HAVE_ILRUN)
  AC_SUBST(HAVE_MONO)
])
================================ m4/csharp.m4 ================================
# csharp.m4 serial 2 (gettext-0.14.2)
dnl Copyright (C) 2004-2005 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.

# Sets CSHARP_CHOICE to the preferred C# implementation:
# 'pnet' or 'mono' or 'any' or 'no'.
AC_DEFUN([gt_CSHARP_CHOICE],
[
  AC_MSG_CHECKING([for preferred C[#] implementation])
  AC_ARG_ENABLE(csharp,
    [  --enable-csharp[[=IMPL]]  choose preferred C[#] implementation (pnet or 
mono)],
    [CSHARP_CHOICE="$enableval"],
    CSHARP_CHOICE=any)
  AC_SUBST(CSHARP_CHOICE)
  AC_MSG_RESULT([$CSHARP_CHOICE])
  case "$CSHARP_CHOICE" in
    pnet)
      AC_DEFINE([CSHARP_CHOICE_PNET], 1,
        [Define if pnet is the preferred C# implementation.])
      ;;
    mono)
      AC_DEFINE([CSHARP_CHOICE_MONO], 1,
        [Define if mono is the preferred C# implementation.])
      ;;
  esac
])
==============================================================================





reply via email to

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