xref: /illumos-gate/usr/src/cmd/gencat/gencat.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1991, 1994, Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <nl_types.h>
30*7c478bd9Sstevel@tonic-gate #include <ctype.h>
31*7c478bd9Sstevel@tonic-gate #include <errno.h>
32*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
33*7c478bd9Sstevel@tonic-gate #include <limits.h>
34*7c478bd9Sstevel@tonic-gate #include <memory.h>
35*7c478bd9Sstevel@tonic-gate #include <stdio.h>
36*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
37*7c478bd9Sstevel@tonic-gate #include <string.h>
38*7c478bd9Sstevel@tonic-gate #include <unistd.h>
39*7c478bd9Sstevel@tonic-gate #include <locale.h>
40*7c478bd9Sstevel@tonic-gate #include <libintl.h>
41*7c478bd9Sstevel@tonic-gate 
42*7c478bd9Sstevel@tonic-gate #ifndef NL_MSGMAX
43*7c478bd9Sstevel@tonic-gate #define	NL_MSGMAX 32767
44*7c478bd9Sstevel@tonic-gate #endif
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate #ifndef NL_SETMAX
47*7c478bd9Sstevel@tonic-gate #define	NL_SETMAX 255
48*7c478bd9Sstevel@tonic-gate #endif
49*7c478bd9Sstevel@tonic-gate 
50*7c478bd9Sstevel@tonic-gate #ifndef NL_TEXTMAX
51*7c478bd9Sstevel@tonic-gate #define	NL_TEXTMAX 2048
52*7c478bd9Sstevel@tonic-gate #endif
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate #define	BS		'\b'
55*7c478bd9Sstevel@tonic-gate #define	CR		'\r'
56*7c478bd9Sstevel@tonic-gate #define	DOLLAR	'$'
57*7c478bd9Sstevel@tonic-gate #define	FF		'\f'
58*7c478bd9Sstevel@tonic-gate #define	NEWLINE	'\n'
59*7c478bd9Sstevel@tonic-gate #define	NUL		'\000'
60*7c478bd9Sstevel@tonic-gate #define	REVERSE_SOLIDUS '\\'
61*7c478bd9Sstevel@tonic-gate #define	SPACE	' '
62*7c478bd9Sstevel@tonic-gate #define	TAB		'\t'
63*7c478bd9Sstevel@tonic-gate #define	VTAB	'\v'
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate #define	FPRINTF			(void) fprintf
66*7c478bd9Sstevel@tonic-gate #define	FREE(x)			free((char *)(x))
67*7c478bd9Sstevel@tonic-gate #define	MALLOC(n)		malloc((unsigned)(n))
68*7c478bd9Sstevel@tonic-gate #define	MEMCPY(dst, src, n) \
69*7c478bd9Sstevel@tonic-gate 		(void) memcpy((char *)(dst), (char *)(src), (int)(n))
70*7c478bd9Sstevel@tonic-gate #define	MEMSET(s, c, n)	(void) memset((char *)(s), (int)(c), (int)(n));
71*7c478bd9Sstevel@tonic-gate #define	MSG(n)			gettext(MSG ## n)
72*7c478bd9Sstevel@tonic-gate #define	READ(fd, p, n)	read((int)(fd), (char *)(p), (unsigned)(n))
73*7c478bd9Sstevel@tonic-gate #define	REALLOC(x, n)	realloc((char *)(x), (unsigned)(n))
74*7c478bd9Sstevel@tonic-gate 
75*7c478bd9Sstevel@tonic-gate /* double linked list */
76*7c478bd9Sstevel@tonic-gate struct cat_set {
77*7c478bd9Sstevel@tonic-gate 	struct cat_set	*prev;
78*7c478bd9Sstevel@tonic-gate 	struct cat_set	*next;
79*7c478bd9Sstevel@tonic-gate 	int				set_no;
80*7c478bd9Sstevel@tonic-gate 	struct cat_msg	*first_msg;
81*7c478bd9Sstevel@tonic-gate };
82*7c478bd9Sstevel@tonic-gate 
83*7c478bd9Sstevel@tonic-gate /* double linked list */
84*7c478bd9Sstevel@tonic-gate struct cat_msg {
85*7c478bd9Sstevel@tonic-gate 	struct cat_msg	*prev;
86*7c478bd9Sstevel@tonic-gate 	struct cat_msg	*next;
87*7c478bd9Sstevel@tonic-gate 	int				msg_no;
88*7c478bd9Sstevel@tonic-gate 	int				msg_len;
89*7c478bd9Sstevel@tonic-gate 	char			s[1];
90*7c478bd9Sstevel@tonic-gate };
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate int		catfd;		/* File descriptor of catalog file */
93*7c478bd9Sstevel@tonic-gate char	*catfname;	/* Catalog file name */
94*7c478bd9Sstevel@tonic-gate char	*msgfname;	/* message source file name */
95*7c478bd9Sstevel@tonic-gate int		ateof;		/* boolean indicating END-OF-FILE */
96*7c478bd9Sstevel@tonic-gate int		lineno;		/* the line number of message source file */
97*7c478bd9Sstevel@tonic-gate int		quoting;	/* boolean indicating quotes is used */
98*7c478bd9Sstevel@tonic-gate int		quote;		/* the current quote */
99*7c478bd9Sstevel@tonic-gate int		text_len;	/* message text length */
100*7c478bd9Sstevel@tonic-gate int		text_size;	/* the size of allocated text memory */
101*7c478bd9Sstevel@tonic-gate char	*text;		/* messsge text */
102*7c478bd9Sstevel@tonic-gate 
103*7c478bd9Sstevel@tonic-gate struct _cat_hdr	hdr;
104*7c478bd9Sstevel@tonic-gate int				current_set_no;	/* the current set number */
105*7c478bd9Sstevel@tonic-gate struct cat_set	*first_set;	/* the pointer to the first set */
106*7c478bd9Sstevel@tonic-gate struct cat_set	*current_set;	/* the pointer to the current set */
107*7c478bd9Sstevel@tonic-gate struct cat_msg	*current_msg;	/* the pointer to the first message */
108*7c478bd9Sstevel@tonic-gate 
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate /* Error message */
111*7c478bd9Sstevel@tonic-gate /* 0 */
112*7c478bd9Sstevel@tonic-gate #define	MSG0	""
113*7c478bd9Sstevel@tonic-gate /* 1 */
114*7c478bd9Sstevel@tonic-gate #define	MSG1	"usage: gencat catfile msgfile ...\n"
115*7c478bd9Sstevel@tonic-gate /* 2 */
116*7c478bd9Sstevel@tonic-gate #define	MSG2	"gencat: cannot open \"%s\"\n"
117*7c478bd9Sstevel@tonic-gate /* 3 */
118*7c478bd9Sstevel@tonic-gate #define	MSG3	"gencat: read error on \"%s\"\n"
119*7c478bd9Sstevel@tonic-gate /* 4 */
120*7c478bd9Sstevel@tonic-gate #define	MSG4	"gencat: bad magic number (%#lx)\n"
121*7c478bd9Sstevel@tonic-gate /* 5 */
122*7c478bd9Sstevel@tonic-gate #define	MSG5	"gencat: corrupt catalogue file \"%s\"\n"
123*7c478bd9Sstevel@tonic-gate /* 6 */
124*7c478bd9Sstevel@tonic-gate #define	MSG6	"gencat: memory limit exceeded\n"
125*7c478bd9Sstevel@tonic-gate /* 7 */
126*7c478bd9Sstevel@tonic-gate #define	MSG7	"gencat: seek error on \"%s\"\n"
127*7c478bd9Sstevel@tonic-gate /* 8 */
128*7c478bd9Sstevel@tonic-gate #define	MSG8	"gencat: write error on \"%s\"\n"
129*7c478bd9Sstevel@tonic-gate /* 9 */
130*7c478bd9Sstevel@tonic-gate #define	MSG9	"gencat: \"%s\", line %d: number too large (%s)\n"
131*7c478bd9Sstevel@tonic-gate /* 10 */
132*7c478bd9Sstevel@tonic-gate #define	MSG10	"gencat: \"%s\", line %d: 0 is not a permissible " \
133*7c478bd9Sstevel@tonic-gate 				"message number\n"
134*7c478bd9Sstevel@tonic-gate /* 11 */
135*7c478bd9Sstevel@tonic-gate #define	MSG11	"gencat: \"%s\", line %d: warning, message number %d " \
136*7c478bd9Sstevel@tonic-gate 				"exceeds limit (%d)\n"
137*7c478bd9Sstevel@tonic-gate /* 12 */
138*7c478bd9Sstevel@tonic-gate #define	MSG12	"gencat: \"%s\", line %d: missing quote (%wc)\n"
139*7c478bd9Sstevel@tonic-gate /* 13 */
140*7c478bd9Sstevel@tonic-gate #define	MSG13	"gencat: \"%s\", line %d: character value too large ('\\%o')\n"
141*7c478bd9Sstevel@tonic-gate /* 14 */
142*7c478bd9Sstevel@tonic-gate #define	MSG14	"gencat: \"%s\", line %d: extra characters following " \
143*7c478bd9Sstevel@tonic-gate 				"message text\n"
144*7c478bd9Sstevel@tonic-gate /* 15 */
145*7c478bd9Sstevel@tonic-gate #define	MSG15	"gencat: \"%s\", line %d: extra characters following " \
146*7c478bd9Sstevel@tonic-gate 				"$quote directive\n"
147*7c478bd9Sstevel@tonic-gate /* 16 */
148*7c478bd9Sstevel@tonic-gate #define	MSG16	"gencat: \"%s\", line %d: no set number specified in " \
149*7c478bd9Sstevel@tonic-gate 				"$set directive\n"
150*7c478bd9Sstevel@tonic-gate /* 17 */
151*7c478bd9Sstevel@tonic-gate #define	MSG17	"getcat: \"%s\", line %d: 0 is not a permissible set number\n"
152*7c478bd9Sstevel@tonic-gate /* 18 */
153*7c478bd9Sstevel@tonic-gate #define	MSG18	"gencat: \"%s\", line %d: warning, set number %d " \
154*7c478bd9Sstevel@tonic-gate 				"exceeds limit (%d)\n"
155*7c478bd9Sstevel@tonic-gate /* 19 */
156*7c478bd9Sstevel@tonic-gate #define	MSG19	"gencat: \"%s\", line %d: unknown directive %s\n"
157*7c478bd9Sstevel@tonic-gate /* 20 */
158*7c478bd9Sstevel@tonic-gate #define	MSG20	"gencat: \"%s\", line %d: no set number specified in " \
159*7c478bd9Sstevel@tonic-gate 				"$delset directive\n"
160*7c478bd9Sstevel@tonic-gate /* 21 */
161*7c478bd9Sstevel@tonic-gate #define	MSG21	"stdin"
162*7c478bd9Sstevel@tonic-gate /* 22 */
163*7c478bd9Sstevel@tonic-gate #define	MSG22	"gencat: \"%s\", line %d: number or $ expected\n"
164*7c478bd9Sstevel@tonic-gate 
165*7c478bd9Sstevel@tonic-gate struct cat_set *
new_set(n)166*7c478bd9Sstevel@tonic-gate new_set(n)
167*7c478bd9Sstevel@tonic-gate 	int		n;
168*7c478bd9Sstevel@tonic-gate {
169*7c478bd9Sstevel@tonic-gate 	struct cat_set *p;
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 	p = (struct cat_set *) MALLOC(sizeof (struct cat_set));
172*7c478bd9Sstevel@tonic-gate 	if (p == NULL) {
173*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(6));
174*7c478bd9Sstevel@tonic-gate 		exit(1);
175*7c478bd9Sstevel@tonic-gate 	}
176*7c478bd9Sstevel@tonic-gate 	p->next = NULL;
177*7c478bd9Sstevel@tonic-gate 	p->prev = NULL;
178*7c478bd9Sstevel@tonic-gate 	p->set_no = n;
179*7c478bd9Sstevel@tonic-gate 	p->first_msg = NULL;
180*7c478bd9Sstevel@tonic-gate 	return (p);
181*7c478bd9Sstevel@tonic-gate }
182*7c478bd9Sstevel@tonic-gate 
183*7c478bd9Sstevel@tonic-gate void
find_set(no)184*7c478bd9Sstevel@tonic-gate find_set(no)
185*7c478bd9Sstevel@tonic-gate 	int		no;
186*7c478bd9Sstevel@tonic-gate {
187*7c478bd9Sstevel@tonic-gate 	struct cat_set	*prev, *next;
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	if (current_set && current_set->set_no == no) {
190*7c478bd9Sstevel@tonic-gate 		return;
191*7c478bd9Sstevel@tonic-gate 	}
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate 	current_set_no = no;
194*7c478bd9Sstevel@tonic-gate 	current_msg = NULL;
195*7c478bd9Sstevel@tonic-gate 	/* if no set exists, create a new set */
196*7c478bd9Sstevel@tonic-gate 	if (current_set == NULL) {
197*7c478bd9Sstevel@tonic-gate 		if (first_set == NULL) {
198*7c478bd9Sstevel@tonic-gate 			current_set = first_set = new_set(no);
199*7c478bd9Sstevel@tonic-gate 			return;
200*7c478bd9Sstevel@tonic-gate 		}
201*7c478bd9Sstevel@tonic-gate 		current_set = first_set;
202*7c478bd9Sstevel@tonic-gate 		if (current_set->set_no == no)
203*7c478bd9Sstevel@tonic-gate 			return;
204*7c478bd9Sstevel@tonic-gate 	}
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate 	if (current_set->set_no > no) {
207*7c478bd9Sstevel@tonic-gate 		if (first_set->set_no > no) {
208*7c478bd9Sstevel@tonic-gate 			/* prepend a new set */
209*7c478bd9Sstevel@tonic-gate 			current_set = new_set(no);
210*7c478bd9Sstevel@tonic-gate 			current_set->next = first_set;
211*7c478bd9Sstevel@tonic-gate 			first_set->prev = current_set;
212*7c478bd9Sstevel@tonic-gate 			first_set = current_set;
213*7c478bd9Sstevel@tonic-gate 			return;
214*7c478bd9Sstevel@tonic-gate 		}
215*7c478bd9Sstevel@tonic-gate 		current_set = first_set;
216*7c478bd9Sstevel@tonic-gate 		if (current_set->set_no == no)
217*7c478bd9Sstevel@tonic-gate 			return;
218*7c478bd9Sstevel@tonic-gate 	}
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate 	/* search for the set number 'no' */
221*7c478bd9Sstevel@tonic-gate 	while (current_set->next && current_set->next->set_no < no)
222*7c478bd9Sstevel@tonic-gate 		current_set = current_set->next;
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate 	if (current_set->next && current_set->next->set_no == no) {
225*7c478bd9Sstevel@tonic-gate 		/* set number 'no' found */
226*7c478bd9Sstevel@tonic-gate 		current_set = current_set->next;
227*7c478bd9Sstevel@tonic-gate 		return;
228*7c478bd9Sstevel@tonic-gate 	}
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 	/* If set number is not found, insert a new set in the middle */
231*7c478bd9Sstevel@tonic-gate 	prev = current_set;
232*7c478bd9Sstevel@tonic-gate 	next = current_set->next;
233*7c478bd9Sstevel@tonic-gate 	current_set = new_set(no);
234*7c478bd9Sstevel@tonic-gate 	current_set->prev = prev;
235*7c478bd9Sstevel@tonic-gate 	current_set->next = next;
236*7c478bd9Sstevel@tonic-gate 	if (prev)
237*7c478bd9Sstevel@tonic-gate 		prev->next = current_set;
238*7c478bd9Sstevel@tonic-gate 	else
239*7c478bd9Sstevel@tonic-gate 		first_set = current_set;
240*7c478bd9Sstevel@tonic-gate 	if (next)
241*7c478bd9Sstevel@tonic-gate 		next->prev = current_set;
242*7c478bd9Sstevel@tonic-gate }
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate void
delete_set(no)245*7c478bd9Sstevel@tonic-gate delete_set(no)
246*7c478bd9Sstevel@tonic-gate 	int		no;
247*7c478bd9Sstevel@tonic-gate {
248*7c478bd9Sstevel@tonic-gate 	struct cat_set	*prev, *next, *setp;
249*7c478bd9Sstevel@tonic-gate 	struct cat_msg	*p, *q;
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	for (setp = first_set; setp && setp->set_no < no; setp = setp->next)
252*7c478bd9Sstevel@tonic-gate 		continue;
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	if (setp == NULL || setp->set_no != no)	/* set not found */
255*7c478bd9Sstevel@tonic-gate 		return;
256*7c478bd9Sstevel@tonic-gate 
257*7c478bd9Sstevel@tonic-gate 	if (setp == current_set) {
258*7c478bd9Sstevel@tonic-gate 		current_set = NULL;
259*7c478bd9Sstevel@tonic-gate 		current_msg = NULL;
260*7c478bd9Sstevel@tonic-gate 	}
261*7c478bd9Sstevel@tonic-gate 
262*7c478bd9Sstevel@tonic-gate 	/* free all messages in the set */
263*7c478bd9Sstevel@tonic-gate 	for (p = setp->first_msg; p; p) {
264*7c478bd9Sstevel@tonic-gate 		q = p->next;
265*7c478bd9Sstevel@tonic-gate 		FREE(p);
266*7c478bd9Sstevel@tonic-gate 		p = q;
267*7c478bd9Sstevel@tonic-gate 	}
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate 	/* do the link operation to delete the set */
270*7c478bd9Sstevel@tonic-gate 	prev = setp->prev;
271*7c478bd9Sstevel@tonic-gate 	next = setp->next;
272*7c478bd9Sstevel@tonic-gate 	FREE(setp);
273*7c478bd9Sstevel@tonic-gate 	if (prev)
274*7c478bd9Sstevel@tonic-gate 		prev->next = next;
275*7c478bd9Sstevel@tonic-gate 	else
276*7c478bd9Sstevel@tonic-gate 		first_set = next;
277*7c478bd9Sstevel@tonic-gate 	if (next)
278*7c478bd9Sstevel@tonic-gate 		next->prev = prev;
279*7c478bd9Sstevel@tonic-gate }
280*7c478bd9Sstevel@tonic-gate 
281*7c478bd9Sstevel@tonic-gate struct cat_msg *
new_msg(no,len,text)282*7c478bd9Sstevel@tonic-gate new_msg(no, len, text)
283*7c478bd9Sstevel@tonic-gate 	int		no;
284*7c478bd9Sstevel@tonic-gate 	int		len;
285*7c478bd9Sstevel@tonic-gate 	char	*text;
286*7c478bd9Sstevel@tonic-gate {
287*7c478bd9Sstevel@tonic-gate 	struct cat_msg	*p;
288*7c478bd9Sstevel@tonic-gate 
289*7c478bd9Sstevel@tonic-gate 	p = (struct cat_msg *) MALLOC(sizeof (struct cat_msg) + len);
290*7c478bd9Sstevel@tonic-gate 	if (p == NULL) {
291*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(6));
292*7c478bd9Sstevel@tonic-gate 		exit(1);
293*7c478bd9Sstevel@tonic-gate 	}
294*7c478bd9Sstevel@tonic-gate 	p->next = NULL;
295*7c478bd9Sstevel@tonic-gate 	p->prev = NULL;
296*7c478bd9Sstevel@tonic-gate 	p->msg_no = no;
297*7c478bd9Sstevel@tonic-gate 	p->msg_len = len;
298*7c478bd9Sstevel@tonic-gate 	MEMCPY(p->s, text, len);
299*7c478bd9Sstevel@tonic-gate 	return (p);
300*7c478bd9Sstevel@tonic-gate }
301*7c478bd9Sstevel@tonic-gate 
302*7c478bd9Sstevel@tonic-gate 
303*7c478bd9Sstevel@tonic-gate void
insert_msg(no,len,text)304*7c478bd9Sstevel@tonic-gate insert_msg(no, len, text)
305*7c478bd9Sstevel@tonic-gate 	int		no;
306*7c478bd9Sstevel@tonic-gate 	int		len;
307*7c478bd9Sstevel@tonic-gate 	char	*text;
308*7c478bd9Sstevel@tonic-gate {
309*7c478bd9Sstevel@tonic-gate 	struct cat_msg	*prev, *next;
310*7c478bd9Sstevel@tonic-gate 
311*7c478bd9Sstevel@tonic-gate 	if (current_msg == NULL) {
312*7c478bd9Sstevel@tonic-gate 		if (current_set == NULL)
313*7c478bd9Sstevel@tonic-gate 			find_set(current_set_no);
314*7c478bd9Sstevel@tonic-gate 		current_msg = current_set->first_msg;
315*7c478bd9Sstevel@tonic-gate 		if (current_msg == NULL) {
316*7c478bd9Sstevel@tonic-gate 			current_msg = new_msg(no, len, text);
317*7c478bd9Sstevel@tonic-gate 			current_set->first_msg = current_msg;
318*7c478bd9Sstevel@tonic-gate 			return;
319*7c478bd9Sstevel@tonic-gate 		}
320*7c478bd9Sstevel@tonic-gate 	}
321*7c478bd9Sstevel@tonic-gate 	if (current_msg->msg_no >= no) {
322*7c478bd9Sstevel@tonic-gate 		current_msg = current_set->first_msg;
323*7c478bd9Sstevel@tonic-gate 		if (current_msg->msg_no > no) {
324*7c478bd9Sstevel@tonic-gate 			current_msg = new_msg(no, len, text);
325*7c478bd9Sstevel@tonic-gate 			current_msg->next = current_set->first_msg;
326*7c478bd9Sstevel@tonic-gate 			current_set->first_msg->prev = current_msg;
327*7c478bd9Sstevel@tonic-gate 			current_set->first_msg = current_msg;
328*7c478bd9Sstevel@tonic-gate 			return;
329*7c478bd9Sstevel@tonic-gate 		}
330*7c478bd9Sstevel@tonic-gate 		if (current_msg->msg_no == no) {
331*7c478bd9Sstevel@tonic-gate 			current_msg = new_msg(no, len, text);
332*7c478bd9Sstevel@tonic-gate 			current_msg->next = current_set->first_msg->next;
333*7c478bd9Sstevel@tonic-gate 			if (current_set->first_msg->next)
334*7c478bd9Sstevel@tonic-gate 				current_set->first_msg->next->prev =
335*7c478bd9Sstevel@tonic-gate 					current_msg;
336*7c478bd9Sstevel@tonic-gate 			FREE(current_set->first_msg);
337*7c478bd9Sstevel@tonic-gate 			current_set->first_msg = current_msg;
338*7c478bd9Sstevel@tonic-gate 			return;
339*7c478bd9Sstevel@tonic-gate 		}
340*7c478bd9Sstevel@tonic-gate 	}
341*7c478bd9Sstevel@tonic-gate 	while (current_msg->next && current_msg->next->msg_no < no)
342*7c478bd9Sstevel@tonic-gate 		current_msg = current_msg->next;
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 	/*
345*7c478bd9Sstevel@tonic-gate 	 * if the same msg number is found, then delte the message and
346*7c478bd9Sstevel@tonic-gate 	 * insert the new message. This is same as replacing message.
347*7c478bd9Sstevel@tonic-gate 	 */
348*7c478bd9Sstevel@tonic-gate 	if (current_msg->next && current_msg->next->msg_no == no) {
349*7c478bd9Sstevel@tonic-gate 		current_msg = current_msg->next;
350*7c478bd9Sstevel@tonic-gate 		prev = current_msg->prev;
351*7c478bd9Sstevel@tonic-gate 		next = current_msg->next;
352*7c478bd9Sstevel@tonic-gate 		FREE(current_msg);
353*7c478bd9Sstevel@tonic-gate 	} else {
354*7c478bd9Sstevel@tonic-gate 		prev = current_msg;
355*7c478bd9Sstevel@tonic-gate 		next = current_msg->next;
356*7c478bd9Sstevel@tonic-gate 	}
357*7c478bd9Sstevel@tonic-gate 
358*7c478bd9Sstevel@tonic-gate 	current_msg = new_msg(no, len, text);
359*7c478bd9Sstevel@tonic-gate 	current_msg->prev = prev;
360*7c478bd9Sstevel@tonic-gate 	current_msg->next = next;
361*7c478bd9Sstevel@tonic-gate 	if (prev)
362*7c478bd9Sstevel@tonic-gate 		prev->next = current_msg;
363*7c478bd9Sstevel@tonic-gate 	else
364*7c478bd9Sstevel@tonic-gate 		current_set->first_msg = current_msg;
365*7c478bd9Sstevel@tonic-gate 	if (next)
366*7c478bd9Sstevel@tonic-gate 		next->prev = current_msg;
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate void
delete_msg(no)370*7c478bd9Sstevel@tonic-gate delete_msg(no)
371*7c478bd9Sstevel@tonic-gate 	int		no;
372*7c478bd9Sstevel@tonic-gate {
373*7c478bd9Sstevel@tonic-gate 	struct cat_set	*p = current_set;
374*7c478bd9Sstevel@tonic-gate 	struct cat_msg	*prev, *next;
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	if (current_msg == NULL) {
377*7c478bd9Sstevel@tonic-gate 		if (current_set == NULL)
378*7c478bd9Sstevel@tonic-gate 			for (p = first_set; p && p->set_no < current_set_no;
379*7c478bd9Sstevel@tonic-gate 							p = p->next)
380*7c478bd9Sstevel@tonic-gate 				continue;
381*7c478bd9Sstevel@tonic-gate 		if (p == NULL || p->set_no != current_set_no)
382*7c478bd9Sstevel@tonic-gate 			return;
383*7c478bd9Sstevel@tonic-gate 		current_set = p;
384*7c478bd9Sstevel@tonic-gate 		current_msg = current_set->first_msg;
385*7c478bd9Sstevel@tonic-gate 		if (current_msg == NULL)
386*7c478bd9Sstevel@tonic-gate 			return;
387*7c478bd9Sstevel@tonic-gate 	}
388*7c478bd9Sstevel@tonic-gate 	if (current_msg->msg_no > no)
389*7c478bd9Sstevel@tonic-gate 		current_msg = current_set->first_msg;
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 	while (current_msg && current_msg->msg_no != no)
392*7c478bd9Sstevel@tonic-gate 		current_msg = current_msg->next;
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 	if (current_msg && current_msg->msg_no == no) {
395*7c478bd9Sstevel@tonic-gate 		prev = current_msg->prev;
396*7c478bd9Sstevel@tonic-gate 		next = current_msg->next;
397*7c478bd9Sstevel@tonic-gate 		FREE(current_msg);
398*7c478bd9Sstevel@tonic-gate 		if (prev) {
399*7c478bd9Sstevel@tonic-gate 			current_msg = prev;
400*7c478bd9Sstevel@tonic-gate 			prev->next = next;
401*7c478bd9Sstevel@tonic-gate 		} else {
402*7c478bd9Sstevel@tonic-gate 			current_set->first_msg = next;
403*7c478bd9Sstevel@tonic-gate 			current_msg = next;
404*7c478bd9Sstevel@tonic-gate 		}
405*7c478bd9Sstevel@tonic-gate 		if (next)
406*7c478bd9Sstevel@tonic-gate 			next->prev = prev;
407*7c478bd9Sstevel@tonic-gate 	}
408*7c478bd9Sstevel@tonic-gate }
409*7c478bd9Sstevel@tonic-gate 
410*7c478bd9Sstevel@tonic-gate int
read_block(fd,p,n,pathname)411*7c478bd9Sstevel@tonic-gate read_block(fd, p, n, pathname)
412*7c478bd9Sstevel@tonic-gate 	int		fd;
413*7c478bd9Sstevel@tonic-gate 	char	*p;
414*7c478bd9Sstevel@tonic-gate 	int		n;
415*7c478bd9Sstevel@tonic-gate 	char	*pathname;
416*7c478bd9Sstevel@tonic-gate {
417*7c478bd9Sstevel@tonic-gate 	int		nbytes, bytes_read;
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate 	if (n == 0)
420*7c478bd9Sstevel@tonic-gate 		return (0);
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	nbytes = 0;
423*7c478bd9Sstevel@tonic-gate 	while (nbytes < n) {
424*7c478bd9Sstevel@tonic-gate 		bytes_read = READ(fd, p + nbytes, n - nbytes);
425*7c478bd9Sstevel@tonic-gate 		if (bytes_read < 0) {
426*7c478bd9Sstevel@tonic-gate 			if (errno != EINTR) {
427*7c478bd9Sstevel@tonic-gate 				FPRINTF(stderr, MSG(3), pathname);
428*7c478bd9Sstevel@tonic-gate 				perror("");
429*7c478bd9Sstevel@tonic-gate 				exit(1);
430*7c478bd9Sstevel@tonic-gate 			}
431*7c478bd9Sstevel@tonic-gate 		} else if (bytes_read == 0)
432*7c478bd9Sstevel@tonic-gate 			break;
433*7c478bd9Sstevel@tonic-gate 		else
434*7c478bd9Sstevel@tonic-gate 			nbytes += bytes_read;
435*7c478bd9Sstevel@tonic-gate 	}
436*7c478bd9Sstevel@tonic-gate 
437*7c478bd9Sstevel@tonic-gate 	return (nbytes);
438*7c478bd9Sstevel@tonic-gate }
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate /*
441*7c478bd9Sstevel@tonic-gate  * Check if catalog file read is valid
442*7c478bd9Sstevel@tonic-gate  *
443*7c478bd9Sstevel@tonic-gate  */
444*7c478bd9Sstevel@tonic-gate int
cat_ok(cat)445*7c478bd9Sstevel@tonic-gate cat_ok(cat)
446*7c478bd9Sstevel@tonic-gate 	char	*cat;
447*7c478bd9Sstevel@tonic-gate {
448*7c478bd9Sstevel@tonic-gate 	int		i, j;
449*7c478bd9Sstevel@tonic-gate 	int		nmsgs;
450*7c478bd9Sstevel@tonic-gate 	int		msg_no;
451*7c478bd9Sstevel@tonic-gate 	struct	_cat_msg_hdr	*msg;
452*7c478bd9Sstevel@tonic-gate 	int		set_no;
453*7c478bd9Sstevel@tonic-gate 	int		first_msg_hdr;
454*7c478bd9Sstevel@tonic-gate 	struct	_cat_set_hdr	*set;
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate 	set = (struct _cat_set_hdr *) cat;
457*7c478bd9Sstevel@tonic-gate 	set_no = 0;
458*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < hdr.__nsets; ++set, ++i) {
459*7c478bd9Sstevel@tonic-gate 		if (set->__set_no < set_no)
460*7c478bd9Sstevel@tonic-gate 			return (0);
461*7c478bd9Sstevel@tonic-gate 		set_no = set->__set_no;
462*7c478bd9Sstevel@tonic-gate 		nmsgs = set->__nmsgs;
463*7c478bd9Sstevel@tonic-gate 		if (nmsgs < 0)
464*7c478bd9Sstevel@tonic-gate 			return (0);
465*7c478bd9Sstevel@tonic-gate 		if (nmsgs == 0)
466*7c478bd9Sstevel@tonic-gate 			continue;
467*7c478bd9Sstevel@tonic-gate 		first_msg_hdr = set->__first_msg_hdr;
468*7c478bd9Sstevel@tonic-gate 		if (first_msg_hdr < 0)
469*7c478bd9Sstevel@tonic-gate 			return (0);
470*7c478bd9Sstevel@tonic-gate 		if (hdr.__msg_hdr_offset + (first_msg_hdr + nmsgs) *
471*7c478bd9Sstevel@tonic-gate 					_CAT_MSG_HDR_SIZE > hdr.__mem)
472*7c478bd9Sstevel@tonic-gate 			return (0);
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 		msg = (struct _cat_msg_hdr *) (cat + hdr.__msg_hdr_offset) +
475*7c478bd9Sstevel@tonic-gate 						first_msg_hdr;
476*7c478bd9Sstevel@tonic-gate 		msg_no = 0;
477*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < nmsgs; ++msg, ++j) {
478*7c478bd9Sstevel@tonic-gate 			if (msg->__msg_no < msg_no)
479*7c478bd9Sstevel@tonic-gate 				return (0);
480*7c478bd9Sstevel@tonic-gate 			msg_no = msg->__msg_no;
481*7c478bd9Sstevel@tonic-gate 			if (msg->__msg_offset < 0)
482*7c478bd9Sstevel@tonic-gate 				return (0);
483*7c478bd9Sstevel@tonic-gate 			if (hdr.__msg_text_offset + msg->__msg_offset +
484*7c478bd9Sstevel@tonic-gate 						msg->__msg_len > hdr.__mem)
485*7c478bd9Sstevel@tonic-gate 				return (0);
486*7c478bd9Sstevel@tonic-gate 		}
487*7c478bd9Sstevel@tonic-gate 	}
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate 	return (1);
490*7c478bd9Sstevel@tonic-gate }
491*7c478bd9Sstevel@tonic-gate 
492*7c478bd9Sstevel@tonic-gate /*
493*7c478bd9Sstevel@tonic-gate  * convert a chunk of catalog file into double linked list format
494*7c478bd9Sstevel@tonic-gate  */
495*7c478bd9Sstevel@tonic-gate void
initcat(cat)496*7c478bd9Sstevel@tonic-gate initcat(cat)
497*7c478bd9Sstevel@tonic-gate 	char	*cat;
498*7c478bd9Sstevel@tonic-gate {
499*7c478bd9Sstevel@tonic-gate 	int		i, j;
500*7c478bd9Sstevel@tonic-gate 	int		nmsgs;
501*7c478bd9Sstevel@tonic-gate 	struct	_cat_set_hdr	*set;
502*7c478bd9Sstevel@tonic-gate 	struct	_cat_msg_hdr	*msg;
503*7c478bd9Sstevel@tonic-gate 
504*7c478bd9Sstevel@tonic-gate 	set = (struct _cat_set_hdr *) cat;
505*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < hdr.__nsets; ++set, ++i) {
506*7c478bd9Sstevel@tonic-gate 		nmsgs = set->__nmsgs;
507*7c478bd9Sstevel@tonic-gate 		if (nmsgs == 0)
508*7c478bd9Sstevel@tonic-gate 			continue;
509*7c478bd9Sstevel@tonic-gate 		find_set(set->__set_no);
510*7c478bd9Sstevel@tonic-gate 		msg = (struct _cat_msg_hdr *) (cat + hdr.__msg_hdr_offset)
511*7c478bd9Sstevel@tonic-gate 			+ set->__first_msg_hdr;
512*7c478bd9Sstevel@tonic-gate 		current_msg = current_set->first_msg;
513*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < nmsgs; ++msg, ++j) {
514*7c478bd9Sstevel@tonic-gate 			insert_msg(msg->__msg_no, msg->__msg_len,
515*7c478bd9Sstevel@tonic-gate 			    cat + hdr.__msg_text_offset + msg->__msg_offset);
516*7c478bd9Sstevel@tonic-gate 		}
517*7c478bd9Sstevel@tonic-gate 	}
518*7c478bd9Sstevel@tonic-gate }
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate /*
521*7c478bd9Sstevel@tonic-gate  * read a catalog file in a chunk and convert it to double linked list.
522*7c478bd9Sstevel@tonic-gate  */
523*7c478bd9Sstevel@tonic-gate void
readcat(fd,pathname)524*7c478bd9Sstevel@tonic-gate readcat(fd, pathname)
525*7c478bd9Sstevel@tonic-gate 	int		fd;
526*7c478bd9Sstevel@tonic-gate 	char	*pathname;
527*7c478bd9Sstevel@tonic-gate {
528*7c478bd9Sstevel@tonic-gate 	int		i;
529*7c478bd9Sstevel@tonic-gate 	char	*cat;
530*7c478bd9Sstevel@tonic-gate 
531*7c478bd9Sstevel@tonic-gate 	i = read_block(fd, (char *) &hdr, _CAT_HDR_SIZE, pathname);
532*7c478bd9Sstevel@tonic-gate 	if (i == 0)
533*7c478bd9Sstevel@tonic-gate 		return;
534*7c478bd9Sstevel@tonic-gate 
535*7c478bd9Sstevel@tonic-gate 	if (i >= 4 && hdr.__hdr_magic != _CAT_MAGIC) {
536*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(4), hdr.__hdr_magic);
537*7c478bd9Sstevel@tonic-gate 		exit(1);
538*7c478bd9Sstevel@tonic-gate 	}
539*7c478bd9Sstevel@tonic-gate 	if (i < _CAT_HDR_SIZE || hdr.__nsets < 0) {
540*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(5), pathname);
541*7c478bd9Sstevel@tonic-gate 		exit(1);
542*7c478bd9Sstevel@tonic-gate 	}
543*7c478bd9Sstevel@tonic-gate 	if (hdr.__nsets == 0)
544*7c478bd9Sstevel@tonic-gate 		return;
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate 	if (hdr.__mem < 0 ||
547*7c478bd9Sstevel@tonic-gate 	    hdr.__msg_hdr_offset < 0 ||
548*7c478bd9Sstevel@tonic-gate 	    hdr.__msg_text_offset < 0 ||
549*7c478bd9Sstevel@tonic-gate 	    hdr.__mem < hdr.__nsets * _CAT_SET_HDR_SIZE ||
550*7c478bd9Sstevel@tonic-gate 	    hdr.__mem < hdr.__msg_hdr_offset ||
551*7c478bd9Sstevel@tonic-gate 	    hdr.__mem < hdr.__msg_text_offset) {
552*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(5), pathname);
553*7c478bd9Sstevel@tonic-gate 		exit(1);
554*7c478bd9Sstevel@tonic-gate 	}
555*7c478bd9Sstevel@tonic-gate 	cat = MALLOC(hdr.__mem);
556*7c478bd9Sstevel@tonic-gate 	if (cat == NULL) {
557*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(6));
558*7c478bd9Sstevel@tonic-gate 		exit(1);
559*7c478bd9Sstevel@tonic-gate 	}
560*7c478bd9Sstevel@tonic-gate 	i = read_block(fd, cat, hdr.__mem, pathname);
561*7c478bd9Sstevel@tonic-gate 	if (i < hdr.__mem || !cat_ok(cat)) {
562*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(5), pathname);
563*7c478bd9Sstevel@tonic-gate 		exit(1);
564*7c478bd9Sstevel@tonic-gate 	}
565*7c478bd9Sstevel@tonic-gate 	initcat(cat);
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	FREE(cat);
568*7c478bd9Sstevel@tonic-gate }
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate /*
571*7c478bd9Sstevel@tonic-gate  * Extend the memory in 1000 byte chunks whenever runs out of text space.
572*7c478bd9Sstevel@tonic-gate  */
573*7c478bd9Sstevel@tonic-gate void
extend_text()574*7c478bd9Sstevel@tonic-gate extend_text()
575*7c478bd9Sstevel@tonic-gate {
576*7c478bd9Sstevel@tonic-gate 	text_size += 1000;
577*7c478bd9Sstevel@tonic-gate 	if (text)
578*7c478bd9Sstevel@tonic-gate 		text = REALLOC(text, text_size);
579*7c478bd9Sstevel@tonic-gate 	else
580*7c478bd9Sstevel@tonic-gate 		text = MALLOC(text_size);
581*7c478bd9Sstevel@tonic-gate 	if (text == NULL) {
582*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(6));
583*7c478bd9Sstevel@tonic-gate 		exit(1);
584*7c478bd9Sstevel@tonic-gate 	}
585*7c478bd9Sstevel@tonic-gate }
586*7c478bd9Sstevel@tonic-gate 
587*7c478bd9Sstevel@tonic-gate int
get_number(fp,c)588*7c478bd9Sstevel@tonic-gate get_number(fp, c)
589*7c478bd9Sstevel@tonic-gate 	FILE	*fp;
590*7c478bd9Sstevel@tonic-gate 	int		c;
591*7c478bd9Sstevel@tonic-gate {
592*7c478bd9Sstevel@tonic-gate 	int		i, n;
593*7c478bd9Sstevel@tonic-gate 	char	*s, *t;
594*7c478bd9Sstevel@tonic-gate 
595*7c478bd9Sstevel@tonic-gate 	i = 0;
596*7c478bd9Sstevel@tonic-gate 	do {
597*7c478bd9Sstevel@tonic-gate 		while (i >= text_size)
598*7c478bd9Sstevel@tonic-gate 			extend_text();
599*7c478bd9Sstevel@tonic-gate 		text[i] = c;
600*7c478bd9Sstevel@tonic-gate 		++i;
601*7c478bd9Sstevel@tonic-gate 		c = getc(fp);
602*7c478bd9Sstevel@tonic-gate 	}
603*7c478bd9Sstevel@tonic-gate 	while (isdigit(c));
604*7c478bd9Sstevel@tonic-gate 	(void) ungetc(c, fp);
605*7c478bd9Sstevel@tonic-gate 
606*7c478bd9Sstevel@tonic-gate 	while (i >= text_size)
607*7c478bd9Sstevel@tonic-gate 		extend_text();
608*7c478bd9Sstevel@tonic-gate 	text[i] = NUL;
609*7c478bd9Sstevel@tonic-gate 
610*7c478bd9Sstevel@tonic-gate 	for (s = text; *s == '0'; ++s)
611*7c478bd9Sstevel@tonic-gate 		continue;
612*7c478bd9Sstevel@tonic-gate 
613*7c478bd9Sstevel@tonic-gate 	n = 0;
614*7c478bd9Sstevel@tonic-gate 	for (t = s; isdigit(*t); ++t) {
615*7c478bd9Sstevel@tonic-gate 		if (n > INT_MAX / 10 ||
616*7c478bd9Sstevel@tonic-gate 			(n == INT_MAX / 10 && *t > '0' + INT_MAX % 10)) {
617*7c478bd9Sstevel@tonic-gate 			FPRINTF(stderr, MSG(9), msgfname, lineno, s);
618*7c478bd9Sstevel@tonic-gate 			exit(1);
619*7c478bd9Sstevel@tonic-gate 		}
620*7c478bd9Sstevel@tonic-gate 		n = 10 * n + (*t - '0');
621*7c478bd9Sstevel@tonic-gate 	}
622*7c478bd9Sstevel@tonic-gate 
623*7c478bd9Sstevel@tonic-gate 	return (n);
624*7c478bd9Sstevel@tonic-gate }
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate void
get_text(fp)627*7c478bd9Sstevel@tonic-gate get_text(fp)
628*7c478bd9Sstevel@tonic-gate 	FILE	*fp;
629*7c478bd9Sstevel@tonic-gate {
630*7c478bd9Sstevel@tonic-gate 	int		c;
631*7c478bd9Sstevel@tonic-gate 	int		n;
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate 	text_len = 0;
634*7c478bd9Sstevel@tonic-gate 	c = fgetwc(fp);
635*7c478bd9Sstevel@tonic-gate 	if (quoting && c == quote) {	/* quote is used */
636*7c478bd9Sstevel@tonic-gate 		c = fgetwc(fp);
637*7c478bd9Sstevel@tonic-gate 		while (c != quote) {
638*7c478bd9Sstevel@tonic-gate 			if (c == NEWLINE || c == EOF) {
639*7c478bd9Sstevel@tonic-gate 				FPRINTF(stderr, MSG(12), msgfname, lineno,
640*7c478bd9Sstevel@tonic-gate 								quote);
641*7c478bd9Sstevel@tonic-gate 				exit(1);
642*7c478bd9Sstevel@tonic-gate 			}
643*7c478bd9Sstevel@tonic-gate 			if (c == REVERSE_SOLIDUS) {
644*7c478bd9Sstevel@tonic-gate 				c = fgetwc(fp);
645*7c478bd9Sstevel@tonic-gate 				switch (c) {
646*7c478bd9Sstevel@tonic-gate 				case EOF:
647*7c478bd9Sstevel@tonic-gate 					FPRINTF(stderr, MSG(12), msgfname,
648*7c478bd9Sstevel@tonic-gate 						lineno, quote);
649*7c478bd9Sstevel@tonic-gate 					exit(1);
650*7c478bd9Sstevel@tonic-gate 					break;
651*7c478bd9Sstevel@tonic-gate 				case NEWLINE:
652*7c478bd9Sstevel@tonic-gate 					++lineno;
653*7c478bd9Sstevel@tonic-gate 					c = fgetwc(fp);
654*7c478bd9Sstevel@tonic-gate 					continue;
655*7c478bd9Sstevel@tonic-gate 					/* NOTREACHED */
656*7c478bd9Sstevel@tonic-gate 					break;
657*7c478bd9Sstevel@tonic-gate 				case '0':
658*7c478bd9Sstevel@tonic-gate 				case '1':
659*7c478bd9Sstevel@tonic-gate 				case '2':
660*7c478bd9Sstevel@tonic-gate 				case '3':
661*7c478bd9Sstevel@tonic-gate 				case '4':
662*7c478bd9Sstevel@tonic-gate 				case '5':
663*7c478bd9Sstevel@tonic-gate 				case '6':
664*7c478bd9Sstevel@tonic-gate 				case '7':
665*7c478bd9Sstevel@tonic-gate 					n = (c - '0');
666*7c478bd9Sstevel@tonic-gate 					c = fgetwc(fp);
667*7c478bd9Sstevel@tonic-gate 					if (c >= '0' && c <= '7') {
668*7c478bd9Sstevel@tonic-gate 						n = 8 * n + (c - '0');
669*7c478bd9Sstevel@tonic-gate 						c = fgetwc(fp);
670*7c478bd9Sstevel@tonic-gate 						if (c >= '0' && c <= '7')
671*7c478bd9Sstevel@tonic-gate 							n = 8 * n + (c - '0');
672*7c478bd9Sstevel@tonic-gate 						else
673*7c478bd9Sstevel@tonic-gate 							(void) ungetwc(c, fp);
674*7c478bd9Sstevel@tonic-gate 					} else
675*7c478bd9Sstevel@tonic-gate 						(void) ungetwc(c, fp);
676*7c478bd9Sstevel@tonic-gate 					if (n > UCHAR_MAX) {
677*7c478bd9Sstevel@tonic-gate 						FPRINTF(stderr, MSG(13),
678*7c478bd9Sstevel@tonic-gate 							msgfname, lineno, n);
679*7c478bd9Sstevel@tonic-gate 						exit(1);
680*7c478bd9Sstevel@tonic-gate 					}
681*7c478bd9Sstevel@tonic-gate 					c = n;
682*7c478bd9Sstevel@tonic-gate 					break;
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 				case 'n':
685*7c478bd9Sstevel@tonic-gate 					c = NEWLINE;
686*7c478bd9Sstevel@tonic-gate 					break;
687*7c478bd9Sstevel@tonic-gate 
688*7c478bd9Sstevel@tonic-gate 				case 't':
689*7c478bd9Sstevel@tonic-gate 					c = TAB;
690*7c478bd9Sstevel@tonic-gate 					break;
691*7c478bd9Sstevel@tonic-gate 
692*7c478bd9Sstevel@tonic-gate 				case 'v':
693*7c478bd9Sstevel@tonic-gate 					c = VTAB;
694*7c478bd9Sstevel@tonic-gate 					break;
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 				case 'b':
697*7c478bd9Sstevel@tonic-gate 					c = BS;
698*7c478bd9Sstevel@tonic-gate 					break;
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate 				case 'r':
701*7c478bd9Sstevel@tonic-gate 					c = CR;
702*7c478bd9Sstevel@tonic-gate 					break;
703*7c478bd9Sstevel@tonic-gate 
704*7c478bd9Sstevel@tonic-gate 				case 'f':
705*7c478bd9Sstevel@tonic-gate 					c = FF;
706*7c478bd9Sstevel@tonic-gate 					break;
707*7c478bd9Sstevel@tonic-gate 				}
708*7c478bd9Sstevel@tonic-gate 			}
709*7c478bd9Sstevel@tonic-gate 			while ((text_len + (int)MB_CUR_MAX + 1) >= text_size)
710*7c478bd9Sstevel@tonic-gate 				extend_text();
711*7c478bd9Sstevel@tonic-gate 			if ((n = wctomb(&text[text_len], c)) > 0)
712*7c478bd9Sstevel@tonic-gate 				text_len += n;
713*7c478bd9Sstevel@tonic-gate 			c = fgetwc(fp);
714*7c478bd9Sstevel@tonic-gate 		}
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 		while ((text_len + 1) >= text_size)
717*7c478bd9Sstevel@tonic-gate 			extend_text();
718*7c478bd9Sstevel@tonic-gate 		text[text_len] = '\0';
719*7c478bd9Sstevel@tonic-gate 		++text_len;
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 		do {
722*7c478bd9Sstevel@tonic-gate 			c = getc(fp);
723*7c478bd9Sstevel@tonic-gate 		} while (c == SPACE || c == TAB);
724*7c478bd9Sstevel@tonic-gate 		if (c == NEWLINE) {
725*7c478bd9Sstevel@tonic-gate 			++lineno;
726*7c478bd9Sstevel@tonic-gate 			return;
727*7c478bd9Sstevel@tonic-gate 		}
728*7c478bd9Sstevel@tonic-gate 		if (c == EOF) {
729*7c478bd9Sstevel@tonic-gate 			ateof = 1;
730*7c478bd9Sstevel@tonic-gate 			return;
731*7c478bd9Sstevel@tonic-gate 		}
732*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(14), msgfname, lineno);
733*7c478bd9Sstevel@tonic-gate 		exit(1);
734*7c478bd9Sstevel@tonic-gate 	}
735*7c478bd9Sstevel@tonic-gate 
736*7c478bd9Sstevel@tonic-gate 	while (c != NEWLINE && c != EOF) {	/* quote is not used */
737*7c478bd9Sstevel@tonic-gate 		if (c == REVERSE_SOLIDUS) {
738*7c478bd9Sstevel@tonic-gate 			c = fgetwc(fp);
739*7c478bd9Sstevel@tonic-gate 			switch (c) {
740*7c478bd9Sstevel@tonic-gate 			case EOF:
741*7c478bd9Sstevel@tonic-gate 				return;
742*7c478bd9Sstevel@tonic-gate 
743*7c478bd9Sstevel@tonic-gate 			case NEWLINE:
744*7c478bd9Sstevel@tonic-gate 				++lineno;
745*7c478bd9Sstevel@tonic-gate 				c = fgetwc(fp);
746*7c478bd9Sstevel@tonic-gate 				continue;
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 			case '0':
749*7c478bd9Sstevel@tonic-gate 			case '1':
750*7c478bd9Sstevel@tonic-gate 			case '2':
751*7c478bd9Sstevel@tonic-gate 			case '3':
752*7c478bd9Sstevel@tonic-gate 			case '4':
753*7c478bd9Sstevel@tonic-gate 			case '5':
754*7c478bd9Sstevel@tonic-gate 			case '6':
755*7c478bd9Sstevel@tonic-gate 			case '7':
756*7c478bd9Sstevel@tonic-gate 				n = (c - '0');
757*7c478bd9Sstevel@tonic-gate 				c = fgetwc(fp);
758*7c478bd9Sstevel@tonic-gate 				if (c >= '0' && c <= '7') {
759*7c478bd9Sstevel@tonic-gate 					n = 8 * n + (c - '0');
760*7c478bd9Sstevel@tonic-gate 					c = fgetwc(fp);
761*7c478bd9Sstevel@tonic-gate 					if (c >= '0' && c <= '7')
762*7c478bd9Sstevel@tonic-gate 						n = 8 * n + (c - '0');
763*7c478bd9Sstevel@tonic-gate 					else
764*7c478bd9Sstevel@tonic-gate 						(void) ungetwc(c, fp);
765*7c478bd9Sstevel@tonic-gate 				} else
766*7c478bd9Sstevel@tonic-gate 					(void) ungetwc(c, fp);
767*7c478bd9Sstevel@tonic-gate 				if (n > UCHAR_MAX) {
768*7c478bd9Sstevel@tonic-gate 					FPRINTF(stderr, MSG(13), msgfname,
769*7c478bd9Sstevel@tonic-gate 							lineno, n);
770*7c478bd9Sstevel@tonic-gate 					exit(1);
771*7c478bd9Sstevel@tonic-gate 				}
772*7c478bd9Sstevel@tonic-gate 				c = n;
773*7c478bd9Sstevel@tonic-gate 				break;
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate 			case 'n':
776*7c478bd9Sstevel@tonic-gate 				c = NEWLINE;
777*7c478bd9Sstevel@tonic-gate 				break;
778*7c478bd9Sstevel@tonic-gate 
779*7c478bd9Sstevel@tonic-gate 			case 't':
780*7c478bd9Sstevel@tonic-gate 				c = TAB;
781*7c478bd9Sstevel@tonic-gate 				break;
782*7c478bd9Sstevel@tonic-gate 
783*7c478bd9Sstevel@tonic-gate 			case 'v':
784*7c478bd9Sstevel@tonic-gate 				c = VTAB;
785*7c478bd9Sstevel@tonic-gate 				break;
786*7c478bd9Sstevel@tonic-gate 
787*7c478bd9Sstevel@tonic-gate 			case 'b':
788*7c478bd9Sstevel@tonic-gate 				c = BS;
789*7c478bd9Sstevel@tonic-gate 				break;
790*7c478bd9Sstevel@tonic-gate 
791*7c478bd9Sstevel@tonic-gate 			case 'r':
792*7c478bd9Sstevel@tonic-gate 				c = CR;
793*7c478bd9Sstevel@tonic-gate 				break;
794*7c478bd9Sstevel@tonic-gate 
795*7c478bd9Sstevel@tonic-gate 			case 'f':
796*7c478bd9Sstevel@tonic-gate 				c = FF;
797*7c478bd9Sstevel@tonic-gate 				break;
798*7c478bd9Sstevel@tonic-gate 			}
799*7c478bd9Sstevel@tonic-gate 		}
800*7c478bd9Sstevel@tonic-gate 		while ((text_len + (int)MB_CUR_MAX + 1) >= text_size)
801*7c478bd9Sstevel@tonic-gate 			extend_text();
802*7c478bd9Sstevel@tonic-gate 		if ((n = wctomb(&text[text_len], c)) > 0)
803*7c478bd9Sstevel@tonic-gate 			text_len += n;
804*7c478bd9Sstevel@tonic-gate 		c = fgetwc(fp);
805*7c478bd9Sstevel@tonic-gate 	}
806*7c478bd9Sstevel@tonic-gate 
807*7c478bd9Sstevel@tonic-gate 	while ((text_len + 1) >= text_size)
808*7c478bd9Sstevel@tonic-gate 		extend_text();
809*7c478bd9Sstevel@tonic-gate 	text[text_len] = '\0';
810*7c478bd9Sstevel@tonic-gate 	++text_len;
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate 	if (c == NEWLINE)
813*7c478bd9Sstevel@tonic-gate 		++lineno;
814*7c478bd9Sstevel@tonic-gate 	else
815*7c478bd9Sstevel@tonic-gate 		ateof = 1;
816*7c478bd9Sstevel@tonic-gate }
817*7c478bd9Sstevel@tonic-gate 
818*7c478bd9Sstevel@tonic-gate /*
819*7c478bd9Sstevel@tonic-gate  * This routine handles $ <comment>, $set, $delset, $quote
820*7c478bd9Sstevel@tonic-gate  */
821*7c478bd9Sstevel@tonic-gate void
directive(fp)822*7c478bd9Sstevel@tonic-gate directive(fp)
823*7c478bd9Sstevel@tonic-gate 	FILE	*fp;
824*7c478bd9Sstevel@tonic-gate {
825*7c478bd9Sstevel@tonic-gate 	int		c;
826*7c478bd9Sstevel@tonic-gate 	int		n;
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate 	c = fgetwc(fp);
829*7c478bd9Sstevel@tonic-gate 	if (c == SPACE || c == TAB) {	/* $ <comment */
830*7c478bd9Sstevel@tonic-gate 		do {
831*7c478bd9Sstevel@tonic-gate 			c = fgetwc(fp);
832*7c478bd9Sstevel@tonic-gate 		} while (c != NEWLINE && c != EOF);
833*7c478bd9Sstevel@tonic-gate 	}
834*7c478bd9Sstevel@tonic-gate 	if (c == NEWLINE) {
835*7c478bd9Sstevel@tonic-gate 		++lineno;
836*7c478bd9Sstevel@tonic-gate 		return;
837*7c478bd9Sstevel@tonic-gate 	}
838*7c478bd9Sstevel@tonic-gate 	if (c == EOF) {
839*7c478bd9Sstevel@tonic-gate 		ateof = 1;
840*7c478bd9Sstevel@tonic-gate 		return;
841*7c478bd9Sstevel@tonic-gate 	}
842*7c478bd9Sstevel@tonic-gate 	text_len = 1;
843*7c478bd9Sstevel@tonic-gate 	while (text_len >= text_size)
844*7c478bd9Sstevel@tonic-gate 		extend_text();
845*7c478bd9Sstevel@tonic-gate 	text[0] = DOLLAR;
846*7c478bd9Sstevel@tonic-gate 	while (isascii(c) && isalpha(c)) {
847*7c478bd9Sstevel@tonic-gate 		while ((text_len + 1) >= text_size)
848*7c478bd9Sstevel@tonic-gate 			extend_text();
849*7c478bd9Sstevel@tonic-gate 		text[text_len] = c;
850*7c478bd9Sstevel@tonic-gate 		++text_len;
851*7c478bd9Sstevel@tonic-gate 		c = fgetwc(fp);
852*7c478bd9Sstevel@tonic-gate 	}
853*7c478bd9Sstevel@tonic-gate 
854*7c478bd9Sstevel@tonic-gate 	while ((text_len + 1) >= text_size)
855*7c478bd9Sstevel@tonic-gate 		extend_text();
856*7c478bd9Sstevel@tonic-gate 	text[text_len] = NUL;
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 	if (strcmp(text, "$set") == 0) {
859*7c478bd9Sstevel@tonic-gate 		while (c == SPACE || c == TAB)
860*7c478bd9Sstevel@tonic-gate 			c = fgetwc(fp);
861*7c478bd9Sstevel@tonic-gate 		if (!isascii(c) || !isdigit(c)) {
862*7c478bd9Sstevel@tonic-gate 			FPRINTF(stderr, MSG(16), msgfname, lineno);
863*7c478bd9Sstevel@tonic-gate 			exit(1);
864*7c478bd9Sstevel@tonic-gate 		}
865*7c478bd9Sstevel@tonic-gate 		n = get_number(fp, c);
866*7c478bd9Sstevel@tonic-gate 		if (n == 0) {
867*7c478bd9Sstevel@tonic-gate 			FPRINTF(stderr, MSG(17), msgfname, lineno);
868*7c478bd9Sstevel@tonic-gate 			exit(1);
869*7c478bd9Sstevel@tonic-gate 		}
870*7c478bd9Sstevel@tonic-gate 		if (n > NL_SETMAX) {
871*7c478bd9Sstevel@tonic-gate 			FPRINTF(stderr, MSG(18), msgfname, lineno,
872*7c478bd9Sstevel@tonic-gate 						n, NL_SETMAX);
873*7c478bd9Sstevel@tonic-gate 		}
874*7c478bd9Sstevel@tonic-gate 		find_set(n);
875*7c478bd9Sstevel@tonic-gate 		do {	/* skip comment */
876*7c478bd9Sstevel@tonic-gate 			c = getc(fp);
877*7c478bd9Sstevel@tonic-gate 		} while (c != NEWLINE && c != EOF);
878*7c478bd9Sstevel@tonic-gate 		if (c == NEWLINE)
879*7c478bd9Sstevel@tonic-gate 			++lineno;
880*7c478bd9Sstevel@tonic-gate 		else
881*7c478bd9Sstevel@tonic-gate 			ateof = 1;
882*7c478bd9Sstevel@tonic-gate 		return;
883*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(text, "$delset") == 0) {
884*7c478bd9Sstevel@tonic-gate 		while (c == SPACE || c == TAB)
885*7c478bd9Sstevel@tonic-gate 			c = fgetwc(fp);
886*7c478bd9Sstevel@tonic-gate 		if (!isascii(c) || !isdigit(c)) {
887*7c478bd9Sstevel@tonic-gate 			FPRINTF(stderr, MSG(20), msgfname, lineno);
888*7c478bd9Sstevel@tonic-gate 			exit(1);
889*7c478bd9Sstevel@tonic-gate 		}
890*7c478bd9Sstevel@tonic-gate 		n = get_number(fp, c);
891*7c478bd9Sstevel@tonic-gate 		if (n == 0) {
892*7c478bd9Sstevel@tonic-gate 			FPRINTF(stderr, MSG(17), msgfname, lineno);
893*7c478bd9Sstevel@tonic-gate 			exit(1);
894*7c478bd9Sstevel@tonic-gate 		}
895*7c478bd9Sstevel@tonic-gate 		if (n > NL_SETMAX) {
896*7c478bd9Sstevel@tonic-gate 			FPRINTF(stderr, MSG(18), msgfname, lineno,
897*7c478bd9Sstevel@tonic-gate 						n, NL_SETMAX);
898*7c478bd9Sstevel@tonic-gate 		}
899*7c478bd9Sstevel@tonic-gate 		delete_set(n);
900*7c478bd9Sstevel@tonic-gate 		do {	/* skip comment */
901*7c478bd9Sstevel@tonic-gate 			c = getc(fp);
902*7c478bd9Sstevel@tonic-gate 		} while (c != NEWLINE && c != EOF);
903*7c478bd9Sstevel@tonic-gate 		if (c == NEWLINE)
904*7c478bd9Sstevel@tonic-gate 			++lineno;
905*7c478bd9Sstevel@tonic-gate 		else
906*7c478bd9Sstevel@tonic-gate 			ateof = 1;
907*7c478bd9Sstevel@tonic-gate 		return;
908*7c478bd9Sstevel@tonic-gate 	} else if (strcmp(text, "$quote") == 0) {
909*7c478bd9Sstevel@tonic-gate 		if (c == NEWLINE) {
910*7c478bd9Sstevel@tonic-gate 			quoting = 0;
911*7c478bd9Sstevel@tonic-gate 			++lineno;
912*7c478bd9Sstevel@tonic-gate 			return;
913*7c478bd9Sstevel@tonic-gate 		}
914*7c478bd9Sstevel@tonic-gate 		if (c == EOF) {
915*7c478bd9Sstevel@tonic-gate 			quoting = 0;
916*7c478bd9Sstevel@tonic-gate 			ateof = 1;
917*7c478bd9Sstevel@tonic-gate 			return;
918*7c478bd9Sstevel@tonic-gate 		}
919*7c478bd9Sstevel@tonic-gate 		if (c == SPACE || c == TAB)
920*7c478bd9Sstevel@tonic-gate 			c = fgetwc(fp);
921*7c478bd9Sstevel@tonic-gate 		if (c == NEWLINE) {
922*7c478bd9Sstevel@tonic-gate 			quoting = 0;
923*7c478bd9Sstevel@tonic-gate 			++lineno;
924*7c478bd9Sstevel@tonic-gate 			return;
925*7c478bd9Sstevel@tonic-gate 		}
926*7c478bd9Sstevel@tonic-gate 		if (c == EOF) {
927*7c478bd9Sstevel@tonic-gate 			quoting = 0;
928*7c478bd9Sstevel@tonic-gate 			ateof = 1;
929*7c478bd9Sstevel@tonic-gate 			return;
930*7c478bd9Sstevel@tonic-gate 		}
931*7c478bd9Sstevel@tonic-gate 		quoting = 1;
932*7c478bd9Sstevel@tonic-gate 		quote = c;
933*7c478bd9Sstevel@tonic-gate 		do {	/* skip comment */
934*7c478bd9Sstevel@tonic-gate 			c = getc(fp);
935*7c478bd9Sstevel@tonic-gate 		} while (c == SPACE || c == TAB);
936*7c478bd9Sstevel@tonic-gate 		if (c == NEWLINE) {
937*7c478bd9Sstevel@tonic-gate 			++lineno;
938*7c478bd9Sstevel@tonic-gate 			return;
939*7c478bd9Sstevel@tonic-gate 		}
940*7c478bd9Sstevel@tonic-gate 		if (c == EOF) {
941*7c478bd9Sstevel@tonic-gate 			ateof = 1;
942*7c478bd9Sstevel@tonic-gate 			return;
943*7c478bd9Sstevel@tonic-gate 		}
944*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(15), msgfname, lineno);
945*7c478bd9Sstevel@tonic-gate 		exit(1);
946*7c478bd9Sstevel@tonic-gate 	} else {
947*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(19), msgfname, lineno, text);
948*7c478bd9Sstevel@tonic-gate 		exit(1);
949*7c478bd9Sstevel@tonic-gate 	}
950*7c478bd9Sstevel@tonic-gate }
951*7c478bd9Sstevel@tonic-gate 
952*7c478bd9Sstevel@tonic-gate /*
953*7c478bd9Sstevel@tonic-gate  * Read message source file and update double linked list message catalog.
954*7c478bd9Sstevel@tonic-gate  */
955*7c478bd9Sstevel@tonic-gate void
read_msgfile(fp,pathname)956*7c478bd9Sstevel@tonic-gate read_msgfile(fp, pathname)
957*7c478bd9Sstevel@tonic-gate 	FILE	*fp;
958*7c478bd9Sstevel@tonic-gate 	char	*pathname;
959*7c478bd9Sstevel@tonic-gate {
960*7c478bd9Sstevel@tonic-gate 	int		c;
961*7c478bd9Sstevel@tonic-gate 	int		no;
962*7c478bd9Sstevel@tonic-gate 
963*7c478bd9Sstevel@tonic-gate 	ateof = 0;
964*7c478bd9Sstevel@tonic-gate 	msgfname = pathname;
965*7c478bd9Sstevel@tonic-gate 	lineno = 1;
966*7c478bd9Sstevel@tonic-gate 	quoting = 0;
967*7c478bd9Sstevel@tonic-gate 	current_set_no = NL_SETD;
968*7c478bd9Sstevel@tonic-gate 	current_set = NULL;
969*7c478bd9Sstevel@tonic-gate 	current_msg = NULL;
970*7c478bd9Sstevel@tonic-gate 
971*7c478bd9Sstevel@tonic-gate 	for (;;) {
972*7c478bd9Sstevel@tonic-gate 		if (ateof)
973*7c478bd9Sstevel@tonic-gate 			return;
974*7c478bd9Sstevel@tonic-gate 		do {
975*7c478bd9Sstevel@tonic-gate 			c = fgetwc(fp);
976*7c478bd9Sstevel@tonic-gate 		} while (c == SPACE || c == TAB);
977*7c478bd9Sstevel@tonic-gate 		if (c == DOLLAR) {
978*7c478bd9Sstevel@tonic-gate 			directive(fp);
979*7c478bd9Sstevel@tonic-gate 			continue;
980*7c478bd9Sstevel@tonic-gate 		}
981*7c478bd9Sstevel@tonic-gate 
982*7c478bd9Sstevel@tonic-gate 		if (isascii(c) && isdigit(c)) {
983*7c478bd9Sstevel@tonic-gate 			no = get_number(fp, c);
984*7c478bd9Sstevel@tonic-gate 			if (no == 0) {
985*7c478bd9Sstevel@tonic-gate 				FPRINTF(stderr, MSG(10), msgfname, lineno);
986*7c478bd9Sstevel@tonic-gate 				exit(1);
987*7c478bd9Sstevel@tonic-gate 			}
988*7c478bd9Sstevel@tonic-gate 			if (no > NL_MSGMAX) {
989*7c478bd9Sstevel@tonic-gate 				FPRINTF(stderr, MSG(11), msgfname,
990*7c478bd9Sstevel@tonic-gate 					lineno, no, NL_MSGMAX);
991*7c478bd9Sstevel@tonic-gate 			}
992*7c478bd9Sstevel@tonic-gate 			c = fgetwc(fp);
993*7c478bd9Sstevel@tonic-gate 			if (c == NEWLINE || c == EOF) {
994*7c478bd9Sstevel@tonic-gate 				delete_msg(no);
995*7c478bd9Sstevel@tonic-gate 				if (c == NEWLINE)
996*7c478bd9Sstevel@tonic-gate 					++lineno;
997*7c478bd9Sstevel@tonic-gate 				else
998*7c478bd9Sstevel@tonic-gate 					return;
999*7c478bd9Sstevel@tonic-gate 				continue;
1000*7c478bd9Sstevel@tonic-gate 			} else {
1001*7c478bd9Sstevel@tonic-gate 				if (c != SPACE && c != TAB)
1002*7c478bd9Sstevel@tonic-gate 					(void) ungetwc(c, fp);
1003*7c478bd9Sstevel@tonic-gate 				get_text(fp);
1004*7c478bd9Sstevel@tonic-gate 				insert_msg(no, text_len, text);
1005*7c478bd9Sstevel@tonic-gate 				continue;
1006*7c478bd9Sstevel@tonic-gate 			}
1007*7c478bd9Sstevel@tonic-gate 		}
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate 		if (c == NEWLINE) {
1010*7c478bd9Sstevel@tonic-gate 			++lineno;
1011*7c478bd9Sstevel@tonic-gate 			continue;
1012*7c478bd9Sstevel@tonic-gate 		}
1013*7c478bd9Sstevel@tonic-gate 		if (c == EOF)
1014*7c478bd9Sstevel@tonic-gate 			return;
1015*7c478bd9Sstevel@tonic-gate 
1016*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(22), msgfname, lineno);
1017*7c478bd9Sstevel@tonic-gate 		exit(1);
1018*7c478bd9Sstevel@tonic-gate 	}
1019*7c478bd9Sstevel@tonic-gate }
1020*7c478bd9Sstevel@tonic-gate 
1021*7c478bd9Sstevel@tonic-gate /*
1022*7c478bd9Sstevel@tonic-gate  * Write double linked list to the file.
1023*7c478bd9Sstevel@tonic-gate  * It first converts a linked list to one chunk of memory and
1024*7c478bd9Sstevel@tonic-gate  * write it to file.
1025*7c478bd9Sstevel@tonic-gate  */
1026*7c478bd9Sstevel@tonic-gate void
writecat(fd,pathname)1027*7c478bd9Sstevel@tonic-gate writecat(fd, pathname)
1028*7c478bd9Sstevel@tonic-gate 	int		fd;
1029*7c478bd9Sstevel@tonic-gate 	char	*pathname;
1030*7c478bd9Sstevel@tonic-gate {
1031*7c478bd9Sstevel@tonic-gate 	int		i, n;
1032*7c478bd9Sstevel@tonic-gate 	int		nsets;
1033*7c478bd9Sstevel@tonic-gate 	int		mem;
1034*7c478bd9Sstevel@tonic-gate 	int		nmsgs;
1035*7c478bd9Sstevel@tonic-gate 	int		text_size;
1036*7c478bd9Sstevel@tonic-gate 	int		first_msg_hdr;
1037*7c478bd9Sstevel@tonic-gate 	int		msg_offset;
1038*7c478bd9Sstevel@tonic-gate 	unsigned	nbytes;
1039*7c478bd9Sstevel@tonic-gate 	char	*cat;
1040*7c478bd9Sstevel@tonic-gate 	struct	_cat_hdr	*hdrp;
1041*7c478bd9Sstevel@tonic-gate 	struct	cat_set		*setp;
1042*7c478bd9Sstevel@tonic-gate 	struct	cat_msg		*msgp;
1043*7c478bd9Sstevel@tonic-gate 	struct	_cat_set_hdr	*set;
1044*7c478bd9Sstevel@tonic-gate 	struct	_cat_msg_hdr	*msg;
1045*7c478bd9Sstevel@tonic-gate 	char	*text;
1046*7c478bd9Sstevel@tonic-gate 
1047*7c478bd9Sstevel@tonic-gate 	/* compute number of sets, number of messages, the total text size */
1048*7c478bd9Sstevel@tonic-gate 	nsets = 0;
1049*7c478bd9Sstevel@tonic-gate 	nmsgs = 0;
1050*7c478bd9Sstevel@tonic-gate 	text_size = 0;
1051*7c478bd9Sstevel@tonic-gate 	for (setp = first_set; setp; setp = setp->next) {
1052*7c478bd9Sstevel@tonic-gate 		++nsets;
1053*7c478bd9Sstevel@tonic-gate 		for (msgp = setp->first_msg; msgp; msgp = msgp->next) {
1054*7c478bd9Sstevel@tonic-gate 			++nmsgs;
1055*7c478bd9Sstevel@tonic-gate 			text_size += msgp->msg_len;
1056*7c478bd9Sstevel@tonic-gate 		}
1057*7c478bd9Sstevel@tonic-gate 	}
1058*7c478bd9Sstevel@tonic-gate 
1059*7c478bd9Sstevel@tonic-gate 	mem = nsets * _CAT_SET_HDR_SIZE + nmsgs * _CAT_MSG_HDR_SIZE + text_size;
1060*7c478bd9Sstevel@tonic-gate 	n = _CAT_HDR_SIZE + mem;
1061*7c478bd9Sstevel@tonic-gate 	cat = MALLOC(n);
1062*7c478bd9Sstevel@tonic-gate 	if (cat == 0) {
1063*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(6));
1064*7c478bd9Sstevel@tonic-gate 		exit(1);
1065*7c478bd9Sstevel@tonic-gate 	}
1066*7c478bd9Sstevel@tonic-gate 	MEMSET(cat, 0, n);
1067*7c478bd9Sstevel@tonic-gate 
1068*7c478bd9Sstevel@tonic-gate 	hdrp = (struct _cat_hdr *) cat;
1069*7c478bd9Sstevel@tonic-gate 	hdrp->__hdr_magic = _CAT_MAGIC;
1070*7c478bd9Sstevel@tonic-gate 	hdrp->__nsets = nsets;
1071*7c478bd9Sstevel@tonic-gate 	hdrp->__mem = mem;
1072*7c478bd9Sstevel@tonic-gate 	hdrp->__msg_hdr_offset = nsets * _CAT_SET_HDR_SIZE;
1073*7c478bd9Sstevel@tonic-gate 	hdrp->__msg_text_offset = nsets * _CAT_SET_HDR_SIZE +
1074*7c478bd9Sstevel@tonic-gate 				nmsgs * _CAT_MSG_HDR_SIZE;
1075*7c478bd9Sstevel@tonic-gate 
1076*7c478bd9Sstevel@tonic-gate 	set = (struct _cat_set_hdr *) (cat + _CAT_HDR_SIZE);
1077*7c478bd9Sstevel@tonic-gate 	msg = (struct _cat_msg_hdr *) (set + nsets);
1078*7c478bd9Sstevel@tonic-gate 	text = (char *) (msg + nmsgs);
1079*7c478bd9Sstevel@tonic-gate 
1080*7c478bd9Sstevel@tonic-gate 	/* convert linked list to one chunk of memory */
1081*7c478bd9Sstevel@tonic-gate 	first_msg_hdr = 0;
1082*7c478bd9Sstevel@tonic-gate 	msg_offset = 0;
1083*7c478bd9Sstevel@tonic-gate 	for (setp = first_set; setp; ++set, setp = setp->next) {
1084*7c478bd9Sstevel@tonic-gate 		set->__set_no = setp->set_no;
1085*7c478bd9Sstevel@tonic-gate 		set->__first_msg_hdr = first_msg_hdr;
1086*7c478bd9Sstevel@tonic-gate 		nmsgs = 0;
1087*7c478bd9Sstevel@tonic-gate 		for (msgp = setp->first_msg; msgp; ++msg, msgp = msgp->next) {
1088*7c478bd9Sstevel@tonic-gate 			++nmsgs;
1089*7c478bd9Sstevel@tonic-gate 			msg->__msg_no = msgp->msg_no;
1090*7c478bd9Sstevel@tonic-gate 			msg->__msg_len = msgp->msg_len;
1091*7c478bd9Sstevel@tonic-gate 			msg->__msg_offset = msg_offset;
1092*7c478bd9Sstevel@tonic-gate 			if (msgp->msg_len > 0) {
1093*7c478bd9Sstevel@tonic-gate 				MEMCPY(text, msgp->s, msgp->msg_len);
1094*7c478bd9Sstevel@tonic-gate 				text += msgp->msg_len;
1095*7c478bd9Sstevel@tonic-gate 				msg_offset += msgp->msg_len;
1096*7c478bd9Sstevel@tonic-gate 			}
1097*7c478bd9Sstevel@tonic-gate 		}
1098*7c478bd9Sstevel@tonic-gate 		set->__nmsgs = nmsgs;
1099*7c478bd9Sstevel@tonic-gate 		first_msg_hdr += nmsgs;
1100*7c478bd9Sstevel@tonic-gate 	}
1101*7c478bd9Sstevel@tonic-gate 
1102*7c478bd9Sstevel@tonic-gate 	/* write one chunk of memory to file */
1103*7c478bd9Sstevel@tonic-gate 	nbytes = 0;
1104*7c478bd9Sstevel@tonic-gate 	while (nbytes < n) {
1105*7c478bd9Sstevel@tonic-gate 		i = write(fd, cat + nbytes, n - nbytes);
1106*7c478bd9Sstevel@tonic-gate 		if (i < 0) {
1107*7c478bd9Sstevel@tonic-gate 			if (errno != EINTR) {
1108*7c478bd9Sstevel@tonic-gate 				FPRINTF(stderr, MSG(8), pathname);
1109*7c478bd9Sstevel@tonic-gate 				perror("");
1110*7c478bd9Sstevel@tonic-gate 				exit(1);
1111*7c478bd9Sstevel@tonic-gate 			}
1112*7c478bd9Sstevel@tonic-gate 		} else {
1113*7c478bd9Sstevel@tonic-gate 			nbytes += n;
1114*7c478bd9Sstevel@tonic-gate 		}
1115*7c478bd9Sstevel@tonic-gate 	}
1116*7c478bd9Sstevel@tonic-gate 
1117*7c478bd9Sstevel@tonic-gate 	free(cat);
1118*7c478bd9Sstevel@tonic-gate }
1119*7c478bd9Sstevel@tonic-gate 
1120*7c478bd9Sstevel@tonic-gate int
main(argc,argv)1121*7c478bd9Sstevel@tonic-gate main(argc, argv)
1122*7c478bd9Sstevel@tonic-gate 	int		argc;
1123*7c478bd9Sstevel@tonic-gate 	char	*argv[];
1124*7c478bd9Sstevel@tonic-gate {
1125*7c478bd9Sstevel@tonic-gate 	int		i;
1126*7c478bd9Sstevel@tonic-gate 	int		cat_exists;
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
1129*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* Should be defined by cc -D */
1130*7c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN	"SYS_TEST"	/* Use this only if it weren't */
1131*7c478bd9Sstevel@tonic-gate #endif
1132*7c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
1133*7c478bd9Sstevel@tonic-gate 
1134*7c478bd9Sstevel@tonic-gate 	if (argc < 3) {
1135*7c478bd9Sstevel@tonic-gate 		FPRINTF(stderr, MSG(1));
1136*7c478bd9Sstevel@tonic-gate 		exit(1);
1137*7c478bd9Sstevel@tonic-gate 	}
1138*7c478bd9Sstevel@tonic-gate 	catfname = argv[1];
1139*7c478bd9Sstevel@tonic-gate 	cat_exists = 0;
1140*7c478bd9Sstevel@tonic-gate 	if ((*catfname == '-') && (*(catfname + 1) == '\0')) {
1141*7c478bd9Sstevel@tonic-gate 		catfd = 1;				/* Use stdout */
1142*7c478bd9Sstevel@tonic-gate 	} else {
1143*7c478bd9Sstevel@tonic-gate 		catfd = open(catfname, O_WRONLY | O_CREAT | O_EXCL, 0666);
1144*7c478bd9Sstevel@tonic-gate 		if (catfd < 0) {	/* file exists */
1145*7c478bd9Sstevel@tonic-gate 			if (errno != EEXIST ||
1146*7c478bd9Sstevel@tonic-gate 			    (catfd = open(catfname, O_RDWR)) < 0) {
1147*7c478bd9Sstevel@tonic-gate 				/* cannot open file */
1148*7c478bd9Sstevel@tonic-gate 				FPRINTF(stderr, MSG(2), catfname);
1149*7c478bd9Sstevel@tonic-gate 				perror("");
1150*7c478bd9Sstevel@tonic-gate 				exit(1);
1151*7c478bd9Sstevel@tonic-gate 			}
1152*7c478bd9Sstevel@tonic-gate 			cat_exists = 1;
1153*7c478bd9Sstevel@tonic-gate 			/* read catalog file into memory */
1154*7c478bd9Sstevel@tonic-gate 			readcat(catfd, catfname);
1155*7c478bd9Sstevel@tonic-gate 			if (lseek(catfd, 0L, 0) < 0) {
1156*7c478bd9Sstevel@tonic-gate 				FPRINTF(stderr, MSG(7), catfname);
1157*7c478bd9Sstevel@tonic-gate 				perror("");
1158*7c478bd9Sstevel@tonic-gate 				exit(1);
1159*7c478bd9Sstevel@tonic-gate 			}
1160*7c478bd9Sstevel@tonic-gate 		}
1161*7c478bd9Sstevel@tonic-gate 	}
1162*7c478bd9Sstevel@tonic-gate 
1163*7c478bd9Sstevel@tonic-gate 	/* process all message source files */
1164*7c478bd9Sstevel@tonic-gate 	if ((**(argv + 2) == '-') && (*(*(argv + 2) + 1) == '\0')) {
1165*7c478bd9Sstevel@tonic-gate 		if (argc != 3) {
1166*7c478bd9Sstevel@tonic-gate 			FPRINTF(stderr, MSG(1));
1167*7c478bd9Sstevel@tonic-gate 			exit(1);
1168*7c478bd9Sstevel@tonic-gate 		} else {
1169*7c478bd9Sstevel@tonic-gate 			read_msgfile(stdin, MSG(21));
1170*7c478bd9Sstevel@tonic-gate 		}
1171*7c478bd9Sstevel@tonic-gate 	} else {
1172*7c478bd9Sstevel@tonic-gate 		for (i = 2; i < argc; ++i) {
1173*7c478bd9Sstevel@tonic-gate 			FILE	*fp;
1174*7c478bd9Sstevel@tonic-gate 			fp = fopen(*(argv + i), "r");
1175*7c478bd9Sstevel@tonic-gate 			if (fp == NULL) {
1176*7c478bd9Sstevel@tonic-gate 				FPRINTF(stderr, MSG(2), *(argv + i));
1177*7c478bd9Sstevel@tonic-gate 				perror("");
1178*7c478bd9Sstevel@tonic-gate 				exit(1);
1179*7c478bd9Sstevel@tonic-gate 			}
1180*7c478bd9Sstevel@tonic-gate 			read_msgfile(fp, *(argv + i));
1181*7c478bd9Sstevel@tonic-gate 			(void) fclose(fp);
1182*7c478bd9Sstevel@tonic-gate 		}
1183*7c478bd9Sstevel@tonic-gate 	}
1184*7c478bd9Sstevel@tonic-gate 
1185*7c478bd9Sstevel@tonic-gate 	if (cat_exists)
1186*7c478bd9Sstevel@tonic-gate 		(void) ftruncate(catfd, 0L);
1187*7c478bd9Sstevel@tonic-gate 
1188*7c478bd9Sstevel@tonic-gate 	/* write catalog to file */
1189*7c478bd9Sstevel@tonic-gate 	writecat(catfd, catfname);
1190*7c478bd9Sstevel@tonic-gate 	return (0);
1191*7c478bd9Sstevel@tonic-gate }
1192