[Top][All Lists]
[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
- Patches for OS/2 (3),
Andreas Buening <=