bug-gnu-utils
[Top][All Lists]
Advanced

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

Patches for OS/2 (3)


From: Andreas Buening
Subject: Patches for OS/2 (3)
Date: Sun, 03 Nov 2002 22:52:49 +0100

Hello!

I hope the following explanations are sufficient for you. If this
is not the case, please ask.


loadinfo.h;
I guess, the PATH_SEPARATOR code can be removed from loadinfo.h
because it's already handled in configure.in. So the
#ifndef PATH_SEPARATOR part is not really necessary.

-----------------------------
--- old/gettext-0.11.5/intl/loadinfo.h  Fri Jun 14 11:58:24 2002
+++ gnu/gettext-0.11.5/intl/loadinfo.h  Sun Oct 13 21:23:50 2002
@@ -50,13 +50,15 @@
 # define __builtin_expect(expr, val) (expr)
 #endif

+#ifndef PATH_SEPARATOR
 /* Separator in PATH like lists of pathnames.  */
-#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__

+# if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP_
_
   /* Win32, OS/2, DOS */
-# define PATH_SEPARATOR ';'
-#else
+#  define PATH_SEPARATOR ';'
+# else
   /* Unix */
-# define PATH_SEPARATOR ':'
+#  define PATH_SEPARATOR ':'
+# endif
 #endif

 /* Encoding of locale name parts.  */
-----------------------------


libgnuintl.h:
There is a problem with binary compatibility between 0.11.5 and
earlier libintl releases. It is necessary that programs that have
been compiled with 0.11.5 and later can use 0.10.x shared libraries.
Therefore I defined _INTL_NOREDIRECT so that gettext... is not
redirected to libintl_gettext... when using EMX.

-----------------------------
--- old/gettext-0.11.5/intl/libgnuintl.h        Tue Jul 23 12:27:52 2002
+++ gnu/gettext-0.11.5/intl/libgnuintl.h        Tue Oct 29 22:18:08 2002
@@ -47,6 +47,11 @@
 # undef gettext
 #endif

+/* Keep binary compatibility with earlier versions of GNU gettext for OS/2 */
+#ifdef __EMX__
+# define _INTL_NOREDIRECT
+#endif
+
 /* Use _INTL_PARAMS, not PARAMS, in order to avoid clashes with identifiers
    used by programs.  Similarly, test __PROTOTYPES, not PROTOTYPES.  */
 #ifndef _INTL_PARAMS
@@ -92,7 +97,7 @@
 /* The user can define _INTL_REDIRECT_INLINE or _INTL_REDIRECT_MACROS.
    If he doesn't, we choose the method.  A third possible method is
    _INTL_REDIRECT_ASM, supported only by GCC.  */
-#if !(defined _INTL_REDIRECT_INLINE || defined _INTL_REDIRECT_MACROS)
+#if !(defined _INTL_REDIRECT_INLINE || defined _INTL_REDIRECT_MACROS || 
defined _INTL_NOREDIRECT)
 # if __GNUC__ >= 2 && (defined __STDC__ || defined __cplusplus)
 #  define _INTL_REDIRECT_ASM
 # else
-----------------------------


os2compat.h:
I rewrote this file completely.

-----------------------------
--- old/gettext-0.11.5/intl/os2compat.h Fri Mar 15 18:28:28 2002
+++ gnu/gettext-0.11.5/intl/os2compat.h Sat Oct 19 19:23:24 2002
@@ -18,21 +18,54 @@
    USA.  */
 
 /* When included from os2compat.h we need all the original definitions */
-#ifndef OS2_AWARE
 
-#undef LIBDIR
-#define LIBDIR                 _nlos2_libdir
-extern char *_nlos2_libdir;
+#include<sys/types.h>
+#include<sys/param.h>
 
-#undef LOCALEDIR
-#define LOCALEDIR              _nlos2_localedir
-extern char *_nlos2_localedir;
 
-#undef LOCALE_ALIAS_PATH
-#define LOCALE_ALIAS_PATH      _nlos2_localealiaspath
-extern char *_nlos2_localealiaspath;
+/* This function tries to determine the current charset using DosQueryCp().
+   In the following cases NULL is returned:
+   1) The system is not running in OS/2 mode (but DOS, whatever).
+   2) We are not connected to the /dev/con terminal, i.e. the codepage
+      information may be useless (e.g. for an xterm) and is ignored.
+   3) DosQueryCp() fails. */
+extern const char* 
+_nlos2_get_charset (void);
+
+
+/* This function compares a given codeset name with an alias.
+   codeset and aliases are assumed to be identical if codeset is
+   identical to the first part of aliases, e.g. "en_US" and
+   "en_US.ISO-8859-1" are identical. */
+extern int
+_nlos2_cmp_codeset (const char *codeset, const char *aliases);
+
+
+/* path is assumed to be a list of directories separated by PATH_SEPARATOR.
+   Every directory is processed. unixrootify() is used to find out whether
+   these directories begin with '/' or '\\'. If this is the case (i.e.
+   if there is no drive letter) the UNIXROOT drive letter is prepended
+   to that directory. If path is a valid path this function returns a valid
+   path, too.
+   Example ($UNIXROOT is set to "e:"):
+   ".;/usr/local;d:/usr/local;/etc;e:/etc"
+   -> ".;e:/usr/local;d:/usr/local;e:/etc;e:/etc" */
+extern char*
+_nlos2_unixrootify_path (const char *path);
+
+
+/* This function delivers GNULOCALEDIR if available, otherwise the
+   unixrootified version of path. */
+extern const char*
+_nlos2_deliver_path (const char *path);
+
+
+/* This function delivers the first directory of GNULOCALEDIR if available,
+   otherwise the unixrootified version of dirname (i.e. UNIXROOT is
+   prepended to dirname). */
+extern const char* 
+_nlos2_deliver_dir (const char *dirname);
 
-#endif
 
 #undef HAVE_STRCASECMP
 #define HAVE_STRCASECMP 1
@@ -40,7 +73,8 @@
 #define strncasecmp strnicmp
 
 /* We have our own getenv() which works even if library is compiled as DLL */
-#define getenv _nl_getenv
+//#define getenv _nl_getenv
 
 /* Older versions of gettext used -1 as the value of LC_MESSAGES */
 #define LC_MESSAGES_COMPAT (-1)
+
-----------------------------


os2compat.c:
I rewrote this file completely, too. I removed the global variables
_nlos2_{libdir|localedir|localealiaspath} because they break the
binary compatibility to older versions (Keeping binary compatibility
is a difficult issue, please, don't ask ;-) ).
I added an entry point for dcgettext__ because very old libintl.h
files use it.
The other functions should be self explanatory
I took _nlos2_unixrootify_path() and unixrootify() (with minor
changes) from the current gawk release (file pc/gawkmisc.pc).


-----------------------------
--- old/gettext-0.11.5/intl/os2compat.c Mon Apr 29 17:30:00 2002
+++ gnu/gettext-0.11.5/intl/os2compat.c Tue Oct 29 22:25:14 2002
@@ -16,83 +16,357 @@
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
    USA.  */
 
-#define OS2_AWARE
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
+#include "gettextP.h"
+#ifdef _LIBC
+# include <libintl.h>
+#else
+# include "libgnuintl.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/param.h>
+#include <unistd.h>
 
-/* A version of getenv() that works from DLLs */
-extern unsigned long DosScanEnv (const unsigned char *pszName, unsigned char 
**ppszValue);
+/* For DosQueryCp(). */
+#define INCL_DOS
+#include<os2.h>
 
-char *
-_nl_getenv (const char *name)
+
+#define ISSLASH(C) ((C) == '/' || (C) == '\\')
+
+/* static functions */
+static int is_valid (int fd);
+
+static char* unixrootify (const char *path);
+
+
+
+/* This function delivers GNULOCALEDIR if available, otherwise the
+   unixrootified version of path. */
+const char*
+_nlos2_deliver_path (const char *path)
 {
-  unsigned char *value;
-  if (DosScanEnv (name, &value))
-    return NULL;
-  else
-    return value;
-}
-
-/* A fixed size buffer.  */
-char libintl_nl_default_dirname[MAXPATHLEN+1];
-
-char *_nlos2_libdir = NULL;
-char *_nlos2_localealiaspath = NULL;
-char *_nlos2_localedir = NULL;
-
-static __attribute__((constructor)) void
-nlos2_initialize ()
-{
-  char *root = getenv ("UNIXROOT");
-  char *gnulocaledir = getenv ("GNULOCALEDIR");
-
-  _nlos2_libdir = gnulocaledir;
-  if (!_nlos2_libdir)
-    {
-      if (root)
-        {
-          size_t sl = strlen (root);
-          _nlos2_libdir = (char *) malloc (sl + strlen (LIBDIR) + 1);
-          memcpy (_nlos2_libdir, root, sl);
-          memcpy (_nlos2_libdir + sl, LIBDIR, strlen (LIBDIR) + 1);
-        }
-      else
-        _nlos2_libdir = LIBDIR;
+  const char *gnulocaledir = getenv ("GNULOCALEDIR");
+  char *result = NULL;
+
+  if (gnulocaledir != NULL && *gnulocaledir != '\0')
+    {
+      /* Sigh. The user wants GNULOCALEDIR. Ignore the harcoded path. */
+      result = strdup (gnulocaledir);
     }
 
-  _nlos2_localealiaspath = gnulocaledir;
-  if (!_nlos2_localealiaspath)
+  if (result == NULL)
+    result = _nlos2_unixrootify_path (path);
+
+  if (result == NULL) /* out of memory */
+    result = (char *) path;
+
+  return (result != NULL) ? (const char*) result : path;
+}
+  
+
+
+/* This function delivers the first directory of GNULOCALEDIR if available,
+   otherwise the unixrootified version of dirname (i.e. UNIXROOT is
+   prepended to dirname). */
+const char*
+_nlos2_deliver_dir (const char *dirname)
+{
+  const char *gnulocaledir = getenv ("GNULOCALEDIR");
+  char *result = NULL;
+
+  if (gnulocaledir != NULL && *gnulocaledir != '\0')
     {
-      if (root)
-        {
-          size_t sl = strlen (root);
-          _nlos2_localealiaspath = (char *) malloc (sl + strlen 
(LOCALE_ALIAS_PATH) + 1);
-          memcpy (_nlos2_localealiaspath, root, sl);
-          memcpy (_nlos2_localealiaspath + sl, LOCALE_ALIAS_PATH, strlen 
(LOCALE_ALIAS_PATH) + 1);
-        }
-     else
-        _nlos2_localealiaspath = LOCALE_ALIAS_PATH;
-    }
-
-  _nlos2_localedir = gnulocaledir;
-  if (!_nlos2_localedir)
-    {
-      if (root)
-        {
-          size_t sl = strlen (root);
-          _nlos2_localedir = (char *) malloc (sl + strlen (LOCALEDIR) + 1);
-          memcpy (_nlos2_localedir, root, sl);
-          memcpy (_nlos2_localedir + sl, LOCALEDIR, strlen (LOCALEDIR) + 1);
-        }
+      /* Sigh. The user wants GNULOCALEDIR. Ignore the harcoded path. */
+      const char *end = strchr (gnulocaledir, PATH_SEPARATOR);
+
+      if (end != NULL)
+       {
+         /* Great. There is more than one directory. */
+         /* Allocate memory for the 1st directory. */
+         result = malloc (end - gnulocaledir + 1);
+         memcpy (result, gnulocaledir, end - gnulocaledir);
+         result[end - gnulocaledir] = '\0';
+       }
       else
-        _nlos2_localedir = LOCALEDIR;
+       result = strdup (gnulocaledir);
     }
+         
+  /* unixrootify() uses only the first element of the ';' separated list
+     (if there is more than one directory name). */
+  if (result == NULL)
+    result = unixrootify (dirname);
+  /* if dirname already contained a drive letter, result is NULL. */
+
+  return (result != NULL) ? (const char *) result: dirname;
+}
+
+   
 
-  if (strlen (_nlos2_localedir) <= MAXPATHLEN)
-    strcpy (libintl_nl_default_dirname, _nlos2_localedir);
+
+/* path is assumed to be a list of directories separated by PATH_SEPARATOR.
+   Every directory is processed. unixrootify() is used to find out whether
+   these directories begin with '/' or '\\'. If this is the case (i.e.
+   if there is no drive letter) the UNIXROOT drive letter is prepended
+   to that directory. If path is a valid path this function returns a valid
+   path, too.
+   Example ($UNIXROOT is set to "e:"):
+   ".;/usr/local;d:/usr/local;/etc;e:/etc"
+   -> ".;e:/usr/local;d:/usr/local;e:/etc;e:/etc" */
+
+char*
+_nlos2_unixrootify_path (const char *path)
+{
+  char *result = NULL;
+  const char *p = path;
+  unsigned dir_count = 1;
+  
+  if (path == NULL || path[0] == '\0') return NULL; /* empty path */
+
+  /* "remove" leading path separators */
+  while (*p == PATH_SEPARATOR)
+    p++;
+
+  /* save number of path components in dir_count */
+  while(*p) {
+    if (*p++ == PATH_SEPARATOR && *p != '\0' && *p != PATH_SEPARATOR)
+      dir_count += 1;
+  }
+
+  {
+    const char *list[dir_count]; /* list of char pointers */
+    char *new_list[dir_count];
+    size_t dir_len[dir_count]; /* the according directory length */
+    size_t old_path_len = strlen(path); /* the old path length */
+    size_t total_len;
+    unsigned i = 0;
+
+    while (path[old_path_len - 1] == PATH_SEPARATOR)
+      /* last character is ';' */
+      old_path_len--;
+
+    list[0] = p = path; /* first directory */
+
+    while(*p)
+      {
+       if (*p++ == PATH_SEPARATOR && *p != '\0' && *p != PATH_SEPARATOR)
+         list[++i] = p;
+      }
+    /* now list[i] contains the ith directory of path (no 0-terminated 
strings!!!) */
+
+    /* determine the total length for the new path */
+    total_len = 0;
+
+    for(i = 0; i < dir_count; i++) 
+      {
+       new_list[i] = unixrootify (list[i]);
+       if (new_list[i] != NULL)
+         {
+           dir_len[i] = strlen (new_list[i]);
+           /* replace the old directory by the new one */
+           list[i] = new_list[i]; 
+         }
+       else dir_len[i] = strlen (list[i]);
+
+       total_len += dir_len[i] + 1; /* one character for ';' or '\0' */
+      }
+    /* now new_list[] contains the according directories on the UNIXROOT
+       drive or NULL. total_len contains the total length for the new path
+       including the trailing 0. */
+    result = malloc(total_len);
+
+    if (result)
+      {
+       /* copy the new directories into the new path */
+       char *q = result;
+
+       for(i = 0; i < dir_count; i++)
+         {
+           if (dir_len[i] != 0) 
+             {
+               memcpy(q, list[i], dir_len[i]);
+               q += dir_len[i];
+               /* the last ';' will be overwritten by 0 */
+               *q++ = PATH_SEPARATOR;
+             }
+         }
+
+       result[total_len - 1] = '\0'; /* terminating '\0' */
+      }
+
+    /* free the allocated memory */
+    for(i = 0; i < dir_count; i++) free ((void*) new_list[i]);
+  }
+
+  return result;
 }
+
+
+/* This function tries to determine the current charset using DosQueryCp().
+   In the following cases NULL is returned:
+   1) The system is not running in OS/2 mode (but DOS, whatever).
+   2) We are not connected to the /dev/con terminal, i.e. the codepage
+      information may be useless (e.g. for an xterm) and is ignored.
+   3) DosQueryCp() fails. */
+const char*
+_nlos2_get_charset (void)
+{
+  static char buf[2 + 10 + 1]; /* How many bytes do we really need? */
+
+  if (_osmode == OS2_MODE)
+    {
+      /* We are running in OS/2 mode. */
+      if (is_valid(fileno(stdout)) || is_valid(fileno(stderr))
+         || is_valid(fileno(stdin)))
+       {
+         /* We are connected to /dev/con. */
+         ULONG cp[3]; /* list of codepages */
+         ULONG cplen; /* number of available codepages in cp */
+
+         if (DosQueryCp (sizeof (cp), cp, &cplen) == 0)
+           {
+             /* We could determine the current codepage. */
+             sprintf (buf, "CP%lu", cp[0]);
+             return buf;
+           }
+       }
+      
+      /* "" means: do not perform any charset conversion, even if
+        possible. We may be using an xterm which uses the
+        "Unix default charset". */
+      /* return ""; */
+    }
+
+  /* NULL means: use the charset.alias file */
+  return NULL;
+}
+
+
+
+/* This function compares a given codeset name with an alias.
+   codeset and aliases are assumed to be identical if codeset is
+   identical to the first part of aliases, e.g. "en_US" and
+   "en_US.ISO-8859-1" are identical. */
+int
+_nlos2_cmp_codeset (const char *codeset, const char *aliases)
+{
+  size_t len = strlen (codeset);
+  int error = 1;
+
+  if (len > 0 && strncmp (codeset, aliases, len) == 0)
+    {
+      /* First characters of codeset an aliases match.
+         We have the right alias if
+        (1) the next character is '\0'
+        (2) the next character is one of "_.:@" (there may be others) */
+      const char *p = aliases + strlen (aliases);
+
+      if (*p == '\0')
+       error = 0; /* found: exact match */
+      
+      else if (strchr ("_.:@", *p) != NULL)
+       /* the first character of p is one of "_.:@" */
+       error = 0;
+    }
+  
+  return error;
+}
+
+
+
+/* path is assumed to be a list of directories separated by PATH_SEPARATOR.
+   This function determines whether the first directory of path contains
+   a leading '/' or '\\' but no drive letter. In this case the directory
+   name including the UNIXROOT drive letter is returned, otherwise NULL.
+   The new directory name is allocated by malloc().
+   Example (UNIXROOT is set to "e:"):
+     "c:/usr/share" -> NULL            (already a valid drive letter)
+     "e:/usr/share" -> NULL             (already on the $UNIXROOT drive)
+     "/usr/share"   -> "e:/usr/share"
+     "."            -> NULL             (not an absolute path)
+     "usr/share"    -> NULL             (not an absolute path)
+     "c:usr/share"  -> NULL             (not an absolute path)
+     "/usr/share;d:/etc" -> "e:/usr/share" (only the first directory in path 
is used) */
+
+static char*
+unixrootify(const char *path)
+{
+  static const char *unixroot = NULL;
+  static int unixroot_init = 0; 
+  char *result = NULL; 
+
+  if (unixroot_init == 0) {
+    /* get $UNIXROOT only once */
+    unixroot = getenv("UNIXROOT");
+
+    /* check whether unixroot is valid (must be "x:") */
+    if (unixroot != NULL) {
+      int drive = toupper(unixroot[0]);
+      if (drive < 'A' || drive > 'Z' || unixroot[1] != ':' || unixroot[2] != 
'\0')
+        unixroot = NULL; /* unixroot not valid */
+    }
+
+    unixroot_init = 1; /* initialized */
+  }
+
+  /* note: if unixroot != NULL then it contains a valid drive letter */
+  if (unixroot != NULL && ISSLASH(path[0]))
+    {
+      /* path is an absolute path but without drive letter. */
+
+      size_t old_path_len = strlen(path);
+
+      /* end points to the first ';' in path or to NULL */
+      const char *end = strchr(path, PATH_SEPARATOR);
+
+      /* dir_len is the length of the first directory in path */
+      size_t dir_len = (end) ? end - path : old_path_len;
+
+      /* Allocate the new directory, includes space for drive letter and
+         trailing 0. */
+      result = malloc(dir_len + 3);
+      if (result) { /* do nothing if we are out of memory */
+        result[0] = unixroot[0];
+        result[1] = unixroot[1];
+        memcpy(result + 2, path, dir_len);
+        result[dir_len + 2] = '\0';
+      }
+
+    }
+
+  return result;
+}
+
+
+/* Result is 0 if file descriptor fd is not connected to /dev/con. */
+
+static int
+is_valid (int fd)
+{
+  if (isatty (fd))
+    {
+      const char *s = ttyname (fd);
+      if (s != NULL && strcmp(s, "/dev/con") == 0)
+       return 1; /* fd is connected to /dev/con */
+    }
+
+  return 0;
+}
+
+
+/* Old libintl.h header files (e.g. 0.10.35) used a macro that referred
+   to dcgettext__. To keep binary compatibility we have to add an entry
+   point for this. */
+char *
+dcgettext__ (const char *domainname, const char *msgid, int category)
+{
+  return libintl_dcigettext (domainname, msgid, NULL, 0, 0, category);
+}
+
-----------------------------


Bye,
Andreas




reply via email to

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