1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman * *
3*b30d1939SAndy Fiddaman * This software is part of the ast package *
4*b30d1939SAndy Fiddaman * Copyright (c) 2000-2011 AT&T Intellectual Property *
5*b30d1939SAndy Fiddaman * and is licensed under the *
6*b30d1939SAndy Fiddaman * Eclipse Public License, Version 1.0 *
7*b30d1939SAndy Fiddaman * by AT&T Intellectual Property *
8*b30d1939SAndy Fiddaman * *
9*b30d1939SAndy Fiddaman * A copy of the License is available at *
10*b30d1939SAndy Fiddaman * http://www.eclipse.org/org/documents/epl-v10.html *
11*b30d1939SAndy Fiddaman * (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12*b30d1939SAndy Fiddaman * *
13*b30d1939SAndy Fiddaman * Information and Software Systems Research *
14*b30d1939SAndy Fiddaman * AT&T Research *
15*b30d1939SAndy Fiddaman * Florham Park NJ *
16*b30d1939SAndy Fiddaman * *
17*b30d1939SAndy Fiddaman * Glenn Fowler <gsf@research.att.com> *
18*b30d1939SAndy Fiddaman * *
19*b30d1939SAndy Fiddaman ***********************************************************************/
20*b30d1939SAndy Fiddaman #pragma prototyped
21*b30d1939SAndy Fiddaman /*
22*b30d1939SAndy Fiddaman * Glenn Fowler
23*b30d1939SAndy Fiddaman * AT&T Research
24*b30d1939SAndy Fiddaman */
25*b30d1939SAndy Fiddaman
26*b30d1939SAndy Fiddaman static const char usage[] =
27*b30d1939SAndy Fiddaman "[-?\n@(#)$Id: msggen (AT&T Research) 2002-03-11 $\n]"
28*b30d1939SAndy Fiddaman USAGE_LICENSE
29*b30d1939SAndy Fiddaman "[+NAME?msggen - generate a machine independent formatted message catalog]"
30*b30d1939SAndy Fiddaman "[+DESCRIPTION?\bmsggen\b merges the message text source files \amsgfile\a"
31*b30d1939SAndy Fiddaman " into a machine independent formatted message catalog \acatfile\a."
32*b30d1939SAndy Fiddaman " The file \acatfile\a will be created if it does not already exist."
33*b30d1939SAndy Fiddaman " If \acatfile\a does exist, its messages will be included in the new"
34*b30d1939SAndy Fiddaman " \acatfile\a. If set and message numbers collide, the new message"
35*b30d1939SAndy Fiddaman " text defined in \amsgfile\a will replace the old message text"
36*b30d1939SAndy Fiddaman " currently contained in \acatfile\a. Non-ASCII characters must be"
37*b30d1939SAndy Fiddaman " UTF-8 encoded. \biconv\b(1) can be used to convert to/from UTF-8.]"
38*b30d1939SAndy Fiddaman "[f:format?List the \bprintf\b(3) format signature for each message in"
39*b30d1939SAndy Fiddaman " \acatfile\a. A format signature is one line containing one character"
40*b30d1939SAndy Fiddaman " per format specification:]{"
41*b30d1939SAndy Fiddaman " [c?char]"
42*b30d1939SAndy Fiddaman " [d?double]"
43*b30d1939SAndy Fiddaman " [D?long double]"
44*b30d1939SAndy Fiddaman " [f?float]"
45*b30d1939SAndy Fiddaman " [h?short]"
46*b30d1939SAndy Fiddaman " [i?int]"
47*b30d1939SAndy Fiddaman " [j?long long]"
48*b30d1939SAndy Fiddaman " [l?long]"
49*b30d1939SAndy Fiddaman " [p?void*]"
50*b30d1939SAndy Fiddaman " [s?string]"
51*b30d1939SAndy Fiddaman " [t?ptrdiff_t]"
52*b30d1939SAndy Fiddaman " [z?size_t]"
53*b30d1939SAndy Fiddaman " [???unknown]"
54*b30d1939SAndy Fiddaman "}"
55*b30d1939SAndy Fiddaman "[l:list?List \acatfile\a in UTF-8 \amsgfile\a form.]"
56*b30d1939SAndy Fiddaman "[s:set?Convert the \acatfile\a operand to a message set number and"
57*b30d1939SAndy Fiddaman " print the number on the standard output.]"
58*b30d1939SAndy Fiddaman "[+EXTENDED DESCRIPTION?Message text source files are in \bgencat\b(1)"
59*b30d1939SAndy Fiddaman " format, defined as follows. Note that the fields of a message text"
60*b30d1939SAndy Fiddaman " source line are separated by a single blank character. Any other"
61*b30d1939SAndy Fiddaman " blank characters are considered as being part of the subsequent"
62*b30d1939SAndy Fiddaman " field. The \bNL_*\b constants are defined in one or both of"
63*b30d1939SAndy Fiddaman " \b<limits.h>\b and \b<nl_types.h>\b.]{"
64*b30d1939SAndy Fiddaman " [+$ \acomment\a?A line beginning with \b$\b followed by a"
65*b30d1939SAndy Fiddaman " blank character is treated as a comment.]"
66*b30d1939SAndy Fiddaman " [+$delset \an\a \acomment\a?This line deletes message set"
67*b30d1939SAndy Fiddaman " \an\a from an existing message catalog. \an\a"
68*b30d1939SAndy Fiddaman " denotes the set number [1, \bNL_SETMAX\b]]. Any"
69*b30d1939SAndy Fiddaman " text following the set number is treated as a"
70*b30d1939SAndy Fiddaman " comment.]"
71*b30d1939SAndy Fiddaman " [+$quote \ac\a?This line specifies an optional quote"
72*b30d1939SAndy Fiddaman " character \ac\a, which can be used to surround"
73*b30d1939SAndy Fiddaman " \amessage-text\a so that trailing spaces or"
74*b30d1939SAndy Fiddaman " empty messages are visible in a message source"
75*b30d1939SAndy Fiddaman " line. By default, or if an empty \b$quote\b"
76*b30d1939SAndy Fiddaman " directive is supplied, no quoting of \amessage-text\a"
77*b30d1939SAndy Fiddaman " will be recognized.]"
78*b30d1939SAndy Fiddaman " [+$set \an\a \acomment\a?This line specifies the set"
79*b30d1939SAndy Fiddaman " identifier of the following messages until the next"
80*b30d1939SAndy Fiddaman " \b$set\b or end-of-file appears. \an\a denotes the set"
81*b30d1939SAndy Fiddaman " identifier, which is defined as a number in the range"
82*b30d1939SAndy Fiddaman " [1, \bNL_SETMAX\b]]. Set numbers need not be"
83*b30d1939SAndy Fiddaman " contiguous. Any text following the set identifier is"
84*b30d1939SAndy Fiddaman " treated as a comment. If no \b$set\b directive is"
85*b30d1939SAndy Fiddaman " specified in a message text source file, all messages"
86*b30d1939SAndy Fiddaman " will be located in message set \b1\b.]"
87*b30d1939SAndy Fiddaman " [+$translation \aidentification\a \aYYYY-MM-DD\a[,...]]?Append"
88*b30d1939SAndy Fiddaman " translation info to the message catalog header. Only"
89*b30d1939SAndy Fiddaman " the newest date for a given \aidentification\a"
90*b30d1939SAndy Fiddaman " is retained in the catalog. Multiple translation lines"
91*b30d1939SAndy Fiddaman " are combined into a single \b,\b separated list.]"
92*b30d1939SAndy Fiddaman " [+\am\a \amessage-text\a?\am\a denotes the message identifier,"
93*b30d1939SAndy Fiddaman " which is defined as a number in the range"
94*b30d1939SAndy Fiddaman " [1, \bNL_MSGMAX\b]]. The message-text is stored in the"
95*b30d1939SAndy Fiddaman " message catalogue with the set identifier specified by"
96*b30d1939SAndy Fiddaman " the last \b$set\b directive, and with message"
97*b30d1939SAndy Fiddaman " identifier \am\a. If the \amessage-text\a is empty,"
98*b30d1939SAndy Fiddaman " and a blank character field separator is present, an"
99*b30d1939SAndy Fiddaman " empty string is stored in the message catalogue. If a"
100*b30d1939SAndy Fiddaman " message source line has a message number, but neither"
101*b30d1939SAndy Fiddaman " a field separator nor \amessage-text\a, the existing"
102*b30d1939SAndy Fiddaman " message with that number (if any) is deleted from the"
103*b30d1939SAndy Fiddaman " catalogue. Message identifiers need not be contiguous."
104*b30d1939SAndy Fiddaman " There are no \amessage-text\a length restrictions.]"
105*b30d1939SAndy Fiddaman "}"
106*b30d1939SAndy Fiddaman
107*b30d1939SAndy Fiddaman "\n"
108*b30d1939SAndy Fiddaman "\ncatfile [ msgfile ]\n"
109*b30d1939SAndy Fiddaman "\n"
110*b30d1939SAndy Fiddaman
111*b30d1939SAndy Fiddaman "[+SEE ALSO?\bgencat\b(1), \biconv\b(1), \bmsgcc\b(1), \btranslate\b(1),"
112*b30d1939SAndy Fiddaman " \bfmtfmt\b(3)]"
113*b30d1939SAndy Fiddaman ;
114*b30d1939SAndy Fiddaman
115*b30d1939SAndy Fiddaman #include <ast.h>
116*b30d1939SAndy Fiddaman #include <ctype.h>
117*b30d1939SAndy Fiddaman #include <ccode.h>
118*b30d1939SAndy Fiddaman #include <error.h>
119*b30d1939SAndy Fiddaman #include <mc.h>
120*b30d1939SAndy Fiddaman
121*b30d1939SAndy Fiddaman typedef struct Xl_s
122*b30d1939SAndy Fiddaman {
123*b30d1939SAndy Fiddaman struct Xl_s* next;
124*b30d1939SAndy Fiddaman char* date;
125*b30d1939SAndy Fiddaman char name[1];
126*b30d1939SAndy Fiddaman } Xl_t;
127*b30d1939SAndy Fiddaman
128*b30d1939SAndy Fiddaman /*
129*b30d1939SAndy Fiddaman * append s to the translation list
130*b30d1939SAndy Fiddaman */
131*b30d1939SAndy Fiddaman
132*b30d1939SAndy Fiddaman static Xl_t*
translation(Xl_t * xp,register char * s)133*b30d1939SAndy Fiddaman translation(Xl_t* xp, register char* s)
134*b30d1939SAndy Fiddaman {
135*b30d1939SAndy Fiddaman register Xl_t* px;
136*b30d1939SAndy Fiddaman register char* t;
137*b30d1939SAndy Fiddaman char* d;
138*b30d1939SAndy Fiddaman char* e;
139*b30d1939SAndy Fiddaman
140*b30d1939SAndy Fiddaman do
141*b30d1939SAndy Fiddaman {
142*b30d1939SAndy Fiddaman for (; isspace(*s); s++);
143*b30d1939SAndy Fiddaman for (d = e = 0, t = s; *t; t++)
144*b30d1939SAndy Fiddaman if (*t == ',')
145*b30d1939SAndy Fiddaman {
146*b30d1939SAndy Fiddaman e = t;
147*b30d1939SAndy Fiddaman *e++ = 0;
148*b30d1939SAndy Fiddaman break;
149*b30d1939SAndy Fiddaman }
150*b30d1939SAndy Fiddaman else if (isspace(*t))
151*b30d1939SAndy Fiddaman d = t;
152*b30d1939SAndy Fiddaman if (d)
153*b30d1939SAndy Fiddaman {
154*b30d1939SAndy Fiddaman *d++ = 0;
155*b30d1939SAndy Fiddaman for (px = xp; px; px = px->next)
156*b30d1939SAndy Fiddaman if (streq(px->name, s))
157*b30d1939SAndy Fiddaman {
158*b30d1939SAndy Fiddaman if (strcoll(px->date, d) < 0)
159*b30d1939SAndy Fiddaman {
160*b30d1939SAndy Fiddaman free(px->date);
161*b30d1939SAndy Fiddaman if (!(px->date = strdup(d)))
162*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "out of space [translation]");
163*b30d1939SAndy Fiddaman }
164*b30d1939SAndy Fiddaman break;
165*b30d1939SAndy Fiddaman }
166*b30d1939SAndy Fiddaman if (!px)
167*b30d1939SAndy Fiddaman {
168*b30d1939SAndy Fiddaman if (!(px = newof(0, Xl_t, 1, strlen(s))) || !(px->date = strdup(d)))
169*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "out of space [translation]");
170*b30d1939SAndy Fiddaman strcpy(px->name, s);
171*b30d1939SAndy Fiddaman px->next = xp;
172*b30d1939SAndy Fiddaman xp = px;
173*b30d1939SAndy Fiddaman }
174*b30d1939SAndy Fiddaman }
175*b30d1939SAndy Fiddaman } while (s = e);
176*b30d1939SAndy Fiddaman return xp;
177*b30d1939SAndy Fiddaman }
178*b30d1939SAndy Fiddaman
179*b30d1939SAndy Fiddaman /*
180*b30d1939SAndy Fiddaman * sfprintf() with ccmaps(from,to)
181*b30d1939SAndy Fiddaman */
182*b30d1939SAndy Fiddaman
183*b30d1939SAndy Fiddaman static int
ccsfprintf(int from,int to,Sfio_t * sp,const char * format,...)184*b30d1939SAndy Fiddaman ccsfprintf(int from, int to, Sfio_t* sp, const char* format, ...)
185*b30d1939SAndy Fiddaman {
186*b30d1939SAndy Fiddaman va_list ap;
187*b30d1939SAndy Fiddaman Sfio_t* tp;
188*b30d1939SAndy Fiddaman char* s;
189*b30d1939SAndy Fiddaman int n;
190*b30d1939SAndy Fiddaman
191*b30d1939SAndy Fiddaman va_start(ap, format);
192*b30d1939SAndy Fiddaman if (from == to)
193*b30d1939SAndy Fiddaman n = sfvprintf(sp, format, ap);
194*b30d1939SAndy Fiddaman else if (tp = sfstropen())
195*b30d1939SAndy Fiddaman {
196*b30d1939SAndy Fiddaman n = sfvprintf(tp, format, ap);
197*b30d1939SAndy Fiddaman s = sfstrbase(tp);
198*b30d1939SAndy Fiddaman ccmaps(s, n, from, to);
199*b30d1939SAndy Fiddaman n = sfwrite(sp, s, n);
200*b30d1939SAndy Fiddaman sfstrclose(tp);
201*b30d1939SAndy Fiddaman }
202*b30d1939SAndy Fiddaman else
203*b30d1939SAndy Fiddaman n = -1;
204*b30d1939SAndy Fiddaman return n;
205*b30d1939SAndy Fiddaman }
206*b30d1939SAndy Fiddaman
207*b30d1939SAndy Fiddaman int
main(int argc,char ** argv)208*b30d1939SAndy Fiddaman main(int argc, char** argv)
209*b30d1939SAndy Fiddaman {
210*b30d1939SAndy Fiddaman register Mc_t* mc;
211*b30d1939SAndy Fiddaman register char* s;
212*b30d1939SAndy Fiddaman register char* t;
213*b30d1939SAndy Fiddaman register int c;
214*b30d1939SAndy Fiddaman register int q;
215*b30d1939SAndy Fiddaman register int i;
216*b30d1939SAndy Fiddaman int num;
217*b30d1939SAndy Fiddaman char* b;
218*b30d1939SAndy Fiddaman char* e;
219*b30d1939SAndy Fiddaman char* catfile;
220*b30d1939SAndy Fiddaman char* msgfile;
221*b30d1939SAndy Fiddaman Sfio_t* sp;
222*b30d1939SAndy Fiddaman Sfio_t* mp;
223*b30d1939SAndy Fiddaman Sfio_t* tp;
224*b30d1939SAndy Fiddaman Xl_t* px;
225*b30d1939SAndy Fiddaman Xl_t* bp;
226*b30d1939SAndy Fiddaman
227*b30d1939SAndy Fiddaman Xl_t* xp = 0;
228*b30d1939SAndy Fiddaman int format = 0;
229*b30d1939SAndy Fiddaman int list = 0;
230*b30d1939SAndy Fiddaman int set = 0;
231*b30d1939SAndy Fiddaman
232*b30d1939SAndy Fiddaman NoP(argc);
233*b30d1939SAndy Fiddaman error_info.id = "msggen";
234*b30d1939SAndy Fiddaman for (;;)
235*b30d1939SAndy Fiddaman {
236*b30d1939SAndy Fiddaman switch (optget(argv, usage))
237*b30d1939SAndy Fiddaman {
238*b30d1939SAndy Fiddaman case 'f':
239*b30d1939SAndy Fiddaman format = list = 1;
240*b30d1939SAndy Fiddaman continue;
241*b30d1939SAndy Fiddaman case 'l':
242*b30d1939SAndy Fiddaman list = 1;
243*b30d1939SAndy Fiddaman continue;
244*b30d1939SAndy Fiddaman case 's':
245*b30d1939SAndy Fiddaman set = 1;
246*b30d1939SAndy Fiddaman continue;
247*b30d1939SAndy Fiddaman case '?':
248*b30d1939SAndy Fiddaman error(ERROR_USAGE|4, "%s", opt_info.arg);
249*b30d1939SAndy Fiddaman continue;
250*b30d1939SAndy Fiddaman case ':':
251*b30d1939SAndy Fiddaman error(2, "%s", opt_info.arg);
252*b30d1939SAndy Fiddaman continue;
253*b30d1939SAndy Fiddaman }
254*b30d1939SAndy Fiddaman break;
255*b30d1939SAndy Fiddaman }
256*b30d1939SAndy Fiddaman argv += opt_info.index;
257*b30d1939SAndy Fiddaman if (error_info.errors || !(catfile = *argv++))
258*b30d1939SAndy Fiddaman error(ERROR_USAGE|4, "%s", optusage(NiL));
259*b30d1939SAndy Fiddaman
260*b30d1939SAndy Fiddaman /*
261*b30d1939SAndy Fiddaman * set and list only need catfile
262*b30d1939SAndy Fiddaman */
263*b30d1939SAndy Fiddaman
264*b30d1939SAndy Fiddaman if (set)
265*b30d1939SAndy Fiddaman {
266*b30d1939SAndy Fiddaman sfprintf(sfstdout, "%d\n", mcindex(catfile, NiL, NiL, NiL));
267*b30d1939SAndy Fiddaman return error_info.errors != 0;
268*b30d1939SAndy Fiddaman }
269*b30d1939SAndy Fiddaman else if (list)
270*b30d1939SAndy Fiddaman {
271*b30d1939SAndy Fiddaman if (!(sp = sfopen(NiL, catfile, "r")))
272*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "%s: cannot read catalog", catfile);
273*b30d1939SAndy Fiddaman if (!(mc = mcopen(sp)))
274*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "%s: catalog content error", catfile);
275*b30d1939SAndy Fiddaman sfclose(sp);
276*b30d1939SAndy Fiddaman if (format)
277*b30d1939SAndy Fiddaman {
278*b30d1939SAndy Fiddaman for (set = 1; set <= mc->num; set++)
279*b30d1939SAndy Fiddaman if (mc->set[set].num)
280*b30d1939SAndy Fiddaman {
281*b30d1939SAndy Fiddaman sfprintf(sfstdout, "$set %d\n", set);
282*b30d1939SAndy Fiddaman for (num = 1; num <= mc->set[set].num; num++)
283*b30d1939SAndy Fiddaman if (s = mc->set[set].msg[num])
284*b30d1939SAndy Fiddaman sfprintf(sfstdout, "%d \"%s\"\n", num, fmtfmt(s));
285*b30d1939SAndy Fiddaman }
286*b30d1939SAndy Fiddaman }
287*b30d1939SAndy Fiddaman else
288*b30d1939SAndy Fiddaman {
289*b30d1939SAndy Fiddaman if (*mc->translation)
290*b30d1939SAndy Fiddaman {
291*b30d1939SAndy Fiddaman ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$translation ");
292*b30d1939SAndy Fiddaman sfprintf(sfstdout, "%s", mc->translation);
293*b30d1939SAndy Fiddaman ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\n");
294*b30d1939SAndy Fiddaman }
295*b30d1939SAndy Fiddaman ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$quote \"\n");
296*b30d1939SAndy Fiddaman for (set = 1; set <= mc->num; set++)
297*b30d1939SAndy Fiddaman if (mc->set[set].num)
298*b30d1939SAndy Fiddaman {
299*b30d1939SAndy Fiddaman ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$set %d\n", set);
300*b30d1939SAndy Fiddaman for (num = 1; num <= mc->set[set].num; num++)
301*b30d1939SAndy Fiddaman if (s = mc->set[set].msg[num])
302*b30d1939SAndy Fiddaman {
303*b30d1939SAndy Fiddaman ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "%d \"", num);
304*b30d1939SAndy Fiddaman while (c = *s++)
305*b30d1939SAndy Fiddaman {
306*b30d1939SAndy Fiddaman /*INDENT...*/
307*b30d1939SAndy Fiddaman
308*b30d1939SAndy Fiddaman switch (c)
309*b30d1939SAndy Fiddaman {
310*b30d1939SAndy Fiddaman case 0x22: /* " */
311*b30d1939SAndy Fiddaman case 0x5C: /* \ */
312*b30d1939SAndy Fiddaman sfputc(sfstdout, 0x5C);
313*b30d1939SAndy Fiddaman break;
314*b30d1939SAndy Fiddaman case 0x07: /* \a */
315*b30d1939SAndy Fiddaman c = 0x61;
316*b30d1939SAndy Fiddaman sfputc(sfstdout, 0x5C);
317*b30d1939SAndy Fiddaman break;
318*b30d1939SAndy Fiddaman case 0x08: /* \b */
319*b30d1939SAndy Fiddaman c = 0x62;
320*b30d1939SAndy Fiddaman sfputc(sfstdout, 0x5C);
321*b30d1939SAndy Fiddaman break;
322*b30d1939SAndy Fiddaman case 0x0A: /* \n */
323*b30d1939SAndy Fiddaman c = 0x6E;
324*b30d1939SAndy Fiddaman sfputc(sfstdout, 0x5C);
325*b30d1939SAndy Fiddaman break;
326*b30d1939SAndy Fiddaman case 0x0B: /* \v */
327*b30d1939SAndy Fiddaman c = 0x76;
328*b30d1939SAndy Fiddaman sfputc(sfstdout, 0x5C);
329*b30d1939SAndy Fiddaman break;
330*b30d1939SAndy Fiddaman case 0x0C: /* \f */
331*b30d1939SAndy Fiddaman c = 0x66;
332*b30d1939SAndy Fiddaman sfputc(sfstdout, 0x5C);
333*b30d1939SAndy Fiddaman break;
334*b30d1939SAndy Fiddaman case 0x0D: /* \r */
335*b30d1939SAndy Fiddaman c = 0x72;
336*b30d1939SAndy Fiddaman sfputc(sfstdout, 0x5C);
337*b30d1939SAndy Fiddaman break;
338*b30d1939SAndy Fiddaman }
339*b30d1939SAndy Fiddaman
340*b30d1939SAndy Fiddaman /*...UNDENT*/
341*b30d1939SAndy Fiddaman sfputc(sfstdout, c);
342*b30d1939SAndy Fiddaman }
343*b30d1939SAndy Fiddaman ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\"\n");
344*b30d1939SAndy Fiddaman }
345*b30d1939SAndy Fiddaman }
346*b30d1939SAndy Fiddaman }
347*b30d1939SAndy Fiddaman mcclose(mc);
348*b30d1939SAndy Fiddaman return error_info.errors != 0;
349*b30d1939SAndy Fiddaman }
350*b30d1939SAndy Fiddaman else if (!(msgfile = *argv++) || *argv)
351*b30d1939SAndy Fiddaman error(3, "exactly one message file must be specified");
352*b30d1939SAndy Fiddaman
353*b30d1939SAndy Fiddaman /*
354*b30d1939SAndy Fiddaman * open the files and handles
355*b30d1939SAndy Fiddaman */
356*b30d1939SAndy Fiddaman
357*b30d1939SAndy Fiddaman if (!(tp = sfstropen()))
358*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "out of space [string stream]");
359*b30d1939SAndy Fiddaman if (!(mp = sfopen(NiL, msgfile, "r")))
360*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "%s: cannot read message file", msgfile);
361*b30d1939SAndy Fiddaman sp = sfopen(NiL, catfile, "r");
362*b30d1939SAndy Fiddaman if (!(mc = mcopen(sp)))
363*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "%s: catalog content error", catfile);
364*b30d1939SAndy Fiddaman if (sp)
365*b30d1939SAndy Fiddaman sfclose(sp);
366*b30d1939SAndy Fiddaman xp = translation(xp, mc->translation);
367*b30d1939SAndy Fiddaman
368*b30d1939SAndy Fiddaman /*
369*b30d1939SAndy Fiddaman * read the message file
370*b30d1939SAndy Fiddaman */
371*b30d1939SAndy Fiddaman
372*b30d1939SAndy Fiddaman q = 0;
373*b30d1939SAndy Fiddaman set = 1;
374*b30d1939SAndy Fiddaman error_info.file = msgfile;
375*b30d1939SAndy Fiddaman while (s = sfgetr(mp, '\n', 1))
376*b30d1939SAndy Fiddaman {
377*b30d1939SAndy Fiddaman error_info.line++;
378*b30d1939SAndy Fiddaman if (!*s)
379*b30d1939SAndy Fiddaman continue;
380*b30d1939SAndy Fiddaman if (*s == '$')
381*b30d1939SAndy Fiddaman {
382*b30d1939SAndy Fiddaman if (!*++s || isspace(*s))
383*b30d1939SAndy Fiddaman continue;
384*b30d1939SAndy Fiddaman for (t = s; *s && !isspace(*s); s++);
385*b30d1939SAndy Fiddaman if (*s)
386*b30d1939SAndy Fiddaman *s++ = 0;
387*b30d1939SAndy Fiddaman if (streq(t, "delset"))
388*b30d1939SAndy Fiddaman {
389*b30d1939SAndy Fiddaman while (isspace(*s))
390*b30d1939SAndy Fiddaman s++;
391*b30d1939SAndy Fiddaman num = (int)strtol(s, NiL, 0);
392*b30d1939SAndy Fiddaman if (num < mc->num && mc->set[num].num)
393*b30d1939SAndy Fiddaman for (i = 1; i <= mc->set[num].num; i++)
394*b30d1939SAndy Fiddaman mcput(mc, num, i, NiL);
395*b30d1939SAndy Fiddaman }
396*b30d1939SAndy Fiddaman else if (streq(t, "quote"))
397*b30d1939SAndy Fiddaman q = *s ? *s : 0;
398*b30d1939SAndy Fiddaman else if (streq(t, "set"))
399*b30d1939SAndy Fiddaman {
400*b30d1939SAndy Fiddaman while (isspace(*s))
401*b30d1939SAndy Fiddaman s++;
402*b30d1939SAndy Fiddaman num = (int)strtol(s, &e, 0);
403*b30d1939SAndy Fiddaman if (e != s)
404*b30d1939SAndy Fiddaman set = num;
405*b30d1939SAndy Fiddaman else
406*b30d1939SAndy Fiddaman error(2, "set number expected");
407*b30d1939SAndy Fiddaman }
408*b30d1939SAndy Fiddaman else if (streq(t, "translation"))
409*b30d1939SAndy Fiddaman xp = translation(xp, s);
410*b30d1939SAndy Fiddaman }
411*b30d1939SAndy Fiddaman else
412*b30d1939SAndy Fiddaman {
413*b30d1939SAndy Fiddaman t = s + sfvalue(mp);
414*b30d1939SAndy Fiddaman num = (int)strtol(s, &e, 0);
415*b30d1939SAndy Fiddaman if (e != s)
416*b30d1939SAndy Fiddaman {
417*b30d1939SAndy Fiddaman s = e;
418*b30d1939SAndy Fiddaman if (!*s)
419*b30d1939SAndy Fiddaman {
420*b30d1939SAndy Fiddaman if (mcput(mc, set, num, NiL))
421*b30d1939SAndy Fiddaman error(2, "(%d,%d): cannot delete message", set, num);
422*b30d1939SAndy Fiddaman }
423*b30d1939SAndy Fiddaman else if (isspace(*s++))
424*b30d1939SAndy Fiddaman {
425*b30d1939SAndy Fiddaman if (t > (s + 1) && *(t -= 2) == '\\')
426*b30d1939SAndy Fiddaman {
427*b30d1939SAndy Fiddaman sfwrite(tp, s, t - s);
428*b30d1939SAndy Fiddaman while (s = sfgetr(mp, '\n', 0))
429*b30d1939SAndy Fiddaman {
430*b30d1939SAndy Fiddaman error_info.line++;
431*b30d1939SAndy Fiddaman t = s + sfvalue(mp);
432*b30d1939SAndy Fiddaman if (t <= (s + 1) || *(t -= 2) != '\\')
433*b30d1939SAndy Fiddaman break;
434*b30d1939SAndy Fiddaman sfwrite(tp, s, t - s);
435*b30d1939SAndy Fiddaman }
436*b30d1939SAndy Fiddaman if (!(s = sfstruse(tp)))
437*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "out of space");
438*b30d1939SAndy Fiddaman }
439*b30d1939SAndy Fiddaman if (q)
440*b30d1939SAndy Fiddaman {
441*b30d1939SAndy Fiddaman if (*s++ != q)
442*b30d1939SAndy Fiddaman {
443*b30d1939SAndy Fiddaman error(2, "(%d,%d): %c quote expected", set, num, q);
444*b30d1939SAndy Fiddaman continue;
445*b30d1939SAndy Fiddaman }
446*b30d1939SAndy Fiddaman b = t = s;
447*b30d1939SAndy Fiddaman while (c = *s++)
448*b30d1939SAndy Fiddaman {
449*b30d1939SAndy Fiddaman if (c == '\\')
450*b30d1939SAndy Fiddaman {
451*b30d1939SAndy Fiddaman c = chresc(s - 1, &e);
452*b30d1939SAndy Fiddaman s = e;
453*b30d1939SAndy Fiddaman if (c)
454*b30d1939SAndy Fiddaman *t++ = c;
455*b30d1939SAndy Fiddaman else
456*b30d1939SAndy Fiddaman error(1, "nul character ignored");
457*b30d1939SAndy Fiddaman }
458*b30d1939SAndy Fiddaman else if (c == q)
459*b30d1939SAndy Fiddaman break;
460*b30d1939SAndy Fiddaman else
461*b30d1939SAndy Fiddaman *t++ = c;
462*b30d1939SAndy Fiddaman }
463*b30d1939SAndy Fiddaman if (*s)
464*b30d1939SAndy Fiddaman {
465*b30d1939SAndy Fiddaman error(2, "(%d,%d): characters after quote not expected", set, num);
466*b30d1939SAndy Fiddaman continue;
467*b30d1939SAndy Fiddaman }
468*b30d1939SAndy Fiddaman *t = 0;
469*b30d1939SAndy Fiddaman s = b;
470*b30d1939SAndy Fiddaman }
471*b30d1939SAndy Fiddaman if (mcput(mc, set, num, s))
472*b30d1939SAndy Fiddaman error(2, "(%d,%d): cannot add message", set, num);
473*b30d1939SAndy Fiddaman }
474*b30d1939SAndy Fiddaman else
475*b30d1939SAndy Fiddaman error(2, "message text expected");
476*b30d1939SAndy Fiddaman }
477*b30d1939SAndy Fiddaman else
478*b30d1939SAndy Fiddaman error(2, "message number expected");
479*b30d1939SAndy Fiddaman }
480*b30d1939SAndy Fiddaman }
481*b30d1939SAndy Fiddaman error_info.file = 0;
482*b30d1939SAndy Fiddaman error_info.line = 0;
483*b30d1939SAndy Fiddaman
484*b30d1939SAndy Fiddaman /*
485*b30d1939SAndy Fiddaman * fix up the translation record
486*b30d1939SAndy Fiddaman */
487*b30d1939SAndy Fiddaman
488*b30d1939SAndy Fiddaman if (xp)
489*b30d1939SAndy Fiddaman {
490*b30d1939SAndy Fiddaman t = "";
491*b30d1939SAndy Fiddaman for (;;)
492*b30d1939SAndy Fiddaman {
493*b30d1939SAndy Fiddaman for (bp = 0, px = xp; px; px = px->next)
494*b30d1939SAndy Fiddaman if (px->date && (!bp || strcoll(bp->date, px->date) < 0))
495*b30d1939SAndy Fiddaman bp = px;
496*b30d1939SAndy Fiddaman if (!bp)
497*b30d1939SAndy Fiddaman break;
498*b30d1939SAndy Fiddaman sfprintf(tp, "%s%s %s", t, bp->name, bp->date);
499*b30d1939SAndy Fiddaman t = ", ";
500*b30d1939SAndy Fiddaman bp->date = 0;
501*b30d1939SAndy Fiddaman }
502*b30d1939SAndy Fiddaman if (!(mc->translation = sfstruse(tp)))
503*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "out of space");
504*b30d1939SAndy Fiddaman }
505*b30d1939SAndy Fiddaman
506*b30d1939SAndy Fiddaman /*
507*b30d1939SAndy Fiddaman * dump the catalog to a local temporary
508*b30d1939SAndy Fiddaman * rename if no errors
509*b30d1939SAndy Fiddaman */
510*b30d1939SAndy Fiddaman
511*b30d1939SAndy Fiddaman if (!(s = pathtemp(NiL, 0, "", error_info.id, NiL)) || !(sp = sfopen(NiL, s, "w")))
512*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "%s: cannot write catalog file", catfile);
513*b30d1939SAndy Fiddaman if (mcdump(mc, sp) || mcclose(mc) || sfclose(sp))
514*b30d1939SAndy Fiddaman {
515*b30d1939SAndy Fiddaman remove(s);
516*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "%s: temporary catalog file write error", s);
517*b30d1939SAndy Fiddaman }
518*b30d1939SAndy Fiddaman remove(catfile);
519*b30d1939SAndy Fiddaman if (rename(s, catfile))
520*b30d1939SAndy Fiddaman error(ERROR_SYSTEM|3, "%s: cannot rename from temporary catalog file %s", catfile, s);
521*b30d1939SAndy Fiddaman return error_info.errors != 0;
522*b30d1939SAndy Fiddaman }
523