CUBRID Engine  latest
gencat.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1996 The NetBSD Foundation, Inc.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to The NetBSD Foundation
6  * by J.T. Conklin.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #if !defined(WINDOWS)
31 #include <sys/cdefs.h>
32 #endif
33 #if defined(__RCSID) && !defined(lint)
34 __RCSID ("$NetBSD: gencat.c,v 1.26 2008/11/04 03:14:46 ginsbach Exp $");
35 #endif
36 
37 /***********************************************************
38 Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
39 
40  All Rights Reserved
41 
42 Permission to use, copy, modify, and distribute this software and its
43 documentation for any purpose and without fee is hereby granted,
44 provided that the above copyright notice appear in all copies and that
45 both that copyright notice and this permission notice appear in
46 supporting documentation, and that Alfalfa's name not be used in
47 advertising or publicity pertaining to distribution of the software
48 without specific, written prior permission.
49 
50 ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
51 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
52 ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
53 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
54 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
55 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
56 SOFTWARE.
57 
58 If you make any modifications, bugfixes or other changes to this software
59 we'd appreciate it if you could send a copy to us so we can keep things
60 up-to-date. Many thanks.
61  Kee Hinckley
62  Alfalfa Software, Inc.
63  267 Allston St., #3
64  Cambridge, MA 02139 USA
65  nazgul@alfalfa.com
66 
67 ******************************************************************/
68 
69 #if defined(__USE_GNU)
70 #undef __USE_GNU
71 #endif
72 
73 #if HAVE_NBTOOL_CONFIG_H
74 #include "nbtool_config.h"
75 #endif
76 
77 #define _NLS_PRIVATE
78 
79 #include <sys/types.h>
80 #if defined(WINDOWS)
81 #include "queue.h"
82 #else
83 #include <sys/queue.h>
84 #endif
85 
86 #if !defined(WINDOWS)
87 #include <arpa/inet.h> /* Needed for htonl() on POSIX systems */
88 #endif
89 
90 #include <ctype.h>
91 #include <errno.h>
92 #include <fcntl.h>
93 #include <limits.h>
94 #include <stdio.h>
95 #include <stdlib.h>
96 #include <string.h>
97 
98 #if !defined(WINDOWS)
99 #include <unistd.h>
100 #endif
101 
102 #if defined(WINDOWS)
103 #include <io.h>
104 #include <winsock2.h>
105 #if !defined(_MSC_VER) || _MSC_VER < 1800
106 /* ref: https://msdn.microsoft.com/en-us/library/323b6b3k(v=vs.140).aspx
107  * NOTE: Even though the intX_t types are mentioned only in VS 2015 documentation, I know for a fact that they are found in VS 2013 too (_MSC_VER 1800).
108  * Maybe even earlier versions, but I didn't find exact info.
109  */
110 typedef int int32_t;
111 #endif /* _MSC_VER */
112 #endif /* WINDOWS */
113 
114 #include "porting.h"
115 #include "cubrid_getopt.h"
116 
117 #ifndef NL_SETMAX
118 #define NL_SETMAX 255
119 #endif
120 #ifndef NL_MSGMAX
121 #define NL_MSGMAX 2048
122 #endif
123 
124 struct _msgT
125 {
126  long msgId;
127  char *str;
128  LIST_ENTRY (_msgT) entries;
129 };
130 
131 struct _setT
132 {
133  long setId;
134  LIST_HEAD (msghead, _msgT) msghead;
135  LIST_ENTRY (_setT) entries;
136 };
137 
138 #define _NLS_MAGIC 0xff88ff89
139 
141 {
142  int32_t __magic;
143  int32_t __nsets;
144  int32_t __mem;
147 };
148 
150 {
151  int32_t __setno; /* set number: 0 < x <= NL_SETMAX */
152  int32_t __nmsgs; /* number of messages in the set */
153  int32_t __index; /* index of first msg_hdr in msg_hdr table */
154 };
155 
157 {
158  int32_t __msgno; /* msg number: 0 < x <= NL_MSGMAX */
159  int32_t __msglen;
160  int32_t __offset;
161 };
162 
163 #define NL_SETD 0
164 #define NL_CAT_LOCALE 1
165 
166 LIST_HEAD (sethead, _setT) sethead;
167  static struct _setT *curSet;
168 
169  static const char *curfile;
170  static char *curline = NULL;
171  static long lineno = 0;
172 
173  static char *cskip (char *);
174  static void error (const char *);
175  static char *get_line (int);
176  static char *getmsg (int, char *, char);
177  static void warning (const char *, const char *);
178  static char *wskip (char *);
179  static char *xstrdup (const char *);
180  static void *xmalloc (size_t);
181  static void *xrealloc (void *, size_t);
182 
183  void MCParse (int fd);
184  void MCReadCat (int fd);
185  void MCWriteCat (int fd);
186  void MCDelMsg (int msgId);
187  void MCAddMsg (int msgId, const char *msg);
188  void MCAddSet (int setId);
189  void MCDelSet (int setId);
190  int main (int, char **);
191  void usage (void);
192 
193  static char *progname;
194 
195 #define CORRUPT "corrupt message catalog"
196 #define NOMEMORY "out of memory"
197 
198  void usage (void)
199 {
200  fprintf (stderr, "usage: %s catfile msgfile ...\n", progname);
201  exit (1);
202 }
203 
204 int
205 main (int argc, char *argv[])
206 {
207  int ofd, ifd;
208  char *catfile = NULL;
209  int c;
210  int updatecat = 0;
211 
212  progname = argv[0];
213 
214  while ((c = getopt (argc, argv, "")) != -1)
215  {
216  switch (c)
217  {
218  case '?':
219  default:
220  usage ();
221  /* NOTREACHED */
222  }
223  }
224  argc -= optind;
225  argv += optind;
226 
227  if (argc < 2)
228  {
229  usage ();
230  /* NOTREACHED */
231  }
232  catfile = *argv++;
233 
234  if ((catfile[0] == '-') && (catfile[1] == '\0'))
235  {
236 #if defined(WINDOWS)
237  ofd = _fileno (stdout);
238 #else
239  ofd = STDOUT_FILENO;
240 #endif
241 
242  }
243  else
244  {
245  ofd = open (catfile, O_WRONLY | O_CREAT | O_EXCL, 0666);
246  if (ofd < 0)
247  {
248  if (errno == EEXIST)
249  {
250  if ((ofd = open (catfile, O_RDWR)) < 0)
251  {
252  err (1, "Unable to open %s", catfile);
253  /* NOTREACHED */
254  }
255  }
256  else
257  {
258  err (1, "Unable to create new %s", catfile);
259  /* NOTREACHED */
260  }
261  curfile = catfile;
262  updatecat = 1;
263  MCReadCat (ofd);
264  if (lseek (ofd, SEEK_SET, 0) < 0)
265  {
266  err (1, "Unable to seek on %s", catfile);
267  /* NOTREACHED */
268  }
269  }
270  }
271 
272  if (((*argv)[0] == '-') && ((*argv)[1] == '\0'))
273  {
274  if (argc != 2)
275  usage ();
276  /* NOTREACHED */
277 #if defined(WINDOWS)
278  MCParse (_fileno (stdin));
279 #else
280  MCParse (STDIN_FILENO);
281 #endif
282  }
283  else
284  {
285  for (; *argv; argv++)
286  {
287  if ((ifd = open (*argv, O_RDONLY)) < 0)
288  err (1, "Unable to read %s", *argv);
289  curfile = *argv;
290  lineno = 0;
291  MCParse (ifd);
292  close (ifd);
293  }
294  }
295 
296  if (updatecat)
297  {
298  if (ftruncate (ofd, 0) != 0)
299  {
300  err (1, "Unable to truncate %s", catfile);
301  /* NOTREACHED */
302  }
303  }
304 
305  MCWriteCat (ofd);
306  exit (0);
307 }
308 
309 static void
310 warning (const char *cptr, const char *msg)
311 {
312  if (lineno)
313  {
314  fprintf (stderr, "%s: %s on line %ld, %s\n", progname, msg, lineno, curfile);
315  fprintf (stderr, "%s\n", curline);
316  if (cptr)
317  {
318  char *tptr;
319  for (tptr = curline; tptr < cptr; ++tptr)
320  putc (' ', stderr);
321  fprintf (stderr, "^\n");
322  }
323  }
324  else
325  {
326  fprintf (stderr, "%s: %s, %s\n", progname, msg, curfile);
327  }
328 }
329 
330 static void
331 error (const char *msg)
332 {
333  warning (NULL, msg);
334  exit (1);
335 }
336 
337 static void *
338 xmalloc (size_t len)
339 {
340  void *p;
341 
342  if ((p = malloc (len)) == NULL)
343  {
344 #if defined(WINDOWS)
345  error (NOMEMORY);
346 #else
347  errx (1, NOMEMORY);
348 #endif
349  }
350  return (p);
351 }
352 
353 static void *
354 xrealloc (void *ptr, size_t size)
355 {
356  void *const realloc_ptr = realloc (ptr, size);
357  if (realloc_ptr == NULL)
358  {
359 #if defined(WINDOWS)
360  error (NOMEMORY);
361 #else
362  errx (1, NOMEMORY);
363 #endif
364  return NULL;
365  }
366  else
367  {
368  return realloc_ptr;
369  }
370 }
371 
372 static char *
373 xstrdup (const char *str)
374 {
375  char *nstr;
376 
377  if ((nstr = strdup (str)) == NULL)
378  {
379 #if defined(WINDOWS)
380  error (NOMEMORY);
381 #else
382  errx (1, NOMEMORY);
383 #endif
384  }
385  return (nstr);
386 }
387 
388 static char *
389 get_line (int fd)
390 {
391  static long curlen = BUFSIZ;
392  static char buf[BUFSIZ], *bptr = buf, *bend = buf;
393  char *cptr, *cend;
394  long buflen;
395 
396  if (!curline)
397  {
398  curline = (char *) xmalloc (curlen);
399  }
400  ++lineno;
401 
402  cptr = curline;
403  cend = curline + curlen;
404  for (;;)
405  {
406  for (; bptr < bend && cptr < cend; ++cptr, ++bptr)
407  {
408  if (*bptr == '\n')
409  {
410  *cptr = '\0';
411  ++bptr;
412  return (curline);
413  }
414  else if (bptr + 1 < bend && *bptr == '\r' && *(bptr + 1) == '\n')
415  {
416  *cptr = '\0';
417  ++bptr;
418  ++bptr;
419  return (curline);
420  }
421  else
422  {
423  *cptr = *bptr;
424  }
425  }
426  if (cptr == cend)
427  {
428  /* relocate cptr to hold the offset from curline */
429  int offset = (int) (cptr - curline);
430  curline = (char *) xrealloc (curline, curlen *= 2);
431  cptr = curline + offset;
432  cend = curline + curlen;
433  }
434  if (bptr == bend)
435  {
436  char last_char_prev_buf = 0;
437 
438  if (bptr > buf)
439  {
440  last_char_prev_buf = *(bptr - 1);
441  }
442 
443  buflen = read (fd, buf, BUFSIZ);
444  if (buflen <= 0)
445  {
446  if (cptr > curline)
447  {
448  *cptr = '\0';
449  return (curline);
450  }
451  return (NULL);
452  }
453  bend = buf + buflen;
454  bptr = buf;
455 
456  /* special case : <CR><LF> is split at buffer bound */
457  if (last_char_prev_buf == '\r' && *bptr == '\n')
458  {
459  if (cptr > curline)
460  {
461  cptr--;
462  }
463  *cptr = '\0';
464  ++bptr;
465  return (curline);
466  }
467  }
468  }
469 }
470 
471 static char *
472 wskip (char *cptr)
473 {
474  if (!*cptr || !isspace ((unsigned char) *cptr))
475  {
476  warning (cptr, "expected a space");
477  return (cptr);
478  }
479  while (*cptr && isspace ((unsigned char) *cptr))
480  ++cptr;
481  return (cptr);
482 }
483 
484 static char *
485 cskip (char *cptr)
486 {
487  if (!*cptr || isspace ((unsigned char) *cptr))
488  {
489  warning (cptr, "wasn't expecting a space");
490  return (cptr);
491  }
492  while (*cptr && !isspace ((unsigned char) *cptr))
493  ++cptr;
494  return (cptr);
495 }
496 
497 static char *
498 getmsg (int fd, char *cptr, char quote)
499 {
500  static char *msg = NULL;
501  static size_t msglen = 0;
502  size_t clen;
503  int i;
504  char *tptr;
505 
506  if (quote && *cptr == quote)
507  {
508  ++cptr;
509  }
510 
511  clen = strlen (cptr) + 1;
512  if (clen > msglen)
513  {
514  if (msglen)
515  msg = (char *) xrealloc (msg, clen);
516  else
517  msg = (char *) xmalloc (clen);
518  msglen = clen;
519  }
520  tptr = msg;
521 
522  while (*cptr)
523  {
524  if (quote && *cptr == quote)
525  {
526  char *tmp;
527  tmp = cptr + 1;
528  if (*tmp && (!isspace ((unsigned char) *tmp) || *wskip (tmp)))
529  {
530  warning (cptr, "unexpected quote character, ignoring");
531  *tptr++ = *cptr++;
532  }
533  else
534  {
535  *cptr = '\0';
536  }
537  }
538  else
539  {
540  if (*cptr == '\\')
541  {
542  ++cptr;
543  switch (*cptr)
544  {
545  case '\0':
546  cptr = get_line (fd);
547  if (!cptr)
548  error ("premature end of file");
549  msglen += strlen (cptr);
550  i = (int) (tptr - msg);
551  msg = (char *) xrealloc (msg, msglen);
552  tptr = msg + i;
553  break;
554  case 'n':
555  *tptr++ = '\n';
556  ++cptr;
557  break;
558  case 't':
559  *tptr++ = '\t';
560  ++cptr;
561  break;
562  case 'v':
563  *tptr++ = '\v';
564  ++cptr;
565  break;
566  case 'b':
567  *tptr++ = '\b';
568  ++cptr;
569  break;
570  case 'r':
571  *tptr++ = '\r';
572  ++cptr;
573  break;
574  case 'f':
575  *tptr++ = '\f';
576  ++cptr;
577  break;
578  case '"':
579  *tptr++ = '"';
580  ++cptr;
581  break;
582  case '\\':
583  *tptr++ = '\\';
584  ++cptr;
585  break;
586  default:
587  if (quote && *cptr == quote)
588  {
589  *tptr++ = *cptr++;
590  }
591  else if (isdigit ((unsigned char) *cptr))
592  {
593  *tptr = 0;
594  for (i = 0; i < 3; ++i)
595  {
596  if (!isdigit ((unsigned char) *cptr))
597  break;
598  if (*cptr > '7')
599  warning (cptr, "octal number greater than 7?!");
600  *tptr *= 8;
601  *tptr += (*cptr - '0');
602  ++cptr;
603  }
604  }
605  else
606  {
607  warning (cptr, "unrecognized escape sequence");
608  }
609  break;
610  }
611  }
612  else
613  {
614  *tptr++ = *cptr++;
615  }
616  }
617  }
618  *tptr = '\0';
619  return (msg);
620 }
621 
622 void
623 MCParse (int fd)
624 {
625  char *cptr, *str;
626  int msgid = 0;
627  int setid = 0;
628  char quote = 0;
629 
630  /* XXX: init sethead? */
631 
632  while ((cptr = get_line (fd)))
633  {
634  if (*cptr == '$')
635  {
636  ++cptr;
637  if (strncmp (cptr, "set", 3) == 0)
638  {
639  cptr += 3;
640  cptr = wskip (cptr);
641  setid = atoi (cptr);
642  MCAddSet (setid);
643  msgid = 0;
644  }
645  else if (strncmp (cptr, "delset", 6) == 0)
646  {
647  cptr += 6;
648  cptr = wskip (cptr);
649  setid = atoi (cptr);
650  MCDelSet (setid);
651  }
652  else if (strncmp (cptr, "quote", 5) == 0)
653  {
654  cptr += 5;
655  if (!*cptr)
656  quote = 0;
657  else
658  {
659  cptr = wskip (cptr);
660  if (!*cptr)
661  quote = 0;
662  else
663  quote = *cptr;
664  }
665  }
666  else if (isspace ((unsigned char) *cptr))
667  {
668  ;
669  }
670  else
671  {
672  if (*cptr)
673  {
674  cptr = wskip (cptr);
675  if (*cptr)
676  warning (cptr, "unrecognized line");
677  }
678  }
679  }
680  else
681  {
682  /*
683  * First check for (and eat) empty lines....
684  */
685  if (!*cptr)
686  continue;
687  /*
688  * We have a digit? Start of a message. Else,
689  * syntax error.
690  */
691  if (isdigit ((unsigned char) *cptr))
692  {
693  msgid = atoi (cptr);
694  cptr = cskip (cptr);
695  if (*cptr)
696  {
697  cptr = wskip (cptr);
698  if (!*cptr)
699  {
700  MCAddMsg (msgid, "");
701  continue;
702  }
703  }
704  }
705  else
706  {
707  warning (cptr, "neither blank line nor start of a message id");
708  continue;
709  }
710  /*
711  * If no set directive specified, all messages
712  * shall be in default message set NL_SETD.
713  */
714  if (setid == 0)
715  {
716  setid = NL_SETD;
717  MCAddSet (setid);
718  }
719  /*
720  * If we have a message ID, but no message,
721  * then this means "delete this message id
722  * from the catalog".
723  */
724  if (!*cptr)
725  {
726  MCDelMsg (msgid);
727  }
728  else
729  {
730  str = getmsg (fd, cptr, quote);
731  MCAddMsg (msgid, str);
732  }
733  }
734  }
735 }
736 
737 void
738 MCReadCat (int fd)
739 {
740  void *msgcat; /* message catalog data */
741  struct _nls_cat_hdr cat_hdr;
742  struct _nls_set_hdr *set_hdr;
743  struct _nls_msg_hdr *msg_hdr;
744  char *strings;
745  int m, n, s;
746  int msgno, setno;
747 
748  /* XXX init sethead? */
749 
750  n = read (fd, &cat_hdr, sizeof (cat_hdr));
751  if (n < (int) sizeof (cat_hdr))
752  {
753  if (n == 0)
754  return; /* empty file */
755  else if (n == -1)
756  err (1, "header read");
757  else
758  {
759 #if defined(WINDOWS)
760  error (CORRUPT);
761 #else
762  errx (1, CORRUPT);
763 #endif
764  }
765  }
766  if (ntohl (cat_hdr.__magic) != _NLS_MAGIC)
767  {
768 #if defined(WINDOWS)
769  error (CORRUPT);
770 #else
771  errx (1, "%s: bad magic number (%#x)", CORRUPT, cat_hdr.__magic);
772 #endif
773  }
774 
775  cat_hdr.__mem = ntohl (cat_hdr.__mem);
776  msgcat = xmalloc (cat_hdr.__mem);
777 
778  cat_hdr.__nsets = ntohl (cat_hdr.__nsets);
779  cat_hdr.__msg_hdr_offset = ntohl (cat_hdr.__msg_hdr_offset);
780  cat_hdr.__msg_txt_offset = ntohl (cat_hdr.__msg_txt_offset);
781  if ((cat_hdr.__mem < 0) || (cat_hdr.__msg_hdr_offset < 0) || (cat_hdr.__msg_txt_offset < 0)
782  || (cat_hdr.__mem < (cat_hdr.__nsets * (int) sizeof (struct _nls_set_hdr)))
783  || (cat_hdr.__mem < cat_hdr.__msg_hdr_offset) || (cat_hdr.__mem < cat_hdr.__msg_txt_offset))
784  {
785 #if defined(WINDOWS)
786  error (CORRUPT);
787 #else
788  errx (1, "%s: catalog header", CORRUPT);
789 #endif
790 
791  }
792 
793  n = read (fd, msgcat, cat_hdr.__mem);
794  if (n < cat_hdr.__mem)
795  {
796  if (n == -1)
797  err (1, "data read");
798  else
799  {
800 #if defined(WINDOWS)
801  error (CORRUPT);
802 #else
803  errx (1, CORRUPT);
804 #endif
805  }
806  }
807 
808  set_hdr = (struct _nls_set_hdr *) msgcat;
809  msg_hdr = (struct _nls_msg_hdr *) ((char *) msgcat + cat_hdr.__msg_hdr_offset);
810  strings = (char *) msgcat + cat_hdr.__msg_txt_offset;
811 
812  setno = 0;
813  for (s = 0; s < cat_hdr.__nsets; s++, set_hdr++)
814  {
815  set_hdr->__setno = ntohl (set_hdr->__setno);
816  if (set_hdr->__setno < setno)
817  {
818 #if defined(WINDOWS)
819  error (CORRUPT);
820 #else
821  errx (1, "%s: bad set number (%d)", CORRUPT, set_hdr->__setno);
822 #endif
823  }
824  setno = set_hdr->__setno;
825 
826  MCAddSet (setno);
827 
828  set_hdr->__nmsgs = ntohl (set_hdr->__nmsgs);
829  set_hdr->__index = ntohl (set_hdr->__index);
830  if (set_hdr->__nmsgs < 0 || set_hdr->__index < 0)
831  {
832 #if defined(WINDOWS)
833  error (CORRUPT);
834 #else
835  errx (1, "%s: set header", CORRUPT);
836 #endif
837 
838  }
839 
840  /* Get the data */
841  msgno = 0;
842  for (m = 0; m < set_hdr->__nmsgs; m++, msg_hdr++)
843  {
844  msg_hdr->__msgno = ntohl (msg_hdr->__msgno);
845  msg_hdr->__offset = ntohl (msg_hdr->__offset);
846  if (msg_hdr->__msgno < msgno)
847  {
848 #if defined(WINDOWS)
849  error (CORRUPT);
850 #else
851  errx (1, "%s: bad message number (%d)", CORRUPT, msg_hdr->__msgno);
852 #endif
853 
854  }
855  if ((msg_hdr->__offset < 0) || ((strings + msg_hdr->__offset) > ((char *) msgcat + cat_hdr.__mem)))
856  {
857 #if defined(WINDOWS)
858  error (CORRUPT);
859 #else
860  errx (1, "%s: message header", CORRUPT);
861 #endif
862 
863  }
864 
865  msgno = msg_hdr->__msgno;
866  MCAddMsg (msgno, strings + msg_hdr->__offset);
867  }
868  }
869  free (msgcat);
870 }
871 
872 /*
873  * Write message catalog.
874  *
875  * The message catalog is first converted from its internal to its
876  * external representation in a chunk of memory allocated for this
877  * purpose. Then the completed catalog is written. This approach
878  * avoids additional housekeeping variables and/or a lot of seeks
879  * that would otherwise be required.
880  */
881 void
882 MCWriteCat (int fd)
883 {
884  int nsets; /* number of sets */
885  int nmsgs; /* number of msgs */
886  size_t string_size; /* total size of string pool */
887  int msgcat_size; /* total size of message catalog */
888  void *msgcat; /* message catalog data */
889  struct _nls_cat_hdr *cat_hdr;
890  struct _nls_set_hdr *set_hdr;
891  struct _nls_msg_hdr *msg_hdr;
892  char *strings;
893  struct _setT *set;
894  struct _msgT *msg;
895  int msg_index;
896  int msg_offset;
897 
898  /* determine number of sets, number of messages, and size of the string pool */
899  nsets = 0;
900  nmsgs = 0;
901  string_size = 0;
902 
903  for (set = sethead.lh_first; set != NULL; set = set->entries.le_next)
904  {
905  nsets++;
906 
907  for (msg = set->msghead.lh_first; msg != NULL; msg = msg->entries.le_next)
908  {
909  nmsgs++;
910  string_size += strlen (msg->str) + 1;
911  }
912  }
913 
914 #ifdef DEBUG
915  printf ("number of sets: %d\n", nsets);
916  printf ("number of msgs: %d\n", nmsgs);
917  printf ("string pool size: %d\n", string_size);
918 #endif
919 
920  /* determine size and then allocate buffer for constructing external message catalog representation */
921  msgcat_size =
922  (int) (sizeof (struct _nls_cat_hdr) + (nsets * sizeof (struct _nls_set_hdr)) +
923  (nmsgs * sizeof (struct _nls_msg_hdr)) + string_size);
924 
925  msgcat = xmalloc (msgcat_size);
926  if (msgcat == NULL)
927  {
928  return;
929  }
930  memset (msgcat, '\0', msgcat_size);
931 
932  /* fill in msg catalog header */
933  cat_hdr = (struct _nls_cat_hdr *) msgcat;
934  cat_hdr->__magic = htonl (_NLS_MAGIC);
935  cat_hdr->__nsets = htonl (nsets);
936  cat_hdr->__mem = htonl (msgcat_size - sizeof (struct _nls_cat_hdr));
937  cat_hdr->__msg_hdr_offset = htonl (nsets * sizeof (struct _nls_set_hdr));
938  cat_hdr->__msg_txt_offset = htonl (nsets * sizeof (struct _nls_set_hdr) + nmsgs * sizeof (struct _nls_msg_hdr));
939 
940  /* compute offsets for set & msg header tables and string pool */
941  set_hdr = (struct _nls_set_hdr *) ((char *) msgcat + sizeof (struct _nls_cat_hdr));
942  msg_hdr =
943  (struct _nls_msg_hdr *) ((char *) msgcat + sizeof (struct _nls_cat_hdr) + nsets * sizeof (struct _nls_set_hdr));
944  strings =
945  (char *) msgcat + sizeof (struct _nls_cat_hdr) + nsets * sizeof (struct _nls_set_hdr) +
946  nmsgs * sizeof (struct _nls_msg_hdr);
947 
948  msg_index = 0;
949  msg_offset = 0;
950  for (set = sethead.lh_first; set != NULL; set = set->entries.le_next)
951  {
952 
953  nmsgs = 0;
954  for (msg = set->msghead.lh_first; msg != NULL; msg = msg->entries.le_next)
955  {
956  int msg_len = (int) strlen (msg->str) + 1;
957 
958  msg_hdr->__msgno = htonl (msg->msgId);
959  msg_hdr->__msglen = htonl (msg_len);
960  msg_hdr->__offset = htonl (msg_offset);
961 
962  memcpy (strings, msg->str, msg_len);
963  strings += msg_len;
964  msg_offset += msg_len;
965 
966  nmsgs++;
967  msg_hdr++;
968  }
969 
970  set_hdr->__setno = htonl (set->setId);
971  set_hdr->__nmsgs = htonl (nmsgs);
972  set_hdr->__index = htonl (msg_index);
973  msg_index += nmsgs;
974  set_hdr++;
975  }
976 
977  /* write out catalog. XXX: should this be done in small chunks? */
978  write (fd, msgcat, msgcat_size);
979  free (msgcat);
980 }
981 
982 void
983 MCAddSet (int setId)
984 {
985  struct _setT *p, *q;
986 
987  if (setId <= 0)
988  {
989  error ("setId's must be greater than zero");
990  /* NOTREACHED */
991  }
992  if (setId > NL_SETMAX)
993  {
994  error ("setId exceeds limit");
995  /* NOTREACHED */
996  }
997 
998  p = sethead.lh_first;
999  q = NULL;
1000  for (; p != NULL && p->setId < setId; q = p, p = p->entries.le_next);
1001 
1002  if (p && p->setId == setId)
1003  {
1004  ;
1005  }
1006  else
1007  {
1008  p = (struct _setT *) xmalloc (sizeof (struct _setT));
1009  memset (p, '\0', sizeof (struct _setT));
1010  LIST_INIT (&p->msghead);
1011 
1012  p->setId = setId;
1013 
1014  if (q == NULL)
1015  {
1016  LIST_INSERT_HEAD (&sethead, p, entries);
1017  }
1018  else
1019  {
1020  LIST_INSERT_AFTER (q, p, entries);
1021  }
1022  }
1023 
1024  curSet = p;
1025 }
1026 
1027 void
1028 MCAddMsg (int msgId, const char *str)
1029 {
1030  struct _msgT *p, *q;
1031 
1032  if (!curSet)
1033  error ("can't specify a message when no set exists");
1034 
1035  if (msgId <= 0)
1036  {
1037  error ("msgId's must be greater than zero");
1038  /* NOTREACHED */
1039  }
1040  if (msgId > NL_MSGMAX)
1041  {
1042  error ("msgID exceeds limit");
1043  /* NOTREACHED */
1044  }
1045 
1046  p = curSet->msghead.lh_first;
1047  q = NULL;
1048  for (; p != NULL && p->msgId < msgId; q = p, p = p->entries.le_next);
1049 
1050  if (p && p->msgId == msgId)
1051  {
1052  free (p->str);
1053  }
1054  else
1055  {
1056  p = (struct _msgT *) xmalloc (sizeof (struct _msgT));
1057  memset (p, '\0', sizeof (struct _msgT));
1058 
1059  if (q == NULL)
1060  {
1061  LIST_INSERT_HEAD (&curSet->msghead, p, entries);
1062  }
1063  else
1064  {
1065  LIST_INSERT_AFTER (q, p, entries);
1066  }
1067  }
1068 
1069  p->msgId = msgId;
1070  p->str = xstrdup (str);
1071 }
1072 
1073 void
1074 MCDelSet (int setId)
1075 {
1076  struct _setT *set;
1077  struct _msgT *msg;
1078 
1079  if (setId <= 0)
1080  {
1081  error ("setId's must be greater than zero");
1082  /* NOTREACHED */
1083  }
1084  if (setId > NL_SETMAX)
1085  {
1086  error ("setId exceeds limit");
1087  /* NOTREACHED */
1088  }
1089 
1090  set = sethead.lh_first;
1091  for (; set != NULL && set->setId < setId; set = set->entries.le_next);
1092 
1093  if (set && set->setId == setId)
1094  {
1095  LIST_REMOVE (set, entries);
1096  while ((msg = set->msghead.lh_first) != NULL)
1097  {
1098  LIST_REMOVE (msg, entries);
1099  free (msg->str);
1100  free (msg);
1101  }
1102  free (set);
1103  return;
1104  }
1105  warning (NULL, "specified set doesn't exist");
1106 }
1107 
1108 void
1109 MCDelMsg (int msgId)
1110 {
1111  struct _msgT *msg;
1112 
1113  if (!curSet)
1114  error ("you can't delete a message before defining the set");
1115 
1116  msg = curSet->msghead.lh_first;
1117  for (; msg != NULL && msg->msgId < msgId; msg = msg->entries.le_next);
1118 
1119  if (msg && msg->msgId == msgId)
1120  {
1121  LIST_REMOVE (msg, entries);
1122  free (msg->str);
1123  free (msg);
1124  return;
1125  }
1126  warning (NULL, "specified msg doesn't exist");
1127 }
DllImport int optind
int main(int argc, char *argv[])
Definition: gencat.c:205
long setId
Definition: gencat.c:133
static char * getmsg(int fd, char *cptr, char quote)
Definition: gencat.c:498
int getopt(int, char *const *, const char *)
int argc
Definition: dynamic_load.c:951
unsigned int htonl(unsigned int from)
char * str
Definition: gencat.c:127
long msgId
Definition: gencat.c:126
int32_t __msg_txt_offset
Definition: gencat.c:146
#define _NLS_MAGIC
Definition: gencat.c:138
int32_t __setno
Definition: gencat.c:151
#define NL_SETD
Definition: gencat.c:163
static const char * progname
int32_t __nsets
Definition: gencat.c:143
#define NOMEMORY
int32_t __msglen
Definition: gencat.c:159
static char * wskip(char *cptr)
Definition: gencat.c:472
static char * get_line(int fd)
Definition: gencat.c:389
void MCDelSet(int setId)
Definition: gencat.c:1074
int32_t __index
Definition: gencat.c:153
Definition: gencat.c:124
int32_t __msg_hdr_offset
Definition: gencat.c:145
#define NL_MSGMAX
Definition: gencat.c:121
#define NULL
Definition: freelistheap.h:34
LIST_HEAD(static void warning(const char *, _setT)
Definition: gencat.c:166
#define err(fd,...)
Definition: porting.h:431
#define errx(fd,...)
Definition: porting.h:432
int32_t __msgno
Definition: gencat.c:158
void MCDelMsg(int msgId)
Definition: gencat.c:1109
#define NL_SETMAX
Definition: gencat.c:118
static void error(const char *msg)
Definition: gencat.c:331
static char * cskip(char *cptr)
Definition: gencat.c:485
int32_t __mem
Definition: gencat.c:144
static void * xrealloc(void *ptr, size_t size)
Definition: gencat.c:354
void MCAddMsg(int msgId, const char *str)
Definition: gencat.c:1028
static void warning(const char *cptr, const char *msg)
Definition: gencat.c:310
Definition: gencat.c:131
int32_t __magic
Definition: gencat.c:142
const char ** argv
Definition: dynamic_load.c:952
#define strlen(s1)
Definition: intl_support.c:43
#define const
Definition: cnvlex.c:77
void MCParse(int fd)
Definition: gencat.c:623
void MCReadCat(int fd)
Definition: gencat.c:738
int i
Definition: dynamic_load.c:954
for(p=libs;*p;p++)
Definition: dynamic_load.c:968
char * strdup(const char *str)
Definition: porting.c:901
static void * xmalloc(size_t len)
Definition: gencat.c:338
int32_t __nmsgs
Definition: gencat.c:152
unsigned int ntohl(unsigned int from)
void MCAddSet(int setId)
Definition: gencat.c:983
void usage(void)
int32_t __offset
Definition: gencat.c:160
const char ** p
Definition: dynamic_load.c:945
void MCWriteCat(int fd)
Definition: gencat.c:882
#define CORRUPT
static char * xstrdup(const char *str)
Definition: gencat.c:373