From jfh@rpp386.cactus.org Sat Feb 26 14:35:22 EST 1994 Article: 6007 of comp.os.linux.development Newsgroups: comp.os.linux.development Path: bigblue.oit.unc.edu!concert!news-feed-1.peachnet.edu!gatech!swrinde!cs.utexas.edu!chinacat!rpp386!jfh From: jfh@rpp386.cactus.org (John F. Haugh II) Subject: Alpha release of message catalog commands and functions Message-ID: <1994Feb26.052716.15677@rpp386> Sender: jfh@rpp386 (John F. Haugh II) Organization: River Parishes Programming, Austin TX Date: Sat, 26 Feb 1994 05:27:16 GMT Lines: 1257 I've been wanting to add National Language Support to Shadow for some time now but there is no freely redistributable NLS package that I am aware of. I found some stuff in an old hacked up ELM directory, but it didn't look to be complete. This isn't what I'd call "complete", but it's better than anything I've found. And it includes a sample message catalog for the three commands that are included. -- #!/bin/sh # shar: Shell Archiver (v1.29) # # Run the following text with /bin/sh to create: # LICENSE # Makefile # patchlevel.h # gencat.c # gencat.msg.En_US # catgets.c # l_catclose.c # l_catgets.c # l_catopen.c # nl_types.h # sed 's/^X//' << 'SHAR_EOF' > LICENSE && X(* XThis document is freely plagiarised from the 'Artistic Licence', Xdistributed as part of the Perl v4.0 kit by Larry Wall, which is Xavailable from most major archive sites. I stole it from CrackLib. X X @(#)LICENSE 3.1 20:07:28 02 Feb 1994 X*) X XThis documents purpose is to state the conditions under which this XPackage (See definition below) viz: "NLS-LIB", the National Language XLibrary which is held in John Frederick Haugh, II, may be copied, such Xthat the copyright holder maintains some semblance of artistic control Xover the development of the package, while giving the users of the Xpackage the right to use and distribute the Package in a more-or-less Xcustomary fashion, plus the right to make reasonable modifications. X XSo there. X X*************************************************************************** X XDefinitions: X X XA "Package" refers to the collection of files distributed by the XCopyright Holder, and derivatives of that collection of files created Xthrough textual modification, or segments thereof. X X"Standard Version" refers to such a Package if it has not been modified, Xor has been modified in accordance with the wishes of the Copyright XHolder. X X"Copyright Holder" is whoever is named in the copyright or copyrights Xfor the package. X X"You" is you, if you're thinking about copying or distributing this XPackage. X X"Reasonable copying fee" is whatever you can justify on the basis of Xmedia cost, duplication charges, time of people involved, and so on. X(You will not be required to justify it to the Copyright Holder, but Xonly to the computing community at large as a market that must bear the Xfee.) X X"Freely Available" means that no fee is charged for the item itself, Xthough there may be fees involved in handling the item. It also means Xthat recipients of the item may redistribute it under the same Xconditions they received it. X X X1. You may make and give away verbatim copies of the source form of the XStandard Version of this Package without restriction, provided that you Xduplicate all of the original copyright notices and associated Xdisclaimers. X X2. You may apply bug fixes, portability fixes and other modifications Xderived from the Public Domain or from the Copyright Holder. A Package Xmodified in such a way shall still be considered the Standard Version. X X3. You may otherwise modify your copy of this Package in any way, Xprovided that you insert a prominent notice in each changed file stating Xhow and when AND WHY you changed that file, and provided that you do at Xleast ONE of the following: X Xa) place your modifications in the Public Domain or otherwise make them XFreely Available, such as by posting said modifications to Usenet or an Xequivalent medium, or placing the modifications on a major archive site Xsuch as uunet.uu.net, or by allowing the Copyright Holder to include Xyour modifications in the Standard Version of the Package. X Xb) use the modified Package only within your corporation or organization. X Xc) rename any non-standard executables so the names do not conflict with Xstandard executables, which must also be provided, and provide separate Xdocumentation for each non-standard executable that clearly documents Xhow it differs from the Standard Version. X Xd) make other distribution arrangements with the Copyright Holder. X X4. You may distribute the programs of this Package in object code or Xexecutable form, provided that you do at least ONE of the following: X Xa) distribute a Standard Version of the executables and library files, Xtogether with instructions (in the manual page or equivalent) on where Xto get the Standard Version. X Xb) accompany the distribution with the machine-readable source of the XPackage with your modifications. X Xc) accompany any non-standard executables with their corresponding XStandard Version executables, giving the non-standard executables Xnon-standard names, and clearly documenting the differences in manual Xpages (or equivalent), together with instructions on where to get the XStandard Version. X Xd) make other distribution arrangements with the Copyright Holder. X X5. You may charge a reasonable copying fee for any distribution of this XPackage. You may charge any fee you choose for support of this Package. XYOU MAY NOT CHARGE A FEE FOR THIS PACKAGE ITSELF. However, you may Xdistribute this Package in aggregate with other (possibly commercial) Xprograms as part of a larger (possibly commercial) software distribution Xprovided that YOU DO NOT ADVERTISE this package as a product of your Xown. X X6. The name of the Copyright Holder may not be used to endorse or Xpromote products derived from this software without specific prior Xwritten permission. X X7. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED XWARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF XMERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. X X The End SHAR_EOF chmod 0644 LICENSE || echo "restore of LICENSE fails" sed 's/^X//' << 'SHAR_EOF' > Makefile && X# X# Copyright 1994, John F. Haugh II X# An unpublished work. X# All rights reserved. X# X# Permission is granted to copy and create derivative works for any X# non-commercial purpose, provided this copyright notice is preserved X# in all copies of source code, or included in human readable form X# and conspicuously displayed on all copies of object code or X# distribution media. X# X# This software is provided on an AS-IS basis and the author makes X# no warrantee of any kind. The "Artistic License" located in the X# file LICENSE contains complete licensing information. X# X# %W% %U% %G% X XDEBUG = -g XOPTIM = -O XCFLAGS = $(DEBUG) $(OPTIM) XRANLIB = echo X XLANG = En_US X XFILES = LICENSE Makefile patchlevel.h \ X gencat.c gencat.msg.En_US catgets.c \ X l_catclose.c l_catgets.c l_catopen.c nl_types.h X Xall: gencat catgets dspcat libnls.a gencat.cat X Xgencat: gencat.o libnls.a X cc $(DEBUG) -o gencat gencat.o libnls.a X Xcatgets: catgets.o libnls.a X cc $(DEBUG) -o catgets catgets.o libnls.a X Xdspcat: dspcat.o libnls.a X cc $(DEBUG) -o dspcat dspcat.o libnls.a X Xgencat.cat: gencat.msg.$(LANG) X ./gencat gencat.cat gencat.msg.$(LANG) X Xlibnls.a(l_catclose.o): l_catclose.c nl_types.h Xlibnls.a(l_catopen.o): l_catopen.c nl_types.h Xlibnls.a(l_catgets.o): l_catgets.c nl_types.h X Xlibnls.a: \ X libnls.a(l_catclose.o) \ X libnls.a(l_catgets.o) \ X libnls.a(l_catopen.o) X $(RANLIB) libnls.a X Xclean: X rm -f *.o a.out core X Xclobber: clean X rm -f catgets gencat libnls.a gencat.cat X Xshar: libnls.shar X Xlibnls.shar: $(FILES) X shar $(SHARFLAGS) $(FILES) > libnls.shar SHAR_EOF chmod 0644 Makefile || echo "restore of Makefile fails" sed 's/^X//' << 'SHAR_EOF' > patchlevel.h && X/* X * Copyright 1994, John F. Haugh II X * An unpublished work. X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X * X * This software is provided on an AS-IS basis and the author makes X * no warrantee of any kind. The "Artistic License" located in the X * file LICENSE contains complete licensing information. X * X * %W% %U% %G% X */ X X#define RELEASE 1 X#define PATCHLEVEL 0 X#define VERSION "1.0.0" SHAR_EOF chmod 0644 patchlevel.h || echo "restore of patchlevel.h fails" sed 's/^X//' << 'SHAR_EOF' > gencat.c && X/* X * Copyright 1994, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X * X * This software is provided on an AS-IS basis and the author makes X * no warrantee of any kind. The "Artistic License" located in the X * file LICENSE contains complete licensing information. X */ X X#ifndef lint Xstatic char sccsid[] = "%W% %U% %G%"; X#endif X X#include X#include X#include X#include X#include X#include X X#include "nl_types.h" X Xnl_catd catd; X#define M(msg,def) catgets (catd, 1, msg, def) X Xint lineno; Xint quotec; X Xchar **messages[NL_SETMAX]; X Xvoid Xinvalid (FILE * fp) X{ X int c; X X fprintf (stderr, M(3, "invalid input line %d\n"), lineno); X X while ((c = getc (fp)) != '\n' && c != EOF) X ; X} X Xint Xoctal (FILE * fp) X{ X int c; X int c1, c2, c3; X X c1 = getc (fp); X c2 = getc (fp); X c3 = getc (fp); X X if (! (c1 >= '0' && c1 <= '7' && X c2 >= '0' && c2 <= '7' && X c3 >= '0' && c3 <= '7')) X return EOF; X X c = ((c1 - '0') << 6) | ((c2 - '0') << 3) | (c3 - '0'); X return c; X} X Xvoid Xcomment (FILE * fp) X{ X int c; X X while ((c = getc (fp)) != EOF && c != '\n') X ; X} X Xmessage (nl_catd catd, FILE * fp, int set) X{ X int c; X int i; X enum { line_begin, X number, X text_begin, text_mid, text_end, X done X } state = line_begin; X int quoted; X char msg_num[16]; X int cur_msg; X char line[NL_TEXTMAX+2]; X X while (state != done) { X if ((c = getc (fp)) == EOF) { X if (state == text_mid) { X state = done; X continue; X } X invalid (fp); X return; X } X if (state == line_begin) { X if (c == EOF || ! isdigit (c)) { X invalid (fp); X return; X } X state = number; X i = 1; X msg_num[0] = c; X continue; X } X if (state == number) { X if (isdigit (c)) { X if (i >= sizeof msg_num - 1) { X invalid (fp); X return; X } X msg_num[i++] = c; X continue; X } X if (isspace (c)) { X msg_num[i] = '\0'; X cur_msg = atoi (msg_num); X if (cur_msg < 1 || cur_msg > NL_MSGMAX) { X invalid (fp); X return; X } X if (catd->nl_sets < set) X catd->nl_sets = set; X X if (catd->nl_msgs[set-1] == 0) { X catd->nl_msgs[set-1] = (off_t *) X calloc (NL_MSGMAX, X sizeof (off_t)); X } X if (catd->nl_nmsgs[set-1] < cur_msg) X catd->nl_nmsgs[set-1] = cur_msg; X X /* X * Just a number? Delete the message from X * the catalog. X */ X X if (c == '\n') { X if (messages[set-1][cur_msg-1]) { X free (messages[set-1][cur_msg-1]); X messages[set-1][cur_msg-1] = 0; X } X return; X } X X /* X * Message ID followed by whitespace starts X * a valid message. Reset the buffer pointer X * to start collecting characters. X */ X X state = text_begin; X i = 0; X continue; X } X X /* X * There must be whitespace after the number. X */ X X invalid (fp); X return; X } X X /* X * At the beginning of a message a single "quote" character X * is allowed. If `c' is that character, discard it and X * change state. Otherwise, push the charcter back because X * it is part of the actual message text. X */ X X if (state == text_begin) { X X /* X * No characters at all? This is an empty message. X */ X X if (c == '\n') { X ungetc (c, fp); X state = text_end; X continue; X } X if (c != quotec) X ungetc (c, fp); X else X quoted = 1; X X state = text_mid; X continue; X } X X if (state == text_mid) { X if (quoted && c == quotec) { X if ((c = getc (fp)) == EOF || c == '\n') { X ungetc (c, fp); X state = text_end; X continue; X } else { X ungetc (c, fp); X c = quotec; X } X } X if (c == '\n') { X ungetc (c, fp); X state = text_end; X continue; X } X if (c == '\\') { X c = getc (fp); X if (c == EOF) { X invalid (fp); X return; X } X if (c == '\n') X continue; X X switch (c) { X case 'n': c = '\n'; break; X case 't': c = '\t'; break; X case 'v': c = '\v'; break; X case 'b': c = '\b'; break; X case 'r': c = '\r'; break; X case 'f': c = '\f'; break; X case '\\': c = '\\'; break; X default: X if (isdigit (c)) { X ungetc (c, fp); X c = octal (fp); X } X if (c == EOF) { X invalid (fp); X return; X } X } X } X if (i < NL_TEXTMAX) X line[i++] = c; X X continue; X } X X if (state == text_end) { X if (i < NL_TEXTMAX) X line[i] = '\0'; X X state = done; X continue; X } X } X if (i >= NL_TEXTMAX) { X invalid (fp); X return; X } X line[i] = '\0'; X X if (messages[set-1] == (char **) 0) { X messages[set-1] = X (char **) malloc (sizeof (char *) * NL_MSGMAX); X memset (messages[set-1], 0, sizeof (char *) * NL_MSGMAX); X } X if (messages[set-1][cur_msg-1]) X free (messages[set - 1][cur_msg - 1]); X X messages[set - 1][cur_msg - 1] = strdup (line); X} X Xint Xload_catalog (nl_catd new_catd) X{ X int i, j, k; X int c; X nl_cat_header header; X char buf[NL_TEXTMAX+1]; X X if (fread (&header, sizeof header, 1, new_catd->nl_cat_fp) != 1) X return -1; X X if (header.nl_sets < 1 || header.nl_sets > NL_SETMAX) X return -1; X X new_catd->nl_sets = header.nl_sets; X memcpy (new_catd->nl_nmsgs, header.nl_nmsgs, sizeof header.nl_nmsgs); X X for (i = 0;i < NL_SETMAX;i++) { X if (! (new_catd->nl_msgs[i] = (off_t *) calloc X (NL_MSGMAX, sizeof (off_t)))) { X fprintf (stderr, M(11, "no memory")); X exit (1); X } X if (! (messages[i] = (char **) calloc X (NL_MSGMAX, sizeof (char *)))) { X fprintf (stderr, M(11, "no memory")); X exit (1); X } X if (new_catd->nl_nmsgs[i] == 0) X continue; X X if (fread (new_catd->nl_msgs[i], sizeof (off_t), X new_catd->nl_nmsgs[i], new_catd->nl_cat_fp) != X new_catd->nl_nmsgs[i]) X return -1; X } X for (i = 0;i < new_catd->nl_sets;i++) { X for (j = 0;j < new_catd->nl_nmsgs[i];j++) { X for (k = 0;(c = getc (new_catd->nl_cat_fp)) && X c != EOF && k < NL_TEXTMAX;) X buf[k++] = c; X X if (k >= NL_TEXTMAX) X return -1; X X buf[k] = '\0'; X if (! (messages[i][j] = strdup (buf))) { X fprintf (stderr, M(11, "no memory")); X exit (1); X } X } X } X return 0; X} X Xmain (int argc, char ** argv) X{ X int i, j; X int c; X int created = 0; X nl_catd new_catd; X nl_cat_header header; X char error[BUFSIZ]; X int nerrors = 0; X int cur_set = NL_SETD; X FILE *input = 0; X off_t base; X X catd = catopen ("gencat", 0); X X if (argc < 3) { X fprintf (stderr, M(1, "usage: gencat catfile msgfile ...\n")); X exit (1); X } X if (! (new_catd = (nl_catd) malloc (sizeof *new_catd))) { X perror (M(4, "gencat: can't create new catalog descriptor")); X exit (1); X } X memset (new_catd, 0, sizeof *new_catd); X memset (&header, 0, sizeof header); X X /* X * See if the file already exists. If it doesn't we will be X * creating it from scratch. X */ X X if (access (argv[1], 0) == -1) X created = 1; X X /* X * Try to open the message catalog. If it exists, it will be X * opened for read/update, if it doesn't we create a brand new X * empty file. X */ X X if (! (new_catd->nl_cat_fp = fopen (argv[1], created ? "w":"r+"))) { X if (created) X sprintf (error, M(6, "gencat: can't create catalog %s"), X argv[1]); X else X sprintf (error, M(9, "gencat: can't open catalog %s"), X argv[1]); X X perror (error); X exit (1); X } X X /* X * Initialize the catalog descriptor to completely empty. If X * there was an existing catalog file, we're going to go load X * it up in a second. X */ X X new_catd->nl_sets = 0; X for (i = 0;i < NL_SETMAX;i++) { X new_catd->nl_nmsgs[i] = 0; X new_catd->nl_msgs[i] = (off_t *) 0; X } X if (! created) { X if (load_catalog (new_catd)) { X fprintf (stderr, M(10, "invalid catalog file %s\n"), X argv[1]); X exit (1); X } X } X X for (i = 2;i < argc;i++) { X if (input && input != stdin) { X fclose (input); X input = 0; X } X if (strcmp (argv[i], "-") == 0) { X input = stdin; X } else if (! (input = fopen (argv[i], "r"))) { X sprintf (error, M(7, "gencat: can't open %s"), argv[i]); X perror (error); X nerrors++; X continue; X } X lineno = 0; X if (argc > 3) X printf ("%s:\n", argv[i]); X X while ((c = getc (input)) != EOF) { X lineno++; X if (c != '$') { X ungetc (c, input); X message (new_catd, input, cur_set); X continue; X } X if ((c = getc (input)) == EOF) X break; X X if (c == ' ' || c == '\t' || c == '\n') { X if (c != '\n') X comment (input); X X continue; X } X if (c == 's') { X int new_set; X X ungetc (c, input); X if (fscanf (input, "set%*[ ]%d%*[^\n]", X &new_set) != 1) { X invalid (input); X nerrors++; X continue; X } X if (new_set < 1 || new_set > NL_SETMAX) { X invalid (input); X nerrors++; X continue; X } X getc (input); X cur_set = new_set; X continue; X } X if (c == 'd') { X char old_set; X X ungetc (c, input); X if (fscanf (input, "delset%*[ ]%d%*[^\n]", X &old_set) != 1) { X invalid (input); X nerrors++; X continue; X } X if (old_set < 1 || old_set >= NL_SETMAX) { X invalid (input); X nerrors++; X continue; X } X memset (new_catd->nl_msgs[old_set - 1], 0, X NL_MSGMAX * sizeof (off_t)); X new_catd->nl_nmsgs[old_set - 1] = 0; X for (i = 0;i < NL_MSGMAX;i++) { X if (messages[old_set-1][i]) X free (messages[old_set-1][i]); X X messages[old_set-1][i] = 0; X } X getc (input); X continue; X } X if (c == 'q') { X char new_quotec; X X ungetc (c, input); X if (fscanf (input, "quote%*[ ]%c%*[^\n]\n", X &new_quotec) != 1) { X invalid (input); X nerrors++; X continue; X } X getc (input); X quotec = new_quotec; X continue; X } X } X } X X /* X * There were some errors and they were already reported. If we X * created the message catalog go ahead and delete the file. X */ X X if (nerrors) { X if (created) X (void) unlink (argv[1]); X X exit (2); X } X X /* X * Scan the in-core message catalog information to determine X * how many sets were defined and how many messages are in each X * set. The information in the catalog descriptor right now X * may be wrong as sets and messages may have been deleted. X */ X X for (i = 0;i < NL_SETMAX;i++) { X X /* X * If there are no messages at all in the set, or there X * never were, just say so and skip. X */ X X if (new_catd->nl_msgs[i] == (off_t *) 0 || X new_catd->nl_nmsgs[i] == 0) { X new_catd->nl_nmsgs[i] = 0; X continue; X } X X /* X * There must have been a message sometime in the past, X * so set the count to zero and see what the highest X * numbered one is now. X */ X X new_catd->nl_nmsgs[i] = 0; X for (j = 0;j < NL_MSGMAX;j++) { X if (messages[i][j]) X new_catd->nl_nmsgs[i] = j + 1; X } X X /* X * There weren't any? The last one must have been X * deleted, so we completely delete the set now by saying X * it has no messages. X */ X X if (new_catd->nl_nmsgs[i] == 0) X continue; X X /* X * This set has at least one message, make it the highest X * numbered set. X */ X X new_catd->nl_sets = i + 1; X } X header.nl_sets = new_catd->nl_sets; X memcpy (header.nl_nmsgs, new_catd->nl_nmsgs, X new_catd->nl_sets * sizeof (off_t)); X X base = sizeof header; X for (i = 0;i < new_catd->nl_sets;i++) X base += new_catd->nl_nmsgs[i] * sizeof (off_t); X X for (i = 0;i < new_catd->nl_sets;i++) { X for (j = 0;j < new_catd->nl_nmsgs[i];j++) { X if (messages[i][j] == (char *) 0) { X new_catd->nl_msgs[i][j] = 0; X continue; X } X new_catd->nl_msgs[i][j] = base; X base += strlen (messages[i][j]) + 1; X } X } X if (! created) { X if (! (new_catd->nl_cat_fp = fopen (argv[1], "w"))) { X sprintf (error, M(6, "gencat: can't create catalog %s"), X argv[1]); X perror (error); X exit (1); X } X } X if (fwrite (&header, sizeof header, 1, new_catd->nl_cat_fp) != 1) { X sprintf (error, M(8, "gencat: can't write to %s"), argv[1]); X perror (error); X exit (1); X } X for (i = 0;i < new_catd->nl_sets;i++) { X if (new_catd->nl_nmsgs[i] == 0) X continue; X X if (fwrite (new_catd->nl_msgs[i], sizeof (off_t), X new_catd->nl_nmsgs[i], new_catd->nl_cat_fp) != X new_catd->nl_nmsgs[i]) { X sprintf (error, X M(8, "gencat: can't write to %s"), argv[1]); X perror (error); X exit (1); X } X } X for (i = 0;i < new_catd->nl_sets;i++) { X if (new_catd->nl_msgs[i] == (off_t *) 0) X continue; X X for (j = 0;j < new_catd->nl_nmsgs[i];j++) { X if (messages[i][j] == (char *) 0) X continue; X X if (fwrite (messages[i][j], X strlen (messages[i][j]) + 1, 1, X new_catd->nl_cat_fp) != 1) { X sprintf (error, X M(8, "gencat: can't write to %s"), X argv[1]); X perror (error); X exit (1); X } X } X } X exit (0); X} SHAR_EOF chmod 0644 gencat.c || echo "restore of gencat.c fails" sed 's/^X//' << 'SHAR_EOF' > gencat.msg.En_US && X$quote " X$ X$ message catalog for "gencat" X$ X$set 1 X1 Usage: gencat catfile msgfile ...\n X2 gencat: Unable to open the file %s\n X3 Invalid line in input file, line %d\n X4 gencat: Unable to create new message catalog\n X5 gencat: Unable to create temporary file\n X6 gencat: Unable to create message catalog file %s X7 gencat: Unable to open message file %s X8 gencat: Unable to write to message catalog file %s X9 gencat: Unable to open message catalog file %s X10 gencat: The file %s is not a valid message catalog\n X11 gencat: Out of memory loading message catalog X$ X$ message catalog for "catgets" X$ X$set 2 X1 Usage: catgets catalog set msg default\n X$ X$ message catalog for "dspcat" X$ X$set 3 X1 Usage: dspcat catalog [ set [ msg ] ]\n X2 dspcat: Unable to open message catalog file %s\n X3 dspcat: "%s" is an invalid set number.\n X4 dspcat: "%s" is an invalid message number.\n SHAR_EOF chmod 0644 gencat.msg.En_US || echo "restore of gencat.msg.En_US fails" sed 's/^X//' << 'SHAR_EOF' > catgets.c && X/* X * Copyright 1994, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X * X * This software is provided on an AS-IS basis and the author makes X * no warrantee of any kind. The "Artistic License" located in the X * file LICENSE contains complete licensing information. X */ X X#ifndef lint Xstatic char sccsid[] = "%W% %U% %G%"; X#endif X X#include X#include "nl_types.h" X Xnl_catd catd; X#define M(msg,def) catgets (catd, 2, msg, def) X Xmain (int argc, char ** argv) X{ X nl_catd cmd_catd; X char *msg; X X catd = catopen ("gencat", 0); X X if (argc < 5) { X fprintf (stderr, X M(1, "usage: catgets catalog set msg default\n")); X exit (1); X } X cmd_catd = catopen (argv[1], 0); X if (msg = catgets (cmd_catd, atoi (argv[2]), atoi (argv[3]), argv[4])) X write (1, msg, strlen (msg)); X else X write (1, argv[4], strlen (argv[4])); X X exit (1); X} SHAR_EOF chmod 0644 catgets.c || echo "restore of catgets.c fails" sed 's/^X//' << 'SHAR_EOF' > l_catclose.c && X/* X * Copyright 1994, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X * X * This software is provided on an AS-IS basis and the author makes X * no warrantee of any kind. The "Artistic License" located in the X * file LICENSE contains complete licensing information. X */ X X#ifndef lint Xstatic char sccsid[] = "%W% %U% %G%"; X#endif X X#include X#include X#include "nl_types.h" X Xint Xcatclose (nl_catd catd) X{ X int i; X X if (catd == (nl_catd) -1) X return -1; X X fclose (catd->nl_cat_fp); X X for (i = 0;i <= catd->nl_sets;i++) X if (catd->nl_msgs[i]) X free (catd->nl_nmsgs); X X free (catd); X return 0; X} SHAR_EOF chmod 0644 l_catclose.c || echo "restore of l_catclose.c fails" sed 's/^X//' << 'SHAR_EOF' > l_catgets.c && X/* X * Copyright 1994, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X * X * This software is provided on an AS-IS basis and the author makes X * no warrantee of any kind. The "Artistic License" located in the X * file LICENSE contains complete licensing information. X */ X X#ifndef lint Xstatic char sccsid[] = "%W% %U% %G%"; X#endif X X#include X#include X#include "nl_types.h" X Xchar * Xcatgets (nl_catd catd, int set_num, int msg_num, char * def_msg) X{ X static char buf[NL_TEXTMAX]; X int i; X int c; X X if (catd == (nl_catd) -1) X return def_msg; X X if (set_num < 1 || set_num > catd->nl_sets) X return def_msg; X X if (msg_num < 1 || msg_num > catd->nl_nmsgs[set_num-1]) X return def_msg; X X if (catd->nl_msgs[set_num-1][msg_num-1] == (off_t) 0) X return def_msg; X X if (fseek (catd->nl_cat_fp, catd->nl_msgs[set_num-1][msg_num-1], 0)) X return def_msg; X X for (i = 0;i < (NL_TEXTMAX-1);i++) { X if ((c = getc (catd->nl_cat_fp)) == '\0' || c == EOF) X break; X X buf[i] = c; X } X buf[i++] = '\0'; X return buf; X} SHAR_EOF chmod 0644 l_catgets.c || echo "restore of l_catgets.c fails" sed 's/^X//' << 'SHAR_EOF' > l_catopen.c && X/* X * Copyright 1994, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X * X * This software is provided on an AS-IS basis and the author makes X * no warrantee of any kind. The "Artistic License" located in the X * file LICENSE contains complete licensing information. X */ X X#ifndef lint Xstatic char sccsid[] = "%W% %U% %G%"; X#endif X X#include X#include X#include X#include X#include X X#undef NL_MSGMAX X#undef NL_SETMAX X#undef NL_TEXTMAX X X#include "nl_types.h" X Xstatic char lang_var[32]; Xstatic char language[16]; Xstatic char territory[16]; Xstatic char codeset[16]; X Xstatic void Xget_lang_var () X{ X char *lang; X X if (! (lang = getenv ("LANG"))) X lang = "C"; X X strncpy (lang_var, lang, sizeof lang_var); X X switch (sscanf (lang_var, "%16[^_]_%16[^.].%16s", X language, territory, codeset)) { X default: X case 0: X language[0] = '\0'; X case 1: X territory[0] = '\0'; X case 2: X codeset[0] = '\0'; X case 3: X return; X } X} X Xstatic int Xget_cat_name (char * file, const char * path, const char * name) X{ X char *begin, *end; X char *cp1, *cp2; X char dummy[BUFSIZ]; X X strncpy (dummy, path, sizeof dummy - 1); X dummy[BUFSIZ-1] = '\0'; X file[0] = '\0'; X X for (begin = dummy;begin;begin = end) { X if (end = strchr (begin, ':')) X *end++ = '\0'; X X for (cp1 = begin, cp2 = file;*cp1;) { X if (*cp1 != '%') { X *cp2++ = *cp1++; X continue; X } X switch (*++cp1) { X default: X case '%': X *cp2++ = *cp1++; X continue; X case 'N': X strcpy (cp2, name); X cp1++; X cp2 += strlen (name); X continue; X case 'L': X strcpy (cp2, lang_var); X cp1++; X cp2 += strlen (lang_var); X continue; X case 'l': X strcpy (cp2, language); X cp1++; X cp2 += strlen (language); X continue; X case 't': X strcpy (cp2, territory); X cp1++; X cp2 += strlen (territory); X continue; X case 'c': X strcpy (cp2, codeset); X cp1++; X cp2 += strlen (codeset); X continue; X } X } X *cp2 = '\0'; X X if (access (file, 0) == 0) X return 0; X } X return -1; X} X Xnl_catd Xcatopen (const char * name, int oflag) X{ X char *nlspath; X char catalog[PATH_MAX]; X int i; X nl_catd catd; X nl_cat_header header; X X if (! (nlspath = getenv ("NLSPATH"))) X nlspath = "/usr/lib/nls/%L/%N.cat"; X X get_lang_var (); X X if (strcmp (language, "C") == 0) X return (nl_catd) -1; X X if (get_cat_name (catalog, nlspath, name)) X return (nl_catd) -1; X X if (! (catd = (nl_catd) malloc (sizeof *catd))) X return (nl_catd) -1; X X if (! (catd->nl_cat_fp = fopen (catalog, "r"))) { X free (catd); X return (nl_catd) -1; X } X if (fread (&header, sizeof header, 1, catd->nl_cat_fp) != 1) { X fclose (catd->nl_cat_fp); X free (catd); X return (nl_catd) -1; X } X catd->nl_sets = header.nl_sets; X for (i = 0;i < catd->nl_sets;i++) X catd->nl_msgs[i] = (off_t *) 0; X X for (i = 0;i < header.nl_sets;i++) { X catd->nl_nmsgs[i] = header.nl_nmsgs[i]; X X if (catd->nl_nmsgs[i] == 0) { X catd->nl_msgs[i] = (off_t *) 0; X continue; X } X if (! (catd->nl_msgs[i] = (off_t *) X malloc (sizeof (off_t) * header.nl_nmsgs[i]))) X goto fail; X if (fread (catd->nl_msgs[i], sizeof (off_t) * X header.nl_nmsgs[i], 1, catd->nl_cat_fp) != 1) X goto fail; X } X return catd; X Xfail: X fclose (catd->nl_cat_fp); X X for (i = 0;i <= catd->nl_sets;i++) X if (catd->nl_msgs[i]) X free (catd->nl_nmsgs); X X free (catd); X return (nl_catd) -1; X} SHAR_EOF chmod 0644 l_catopen.c || echo "restore of l_catopen.c fails" sed 's/^X//' << 'SHAR_EOF' > nl_types.h && X/* X * Copyright 1994, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X * X * This software is provided on an AS-IS basis and the author makes X * no warrantee of any kind. The "Artistic License" located in the X * file LICENSE contains complete licensing information. X * X * %W% %U% %G% X */ X X#define NL_MSGMAX 256 X#define NL_SETD 1 X#define NL_SETMAX 16 X#define NL_TEXTMAX 1024 X Xtypedef struct { X FILE *nl_cat_fp; X int nl_sets; X int nl_nmsgs[NL_SETMAX]; X off_t *nl_msgs[NL_SETMAX]; X} * nl_catd; X Xtypedef struct { X int nl_sets; X int nl_nmsgs[NL_SETMAX]; X} nl_cat_header; X Xnl_catd catopen (const char *, int); Xint catclose (nl_catd); Xchar *catgets (nl_catd, int, int, char *); SHAR_EOF chmod 0644 nl_types.h || echo "restore of nl_types.h fails" exit 0 -- John F. Haugh II [ NRA-ILA ] [ Kill Barney ] !'s: ...!cs.utexas.edu!rpp386!jfh Ma Bell: (512) 251-2151 [GOP][DoF #17][PADI][ENTJ] @'s: jfh@rpp386.cactus.org There are three documents that run my life: The King James Bible, the United States Constitution, and the UNIX System V Release 4 Programmer's Reference.