diff options
author | 1996-05-22 11:38:46 +0000 | |
---|---|---|
committer | 1996-05-22 11:38:46 +0000 | |
commit | deeceb4f92accc4deb336d37d16baca4eb48c4d8 (patch) | |
tree | 14611afb3e2550d8180d62f2c75184f1dd0af09b | |
parent | libutil (diff) | |
download | wireguard-openbsd-deeceb4f92accc4deb336d37d16baca4eb48c4d8.tar.xz wireguard-openbsd-deeceb4f92accc4deb336d37d16baca4eb48c4d8.zip |
svr4-style gencat
-rw-r--r-- | include/nl_types.h | 119 | ||||
-rw-r--r-- | lib/libc/nls/Makefile.inc | 7 | ||||
-rw-r--r-- | lib/libc/nls/_catclose.c | 25 | ||||
-rw-r--r-- | lib/libc/nls/_catgets.c | 28 | ||||
-rw-r--r-- | lib/libc/nls/_catopen.c | 26 | ||||
-rw-r--r-- | lib/libc/nls/catclose.c | 66 | ||||
-rw-r--r-- | lib/libc/nls/catgets.c | 110 | ||||
-rw-r--r-- | lib/libc/nls/catopen.c | 154 | ||||
-rw-r--r-- | lib/libc/nls/msgcat.c | 396 | ||||
-rw-r--r-- | lib/libc/nls/msgcat.h | 170 | ||||
-rw-r--r-- | usr.bin/gencat/Makefile | 5 | ||||
-rw-r--r-- | usr.bin/gencat/gencat.c | 912 | ||||
-rw-r--r-- | usr.bin/gencat/gencat.h | 107 | ||||
-rw-r--r-- | usr.bin/gencat/genlib.c | 888 |
14 files changed, 1170 insertions, 1843 deletions
diff --git a/include/nl_types.h b/include/nl_types.h index 37cbee8834d..8ae1baadf33 100644 --- a/include/nl_types.h +++ b/include/nl_types.h @@ -1,48 +1,95 @@ -/* $NetBSD: nl_types.h,v 1.5 1995/03/01 08:01:23 jtc Exp $ */ - -/*********************************************************** -Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that Alfalfa's name not be used in -advertising or publicity pertaining to distribution of the software -without specific, written prior permission. - -ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -If you make any modifications, bugfixes or other changes to this software -we'd appreciate it if you could send a copy to us so we can keep things -up-to-date. Many thanks. - Kee Hinckley - Alfalfa Software, Inc. - 267 Allston St., #3 - Cambridge, MA 02139 USA - nazgul@alfalfa.com - -******************************************************************/ +/* $NetBSD: nl_types.h,v 1.6 1996/05/13 23:11:15 jtc Exp $ */ + +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by J.T. Conklin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ #ifndef _NL_TYPES_H_ #define _NL_TYPES_H_ #include <sys/cdefs.h> -#define NL_SETD 0 +#ifdef _NLS_PRIVATE +/* + * MESSAGE CATALOG FILE FORMAT. + * + * The NetBSD message catalog format is similar to the format used by + * Svr4 systems. The differences are: + * * fixed byte order (big endian) + * * fixed data field sizes + * + * A message catalog contains four data types: a catalog header, one + * or more set headers, one or more message headers, and one or more + * text strings. + */ + +#define _NLS_MAGIC 0xff88ff89 + +struct _nls_cat_hdr { + int32_t __magic; + int32_t __nsets; + int32_t __mem; + int32_t __msg_hdr_offset; + int32_t __msg_txt_offset; +} ; + +struct _nls_set_hdr { + int32_t __setno; /* set number: 0 < x <= NL_SETMAX */ + int32_t __nmsgs; /* number of messages in the set */ + int32_t __index; /* index of first msg_hdr in msg_hdr table */ +} ; + +struct _nls_msg_hdr { + int32_t __msgno; /* msg number: 0 < x <= NL_MSGMAX */ + int32_t __msglen; + int32_t __offset; +} ; + +#endif + +#define NL_SETD 1 +#define NL_CAT_LOCALE 1 + +typedef struct { + void *__data; + int __size; +} *nl_catd; -typedef long nl_catd; typedef long nl_item; extern nl_catd catopen __P((__const char *, int)); -extern char *catgets __P((nl_catd, int, int, char *)); +extern char *catgets __P((nl_catd, int, int, const char *)); extern int catclose __P((nl_catd)); #endif /* _NL_TYPES_H_ */ diff --git a/lib/libc/nls/Makefile.inc b/lib/libc/nls/Makefile.inc index f72d0917f33..c1fef07abaf 100644 --- a/lib/libc/nls/Makefile.inc +++ b/lib/libc/nls/Makefile.inc @@ -1,6 +1,9 @@ -# $NetBSD: Makefile.inc,v 1.7 1995/02/27 13:06:20 cgd Exp $ +# $NetBSD: Makefile.inc,v 1.8 1996/05/13 23:29:32 jtc Exp $ .PATH: ${.CURDIR}/nls -SRCS+= catclose.c catgets.c catopen.c msgcat.c +SRCS+= catclose.c catgets.c catopen.c MAN+= catclose.3 catgets.3 catopen.3 + +# indirect reference stubs, to be removed soon. +SRCS+= _catclose.c _catgets.c _catopen.c diff --git a/lib/libc/nls/_catclose.c b/lib/libc/nls/_catclose.c new file mode 100644 index 00000000000..74c214d97a4 --- /dev/null +++ b/lib/libc/nls/_catclose.c @@ -0,0 +1,25 @@ +/* $NetBSD: _catclose.c,v 1.1 1996/05/13 23:29:34 jtc Exp $ */ + +/* + * Written by J.T. Conklin, 10/05/94 + * Public domain. + */ + +#include <sys/cdefs.h> + +#ifdef __indr_reference +__indr_reference(_catclose,catclose); +#else + +#include <nl_types.h> + +extern int _catclose __P((nl_catd)); + +int +catclose(catd) + nl_catd catd; +{ + return _catclose(catd); +} + +#endif diff --git a/lib/libc/nls/_catgets.c b/lib/libc/nls/_catgets.c new file mode 100644 index 00000000000..2648bfb0222 --- /dev/null +++ b/lib/libc/nls/_catgets.c @@ -0,0 +1,28 @@ +/* $NetBSD: _catgets.c,v 1.2 1996/05/16 21:51:22 cgd Exp $ */ + +/* + * Written by J.T. Conklin, 10/05/94 + * Public domain. + */ + +#include <sys/cdefs.h> + +#ifdef __indr_reference +__indr_reference(_catgets,catgets); +#else + +#include <nl_types.h> + +extern char * _catgets __P((nl_catd, int, int, const char *)); + +char * +catgets(catd, set_id, msg_id, s) + nl_catd catd; + int set_id; + int msg_id; + const char *s; +{ + return _catgets(catd, set_id, msg_id, s); +} + +#endif diff --git a/lib/libc/nls/_catopen.c b/lib/libc/nls/_catopen.c new file mode 100644 index 00000000000..30cd40c7375 --- /dev/null +++ b/lib/libc/nls/_catopen.c @@ -0,0 +1,26 @@ +/* $NetBSD: _catopen.c,v 1.1 1996/05/13 23:29:36 jtc Exp $ */ + +/* + * Written by J.T. Conklin, 10/05/94 + * Public domain. + */ + +#include <sys/cdefs.h> + +#ifdef __indr_reference +__indr_reference(_catopen,catopen); +#else + +#include <nl_types.h> + +extern nl_catd _catopen __P((__const char *, int)); + +nl_catd +catopen(name, oflag) + __const char *name; + int oflag; +{ + return _catopen(name, oflag); +} + +#endif diff --git a/lib/libc/nls/catclose.c b/lib/libc/nls/catclose.c index d10d1826b35..7054ada5f2a 100644 --- a/lib/libc/nls/catclose.c +++ b/lib/libc/nls/catclose.c @@ -1,25 +1,61 @@ -/* $NetBSD: catclose.c,v 1.6 1995/03/23 19:59:03 jtc Exp $ */ +/* $NetBSD: catclose.c,v 1.7 1996/05/13 23:29:37 jtc Exp $ */ -/* - * Written by J.T. Conklin, 10/05/94 - * Public domain. +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by J.T. Conklin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> - -#ifdef __indr_reference -__indr_reference(_catclose,catclose); -#else +#define _NLS_PRIVATE +#include <sys/types.h> +#include <sys/mman.h> +#include <errno.h> #include <nl_types.h> -extern int _catclose __P((nl_catd)); - int -catclose(catd) +_catclose(catd) nl_catd catd; { - return _catclose(catd); -} + if (catd == (nl_catd) -1) { + errno = EBADF; + return -1; + } + + if (catd) { + munmap(catd->__data, catd->__size); + free (catd); + } -#endif + return 0; +} diff --git a/lib/libc/nls/catgets.c b/lib/libc/nls/catgets.c index 9f361ea8490..248e6ffd4ef 100644 --- a/lib/libc/nls/catgets.c +++ b/lib/libc/nls/catgets.c @@ -1,28 +1,106 @@ -/* $NetBSD: catgets.c,v 1.7 1995/03/23 19:59:05 jtc Exp $ */ +/* $NetBSD: catgets.c,v 1.8 1996/05/13 23:29:38 jtc Exp $ */ -/* - * Written by J.T. Conklin, 10/05/94 - * Public domain. +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by J.T. Conklin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> - -#ifdef __indr_reference -__indr_reference(_catgets,catgets); -#else +#define _NLS_PRIVATE +#include <stdlib.h> +#include <string.h> #include <nl_types.h> -extern char * _catgets __P((nl_catd, int, int, char *)); - char * -catgets(catd, set_id, msg_id, s) +_catgets(catd, set_id, msg_id, s) nl_catd catd; int set_id; int msg_id; - char *s; + const char *s; { - return _catgets(catd, set_id, msg_id, s); -} + struct _nls_cat_hdr *cat_hdr; + struct _nls_set_hdr *set_hdr; + struct _nls_msg_hdr *msg_hdr; + int l, u, i, r; + + if (catd == (nl_catd) 0 || catd == (nl_catd) -1) { + return (char *) s; + } + + cat_hdr = (struct _nls_cat_hdr *) catd->__data; + set_hdr = (struct _nls_set_hdr *) (catd->__data + + sizeof(struct _nls_cat_hdr)); + + /* binary search, see knuth algorithm b */ + l = 0; + u = ntohl(cat_hdr->__nsets) - 1; + while (l <= u) { + i = (l + u) / 2; + r = set_id - ntohl(set_hdr[i].__setno); -#endif + if (r == 0) { + msg_hdr = (struct _nls_msg_hdr *) (catd->__data + + sizeof(struct _nls_cat_hdr) + + ntohl(cat_hdr->__msg_hdr_offset)); + + l = ntohl(set_hdr[i].__index); + u = l + ntohl(set_hdr[i].__nmsgs) - 1; + while (l <= u) { + i = (l + u) / 2; + r = msg_id - ntohl(msg_hdr[i].__msgno); + if (r == 0) { + return (char *) (catd->__data + + sizeof(struct _nls_cat_hdr) + + ntohl(cat_hdr->__msg_txt_offset) + + ntohl(msg_hdr[i].__offset)); + } else if (r < 0) { + u = i - 1; + } else { + l = i + 1; + } + } + + /* not found */ + return (char *) s; + + } else if (r < 0) { + u = i - 1; + } else { + l = i + 1; + } + } + + /* not found */ + return (char *) s; +} diff --git a/lib/libc/nls/catopen.c b/lib/libc/nls/catopen.c index 0e2f9716fbb..225f35515b6 100644 --- a/lib/libc/nls/catopen.c +++ b/lib/libc/nls/catopen.c @@ -1,26 +1,150 @@ -/* $NetBSD: catopen.c,v 1.5 1995/03/23 19:59:06 jtc Exp $ */ +/* $NetBSD: catopen.c,v 1.6 1996/05/13 23:29:39 jtc Exp $ */ -/* - * Written by J.T. Conklin, 10/05/94 - * Public domain. +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by J.T. Conklin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. */ -#include <sys/cdefs.h> - -#ifdef __indr_reference -__indr_reference(_catopen,catopen); -#else +#define _NLS_PRIVATE +#include <limits.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> #include <nl_types.h> -extern nl_catd _catopen __P((__const char *, int)); +#define NLS_DEFAULT_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L" +#define NLS_DEFAULT_LANG "C" nl_catd -catopen(name, oflag) - __const char *name; +_catopen(name, oflag) + const char *name; int oflag; { - return _catopen(name, oflag); -} + const char *path; + struct stat st; + nl_catd catd; + int fd; + + struct _nls_cat_hdr *cat_hdr; + + if (name == NULL || *name == '\0') + return (nl_catd) -1; + + /* absolute or relative path? */ + if (strchr (name, '/')) { + if (stat (name, &st)) { + return (nl_catd) 0; + } + path = name; + } else { + char tmppath[PATH_MAX]; + char *nlspath; + char *lang; + char *s, *t; + + if ((nlspath = getenv ("NLSPATH")) == NULL) { + nlspath = NLS_DEFAULT_PATH; + } + if ((lang = getenv ("LANG")) == NULL) { + lang = NLS_DEFAULT_LANG; + } + + for (s = nlspath, t = tmppath; *s; ) { + if (*s == '%') { + if (*(s + 1) == 'L') { + strcpy(t, lang); + t += strlen(lang); + s += 2; + } else if (*(s + 1) == 'N') { + strcpy(t, name); + t += strlen(name); + s += 2; + } else { + *t++ = *s++; + } + } else if (*s == ':') { + *t = '\0'; + + if (stat (tmppath, &st) == 0) { + path = tmppath; + goto load_msgcat; + } + + t = tmppath; + } else { + *t++ = *s++; + } + } -#endif + return (nl_catd) 0; + } + +load_msgcat: + if ((fd = open (path, O_RDONLY)) == -1) + return (nl_catd) 0; + + if (fstat(fd, &st) != 0) { + close (fd); + return (nl_catd) 0; + } + + if ((catd = malloc (sizeof (*catd))) == 0) { + close (fd); + return (nl_catd) 0; + } + + catd->__data = mmap(0, (size_t) st.st_size, PROT_READ, MAP_SHARED, fd, 0); + close (fd); + + if (catd->__data == (void *) -1) { + free (catd); + return (nl_catd) 0; + } + catd->__size = st.st_size; + + cat_hdr = (struct _nls_cat_hdr *) catd->__data; + if (ntohl(cat_hdr->__magic) != _NLS_MAGIC) { + free (catd); + close (fd); + return (nl_catd) 0; + } + + return catd; +} diff --git a/lib/libc/nls/msgcat.c b/lib/libc/nls/msgcat.c deleted file mode 100644 index 2c773f4be20..00000000000 --- a/lib/libc/nls/msgcat.c +++ /dev/null @@ -1,396 +0,0 @@ -/* $NetBSD: msgcat.c,v 1.11 1995/02/27 13:06:51 cgd Exp $ */ - -/*********************************************************** -Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that Alfalfa's name not be used in -advertising or publicity pertaining to distribution of the software -without specific, written prior permission. - -ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -If you make any modifications, bugfixes or other changes to this software -we'd appreciate it if you could send a copy to us so we can keep things -up-to-date. Many thanks. - Kee Hinckley - Alfalfa Software, Inc. - 267 Allston St., #3 - Cambridge, MA 02139 USA - nazgul@alfalfa.com - -******************************************************************/ - -#if defined(LIBC_SCCS) && !defined(lint) -static char *rcsid = "$NetBSD: msgcat.c,v 1.11 1995/02/27 13:06:51 cgd Exp $"; -#endif /* LIBC_SCCS and not lint */ - -/* Edit History - -03/06/91 4 schulert remove working directory from nlspath -01/18/91 2 hamilton #if not rescanned -01/12/91 3 schulert conditionally use prototypes -11/03/90 1 hamilton Alphalpha->Alfalfa & OmegaMail->Poste -10/15/90 2 schulert > #include <unistd.h> if MIPS -08/13/90 1 schulert move from ua to omu -*/ - -/* - * We need a better way of handling errors than printing text. I need - * to add an error handling routine. - */ - -#include "nl_types.h" -#include "msgcat.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#ifndef True -# define True ~0 -# define False 0 -#endif - -/* take care of sysv diffs */ -#ifndef MAXPATHLEN -#define MAXPATHLEN 1024 -#endif - -#ifndef FD_CLOEXEC -#define FD_CLOEXEC 1 -#endif - -#define NLERR ((nl_catd) -1) - -static nl_catd loadCat(); -static nl_catd loadSet(); - -nl_catd _catopen( name, type) -__const char *name; -int type; -{ - char path[MAXPATHLEN]; - __const char *catpath = NULL; - char *nlspath, *tmppath = NULL; - char *lang; - long len; - char *base, *cptr, *pathP; - struct stat sbuf; - - if (!name || !*name) return(NLERR); - - if (strchr(name, '/')) { - catpath = name; - if (stat(catpath, &sbuf)) return(0); - } else { - if ((lang = (char *) getenv("LANG")) == NULL) lang = "C"; - if ((nlspath = (char *) getenv("NLSPATH")) == NULL) { - nlspath = "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L"; - } - - len = strlen(nlspath); - base = cptr = (char *) malloc(len + 2); - if (!base) return(NLERR); - strcpy(cptr, nlspath); - cptr[len] = ':'; - cptr[len+1] = '\0'; - - for (nlspath = cptr; *cptr; ++cptr) { - if (*cptr == ':') { - *cptr = '\0'; - for (pathP = path; *nlspath; ++nlspath) { - if (*nlspath == '%') { - if (*(nlspath + 1) == 'L') { - ++nlspath; - strcpy(pathP, lang); - pathP += strlen(lang); - } else if (*(nlspath + 1) == 'N') { - ++nlspath; - strcpy(pathP, name); - pathP += strlen(name); - } else *(pathP++) = *nlspath; - } else *(pathP++) = *nlspath; - } - *pathP = '\0'; - if (stat(path, &sbuf) == 0) { - catpath = path; - break; - } - nlspath = cptr+1; - } - } - free(base); - if (tmppath) free(tmppath); - - if (!catpath) return(0); - } - - return(loadCat(catpath, type)); -} - -/* - * We've got an odd situation here. The odds are real good that the - * number we are looking for is almost the same as the index. We could - * use the index, check the difference and do something intelligent, but - * I haven't quite figured out what's intelligent. - * - * Here's a start. - * Take an id N. If there are > N items in the list, then N cannot - * be more than N items from the start, since otherwise there would - * have to be duplicate items. So we can safely set the top to N+1 - * (after taking into account that ids start at 1, and arrays at 0) - * - * Let's say we are at position P, and we are looking for N, but have - * V. If N > V, then the furthest away that N could be is - * P + (N-V). So we can safely set hi to P+(N-V)+1. For example: - * We are looking for 10, but have 8 - * 8 ? ? ? ? - * >=9 >=10 >=11 - * - */ -static MCSetT *MCGetSet( cat, setId) -MCCatT *cat; -int setId; -{ - MCSetT *set; - long lo, hi, cur, dir; - - if (!cat || setId <= 0) return(NULL); - - lo = 0; - if (setId - 1 < cat->numSets) { - cur = setId - 1; - hi = setId; - } else { - hi = cat->numSets; - cur = (hi - lo) / 2; - } - - while (True) { - set = cat->sets + cur; - if (set->setId == setId) break; - if (set->setId < setId) { - lo = cur+1; - if (hi > cur + (setId - set->setId) + 1) hi = cur+(setId-set->setId)+1; - dir = 1; - } else { - hi = cur; - dir = -1; - } - if (lo >= hi) return(NULL); - if (hi - lo == 1) cur += dir; - else cur += ((hi - lo) / 2) * dir; - } - if (set->invalid) loadSet(cat, set); - return(set); -} - - -static MCMsgT *MCGetMsg( set, msgId) -MCSetT *set; -int msgId; -{ - MCMsgT *msg; - long lo, hi, cur, dir; - - if (!set || set->invalid || msgId <= 0) return(NULL); - - lo = 0; - if (msgId - 1 < set->numMsgs) { - cur = msgId - 1; - hi = msgId; - } else { - hi = set->numMsgs; - cur = (hi - lo) / 2; - } - - while (True) { - msg = set->u.msgs + cur; - if (msg->msgId == msgId) break; - if (msg->msgId < msgId) { - lo = cur+1; - if (hi > cur + (msgId - msg->msgId) + 1) hi = cur+(msgId-msg->msgId)+1; - dir = 1; - } else { - hi = cur; - dir = -1; - } - if (lo >= hi) return(NULL); - if (hi - lo == 1) cur += dir; - else cur += ((hi - lo) / 2) * dir; - } - return(msg); -} - -char *_catgets( catd, setId, msgId, dflt) -nl_catd catd; -int setId; -int msgId; -char *dflt; -{ - MCMsgT *msg; - MCCatT *cat = (MCCatT *) catd; - char *cptr; - - msg = MCGetMsg(MCGetSet(cat, setId), msgId); - if (msg) cptr = msg->msg.str; - else cptr = dflt; - return(cptr); -} - - -int _catclose( catd) -nl_catd catd; -{ - MCCatT *cat = (MCCatT *) catd; - MCSetT *set; - MCMsgT *msg; - int i, j; - - if (!cat) return -1; - - if (cat->loadType != MCLoadAll) close(cat->fd); - for (i = 0; i < cat->numSets; ++i) { - set = cat->sets + i; - if (!set->invalid) { - free(set->data.str); - free(set->u.msgs); - } - } - free(cat->sets); - free(cat); - - return 0; -} - -/* - * Internal routines - */ - -/* Note that only malloc failures are allowed to return an error */ -#define ERRNAME "Message Catalog System" -#define CORRUPT() {fprintf(stderr, "%s: corrupt file.\n", ERRNAME); return(0);} -#define NOSPACE() {fprintf(stderr, "%s: no more memory.\n", ERRNAME); return(NLERR);} - -static nl_catd loadCat( catpath, type) -__const char *catpath; -int type; -{ - MCHeaderT header; - MCCatT *cat; - MCSetT *set; - MCMsgT *msg; - long i, j; - off_t nextSet; - - cat = (MCCatT *) malloc(sizeof(MCCatT)); - if (!cat) return(NLERR); - cat->loadType = type; - - if ((cat->fd = open(catpath, O_RDONLY)) < 0) { - return(0); - } - - fcntl(cat->fd, F_SETFD, FD_CLOEXEC); - - if (read(cat->fd, &header, sizeof(header)) != sizeof(header)) CORRUPT(); - - if (strncmp(header.magic, MCMagic, MCMagicLen) != 0) CORRUPT(); - - if (header.majorVer != MCMajorVer) { - fprintf(stderr, "%s: %s is version %d, we need %d.\n", ERRNAME, - catpath, header.majorVer, MCMajorVer); - return(0); - } - - if (header.numSets <= 0) { - fprintf(stderr, "%s: %s has %d sets!\n", ERRNAME, catpath, - header.numSets); - return(0); - } - - cat->numSets = header.numSets; - cat->sets = (MCSetT *) malloc(sizeof(MCSetT) * header.numSets); - if (!cat->sets) NOSPACE(); - - nextSet = header.firstSet; - for (i = 0; i < cat->numSets; ++i) { - if (lseek(cat->fd, nextSet, 0) == -1) CORRUPT(); - - /* read in the set header */ - set = cat->sets + i; - if (read(cat->fd, set, sizeof(*set)) != sizeof(*set)) CORRUPT(); - - /* if it's invalid, skip over it (and backup 'i') */ - - if (set->invalid) { - --i; - nextSet = set->nextSet; - continue; - } - - if (cat->loadType == MCLoadAll) { - nl_catd res; - if ((res = loadSet(cat, set)) <= 0) { - if (res == -1) NOSPACE(); - CORRUPT(); - } - } else set->invalid = True; - nextSet = set->nextSet; - } - if (cat->loadType == MCLoadAll) { - close(cat->fd); - cat->fd = -1; - } - return((nl_catd) cat); -} - -static nl_catd loadSet( cat, set) -MCCatT *cat; -MCSetT *set; -{ - MCMsgT *msg; - int i; - - /* Get the data */ - if (lseek(cat->fd, set->data.off, 0) == -1) return(0); - if ((set->data.str = (char *) malloc(set->dataLen)) == NULL) return(-1); - if (read(cat->fd, set->data.str, set->dataLen) != set->dataLen) return(0); - - /* Get the messages */ - if (lseek(cat->fd, set->u.firstMsg, 0) == -1) return(0); - if ((set->u.msgs = (MCMsgT *) malloc(sizeof(MCMsgT) * set->numMsgs)) == NULL) return(-1); - - for (i = 0; i < set->numMsgs; ++i) { - msg = set->u.msgs + i; - if (read(cat->fd, msg, sizeof(*msg)) != sizeof(*msg)) return(0); - if (msg->invalid) { - --i; - continue; - } - msg->msg.str = (char *) (set->data.str + msg->msg.off); - } - set->invalid = False; - return(1); -} - - - - - diff --git a/lib/libc/nls/msgcat.h b/lib/libc/nls/msgcat.h index 82f411f28a0..e69de29bb2d 100644 --- a/lib/libc/nls/msgcat.h +++ b/lib/libc/nls/msgcat.h @@ -1,170 +0,0 @@ -/* $NetBSD: msgcat.h,v 1.3 1995/02/27 13:06:55 cgd Exp $ */ - -/* -*-c++-*- */ - -#ifndef __msgcath - - -/*********************************************************** -Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that Alfalfa's name not be used in -advertising or publicity pertaining to distribution of the software -without specific, written prior permission. - -ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -If you make any modifications, bugfixes or other changes to this software -we'd appreciate it if you could send a copy to us so we can keep things -up-to-date. Many thanks. - Kee Hinckley - Alfalfa Software, Inc. - 267 Allston St., #3 - Cambridge, MA 02139 USA - nazgul@alfalfa.com - -******************************************************************/ - - -#include <sys/types.h> - -/* - * On disk data structures - */ - -/* Edit History - -02/25/91 2 nazgul Byte order flags, upped the version number -11/03/90 1 hamilton Alphalpha->Alfalfa & OmegaMail->Poste -08/13/90 1 schulert move from ua to omu -*/ - -/* For or'd constants */ -#define MCMakeId(s,m) (unsigned long) ( ((unsigned short)s << (sizeof(short)*8)) \ - | (unsigned short)m ) -#define MCSetId(id) (unsigned int) ( id >> (sizeof(short) * 8) ) -#define MCMsgId(id) (unsigned int) ( (id << (sizeof(short) * 8)) \ - >> (sizeof(short) * 8) ) -#undef S -#undef UI -#undef UL - -#define MCMagicLen 8 -#define MCMagic "*nazgul*" -#define MCLastMsg 0 -#define MCLastSet 0 - -#define MCMajorVer 1 -#define MCMinorVer 0 - -/* - * Critical note here. Sets and Messages *MUST* be stored in ascending - * order. There are stored that way (by specification) in the original - * data file, however in the process of merging in new stuff you might - * mix that up. Don't! The catget stuff does a binary search and will - * totally lose it if these aren't in order (not contiguous mind you, just - * in order. If this turns out to be a major problem this could be enhanced - * by adding a 'sorted' flag to the db, and sorting msgs and sets at load - * time if things aren't sorted, but I'd like not to have to do that. - */ - -/* - * I have tried here to define data structures which can be used - * while the catalog is on disk, and at runtime. - * This is rather dangerous of course, but I think it can be done without - * overly increasing the memory usage, and it makes loading and storing - * somewhat simpler and less prone to accidents. I have also tried to - * define on disk data structures which can be updated in place, so that - * with a very large catalog (e.g. all system errors) you don't have to - * load everything in memory in order to add or update one set. With - * this in mind there are "invalid" flags which allow items to be - * invalidated and thus not loaded at runtime. Note however that although - * I pay attention to these when I load the DB, I do not currently use - * them in gencat (it just reads everything into memory), so there is - * no guarantee that this will all work. - */ - -/* These should be publicly available */ - -#define MCLoadBySet 0 /* Load entire sets as they are used */ -#define MCLoadAll 1 /* Load entire DB on catopen */ - -/* - * MCOffsetT - Union to handle both disk and runtime pointers - */ -typedef union { - off_t off; - char *str; - void *ptr; - struct _MCMsgT *msg; - struct _MCSetT *set; -} MCOffsetT; - -/* - * MCMsgT - Message structure (disk and runtime) - */ -typedef struct _MCMsgT { - long msgId; /* Id of this message */ - MCOffsetT msg; /* Relative offset on disk or pointer in memory */ - long invalid; /* Valid on disk, loaded in memory */ -} MCMsgT; - -/* - * MCSetT - Set structure (disk and runtime) - */ -typedef struct _MCSetT { - long setId; /* Id of this set */ - off_t nextSet; /* Offset of next set on disk */ - union { - off_t firstMsg; /* Offset to first Msg (while on disk) */ - MCMsgT *msgs; /* Pointer to array of msgs (in mem, loaded) */ - } u; - MCOffsetT data; /* Offset to data, or pointer to data */ - long dataLen; /* Length of data area on disk */ - long numMsgs; /* Number of messages */ - long invalid; /* Valid on disk, loaded in memory */ -} MCSetT; - -/* - * MCCatT - Runtime catalog pointer - */ -typedef struct { - long loadType; /* How to load the messages (see MSLoadType) */ - int fd; /* File descriptor of catalog (if load-on-demand) */ - long numSets; /* Number of sets */ - MCSetT *sets; /* Pointer to the sets */ - off_t firstSet; /* Offset of first set on disk */ -} MCCatT; - -/* - * MCHeaderT - Disk file header - */ -typedef struct { - char magic[MCMagicLen]; /* Magic cookie "*nazgul*" */ - long majorVer; /* ++ on incompatible changes */ - long minorVer; /* ++ on compatible changes */ - long flags; /* Informational flags */ - long numSets; /* Number of valid Sets */ - off_t firstSet; /* Offset of first set on disk */ -} MCHeaderT; - -/* Some flags */ -#define MC68KByteOrder 0x01 -#define MCn86ByteOrder 0x02 - - - - -#endif diff --git a/usr.bin/gencat/Makefile b/usr.bin/gencat/Makefile index 5330390c7d6..af94c1a9f17 100644 --- a/usr.bin/gencat/Makefile +++ b/usr.bin/gencat/Makefile @@ -1,9 +1,6 @@ -# $Id: Makefile,v 1.1.1.1 1995/10/18 08:45:19 deraadt Exp $ +# $Id: Makefile,v 1.2 1996/05/22 11:38:52 deraadt Exp $ PROG= gencat -SRCS= gencat.c genlib.c NOMAN= -CFLAGS+= -I${.CURDIR}/../../lib/libc/nls - .include <bsd.prog.mk> diff --git a/usr.bin/gencat/gencat.c b/usr.bin/gencat/gencat.c index b6b6b2afe0d..b023c6e3181 100644 --- a/usr.bin/gencat/gencat.c +++ b/usr.bin/gencat/gencat.c @@ -1,3 +1,38 @@ +/*- + * Copyright (c) 1996 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by J.T. Conklin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ /*********************************************************** Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. @@ -28,227 +63,716 @@ up-to-date. Many thanks. 267 Allston St., #3 Cambridge, MA 02139 USA nazgul@alfalfa.com - -******************************************************************/ -/* Edit History +******************************************************************/ -01/18/91 3 hamilton #if not reparsed -01/12/91 2 schulert conditionally use prototypes -12/23/90 2 hamilton Fix fd == NULL to fd < 0 -11/03/90 1 hamilton Alphalpha->Alfalfa & OmegaMail->Poste -08/13/90 1 schulert move from ua to omu -*/ +#define _NLS_PRIVATE +#include <sys/queue.h> +#include <ctype.h> #include <stdio.h> -#include <sys/types.h> -#ifdef SYSV -#include <sys/fcntl.h> -#define L_SET SEEK_SET -#define L_INCR SEEK_CUR -#endif -#include <sys/file.h> -#include <sys/stat.h> -#include "gencat.h" +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <nl_types.h> -/* - * The spec says the syntax is "gencat catfile msgfile...". - * We extend it to: - * gencat [-lang C|C++|ANSIC] catfile msgfile [-h <header-file>]... - * Flags are order dependant, we'll take whatever lang was most recently chosen - * and use it to generate the next header file. The header files are generated - * at the point in the command line they are listed. Thus the sequence: - * gencat -lang C foo.cat foo.mcs -h foo.h -lang C++ bar.mcs -h bar.H - * will put constants from foo.mcs into foo.h and constants from bar.mcs into - * bar.h. Constants are not saved in the catalog file, so nothing will come - * from that, even if things have been defined before. The constants in foo.h - * will be in C syntax, in bar.H in C++ syntax. - */ +extern void MCAddSet __P((int setId)); +extern void MCDelSet __P((int setId)); +extern void MCAddMsg __P((int msgId, const char *msg)); +extern void MCDelMsg __P((int msgId)); +extern void MCParse __P((int fd)); +extern void MCReadCat __P((int fd)); +extern void MCWriteCat __P((int fd)); -#if ANSI_C || defined(__cplusplus) -# define P_(x) x -#else -# define P_(x) /**/ -#endif +struct _msgT { + long msgId; + char *str; + LIST_ENTRY(_msgT) entries; +}; + +struct _setT { + long setId; + LIST_HEAD(msghead, _msgT) msghead; + LIST_ENTRY(_setT) entries; +}; -static void writeIfChanged P_((char *fname, int lang, int orConsts)); +LIST_HEAD(sethead, _setT) sethead; +static struct _setT *curSet; -#undef P_ +static char *curline = NULL; +static long lineno = 0; -void usage() { - fprintf(stderr, "Use: gencat [-new] [-or] [-lang C|C++|ANSIC]\n"); - fprintf(stderr, " catfile msgfile [-h <header-file>]...\n"); +void +usage() +{ + fprintf(stderr, "Use: gencat catfile msgfile ...\n"); + exit(1); } -int main( -#if ANSI_C || defined(__cplusplus) - int argc, char *argv[]) -#else - argc, argv) -int argc; -char *argv[]; -#endif +int +main(argc, argv) + int argc; + char *argv[]; { - int ofd, ifd, i; - FILE *fptr; - char *catfile = NULL; - char *input = NULL; - int lang = MCLangC; - int new = False; - int orConsts = False; - - for (i = 1; i < argc; ++i) { - if (argv[i][0] == '-') { - if (strcmp(argv[i], "-lang") == 0) { - ++i; - if (strcmp(argv[i], "C") == 0) lang = MCLangC; - else if (strcmp(argv[i], "C++") == 0) lang = MCLangCPlusPlus; - else if (strcmp(argv[i], "ANSIC") == 0) lang = MCLangANSIC; - else { - fprintf(stderr, "gencat: Unrecognized language: %s\n", argv[i]); - exit(1); - } - } else if (strcmp(argv[i], "-h") == 0) { - if (!input) { - fprintf(stderr, "gencat: Can't write to a header before reading something.\n"); - exit(1); - } - ++i; - writeIfChanged(argv[i], lang, orConsts); - } else if (strcmp(argv[i], "-new") == 0) { - if (catfile) { - fprintf(stderr, "gencat: You must specify -new before the catalog file name\n"); - exit(1); + int ofd, ifd; + char *catfile = NULL; + int c; + + while ((c = getopt(argc, argv, "")) != -1) { + switch (c) { + case '?': + default: + usage(); + /* NOTREACHED */ } - new = True; - } else if (strcmp(argv[i], "-or") == 0) { - orConsts = ~orConsts; - } else { + } + argc -= optind; + argv += optind; + + if (argc < 2) { usage(); - exit(1); - } - } else { - if (!catfile) { - catfile = argv[i]; - if (new) { - if ((ofd = open(catfile, O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { - fprintf(stderr, "gencat: Unable to create a new %s.\n", catfile); - exit(1); - } - } else if ((ofd = open(catfile, O_RDONLY)) < 0) { - if ((ofd = open(catfile, O_WRONLY|O_CREAT, 0666)) < 0) { - fprintf(stderr, "gencat: Unable to create %s.\n", catfile); - exit(1); - } - } else { - MCReadCat(ofd); - close(ofd); - if ((ofd = open(catfile, O_WRONLY|O_TRUNC)) < 0) { - fprintf(stderr, "gencat: Unable to truncate %s.\n", catfile); + /* NOTREACHED */ + } + catfile = *argv++; + + for (; *argv; argv++) { + if ((ifd = open(*argv, O_RDONLY)) < 0) { + fprintf(stderr, "gencat: Unable to read %s\n", *argv); exit(1); - } - } - } else { - input = argv[i]; - if ((ifd = open(input, O_RDONLY)) < 0) { - fprintf(stderr, "gencat: Unable to read %s\n", input); - exit(1); } MCParse(ifd); close(ifd); - } } - } - if (catfile) { + + if ((ofd = open(catfile, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) { + fprintf(stderr, "gencat: Unable to create a new %s.\n", + catfile); + exit(1); + } MCWriteCat(ofd); exit(0); - } else { - usage(); +} + +static void +warning(cptr, msg) + char *cptr; + char *msg; +{ + fprintf(stderr, "gencat: %s on line %ld\n", msg, lineno); + fprintf(stderr, "%s\n", curline); + if (cptr) { + char *tptr; + for (tptr = curline; tptr < cptr; ++tptr) + putc(' ', stderr); + fprintf(stderr, "^\n"); + } +} + +static void +error(cptr, msg) + char *cptr; + char *msg; +{ + warning(cptr, msg); exit(1); - } } -static void writeIfChanged( -#if ANSI_C || defined(__cplusplus) - char *fname, int lang, int orConsts) -#else - fname, lang, orConsts) -char *fname; -int lang; -int orConsts; +static void +corrupt() +{ + error(NULL, "corrupt message catalog"); +} + +static void +nomem() +{ + error(NULL, "out of memory"); +} + +static void * +xmalloc(len) + size_t len; +{ + void *p; + + if ((p = malloc(len)) == NULL) + nomem(); + return (p); +} + +static void * +xrealloc(ptr, size) + void *ptr; + size_t size; +{ + if ((ptr = realloc(ptr, size)) == NULL) + nomem(); + return (ptr); +} + +static char * +xstrdup(str) + char *str; +{ + if ((str = strdup(str)) == NULL) + nomem(); + return (str); +} + +static char * +getline(fd) + int fd; +{ + static long curlen = BUFSIZ; + static char buf[BUFSIZ], *bptr = buf, *bend = buf; + char *cptr, *cend; + long buflen; + + if (!curline) { + curline = xmalloc(curlen); + } + ++lineno; + + cptr = curline; + cend = curline + curlen; + for (;;) { + for (; bptr < bend && cptr < cend; ++cptr, ++bptr) { + if (*bptr == '\n') { + *cptr = '\0'; + ++bptr; + return (curline); + } else + *cptr = *bptr; + } + if (bptr == bend) { + buflen = read(fd, buf, BUFSIZ); + if (buflen <= 0) { + if (cptr > curline) { + *cptr = '\0'; + return (curline); + } + return (NULL); + } + bend = buf + buflen; + bptr = buf; + } + if (cptr == cend) { + cptr = curline = xrealloc(curline, curlen *= 2); + cend = curline + curlen; + } + } +} + +static char * +wskip(cptr) + char *cptr; +{ + if (!*cptr || !isspace(*cptr)) { + warning(cptr, "expected a space"); + return (cptr); + } + while (*cptr && isspace(*cptr)) + ++cptr; + return (cptr); +} + +static char * +cskip(cptr) + char *cptr; +{ + if (!*cptr || isspace(*cptr)) { + warning(cptr, "wasn't expecting a space"); + return (cptr); + } + while (*cptr && !isspace(*cptr)) + ++cptr; + return (cptr); +} + +static char * +getmsg(fd, cptr, quote) + int fd; + char *cptr; + char quote; +{ + static char *msg = NULL; + static long msglen = 0; + long clen, i; + char *tptr; + + if (quote && *cptr == quote) { + ++cptr; + } + + clen = strlen(cptr) + 1; + if (clen > msglen) { + if (msglen) + msg = xrealloc(msg, clen); + else + msg = xmalloc(clen); + msglen = clen; + } + tptr = msg; + + while (*cptr) { + if (quote && *cptr == quote) { + char *tmp; + tmp = cptr + 1; + if (*tmp && (!isspace(*tmp) || *wskip(tmp))) { + warning(cptr, "unexpected quote character, ignoreing"); + *tptr++ = *cptr++; + } else { + *cptr = '\0'; + } + } else + if (*cptr == '\\') { + ++cptr; + switch (*cptr) { + case '\0': + cptr = getline(fd); + if (!cptr) + error(NULL, "premature end of file"); + msglen += strlen(cptr); + i = tptr - msg; + msg = xrealloc(msg, msglen); + tptr = msg + i; + break; + case 'n': + *tptr++ = '\n'; + ++cptr; + break; + case 't': + *tptr++ = '\t'; + ++cptr; + break; + case 'v': + *tptr++ = '\v'; + ++cptr; + break; + case 'b': + *tptr++ = '\b'; + ++cptr; + break; + case 'r': + *tptr++ = '\r'; + ++cptr; + break; + case 'f': + *tptr++ = '\f'; + ++cptr; + break; + case '\\': + *tptr++ = '\\'; + ++cptr; + break; + default: + if (isdigit(*cptr)) { + *tptr = 0; + for (i = 0; i < 3; ++i) { + if (!isdigit(*cptr)) + break; + if (*cptr > '7') + warning(cptr, "octal number greater than 7?!"); + *tptr *= 8; + *tptr += (*cptr - '0'); + ++cptr; + } + } else { + warning(cptr, "unrecognized escape sequence"); + } + } + } else { + *tptr++ = *cptr++; + } + } + *tptr = '\0'; + return (msg); +} + +void +MCParse(fd) + int fd; +{ + char *cptr, *str; + int setid, msgid = 0; + char quote = 0; + + /* XXX: init sethead? */ + + while ((cptr = getline(fd))) { + if (*cptr == '$') { + ++cptr; + if (strncmp(cptr, "set", 3) == 0) { + cptr += 3; + cptr = wskip(cptr); + setid = atoi(cptr); + MCAddSet(setid); + msgid = 0; + } else if (strncmp(cptr, "delset", 6) == 0) { + cptr += 6; + cptr = wskip(cptr); + setid = atoi(cptr); + MCDelSet(setid); + } else if (strncmp(cptr, "quote", 5) == 0) { + cptr += 5; + if (!*cptr) + quote = 0; + else { + cptr = wskip(cptr); + if (!*cptr) + quote = 0; + else + quote = *cptr; + } + } else if (isspace(*cptr)) { + ; + } else { + if (*cptr) { + cptr = wskip(cptr); + if (*cptr) + warning(cptr, "unrecognized line"); + } + } + } else { + if (isdigit(*cptr)) { + msgid = atoi(cptr); + cptr = cskip(cptr); + cptr = wskip(cptr); + /* if (*cptr) ++cptr; */ + } + if (!*cptr) + MCDelMsg(msgid); + else { + str = getmsg(fd, cptr, quote); + MCAddMsg(msgid, str); + } + } + } +} + +void +MCReadCat(fd) + int fd; +{ +#if 0 + MCHeaderT mcHead; + MCMsgT mcMsg; + MCSetT mcSet; + msgT *msg; + setT *set; + int i; + char *data; + + /* XXX init sethead? */ + + if (read(fd, &mcHead, sizeof(mcHead)) != sizeof(mcHead)) + corrupt(); + if (strncmp(mcHead.magic, MCMagic, MCMagicLen) != 0) + corrupt(); + if (mcHead.majorVer != MCMajorVer) + error(NULL, "unrecognized catalog version"); + if ((mcHead.flags & MCGetByteOrder()) == 0) + error(NULL, "wrong byte order"); + + if (lseek(fd, mcHead.firstSet, SEEK_SET) == -1) + corrupt(); + + for (;;) { + if (read(fd, &mcSet, sizeof(mcSet)) != sizeof(mcSet)) + corrupt(); + if (mcSet.invalid) + continue; + + set = xmalloc(sizeof(setT)); + memset(set, '\0', sizeof(*set)); + if (cat->first) { + cat->last->next = set; + set->prev = cat->last; + cat->last = set; + } else + cat->first = cat->last = set; + + set->setId = mcSet.setId; + + /* Get the data */ + if (mcSet.dataLen) { + data = xmalloc(mcSet.dataLen); + if (lseek(fd, mcSet.data.off, SEEK_SET) == -1) + corrupt(); + if (read(fd, data, mcSet.dataLen) != mcSet.dataLen) + corrupt(); + if (lseek(fd, mcSet.u.firstMsg, SEEK_SET) == -1) + corrupt(); + + for (i = 0; i < mcSet.numMsgs; ++i) { + if (read(fd, &mcMsg, sizeof(mcMsg)) != sizeof(mcMsg)) + corrupt(); + if (mcMsg.invalid) { + --i; + continue; + } + msg = xmalloc(sizeof(msgT)); + memset(msg, '\0', sizeof(*msg)); + if (set->first) { + set->last->next = msg; + msg->prev = set->last; + set->last = msg; + } else + set->first = set->last = msg; + + msg->msgId = mcMsg.msgId; + msg->str = xstrdup((char *) (data + mcMsg.msg.off)); + } + free(data); + } + if (!mcSet.nextSet) + break; + if (lseek(fd, mcSet.nextSet, SEEK_SET) == -1) + corrupt(); + } #endif +} + +/* + * Write message catalog. + * + * The message catalog is first converted from its internal to its + * external representation in a chunk of memory allocated for this + * purpose. Then the completed catalog is written. This approach + * avoids additional housekeeping variables and/or a lot of seeks + * that would otherwise be required. + */ +void +MCWriteCat(fd) + int fd; { - char tmpname[32]; - char buf[BUFSIZ], tbuf[BUFSIZ], *cptr, *tptr; - int fd, tfd; - int diff = False; - int c, len, tlen; - struct stat sbuf; - - /* If it doesn't exist, just create it */ - if (stat(fname, &sbuf)) { - if ((fd = open(fname, O_WRONLY|O_CREAT, 0666)) < 0) { - fprintf(stderr, "gencat: Unable to create header file %s.\n", fname); - exit(1); - } - MCWriteConst(fd, lang, orConsts); - close(fd); - return; - } - - /* If it does exist, create a temp file for now */ - sprintf(tmpname, "/tmp/gencat.%d", (int) getpid()); - if ((tfd = open(tmpname, O_RDWR|O_CREAT, 0666)) < 0) { - fprintf(stderr, "gencat: Unable to open temporary file: %s\n", tmpname); - exit(1); - } - unlink(tmpname); + int nsets; /* number of sets */ + int nmsgs; /* number of msgs */ + int string_size; /* total size of string pool */ + int msgcat_size; /* total size of message catalog */ + void *msgcat; /* message catalog data */ + struct _nls_cat_hdr *cat_hdr; + struct _nls_set_hdr *set_hdr; + struct _nls_msg_hdr *msg_hdr; + char *strings; + struct _setT *set; + struct _msgT *msg; + int msg_index; + int msg_offset; - /* Write to the temp file and rewind */ - MCWriteConst(tfd, lang, orConsts); + /* determine number of sets, number of messages, and size of the + * string pool */ + nsets = 0; + nmsgs = 0; + string_size = 0; - /* Open the real header file */ - if ((fd = open(fname, O_RDONLY)) < 0) { - fprintf(stderr, "gencat: Unable to read header file: %s\n", fname); - exit(1); - } + for (set = sethead.lh_first; set != NULL; + set = set->entries.le_next) { + nsets++; - /* Backup to the start of the temp file */ - if (lseek(tfd, 0L, L_SET) < 0) { - fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname); - exit(1); - } - - /* Now compare them */ - while ((tlen = read(tfd, tbuf, BUFSIZ)) > 0) { - if ((len = read(fd, buf, BUFSIZ)) != tlen) { - diff = True; - goto done; - } - for (cptr = buf, tptr = tbuf; cptr < buf+len; ++cptr, ++tptr) { - if (*tptr != *cptr) { - diff = True; - goto done; - } - } - } -done: - if (diff) { - if (lseek(tfd, 0L, L_SET) < 0) { - fprintf(stderr, "gencat: Unable to seek in tempfile: %s\n", tmpname); - exit(1); - } - close(fd); - if ((fd = open(fname, O_WRONLY|O_TRUNC)) < 0) { - fprintf(stderr, "gencat: Unable to truncate header file: %s\n", fname); - exit(1); - } - while ((len = read(tfd, buf, BUFSIZ)) > 0) { - if (write(fd, buf, len) != len) { - fprintf(stderr, "gencat: Error writing to header file: %s\n", fname); - } - } - } - close(fd); - close(tfd); + for (msg = set->msghead.lh_first; msg != NULL; + msg = msg->entries.le_next) { + nmsgs++; + string_size += strlen(msg->str) + 1; + } + } + +#ifdef DEBUG + printf("number of sets: %d\n", nsets); + printf("number of msgs: %d\n", nmsgs); + printf("string pool size: %d\n", string_size); +#endif + + /* determine size and then allocate buffer for constructing external + * message catalog representation */ + msgcat_size = sizeof(struct _nls_cat_hdr) + + (nsets * sizeof(struct _nls_set_hdr)) + + (nmsgs * sizeof(struct _nls_msg_hdr)) + + string_size; + + msgcat = xmalloc(msgcat_size); + memset(msgcat, '\0', msgcat_size); + + /* fill in msg catalog header */ + cat_hdr = (struct _nls_cat_hdr *) msgcat; + cat_hdr->__magic = htonl(_NLS_MAGIC); + cat_hdr->__nsets = htonl(nsets); + cat_hdr->__mem = htonl(msgcat_size - sizeof(struct _nls_cat_hdr)); + cat_hdr->__msg_hdr_offset = + htonl(nsets * sizeof(struct _nls_set_hdr)); + cat_hdr->__msg_txt_offset = + htonl(nsets * sizeof(struct _nls_set_hdr) + + nmsgs * sizeof(struct _nls_msg_hdr)); + + /* compute offsets for set & msg header tables and string pool */ + set_hdr = (struct _nls_set_hdr *) ((char *) msgcat + + sizeof(struct _nls_cat_hdr)); + msg_hdr = (struct _nls_msg_hdr *) ((char *) msgcat + + sizeof(struct _nls_cat_hdr) + + nsets * sizeof(struct _nls_set_hdr)); + strings = (char *) msgcat + + sizeof(struct _nls_cat_hdr) + + nsets * sizeof(struct _nls_set_hdr) + + nmsgs * sizeof(struct _nls_msg_hdr); + + msg_index = 0; + msg_offset = 0; + for (set = sethead.lh_first; set != NULL; + set = set->entries.le_next) { + + nmsgs = 0; + for (msg = set->msghead.lh_first; msg != NULL; + msg = msg->entries.le_next) { + int msg_len = strlen(msg->str) + 1; + + msg_hdr->__msgno = htonl(msg->msgId); + msg_hdr->__msglen = htonl(msg_len); + msg_hdr->__offset = htonl(msg_offset); + + memcpy(strings, msg->str, msg_len); + strings += msg_len; + msg_offset += msg_len; + + nmsgs++; + msg_hdr++; + } + + set_hdr->__setno = htonl(set->setId); + set_hdr->__nmsgs = htonl(nmsgs); + set_hdr->__index = htonl(msg_index); + msg_index += nmsgs; + set_hdr++; + } + + /* write out catalog. XXX: should this be done in small chunks? */ + write(fd, msgcat, msgcat_size); +} + +void +MCAddSet(setId) + int setId; +{ + struct _setT *p, *q; + + if (setId <= 0) { + error(NULL, "setId's must be greater than zero"); + /* NOTREACHED */ + } +#if 0 + /* XXX */ + if (setId > NL_SETMAX) { + error(NULL, "setId %d exceeds limit (%d)"); + /* NOTREACHED */ + } +#endif + + p = sethead.lh_first; + q = NULL; + for (; p != NULL && p->setId < setId; q = p, p = p->entries.le_next); + + if (p && p->setId == setId) { + ; + } else { + p = xmalloc(sizeof(struct _setT)); + memset(p, '\0', sizeof(struct _setT)); + LIST_INIT(&p->msghead); + + p->setId = setId; + + if (q == NULL) { + LIST_INSERT_HEAD(&sethead, p, entries); + } else { + LIST_INSERT_AFTER(q, p, entries); + } + } + + curSet = p; +} + +void +MCAddMsg(msgId, str) + int msgId; + const char *str; +{ + struct _msgT *p, *q; + + if (!curSet) + error(NULL, "can't specify a message when no set exists"); + + if (msgId <= 0) { + error(NULL, "msgId's must be greater than zero"); + /* NOTREACHED */ + } +#if 0 + /* XXX */ + if (msgId > NL_SETMAX) { + error(NULL, "msgID %d exceeds limit (%d)"); + /* NOTREACHED */ + } +#endif + + p = curSet->msghead.lh_first; + q = NULL; + for (; p != NULL && p->msgId < msgId; q = p, p = p->entries.le_next); + + if (p && p->msgId == msgId) { + free(p->str); + } else { + p = xmalloc(sizeof(struct _msgT)); + memset(p, '\0', sizeof(struct _msgT)); + + if (q == NULL) { + LIST_INSERT_HEAD(&curSet->msghead, p, entries); + } else { + LIST_INSERT_AFTER(q, p, entries); + } + } + + p->msgId = msgId; + p->str = xstrdup(str); +} + +void +MCDelSet(setId) + int setId; +{ + struct _setT *set; + struct _msgT *msg; + + set = sethead.lh_first; + for (; set != NULL && set->setId < setId; set = set->entries.le_next); + + if (set && set->setId == setId) { + + msg = set->msghead.lh_first; + while (msg) { + free(msg->str); + LIST_REMOVE(msg, entries) + } + + LIST_REMOVE(set, entries); + return; + } + warning(NULL, "specified set doesn't exist"); +} + +void +MCDelMsg(msgId) + int msgId; +{ + struct _msgT *msg; + + if (!curSet) + error(NULL, "you can't delete a message before defining the set"); + + msg = curSet->msghead.lh_first; + for (; msg != NULL && msg->msgId < msgId; msg = msg->entries.le_next); + + if (msg && msg->msgId == msgId) { + free(msg->str); + LIST_REMOVE(msg, entries); + return; + } + warning(NULL, "specified msg doesn't exist"); } diff --git a/usr.bin/gencat/gencat.h b/usr.bin/gencat/gencat.h deleted file mode 100644 index fcf20b7782a..00000000000 --- a/usr.bin/gencat/gencat.h +++ /dev/null @@ -1,107 +0,0 @@ - -/*********************************************************** -Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that Alfalfa's name not be used in -advertising or publicity pertaining to distribution of the software -without specific, written prior permission. - -ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -If you make any modifications, bugfixes or other changes to this software -we'd appreciate it if you could send a copy to us so we can keep things -up-to-date. Many thanks. - Kee Hinckley - Alfalfa Software, Inc. - 267 Allston St., #3 - Cambridge, MA 02139 USA - nazgul@alfalfa.com - -******************************************************************/ - -/* Edit History - -02/25/91 2 nazgul Added MCGetByteOrder -01/18/91 2 hamilton #if not reparsed -01/12/91 2 schulert conditionally use prototypes -11/03/90 1 hamilton Alphalpha->Alfalfa & OmegaMail->Poste -08/13/90 1 schulert move from ua to omu -*/ - -#ifndef gencat_h -#define gencat_h - -/* - * $set n comment - * My extension: If the comment begins with # treat the next string - * as a constant identifier. - * $delset n comment - * n goes from 1 to NL_SETMAX - * Deletes a set from the MC - * $ comment - * My extension: If comment begins with # treat the next string as - * a constant identifier for the next message. - * m message-text - * m goes from 1 to NL_MSGMAX - * If message-text is empty, and a space or tab is present, put - * empty string in catalog. - * If message-text is empty, delete the message. - * Length of text is 0 to NL_TEXTMAX - * My extension: If '#' is used instead of a number, the number - * is generated automatically. A # followed by anything is an empty message. - * $quote c - * Optional quote character which can suround message-text to - * show where spaces are. - * - * Escape Characters - * \n (newline), \t (horiz tab), \v (vert tab), \b (backspace), - * \r (carriage return), \f (formfeed), \\ (backslash), \ddd (bitpattern - * in octal). - * Also, \ at end of line is a continuation. - * - */ - -#define MCLangC 0 -#define MCLangCPlusPlus 1 -#define MCLangANSIC 2 - -#define MAXTOKEN 1024 - -#if !defined(ANSI_C) && (defined(__STDC__) || defined(_AIX)) -# define ANSI_C 1 -#endif - -#if ANSI_C || defined(__cplusplus) -# define P_(x) x -#else -# define P_(x) /**/ -#endif - -extern void MCAddSet P_((int setId, char *c)); -extern void MCDelSet P_((int setId)); -extern void MCAddMsg P_((int msgId, char *msg, char *c)); -extern void MCDelMsg P_((int msgId)); -extern void MCParse P_((int fd)); -extern void MCReadCat P_((int fd)); -extern void MCWriteConst P_((int fd, int type, int orConsts)); -extern void MCWriteCat P_((int fd)); -extern long MCGetByteOrder P_((void)); - -#ifndef True -# define True ~0 -# define False 0 -#endif - -#endif diff --git a/usr.bin/gencat/genlib.c b/usr.bin/gencat/genlib.c deleted file mode 100644 index 2f4dc155f8e..00000000000 --- a/usr.bin/gencat/genlib.c +++ /dev/null @@ -1,888 +0,0 @@ -/* -*-c++-*- */ - - -/*********************************************************** -Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that Alfalfa's name not be used in -advertising or publicity pertaining to distribution of the software -without specific, written prior permission. - -ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -If you make any modifications, bugfixes or other changes to this software -we'd appreciate it if you could send a copy to us so we can keep things -up-to-date. Many thanks. - Kee Hinckley - Alfalfa Software, Inc. - 267 Allston St., #3 - Cambridge, MA 02139 USA - nazgul@alfalfa.com - -******************************************************************/ - -/* Edit History - -02/25/91 5 nazgul Added flag for MS byteorder -01/14/91 4 nazgul Off by one on number specified entries -*/ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#ifdef SYSV -#include <sys/types.h> -#include <unistd.h> -#define L_SET SEEK_SET -#define L_INCR SEEK_CUR -#include <memory.h> -static int bcopy(src, dst, length) -char *src, *dst; -int length; -{ - memcpy(dst, src, length); -} -static int bzero(b, length) -char *b; -int length; -{ - memset(b, '\0', length); -} -#endif -#include <sys/file.h> -#include <ctype.h> -#include "msgcat.h" -#include "gencat.h" - -static char *curline = NULL; -static long lineno = 0; - -static void warning(cptr, msg) -char *cptr; -char *msg; -{ - fprintf(stderr, "gencat: %s on line %d\n", msg, lineno); - fprintf(stderr, "%s\n", curline); - if (cptr) { - char *tptr; - for (tptr = curline; tptr < cptr; ++tptr) putc(' ', stderr); - fprintf(stderr, "^\n"); - } -} - -static void error(cptr, msg) -char *cptr; -char *msg; -{ - warning(cptr, msg); - exit(1); -} - -static void corrupt() { - error(NULL, "corrupt message catalog"); -} -static void nomem() { - error(NULL, "out of memory"); -} - -static char *getline(fd) -int fd; -{ - static long len = 0, curlen = BUFSIZ; - static char buf[BUFSIZ], *bptr = buf, *bend = buf; - char *cptr, *cend; - long buflen; - - if (!curline) { - curline = (char *) malloc(curlen); - if (!curline) nomem(); - } - ++lineno; - - cptr = curline; - cend = curline + curlen; - while (True) { - for (; bptr < bend && cptr < cend; ++cptr, ++bptr) { - if (*bptr == '\n') { - *cptr = '\0'; - ++bptr; - return(curline); - } else *cptr = *bptr; - } - if (bptr == bend) { - buflen = read(fd, buf, BUFSIZ); - if (buflen <= 0) { - if (cptr > curline) { - *cptr = '\0'; - return(curline); - } - return(NULL); - } - bend = buf + buflen; - bptr = buf; - } - if (cptr == cend) { - cptr = curline = (char *) realloc(curline, curlen *= 2); - cend = curline + curlen; - } - } -} - - -static char *token(cptr) -char *cptr; -{ - static char tok[MAXTOKEN+1]; - char *tptr = tok; - - while (*cptr && isspace(*cptr)) ++cptr; - while (*cptr && !isspace(*cptr)) *tptr++ = *cptr++; - *tptr = '\0'; - return(tok); -} -static char *wskip(cptr) -char *cptr; -{ - if (!*cptr || !isspace(*cptr)) { - warning(cptr, "expected a space"); - return(cptr); - } - while (*cptr && isspace(*cptr)) ++cptr; - return(cptr); -} -static char *cskip(cptr) -char *cptr; -{ - if (!*cptr || isspace(*cptr)) { - warning(cptr, "wasn't expecting a space"); - return(cptr); - } - while (*cptr && !isspace(*cptr)) ++cptr; - return(cptr); -} - -static char *getmsg(fd, cptr, quote) -int fd; -char *cptr; -char quote; -{ - static char *msg = NULL; - static long msglen = 0; - long clen, i; - char *tptr; - - int needq; - - if (quote && *cptr == quote) { - needq = True; - ++cptr; - } else needq = False; - - clen = strlen(cptr) + 1; - if (clen > msglen) { - if (msglen) msg = (char *) realloc(msg, clen); - else msg = (char *) malloc(clen); - msglen = clen; - } - tptr = msg; - - while (*cptr) { - if (quote && *cptr == quote) { - char *tmp; - tmp = cptr+1; - if (*tmp && (!isspace(*tmp) || *wskip(tmp))) { - warning(cptr, "unexpected quote character, ignoreing"); - *tptr++ = *cptr++; - } else { - *cptr = '\0'; - } - } else if (*cptr == '\\') { - ++cptr; - switch (*cptr) { - case '\0': - cptr = getline(fd); - if (!cptr) error(NULL, "premature end of file"); - msglen += strlen(cptr); - i = tptr - msg; - msg = (char *) realloc(msg, msglen); - tptr = msg + i; - break; - case 'n': - *tptr++ = '\n'; - ++cptr; - break; - case 't': - *tptr++ = '\t'; - ++cptr; - break; - case 'v': - *tptr++ = '\v'; - ++cptr; - break; - case 'b': - *tptr++ = '\b'; - ++cptr; - break; - case 'r': - *tptr++ = '\r'; - ++cptr; - break; - case 'f': - *tptr++ = '\f'; - ++cptr; - break; - case '\\': - *tptr++ = '\\'; - ++cptr; - break; - default: - if (isdigit(*cptr)) { - *tptr = 0; - for (i = 0; i < 3; ++i) { - if (!isdigit(*cptr)) break; - if (*cptr > '7') warning(cptr, "octal number greater than 7?!"); - *tptr *= 8; - *tptr += (*cptr - '0'); - ++cptr; - } - } else { - warning(cptr, "unrecognized escape sequence"); - } - } - } else { - *tptr++ = *cptr++; - } - } - *tptr = '\0'; - return(msg); -} - - - -static char *dupstr(ostr) -char *ostr; -{ - char *nstr; - - nstr = (char *) malloc(strlen(ostr) + 1); - if (!nstr) error(NULL, "unable to allocate storage"); - strcpy(nstr, ostr); - return(nstr); -} - - -/* - * The Global Stuff - */ - - -typedef struct _msgT { - long msgId; - char *str; - char *hconst; - long offset; - struct _msgT *prev, *next; -} msgT; -typedef struct _setT { - long setId; - char *hconst; - msgT *first, *last; - struct _setT *prev, *next; -} setT; -typedef struct { - setT *first, *last; -} catT; - -static setT *curSet; -static catT *cat; - -/* - * Find the current byte order. There are of course some others, but this will do - * for now. Note that all we care about is "long". - */ -long MCGetByteOrder() { - long l = 0x00010203; - char *cptr = (char *) &l; - - if (cptr[0] == 0 && cptr[1] == 1 && cptr[2] == 2 && cptr[3] == 3) - return MC68KByteOrder; - else return MCn86ByteOrder; -} - - -void MCParse( -#if PROTO - int fd) -#else - fd) -int fd; -#endif -{ - char *cptr, *str; - int setid, msgid = 0; - char hconst[MAXTOKEN+1]; - char quote = 0; - int i; - - if (!cat) { - cat = (catT *) malloc(sizeof(catT)); - if (!cat) nomem(); - bzero(cat, sizeof(catT)); - } - - hconst[0] = '\0'; - - while (cptr = getline(fd)) { - if (*cptr == '$') { - ++cptr; - if (strncmp(cptr, "set", 3) == 0) { - cptr += 3; - cptr = wskip(cptr); - setid = atoi(cptr); - cptr = cskip(cptr); - if (*cptr) cptr = wskip(cptr); - if (*cptr == '#') { - ++cptr; - MCAddSet(setid, token(cptr)); - } else MCAddSet(setid, NULL); - msgid = 0; - } else if (strncmp(cptr, "delset", 6) == 0) { - cptr += 6; - cptr = wskip(cptr); - setid = atoi(cptr); - MCDelSet(setid); - } else if (strncmp(cptr, "quote", 5) == 0) { - cptr += 5; - if (!*cptr) quote = 0; - else { - cptr = wskip(cptr); - if (!*cptr) quote = 0; - else quote = *cptr; - } - } else if (isspace(*cptr)) { - cptr = wskip(cptr); - if (*cptr == '#') { - ++cptr; - strcpy(hconst, token(cptr)); - } - } else { - if (*cptr) { - cptr = wskip(cptr); - if (*cptr) warning(cptr, "unrecognized line"); - } - } - } else { - if (isdigit(*cptr) || *cptr == '#') { - if (*cptr == '#') { - ++msgid; - ++cptr; - if (!*cptr) { - MCAddMsg(msgid, "", hconst); - hconst[0] = '\0'; - continue; - } - if (!isspace(*cptr)) warning(cptr, "expected a space"); - ++cptr; - if (!*cptr) { - MCAddMsg(msgid, "", hconst); - hconst[0] = '\0'; - continue; - } - } else { - msgid = atoi(cptr); - cptr = cskip(cptr); - cptr = wskip(cptr); - /* if (*cptr) ++cptr; */ - } - if (!*cptr) MCDelMsg(msgid); - else { - str = getmsg(fd, cptr, quote); - MCAddMsg(msgid, str, hconst); - hconst[0] = '\0'; - } - } - } - } -} - -void MCReadCat( -#if PROTO - int fd) -#else - fd) -int fd; -#endif -{ - MCHeaderT mcHead; - MCMsgT mcMsg; - MCSetT mcSet; - msgT *msg; - setT *set; - int i; - char *data; - - cat = (catT *) malloc(sizeof(catT)); - if (!cat) nomem(); - bzero(cat, sizeof(catT)); - - if (read(fd, &mcHead, sizeof(mcHead)) != sizeof(mcHead)) corrupt(); - if (strncmp(mcHead.magic, MCMagic, MCMagicLen) != 0) corrupt(); - if (mcHead.majorVer != MCMajorVer) error(NULL, "unrecognized catalog version"); - if ((mcHead.flags & MCGetByteOrder()) == 0) error(NULL, "wrong byte order"); - - if (lseek(fd, mcHead.firstSet, L_SET) == -1) corrupt(); - - while (True) { - if (read(fd, &mcSet, sizeof(mcSet)) != sizeof(mcSet)) corrupt(); - if (mcSet.invalid) continue; - - set = (setT *) malloc(sizeof(setT)); - if (!set) nomem(); - bzero(set, sizeof(*set)); - if (cat->first) { - cat->last->next = set; - set->prev = cat->last; - cat->last = set; - } else cat->first = cat->last = set; - - set->setId = mcSet.setId; - - /* Get the data */ - if (mcSet.dataLen) { - data = (char *) malloc(mcSet.dataLen); - if (!data) nomem(); - if (lseek(fd, mcSet.data.off, L_SET) == -1) corrupt(); - if (read(fd, data, mcSet.dataLen) != mcSet.dataLen) corrupt(); - if (lseek(fd, mcSet.u.firstMsg, L_SET) == -1) corrupt(); - - for (i = 0; i < mcSet.numMsgs; ++i) { - if (read(fd, &mcMsg, sizeof(mcMsg)) != sizeof(mcMsg)) corrupt(); - if (mcMsg.invalid) { - --i; - continue; - } - - msg = (msgT *) malloc(sizeof(msgT)); - if (!msg) nomem(); - bzero(msg, sizeof(*msg)); - if (set->first) { - set->last->next = msg; - msg->prev = set->last; - set->last = msg; - } else set->first = set->last = msg; - - msg->msgId = mcMsg.msgId; - msg->str = dupstr((char *) (data + mcMsg.msg.off)); - } - free(data); - } - if (!mcSet.nextSet) break; - if (lseek(fd, mcSet.nextSet, L_SET) == -1) corrupt(); - } -} - - -static void printS(fd, str) -int fd; -char *str; -{ - write(fd, str, strlen(str)); -} -static void printL(fd, l) -int fd; -long l; -{ - char buf[32]; - sprintf(buf, "%ld", l); - write(fd, buf, strlen(buf)); -} -static void printLX(fd, l) -int fd; -long l; -{ - char buf[32]; - sprintf(buf, "%lx", l); - write(fd, buf, strlen(buf)); -} - -static void genconst(fd, type, setConst, msgConst, val) -int fd; -int type; -char *setConst; -char *msgConst; -long val; -{ - switch (type) { - case MCLangC: - if (!msgConst) { - printS(fd, "\n#define "); - printS(fd, setConst); - printS(fd, "Set"); - } else { - printS(fd, "#define "); - printS(fd, setConst); - printS(fd, msgConst); - } - printS(fd, "\t0x"); - printLX(fd, val); - printS(fd, "\n"); - break; - case MCLangCPlusPlus: - case MCLangANSIC: - if (!msgConst) { - printS(fd, "\nconst long "); - printS(fd, setConst); - printS(fd, "Set"); - } else { - printS(fd, "const long "); - printS(fd, setConst); - printS(fd, msgConst); - } - printS(fd, "\t= "); - printL(fd, val); - printS(fd, ";\n"); - break; - default: - error(NULL, "not a recognized (programming) language type"); - } -} - -void MCWriteConst( -#if PROTO - int fd, int type, int orConsts) -#else - fd, type, orConsts) -int fd; -int type; -int orConsts; -#endif -{ - msgT *msg; - setT *set; - long id; - - if (orConsts && (type == MCLangC || type == MCLangCPlusPlus || type == MCLangANSIC)) { - printS(fd, "/* Use these Macros to compose and decompose setId's and msgId's */\n"); - printS(fd, "#ifndef MCMakeId\n"); - printS(fd, "# define MCMakeId(s,m)\t(unsigned long)(((unsigned short)s<<(sizeof(short)*8))\\\n"); - printS(fd, "\t\t\t\t\t|(unsigned short)m)\n"); - printS(fd, "# define MCSetId(id)\t(unsigned int) (id >> (sizeof(short) * 8))\n"); - printS(fd, "# define MCMsgId(id)\t(unsigned int) ((id << (sizeof(short) * 8))\\\n"); - printS(fd, "\t\t\t\t\t>> (sizeof(short) * 8))\n"); - printS(fd, "#endif\n"); - } - - for (set = cat->first; set; set = set->next) { - if (set->hconst) genconst(fd, type, set->hconst, NULL, set->setId); - - for (msg = set->first; msg; msg = msg->next) { - if (msg->hconst) { - if (orConsts) id = MCMakeId(set->setId, msg->msgId); - else id = msg->msgId; - genconst(fd, type, set->hconst, msg->hconst, id); - free(msg->hconst); - msg->hconst = NULL; - } - } - if (set->hconst) { - free(set->hconst); - set->hconst = NULL; - } - } -} - -void MCWriteCat( -#if PROTO - int fd) -#else - fd) -int fd; -#endif -{ - MCHeaderT mcHead; - int cnt; - setT *set; - msgT *msg; - MCSetT mcSet; - MCMsgT mcMsg; - off_t pos; - - bcopy(MCMagic, mcHead.magic, MCMagicLen); - mcHead.majorVer = MCMajorVer; - mcHead.minorVer = MCMinorVer; - mcHead.flags = MCGetByteOrder(); - mcHead.firstSet = 0; /* We'll be back to set this in a minute */ - - for (cnt = 0, set = cat->first; set; set = set->next) ++cnt; - mcHead.numSets = cnt; - - lseek(fd, 0L, L_SET); - write(fd, &mcHead, sizeof(mcHead)); - mcHead.firstSet = lseek(fd, 0, L_INCR); - lseek(fd, 0L, L_SET); - write(fd, &mcHead, sizeof(mcHead)); - - for (set = cat->first; set; set = set->next) { - bzero(&mcSet, sizeof(mcSet)); - - mcSet.setId = set->setId; - mcSet.invalid = False; - - /* The rest we'll have to come back and change in a moment */ - pos = lseek(fd, 0, L_INCR); - write(fd, &mcSet, sizeof(mcSet)); - - /* Now write all the string data */ - mcSet.data.off = lseek(fd, 0, L_INCR); - cnt = 0; - for (msg = set->first; msg; msg = msg->next) { - msg->offset = lseek(fd, 0, L_INCR) - mcSet.data.off; - mcSet.dataLen += write(fd, msg->str, strlen(msg->str) + 1); - ++cnt; - } - mcSet.u.firstMsg = lseek(fd, 0, L_INCR); - mcSet.numMsgs = cnt; - - /* Now write the message headers */ - for (msg = set->first; msg; msg = msg->next) { - mcMsg.msgId = msg->msgId; - mcMsg.msg.off = msg->offset; - mcMsg.invalid = False; - write(fd, &mcMsg, sizeof(mcMsg)); - } - - /* Go back and fix things up */ - - if (set == cat->last) { - mcSet.nextSet = 0; - lseek(fd, pos, L_SET); - write(fd, &mcSet, sizeof(mcSet)); - } else { - mcSet.nextSet = lseek(fd, 0, L_INCR); - lseek(fd, pos, L_SET); - write(fd, &mcSet, sizeof(mcSet)); - lseek(fd, mcSet.nextSet, L_SET); - } - } -} - - -void MCAddSet( -#if PROTO - int setId, char *hconst) -#else - setId, hconst) -int setId; -char *hconst; -#endif -{ - setT *set; - - if (setId <= 0) { - error(NULL, "setId's must be greater than zero"); - return; - } - - if (hconst && !*hconst) hconst = NULL; - for (set = cat->first; set; set = set->next) { - if (set->setId == setId) { - if (set->hconst && hconst) free(set->hconst); - set->hconst = NULL; - break; - } else if (set->setId > setId) { - setT *newSet; - - newSet = (setT *) malloc(sizeof(setT)); - if (!newSet) nomem(); - bzero(newSet, sizeof(setT)); - newSet->prev = set->prev; - newSet->next = set; - if (set->prev) set->prev->next = newSet; - else cat->first = newSet; - set->prev = newSet; - set = newSet; - break; - } - } - if (!set) { - set = (setT *) malloc(sizeof(setT)); - if (!set) nomem(); - bzero(set, sizeof(setT)); - - if (cat->first) { - set->prev = cat->last; - set->next = NULL; - cat->last->next = set; - cat->last = set; - } else { - set->prev = set->next = NULL; - cat->first = cat->last = set; - } - } - set->setId = setId; - if (hconst) set->hconst = dupstr(hconst); - curSet = set; -} - -void MCAddMsg( -#if PROTO - int msgId, char *str, char *hconst) -#else - msgId, str, hconst) -int msgId; -char *str; -char *hconst; -#endif -{ - msgT *msg; - - if (!curSet) error(NULL, "can't specify a message when no set exists"); - - if (msgId <= 0) { - error(NULL, "msgId's must be greater than zero"); - return; - } - - if (hconst && !*hconst) hconst = NULL; - for (msg = curSet->first; msg; msg = msg->next) { - if (msg->msgId == msgId) { - if (msg->hconst && hconst) free(msg->hconst); - if (msg->str) free(msg->str); - msg->hconst = msg->str = NULL; - break; - } else if (msg->msgId > msgId) { - msgT *newMsg; - - newMsg = (msgT *) malloc(sizeof(msgT)); - if (!newMsg) nomem(); - bzero(newMsg, sizeof(msgT)); - newMsg->prev = msg->prev; - newMsg->next = msg; - if (msg->prev) msg->prev->next = newMsg; - else curSet->first = newMsg; - msg->prev = newMsg; - msg = newMsg; - break; - } - } - if (!msg) { - msg = (msgT *) malloc(sizeof(msgT)); - if (!msg) nomem(); - bzero(msg, sizeof(msgT)); - - if (curSet->first) { - msg->prev = curSet->last; - msg->next = NULL; - curSet->last->next = msg; - curSet->last = msg; - } else { - msg->prev = msg->next = NULL; - curSet->first = curSet->last = msg; - } - } - msg->msgId = msgId; - if (hconst) msg->hconst = dupstr(hconst); - msg->str = dupstr(str); -} - -void MCDelSet( -#if PROTO - int setId) -#else - setId) -int setId; -#endif -{ - setT *set; - msgT *msg; - - for (set = cat->first; set; set = set->next) { - if (set->setId == setId) { - for (msg = set->first; msg; msg = msg->next) { - if (msg->hconst) free(msg->hconst); - if (msg->str) free(msg->str); - free(msg); - } - if (set->hconst) free(set->hconst); - - if (set->prev) set->prev->next = set->next; - else cat->first = set->next; - - if (set->next) set->next->prev = set->prev; - else cat->last = set->prev; - - free(set); - return; - } else if (set->setId > setId) break; - } - warning(NULL, "specified set doesn't exist"); -} - -void MCDelMsg( -#if PROTO - int msgId) -#else - msgId) -int msgId; -#endif -{ - msgT *msg; - - if (!curSet) error(NULL, "you can't delete a message before defining the set"); - - for (msg = curSet->first; msg; msg = msg->next) { - if (msg->msgId == msgId) { - if (msg->hconst) free(msg->hconst); - if (msg->str) free(msg->str); - - if (msg->prev) msg->prev->next = msg->next; - else curSet->first = msg->next; - - if (msg->next) msg->next->prev = msg->prev; - else curSet->last = msg->prev; - - free(msg); - return; - } else if (msg->msgId > msgId) break; - } - warning(NULL, "specified msg doesn't exist"); -} - -void MCDumpcat(fp) -FILE *fp; -{ - msgT *msg; - setT *set; - - if (!cat) { - fprintf(stderr, "No catalog open\n"); - exit (1); - } - - for (set = cat->first; set; set = set->next) { - fprintf(fp, "$set %d", set->setId); - if (set->hconst) - fprintf(fp, " # %s", set->hconst); - fprintf(fp, "\n\n"); - - for (msg = set->first; msg; msg = msg->next) { - if (msg->hconst) - fprintf(fp, "# %s\n", msg->hconst); - fprintf(fp, "%d\t%s\n", msg->msgId, msg->str); - } - fprintf(fp, "\n"); - } - -} |