gencat.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 1990, 1991, 1994, Sun Microsystems, Inc.
* All rights reserved.
*/
#ident "%Z%%M% %I% %E% SMI"
#include <nl_types.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <locale.h>
#include <libintl.h>
#ifndef NL_MSGMAX
#define NL_MSGMAX 32767
#endif
#ifndef NL_SETMAX
#define NL_SETMAX 255
#endif
#ifndef NL_TEXTMAX
#define NL_TEXTMAX 2048
#endif
#define BS '\b'
#define CR '\r'
#define DOLLAR '$'
#define FF '\f'
#define NEWLINE '\n'
#define NUL '\000'
#define REVERSE_SOLIDUS '\\'
#define SPACE ' '
#define TAB '\t'
#define VTAB '\v'
/* double linked list */
struct cat_set {
int set_no;
};
/* double linked list */
struct cat_msg {
int msg_no;
int msg_len;
char s[1];
};
int catfd; /* File descriptor of catalog file */
char *catfname; /* Catalog file name */
char *msgfname; /* message source file name */
int ateof; /* boolean indicating END-OF-FILE */
int lineno; /* the line number of message source file */
int quoting; /* boolean indicating quotes is used */
int quote; /* the current quote */
int text_len; /* message text length */
int text_size; /* the size of allocated text memory */
char *text; /* messsge text */
int current_set_no; /* the current set number */
/* Error message */
/* 0 */
#define MSG0 ""
/* 1 */
#define MSG1 "usage: gencat catfile msgfile ...\n"
/* 2 */
#define MSG2 "gencat: cannot open \"%s\"\n"
/* 3 */
#define MSG3 "gencat: read error on \"%s\"\n"
/* 4 */
#define MSG4 "gencat: bad magic number (%#lx)\n"
/* 5 */
#define MSG5 "gencat: corrupt catalogue file \"%s\"\n"
/* 6 */
#define MSG6 "gencat: memory limit exceeded\n"
/* 7 */
#define MSG7 "gencat: seek error on \"%s\"\n"
/* 8 */
#define MSG8 "gencat: write error on \"%s\"\n"
/* 9 */
#define MSG9 "gencat: \"%s\", line %d: number too large (%s)\n"
/* 10 */
#define MSG10 "gencat: \"%s\", line %d: 0 is not a permissible " \
"message number\n"
/* 11 */
#define MSG11 "gencat: \"%s\", line %d: warning, message number %d " \
"exceeds limit (%d)\n"
/* 12 */
#define MSG12 "gencat: \"%s\", line %d: missing quote (%wc)\n"
/* 13 */
#define MSG13 "gencat: \"%s\", line %d: character value too large ('\\%o')\n"
/* 14 */
#define MSG14 "gencat: \"%s\", line %d: extra characters following " \
"message text\n"
/* 15 */
#define MSG15 "gencat: \"%s\", line %d: extra characters following " \
"$quote directive\n"
/* 16 */
#define MSG16 "gencat: \"%s\", line %d: no set number specified in " \
"$set directive\n"
/* 17 */
#define MSG17 "getcat: \"%s\", line %d: 0 is not a permissible set number\n"
/* 18 */
#define MSG18 "gencat: \"%s\", line %d: warning, set number %d " \
"exceeds limit (%d)\n"
/* 19 */
#define MSG19 "gencat: \"%s\", line %d: unknown directive %s\n"
/* 20 */
#define MSG20 "gencat: \"%s\", line %d: no set number specified in " \
"$delset directive\n"
/* 21 */
#define MSG21 "stdin"
/* 22 */
#define MSG22 "gencat: \"%s\", line %d: number or $ expected\n"
struct cat_set *
new_set(n)
int n;
{
struct cat_set *p;
if (p == NULL) {
exit(1);
}
p->set_no = n;
return (p);
}
void
int no;
{
return;
}
current_set_no = no;
current_msg = NULL;
/* if no set exists, create a new set */
if (current_set == NULL) {
return;
}
return;
}
/* prepend a new set */
return;
}
return;
}
/* search for the set number 'no' */
/* set number 'no' found */
return;
}
/* If set number is not found, insert a new set in the middle */
prev = current_set;
if (prev)
else
if (next)
}
void
int no;
{
struct cat_msg *p, *q;
continue;
return;
if (setp == current_set) {
current_set = NULL;
current_msg = NULL;
}
/* free all messages in the set */
q = p->next;
FREE(p);
p = q;
}
/* do the link operation to delete the set */
if (prev)
else
if (next)
}
struct cat_msg *
int no;
int len;
char *text;
{
struct cat_msg *p;
if (p == NULL) {
exit(1);
}
return (p);
}
void
int no;
int len;
char *text;
{
if (current_msg == NULL) {
if (current_set == NULL)
if (current_msg == NULL) {
return;
}
}
return;
}
return;
}
}
/*
* if the same msg number is found, then delte the message and
* insert the new message. This is same as replacing message.
*/
} else {
prev = current_msg;
}
if (prev)
else
if (next)
}
void
int no;
{
struct cat_set *p = current_set;
if (current_msg == NULL) {
if (current_set == NULL)
p = p->next)
continue;
return;
current_set = p;
if (current_msg == NULL)
return;
}
if (prev) {
current_msg = prev;
} else {
current_msg = next;
}
if (next)
}
}
int
int fd;
char *p;
int n;
char *pathname;
{
int nbytes, bytes_read;
if (n == 0)
return (0);
nbytes = 0;
while (nbytes < n) {
if (bytes_read < 0) {
perror("");
exit(1);
}
} else if (bytes_read == 0)
break;
else
nbytes += bytes_read;
}
return (nbytes);
}
/*
* Check if catalog file read is valid
*
*/
int
char *cat;
{
int i, j;
int nmsgs;
int msg_no;
struct _cat_msg_hdr *msg;
int set_no;
int first_msg_hdr;
struct _cat_set_hdr *set;
set_no = 0;
return (0);
if (nmsgs < 0)
return (0);
if (nmsgs == 0)
continue;
if (first_msg_hdr < 0)
return (0);
return (0);
msg_no = 0;
return (0);
if (msg->__msg_offset < 0)
return (0);
return (0);
}
}
return (1);
}
/*
* convert a chunk of catalog file into double linked list format
*/
void
char *cat;
{
int i, j;
int nmsgs;
struct _cat_set_hdr *set;
struct _cat_msg_hdr *msg;
if (nmsgs == 0)
continue;
+ set->__first_msg_hdr;
}
}
}
/*
* read a catalog file in a chunk and convert it to double linked list.
*/
void
int fd;
char *pathname;
{
int i;
char *cat;
if (i == 0)
return;
exit(1);
}
exit(1);
}
return;
hdr.__msg_hdr_offset < 0 ||
hdr.__msg_text_offset < 0 ||
exit(1);
}
exit(1);
}
exit(1);
}
}
/*
* Extend the memory in 1000 byte chunks whenever runs out of text space.
*/
void
{
text_size += 1000;
if (text)
else
exit(1);
}
}
int
get_number(fp, c)
int c;
{
int i, n;
char *s, *t;
i = 0;
do {
while (i >= text_size)
extend_text();
text[i] = c;
++i;
}
while (isdigit(c));
while (i >= text_size)
extend_text();
for (s = text; *s == '0'; ++s)
continue;
n = 0;
for (t = s; isdigit(*t); ++t) {
if (n > INT_MAX / 10 ||
exit(1);
}
n = 10 * n + (*t - '0');
}
return (n);
}
void
{
int c;
int n;
text_len = 0;
while (c != quote) {
quote);
exit(1);
}
if (c == REVERSE_SOLIDUS) {
switch (c) {
case EOF:
exit(1);
break;
case NEWLINE:
++lineno;
continue;
/* NOTREACHED */
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
n = (c - '0');
if (c >= '0' && c <= '7') {
n = 8 * n + (c - '0');
if (c >= '0' && c <= '7')
n = 8 * n + (c - '0');
else
} else
if (n > UCHAR_MAX) {
exit(1);
}
c = n;
break;
case 'n':
c = NEWLINE;
break;
case 't':
c = TAB;
break;
case 'v':
c = VTAB;
break;
case 'b':
c = BS;
break;
case 'r':
c = CR;
break;
case 'f':
c = FF;
break;
}
}
extend_text();
text_len += n;
}
extend_text();
++text_len;
do {
if (c == NEWLINE) {
++lineno;
return;
}
if (c == EOF) {
ateof = 1;
return;
}
exit(1);
}
if (c == REVERSE_SOLIDUS) {
switch (c) {
case EOF:
return;
case NEWLINE:
++lineno;
continue;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
n = (c - '0');
if (c >= '0' && c <= '7') {
n = 8 * n + (c - '0');
if (c >= '0' && c <= '7')
n = 8 * n + (c - '0');
else
} else
if (n > UCHAR_MAX) {
lineno, n);
exit(1);
}
c = n;
break;
case 'n':
c = NEWLINE;
break;
case 't':
c = TAB;
break;
case 'v':
c = VTAB;
break;
case 'b':
c = BS;
break;
case 'r':
c = CR;
break;
case 'f':
c = FF;
break;
}
}
extend_text();
text_len += n;
}
extend_text();
++text_len;
if (c == NEWLINE)
++lineno;
else
ateof = 1;
}
/*
* This routine handles $ <comment>, $set, $delset, $quote
*/
void
{
int c;
int n;
do {
}
if (c == NEWLINE) {
++lineno;
return;
}
if (c == EOF) {
ateof = 1;
return;
}
text_len = 1;
extend_text();
extend_text();
++text_len;
}
extend_text();
exit(1);
}
n = get_number(fp, c);
if (n == 0) {
exit(1);
}
if (n > NL_SETMAX) {
n, NL_SETMAX);
}
find_set(n);
do { /* skip comment */
if (c == NEWLINE)
++lineno;
else
ateof = 1;
return;
exit(1);
}
n = get_number(fp, c);
if (n == 0) {
exit(1);
}
if (n > NL_SETMAX) {
n, NL_SETMAX);
}
delete_set(n);
do { /* skip comment */
if (c == NEWLINE)
++lineno;
else
ateof = 1;
return;
if (c == NEWLINE) {
quoting = 0;
++lineno;
return;
}
if (c == EOF) {
quoting = 0;
ateof = 1;
return;
}
if (c == NEWLINE) {
quoting = 0;
++lineno;
return;
}
if (c == EOF) {
quoting = 0;
ateof = 1;
return;
}
quoting = 1;
quote = c;
do { /* skip comment */
if (c == NEWLINE) {
++lineno;
return;
}
if (c == EOF) {
ateof = 1;
return;
}
exit(1);
} else {
exit(1);
}
}
/*
* Read message source file and update double linked list message catalog.
*/
void
char *pathname;
{
int c;
int no;
ateof = 0;
lineno = 1;
quoting = 0;
current_set = NULL;
current_msg = NULL;
for (;;) {
if (ateof)
return;
do {
if (c == DOLLAR) {
continue;
}
if (no == 0) {
exit(1);
}
}
delete_msg(no);
if (c == NEWLINE)
++lineno;
else
return;
continue;
} else {
continue;
}
}
if (c == NEWLINE) {
++lineno;
continue;
}
if (c == EOF)
return;
exit(1);
}
}
/*
* Write double linked list to the file.
* It first converts a linked list to one chunk of memory and
* write it to file.
*/
void
int fd;
char *pathname;
{
int i, n;
int nsets;
int mem;
int nmsgs;
int text_size;
int first_msg_hdr;
int msg_offset;
unsigned nbytes;
char *cat;
struct _cat_set_hdr *set;
struct _cat_msg_hdr *msg;
char *text;
/* compute number of sets, number of messages, the total text size */
nsets = 0;
nmsgs = 0;
text_size = 0;
++nsets;
++nmsgs;
}
}
n = _CAT_HDR_SIZE + mem;
if (cat == 0) {
exit(1);
}
/* convert linked list to one chunk of memory */
first_msg_hdr = 0;
msg_offset = 0;
nmsgs = 0;
++nmsgs;
}
}
first_msg_hdr += nmsgs;
}
/* write one chunk of memory to file */
nbytes = 0;
while (nbytes < n) {
if (i < 0) {
perror("");
exit(1);
}
} else {
nbytes += n;
}
}
}
int
int argc;
char *argv[];
{
int i;
int cat_exists;
#if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
#endif
(void) textdomain(TEXT_DOMAIN);
if (argc < 3) {
exit(1);
}
cat_exists = 0;
} else {
if (catfd < 0) { /* file exists */
/* cannot open file */
perror("");
exit(1);
}
cat_exists = 1;
/* read catalog file into memory */
perror("");
exit(1);
}
}
}
/* process all message source files */
if (argc != 3) {
exit(1);
} else {
}
} else {
for (i = 2; i < argc; ++i) {
perror("");
exit(1);
}
}
}
if (cat_exists)
/* write catalog to file */
return (0);
}