da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/***********************************************************************
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* This software is part of the ast package *
34f9b3eef6fdadbda0a846aa4d68691ac40eace5Roland Mainz* Copyright (c) 2000-2009 AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* and is licensed under the *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Common Public License, Version 1.0 *
7c2fbfb345896881c631598ee3852ce9ce33fb07April Chin* by AT&T Intellectual Property *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* A copy of the License is available at *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* http://www.opensource.org/licenses/cpl1.0.txt *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Information and Software Systems Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* AT&T Research *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Florham Park NJ *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* Glenn Fowler <gsf@research.att.com> *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin* *
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin***********************************************************************/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#pragma prototyped
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Glenn Fowler
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * AT&T Research
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic const char usage[] =
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[-?\n@(#)$Id: msggen (AT&T Research) 2002-03-11 $\n]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinUSAGE_LICENSE
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+NAME?msggen - generate a machine independent formatted message catalog]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+DESCRIPTION?\bmsggen\b merges the message text source files \amsgfile\a"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" into a machine independent formatted message catalog \acatfile\a."
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" The file \acatfile\a will be created if it does not already exist."
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" If \acatfile\a does exist, its messages will be included in the new"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \acatfile\a. If set and message numbers collide, the new message"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" text defined in \amsgfile\a will replace the old message text"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" currently contained in \acatfile\a. Non-ASCII characters must be"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" UTF-8 encoded. \biconv\b(1) can be used to convert to/from UTF-8.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[f:format?List the \bprintf\b(3) format signature for each message in"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \acatfile\a. A format signature is one line containing one character"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" per format specification:]{"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [c?char]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [d?double]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [D?long double]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [f?float]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [h?short]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [i?int]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [j?long long]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [l?long]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [p?void*]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [s?string]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [t?ptrdiff_t]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [z?size_t]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [???unknown]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"}"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[l:list?List \acatfile\a in UTF-8 \amsgfile\a form.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[s:set?Convert the \acatfile\a operand to a message set number and"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" print the number on the standard output.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+EXTENDED DESCRIPTION?Message text source files are in \bgencat\b(1)"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" format, defined as follows. Note that the fields of a message text"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" source line are separated by a single blank character. Any other"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" blank characters are considered as being part of the subsequent"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" field. The \bNL_*\b constants are defined in one or both of"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \b<limits.h>\b and \b<nl_types.h>\b.]{"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [+$ \acomment\a?A line beginning with \b$\b followed by a"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" blank character is treated as a comment.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [+$delset \an\a \acomment\a?This line deletes message set"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \an\a from an existing message catalog. \an\a"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" denotes the set number [1, \bNL_SETMAX\b]]. Any"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" text following the set number is treated as a"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" comment.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [+$quote \ac\a?This line specifies an optional quote"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" character \ac\a, which can be used to surround"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \amessage-text\a so that trailing spaces or"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" empty messages are visible in a message source"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" line. By default, or if an empty \b$quote\b"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" directive is supplied, no quoting of \amessage-text\a"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" will be recognized.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [+$set \an\a \acomment\a?This line specifies the set"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" identifier of the following messages until the next"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \b$set\b or end-of-file appears. \an\a denotes the set"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" identifier, which is defined as a number in the range"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [1, \bNL_SETMAX\b]]. Set numbers need not be"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" contiguous. Any text following the set identifier is"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" treated as a comment. If no \b$set\b directive is"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" specified in a message text source file, all messages"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" will be located in message set \b1\b.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [+$translation \aidentification\a \aYYYY-MM-DD\a[,...]]?Append"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" translation info to the message catalog header. Only"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" the newest date for a given \aidentification\a"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" is retained in the catalog. Multiple translation lines"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" are combined into a single \b,\b separated list.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [+\am\a \amessage-text\a?\am\a denotes the message identifier,"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" which is defined as a number in the range"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" [1, \bNL_MSGMAX\b]]. The message-text is stored in the"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" message catalogue with the set identifier specified by"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" the last \b$set\b directive, and with message"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" identifier \am\a. If the \amessage-text\a is empty,"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" and a blank character field separator is present, an"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" empty string is stored in the message catalogue. If a"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" message source line has a message number, but neither"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" a field separator nor \amessage-text\a, the existing"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" message with that number (if any) is deleted from the"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" catalogue. Message identifiers need not be contiguous."
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" There are no \amessage-text\a length restrictions.]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"}"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\ncatfile [ msgfile ]\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"\n"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin"[+SEE ALSO?\bgencat\b(1), \biconv\b(1), \bmsgcc\b(1), \btranslate\b(1),"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin" \bfmtfmt\b(3)]"
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ast.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ctype.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <ccode.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <error.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin#include <mc.h>
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintypedef struct Xl_s
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin struct Xl_s* next;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* date;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char name[1];
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin} Xl_t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * append s to the translation list
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic Xl_t*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chintranslation(Xl_t* xp, register char* s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Xl_t* px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* d;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (; isspace(*s); s++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (d = e = 0, t = s; *t; t++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*t == ',')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin e = t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *e++ = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (isspace(*t))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin d = t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (d)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *d++ = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (px = xp; px; px = px->next)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (streq(px->name, s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (strcoll(px->date, d) < 0)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin free(px->date);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(px->date = strdup(d)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "out of space [translation]");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!px)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(px = newof(0, Xl_t, 1, strlen(s))) || !(px->date = strdup(d)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "out of space [translation]");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin strcpy(px->name, s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin px->next = xp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin xp = px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } while (s = e);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return xp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin/*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * sfprintf() with ccmaps(from,to)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinstatic int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinccsfprintf(int from, int to, Sfio_t* sp, const char* format, ...)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin va_list ap;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* tp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin va_start(ap, format);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (from == to)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = sfvprintf(sp, format, ap);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (tp = sfstropen())
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = sfvprintf(tp, format, ap);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = sfstrbase(tp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ccmaps(s, n, from, to);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = sfwrite(sp, s, n);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfstrclose(tp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin n = -1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return n;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinint
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinmain(int argc, char** argv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin{
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register Mc_t* mc;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register char* t;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int q;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin register int i;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int num;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* b;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* catfile;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin char* msgfile;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* sp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* mp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Sfio_t* tp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Xl_t* px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Xl_t* bp;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin Xl_t* xp = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int format = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int list = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin int set = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin NoP(argc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.id = "msggen";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (optget(argv, usage))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'f':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin format = list = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 'l':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin list = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 's':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin set = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case '?':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_USAGE|4, "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case ':':
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "%s", opt_info.arg);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin argv += opt_info.index;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (error_info.errors || !(catfile = *argv++))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_USAGE|4, "%s", optusage(NiL));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * set and list only need catfile
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (set)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstdout, "%d\n", mcindex(catfile, NiL, NiL, NiL));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return error_info.errors != 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (list)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(sp = sfopen(NiL, catfile, "r")))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "%s: cannot read catalog", catfile);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(mc = mcopen(sp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "%s: catalog content error", catfile);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose(sp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (format)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (set = 1; set <= mc->num; set++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (mc->set[set].num)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstdout, "$set %d\n", set);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (num = 1; num <= mc->set[set].num; num++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (s = mc->set[set].msg[num])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstdout, "%d \"%s\"\n", num, fmtfmt(s));
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*mc->translation)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$translation ");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(sfstdout, "%s", mc->translation);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\n");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$quote \"\n");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (set = 1; set <= mc->num; set++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (mc->set[set].num)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "$set %d\n", set);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (num = 1; num <= mc->set[set].num; num++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (s = mc->set[set].msg[num])
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "%d \"", num);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (c = *s++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*INDENT...*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin switch (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0x22: /* " */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0x5C: /* \ */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(sfstdout, 0x5C);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0x07: /* \a */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 0x61;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(sfstdout, 0x5C);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0x08: /* \b */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 0x62;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(sfstdout, 0x5C);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0x0A: /* \n */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 0x6E;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(sfstdout, 0x5C);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0x0B: /* \v */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 0x76;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(sfstdout, 0x5C);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0x0C: /* \f */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 0x66;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(sfstdout, 0x5C);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin case 0x0D: /* \r */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = 0x72;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(sfstdout, 0x5C);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*...UNDENT*/
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfputc(sfstdout, c);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin ccsfprintf(CC_NATIVE, CC_ASCII, sfstdout, "\"\n");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mcclose(mc);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return error_info.errors != 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (!(msgfile = *argv++) || *argv)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(3, "exactly one message file must be specified");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * open the files and handles
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(tp = sfstropen()))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "out of space [string stream]");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(mp = sfopen(NiL, msgfile, "r")))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "%s: cannot read message file", msgfile);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sp = sfopen(NiL, catfile, "r");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(mc = mcopen(sp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "%s: catalog content error", catfile);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (sp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfclose(sp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin xp = translation(xp, mc->translation);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * read the message file
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin set = 1;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.file = msgfile;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (s = sfgetr(mp, '\n', 1))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.line++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!*s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s == '$')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!*++s || isspace(*s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (t = s; *s && !isspace(*s); s++);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *s++ = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (streq(t, "delset"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isspace(*s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin num = (int)strtol(s, NiL, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (num < mc->num && mc->set[num].num)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i = 1; i <= mc->set[num].num; i++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin mcput(mc, num, i, NiL);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (streq(t, "quote"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin q = *s ? *s : 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (streq(t, "set"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (isspace(*s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin num = (int)strtol(s, &e, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e != s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin set = num;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "set number expected");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (streq(t, "translation"))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin xp = translation(xp, s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = s + sfvalue(mp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin num = (int)strtol(s, &e, 0);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (e != s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!*s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (mcput(mc, set, num, NiL))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "(%d,%d): cannot delete message", set, num);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (isspace(*s++))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (t > (s + 1) && *(t -= 2) == '\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfwrite(tp, s, t - s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (s = sfgetr(mp, '\n', 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.line++;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = s + sfvalue(mp);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (t <= (s + 1) || *(t -= 2) != '\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfwrite(tp, s, t - s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(s = sfstruse(tp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "out of space");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (q)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s++ != q)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "(%d,%d): %c quote expected", set, num, q);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin b = t = s;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin while (c = *s++)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c == '\\')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin c = chresc(s - 1, &e);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = e;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (c)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(1, "nul character ignored");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else if (c == q)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t++ = c;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (*s)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "(%d,%d): characters after quote not expected", set, num);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin continue;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin *t = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin s = b;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (mcput(mc, set, num, s))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "(%d,%d): cannot add message", set, num);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "message text expected");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin else
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(2, "message number expected");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.file = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error_info.line = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * fix up the translation record
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (xp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = "";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (;;)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (bp = 0, px = xp; px; px = px->next)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (px->date && (!bp || strcoll(bp->date, px->date) < 0))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bp = px;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!bp)
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin break;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin sfprintf(tp, "%s%s %s", t, bp->name, bp->date);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin t = ", ";
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin bp->date = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(mc->translation = sfstruse(tp)))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "out of space");
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin /*
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * dump the catalog to a local temporary
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * rename if no errors
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin */
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (!(s = pathtemp(NiL, 0, "", error_info.id, NiL)) || !(sp = sfopen(NiL, s, "w")))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "%s: cannot write catalog file", catfile);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (mcdump(mc, sp) || mcclose(mc) || sfclose(sp))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin remove(s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "%s: temporary catalog file write error", s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin }
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin remove(catfile);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (rename(s, catfile))
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin error(ERROR_SYSTEM|3, "%s: cannot rename from temporary catalog file %s", catfile, s);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin return error_info.errors != 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin}