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