Exceptionally hacky linux fix. gnu gencat is returning != 0 even when it's
[oweals/cde.git] / cde / programs / localized / util / merge.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: merge.c /main/4 1995/12/08 09:44:13 rswiston $ */
24 /*
25     merge.c
26
27     Merge international messages back into CDE files.
28
29     Syntax:
30         merge [-bs][-lang language][-dfile Default.tmsg] Primary.tmsg\
31               < File.nls > File
32   
33         -bs                 : The backslash+n is left alone and not interpreted.
34         -lang language      : Language of messages. (If not specified, the value
35                               of LANG environment variable is used.)
36         -dfile Default.tmsg : Default message file.
37
38         Primary.tmsg        : Primary message file.
39         File.nls            : Template file.
40         File                : Merged file.
41
42
43     June 93 Hatim Amro  -Updated this tool to have support for a default .tmsg
44                          file in case the primery one is not found or missing
45                          a message whose number is in the .nls file. I, also,
46                          rewrote the option stripping and handling code for
47                          better flexibility. I find the Syntax above very
48                          confusing, I provide a simpler one below, which,
49                          includes the new -dfile option.
50     New Syntax:
51      merge [-lang Ja_JP][-dfile Default.tmsg] Primary.tmsg < File.nls > File
52
53     July 93 Hatim Amro  -In order to comply with request from Ann Barnette, the
54                          backslash n is left alone and not interpreted if the
55                          new -bs option is specified in the parameter list.
56                          (this option will not be published)
57
58     New Syntax:
59      merge [-bs][-lang Ja_JP][-dfile Default.tmsg]\
60            Primary.tmsg < File.nls > File
61
62     8/2/93 Masato Suzuki - -lang option is generalized. (This options doesn't
63                            necessarily need to be specified for single-byte
64                            languages.) Error messages are enhanced. And bug
65                            fixes are applied.
66
67     12/13/93 Masato Suzuki -Modified so that the format of message file(*.tmsg)
68                             is compliant to XPG message catalog file. (But it's
69                             subset.)
70
71     Format of message file.
72         $set n [comment] ... n must be 1.
73         $ [comment]
74         m message-text ... Message text may contain following spcial characters
75                            and escape sequences.
76                              \\                  backslash
77                              \n                  newline
78                              \t                  horizontal tab
79                              \ (at end of line)  continue on same line
80
81     Following XPG format and escape sequences are not supported.
82         $delset, $quote, $len
83         \v, \b, \r, \f, \ddd, \xdddd
84 */
85 /*
86  * Following pattern in proforma will be replaced by the matched message in
87  * catalogue. This pattern must be in one line.
88  *
89  *  %|nls-???-###|       : ??? must be numerics.
90  *                         ### is comment, can be nothing.
91  */
92
93
94 #include <stdio.h>
95 #include <stdlib.h>
96 #include <locale.h>
97 #include <nl_types.h>
98
99 nl_catd catfile[2] = {NULL, NULL};      /* [0] for primary, [1] for default */
100 char *big_buff;
101 char *lang = NULL;
102 char envvar[100];
103 char *pfile = NULL;
104 char *dfile = NULL;
105 int bs = 0;
106 int crt_line[3] = {0, 0, 1}; /* current line  [0]: Primary message file */
107                              /*               [1]: Default message file */
108                              /*               [2]: Template file        */
109
110 void process_message ();
111 int get_char ();
112 void cat_open ();
113 int find_message ();
114 int find_msg_in_file ();
115 void get_message ();
116 void fatal ();
117 void get_option ();
118
119
120 void main (argc, argv)
121 int argc;
122 char *argv [];
123 {
124     int c;
125
126     get_option(&argc, argv);
127
128     if(pfile == NULL)
129         fatal("Usage: merge [-lang language][-dfile Default.tmsg] Primary.tmsg < File.nls > File \n", 0, 9);
130
131     if(lang != NULL) {
132         setlocale(LC_ALL, lang);
133         /* LC_CTYPE need to be set to make "gencat" command work correctly */
134         sprintf( envvar, "LC_CTYPE=%s", lang );
135         putenv( envvar );
136     } else
137         setlocale(LC_ALL, "");
138
139     cat_open();
140
141     c = get_char ();
142     while (c != EOF) {
143         while (c == '%') {
144             char *s;
145             char *s0;
146
147             for (s = s0 = "|nls-"; *s != 0; s++)
148                 if (c = get_char (), c != *s)
149                     break;
150
151 /* if the string matchs "%|nls-", go to process_message(). */
152             if (*s == 0) {
153                 process_message ();
154                 c = get_char ();
155             }
156             else {
157                 putchar ('%');
158                 while (s0 != s) {
159                     putchar (*s0);
160                     s0++;
161                 }
162             }
163         }
164         putchar (c);
165         c = get_char ();
166     }
167
168     if ( catfile[0] )
169        catclose(catfile[0]);
170
171     if ( catfile[1] )
172        catclose(catfile[1]);
173
174     unlink("./.dt_pfile.cat");
175     unlink("./.dt_dfile.cat");
176
177     exit (0);
178 }
179
180 /*
181  * If the pattern "%|nls-???-###|" is found in the template file, replace it
182  * by big_buff.
183  */
184 void process_message ()
185 {
186     int c;
187     int m = 0;
188
189     while (c = get_char (), c != '-')
190         switch (c)
191         {
192         case EOF: fatal ("Unterminated NLS sequence.\n", crt_line[2]-1, 2);
193         case '\n': fatal ("Unterminated NLS sequence.\n", crt_line[2]-1, 2);
194         default:  fatal ("Bad character in NLS sequence.\n", crt_line[2], 2);
195         case '0': m = m * 10 + 0; break;
196         case '1': m = m * 10 + 1; break;
197         case '2': m = m * 10 + 2; break;
198         case '3': m = m * 10 + 3; break;
199         case '4': m = m * 10 + 4; break;
200         case '5': m = m * 10 + 5; break;
201         case '6': m = m * 10 + 6; break;
202         case '7': m = m * 10 + 7; break;
203         case '8': m = m * 10 + 8; break;
204         case '9': m = m * 10 + 9; break;
205         }
206
207     while (c = get_char (), c != '|')
208         if (c == '\n' || c == EOF)
209             fatal ("Unterminated NLS sequence.\n", crt_line[2]-1, 2);
210
211     if(find_message(m))
212         printf ("%s", big_buff);
213     else {
214         printf ("....Missing message #%d", m);
215         fprintf (stderr, "*** Error: Missing message #%d\n", m);
216     }
217 }
218
219 /*
220  * Get a character from template. Incriment line count if new line is found.
221  */
222 int get_char ()
223 {
224     int c;
225
226     c = getchar();
227     if(c == '\n')
228         crt_line[2]++;
229     return c;
230 }
231
232 /*
233  * Open message files
234  */
235 void cat_open ()
236 {
237     char line[255];
238
239     unlink("./.dt_pfile.cat");
240     unlink("./.dt_dfile.cat");
241
242     if(pfile != NULL)
243     {
244 #if defined(USL) || defined(__uxp__)
245         sprintf(line,"/usr/bin/gencat -m ./.dt_pfile.cat %s",pfile);
246 #else
247         sprintf(line,"/usr/bin/gencat ./.dt_pfile.cat %s",pfile);
248 #endif
249         if ( system(line) != 0 )
250         {
251         /* Utter Linux HACK, it seems the return value of GNU gencat is != 0
252            even on success */
253 #if !defined(linux)
254            fatal("primary .tmsg file would not gencat\n",0,9);
255 #endif
256         }
257     }
258
259     catfile[0] =  catopen("./.dt_pfile.cat",0);
260
261     if(dfile != NULL)
262     {
263 #if defined(USL) || defined(__uxp__)
264         sprintf(line,"/usr/bin/gencat -m ./.dt_dfile.cat %s",dfile);
265 #else
266         sprintf(line,"/usr/bin/gencat ./.dt_dfile.cat %s",dfile);
267 #endif
268         if ( system(line) != 0 )
269         {
270         /* Utter Linux HACK, it seems the return value of GNU gencat is != 0
271            even on success */
272 #if !defined(linux)
273            fatal("default .tmsg file would not gencat\n",0,9);
274 #endif
275         }
276
277     }
278
279     catfile[1] = catopen("./.dt_dfile.cat",0);
280
281     /* if all fails */
282     if(catfile[0] == NULL && catfile[1] == NULL)
283         fatal("Can't open message files.\n", 0, 9);
284
285 }
286
287 /*
288  * Search a message by specified number. If found, returns 1 and the message
289  * will be set in big_buff. If not found, returns 0.
290  */
291 int find_message (msg)
292 int msg; /* message number to be searched */
293 {
294     int ret = 0;
295
296     if(catfile[0] != NULL)
297         ret = find_msg_in_file(msg, 0);
298     if(ret == 0 && catfile[1] != NULL)
299         ret = find_msg_in_file(msg, 1);
300     return ret;
301 }
302
303 /*
304  * Search a line starts with the message number in specified file. If found,
305  * the line will be passed to get_message() and returns 1.
306  * If not found, returns 0.
307  */
308 int find_msg_in_file (msg, file)
309 int msg; /* message number to be searched */
310 int file; /* 0: Primary message file, 1: Default message file */
311 {
312         big_buff = catgets(catfile[file],1,msg,"MSG_NOT_FOUND");
313         if ( strcmp(big_buff,"MSG_NOT_FOUND") )
314            return(1);
315         else
316            return(0);
317 }
318
319 /*
320  * Display error message and exit program.
321  */
322 void fatal (m, line, file)
323 char *m;
324 int line; /* line where the error found */
325 int file; /* file in which the error found  0: Primary message file */
326           /*                                1: Default message file */
327           /*                                2: Template file        */
328           /*                                9: N/A                  */
329 {
330     fprintf (stderr, "*** Fatal: ");
331     fprintf (stderr, m);
332     switch(file)
333     {
334     case 0:
335         fprintf(stderr, "           [Line %d in Primary message file]\n", line);
336         break;
337     case 1:
338         fprintf(stderr, "           [Line %d in Default message file]\n", line);
339         break;
340     case 2:
341         fprintf(stderr, "           [Line %d in Template file]\n", line);
342     }
343     exit (1);
344 }
345
346 /*
347  * Parse command line options.
348  */
349 void get_option (argc, argv)
350 int *argc;
351 char *argv[];
352 {
353     int i;
354
355     for(i = 1; i < *argc; i++) {
356         if(strcmp(argv[i], "-bs") == 0) {
357             bs = 1;
358         }
359         else if(strcmp(argv[i], "-lang") == 0) {
360             if(argv[i+1] != NULL && strlen(argv[i+1]) > 0) {
361                 lang = (char *)malloc(sizeof(char) * (strlen(argv[i+1]) + 1));
362                 strcpy(lang, argv[i+1]);
363                 i++;
364             }
365         }
366         else if(strcmp(argv[i], "-dfile") == 0) {
367             if(argv[i+1] != NULL && strlen(argv[i+1]) > 0) {
368                 dfile = (char *)malloc(sizeof(char) * (strlen(argv[i+1]) + 1));
369                 strcpy(dfile, argv[i+1]);
370                 i++;
371             }
372         }
373         else {
374             if(strlen(argv[i]) > 0) {
375                 pfile = (char *)malloc(sizeof(char) * (strlen(argv[i]) + 1));
376                 strcpy(pfile, argv[i]);
377             }
378         }
379     }
380 }