version 1.5, 1997/09/21 10:34:00 |
version 1.6, 2000/09/27 23:53:29 |
|
|
/* $OpenBSD$ */ |
/* $OpenBSD$ */ |
|
/* $NetBSD: gencat.c,v 1.9 1998/10/09 17:00:56 itohy Exp $ */ |
|
|
/*- |
/*- |
* Copyright (c) 1996 The NetBSD Foundation, Inc. |
* Copyright (c) 1996 The NetBSD Foundation, Inc. |
|
|
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE |
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
|
* POSSIBILITY OF SUCH DAMAGE. |
* POSSIBILITY OF SUCH DAMAGE. |
*/ |
*/ |
|
|
|
#include <sys/cdefs.h> |
|
#ifndef lint |
|
static char rcsid[] = |
|
"$OpenBSD$"; |
|
#endif /* not lint */ |
|
|
/*********************************************************** |
/*********************************************************** |
Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. |
Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts. |
|
|
|
|
#define _NLS_PRIVATE |
#define _NLS_PRIVATE |
|
|
/* ensure 8-bit cleanliness */ |
/* ensure 8-bit cleanliness */ |
#define ISSPACE(c) (isascii(c) && isspace(c)) |
#define ISSPACE(c) \ |
|
(isascii((unsigned char)c) && isspace((unsigned char)c)) |
|
|
#include <sys/queue.h> |
#include <sys/queue.h> |
#include <ctype.h> |
#include <ctype.h> |
|
#include <err.h> |
|
#include <fcntl.h> |
|
#include <nl_types.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <stdlib.h> |
#include <string.h> |
#include <string.h> |
#include <unistd.h> |
#include <unistd.h> |
#include <fcntl.h> |
|
#include <nl_types.h> |
|
|
|
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 MCWriteCat __P((int fd)); |
|
|
|
struct _msgT { |
struct _msgT { |
long msgId; |
long msgId; |
char *str; |
char *str; |
|
|
static char *curline = NULL; |
static char *curline = NULL; |
static long lineno = 0; |
static long lineno = 0; |
|
|
|
extern char *__progname; /* from crt0.o */ |
|
|
|
static char *cskip __P((char *)); |
|
static void error __P((char *, char *)); |
|
static void nomem __P((void)); |
|
static char *getline __P((int)); |
|
static char *getmsg __P((int, char *, char)); |
|
static void warning __P((char *, char *)); |
|
static char *wskip __P((char *)); |
|
static char *xstrdup __P((const char *)); |
|
static void *xmalloc __P((size_t)); |
|
static void *xrealloc __P((void *, size_t)); |
|
|
|
void MCParse __P((int fd)); |
|
void MCWriteCat __P((int fd)); |
|
void MCDelMsg __P((int msgId)); |
|
void MCAddMsg __P((int msgId, const char *msg)); |
|
void MCAddSet __P((int setId)); |
|
void MCDelSet __P((int setId)); |
|
int main __P((int, char **)); |
|
void usage __P((void)); |
|
|
|
|
void |
void |
usage() |
usage() |
{ |
{ |
fprintf(stderr, "Use: gencat catfile msgfile ...\n"); |
fprintf(stderr, "Usage: %s catfile msgfile ...\n", __progname); |
exit(1); |
exit(1); |
} |
} |
|
|
|
|
catfile = *argv++; |
catfile = *argv++; |
|
|
for (; *argv; argv++) { |
for (; *argv; argv++) { |
if ((ifd = open(*argv, O_RDONLY)) < 0) { |
if ((ifd = open(*argv, O_RDONLY)) < 0) |
fprintf(stderr, "gencat: Unable to read %s\n", *argv); |
err(1, "Unable to read %s", *argv); |
exit(1); |
|
} |
|
MCParse(ifd); |
MCParse(ifd); |
close(ifd); |
close(ifd); |
} |
} |
|
|
if ((ofd = open(catfile, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) { |
if ((ofd = open(catfile, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) |
fprintf(stderr, "gencat: Unable to create a new %s.\n", |
err(1, "Unable to create a new %s", catfile); |
catfile); |
|
exit(1); |
|
} |
|
MCWriteCat(ofd); |
MCWriteCat(ofd); |
exit(0); |
exit(0); |
} |
} |
|
|
char *cptr; |
char *cptr; |
char *msg; |
char *msg; |
{ |
{ |
fprintf(stderr, "gencat: %s on line %ld\n", msg, lineno); |
fprintf(stderr, "%s: %s on line %ld\n", __progname, msg, lineno); |
fprintf(stderr, "%s\n", curline); |
fprintf(stderr, "%s\n", curline); |
if (cptr) { |
if (cptr) { |
char *tptr; |
char *tptr; |
|
|
|
|
static char * |
static char * |
xstrdup(str) |
xstrdup(str) |
char *str; |
const char *str; |
{ |
{ |
if ((str = strdup(str)) == NULL) |
char *nstr; |
|
|
|
if ((nstr = strdup(str)) == NULL) |
nomem(); |
nomem(); |
return (str); |
return (nstr); |
} |
} |
|
|
static char * |
static char * |
|
|
|
|
if (quote && *cptr == quote) { |
if (quote && *cptr == quote) { |
++cptr; |
++cptr; |
}; |
} |
|
|
clen = strlen(cptr) + 1; |
clen = strlen(cptr) + 1; |
if (clen > msglen) { |
if (clen > msglen) { |
|
|
*tptr++ = '\\'; |
*tptr++ = '\\'; |
++cptr; |
++cptr; |
break; |
break; |
case '"': |
case '"': |
|
/* FALLTHROUGH */ |
case '\'': |
case '\'': |
/* |
/* |
* While it isn't necessary to |
* While it isn't necessary to |
* escape ' and ", let's accept |
* escape ' and ", let's accept |
* them escaped and not complain. |
* them escaped and not complain. |
* (XPG4 states that '\' should be |
* (XPG4 states that '\' should be |
* ignored when not used in a |
* ignored when not used in a |
* valid escape sequence) |
* valid escape sequence) |
*/ |
*/ |
*tptr++ = '"'; |
*tptr++ = '"'; |
++cptr; |
++cptr; |
break; |
break; |
default: |
default: |
if (isdigit(*cptr)) { |
if (quote && *cptr == quote) { |
|
*tptr++ = *cptr++; |
|
} else if (isdigit((unsigned char) *cptr)) { |
*tptr = 0; |
*tptr = 0; |
for (i = 0; i < 3; ++i) { |
for (i = 0; i < 3; ++i) { |
if (!isdigit(*cptr)) |
if (!isdigit((unsigned char) *cptr)) |
break; |
break; |
if (*cptr > '7') |
if (*cptr > '7') |
warning(cptr, "octal number greater than 7?!"); |
warning(cptr, "octal number greater than 7?!"); |
|
|
++cptr; |
++cptr; |
} |
} |
} else { |
} else { |
warning(cptr, "unrecognized escape sequence; ignoring escape character"); |
warning(cptr, "unrecognized escape sequence; ignoring esacpe character"); |
} |
} |
|
break; |
} |
} |
} else { |
} else { |
*tptr++ = *cptr++; |
*tptr++ = *cptr++; |
|
|
} |
} |
} |
} |
} else { |
} else { |
if (isdigit(*cptr)) { |
/* |
|
* First check for (and eat) empty lines.... |
|
*/ |
|
if (!*cptr) |
|
continue; |
|
/* |
|
* We have a digit? Start of a message. Else, |
|
* syntax error. |
|
*/ |
|
if (isdigit((unsigned char) *cptr)) { |
msgid = atoi(cptr); |
msgid = atoi(cptr); |
cptr = cskip(cptr); |
cptr = cskip(cptr); |
cptr = wskip(cptr); |
cptr = wskip(cptr); |
/* if (*cptr) ++cptr; */ |
/* if (*cptr) ++cptr; */ |
|
} else { |
|
warning(cptr, "neither blank line nor start of a message id"); |
|
continue; |
} |
} |
if (!*cptr) |
/* |
|
* If we have a message ID, but no message, |
|
* then this means "delete this message id |
|
* from the catalog". |
|
*/ |
|
if (!*cptr) { |
MCDelMsg(msgid); |
MCDelMsg(msgid); |
else { |
} else { |
str = getmsg(fd, cptr, quote); |
str = getmsg(fd, cptr, quote); |
MCAddMsg(msgid, str); |
MCAddMsg(msgid, str); |
} |
} |