Remove Unixware and openserver support
[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 libraries 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 <string.h>
97 #include <locale.h>
98 #include <nl_types.h>
99
100 nl_catd catfile[2] = {NULL, NULL};      /* [0] for primary, [1] for default */
101 char *big_buff;
102 char *lang = NULL;
103 char envvar[100];
104 char *pfile = NULL;
105 char *dfile = NULL;
106 int bs = 0;
107 int crt_line[3] = {0, 0, 1}; /* current line  [0]: Primary message file */
108                              /*               [1]: Default message file */
109                              /*               [2]: Template file        */
110
111 void process_message ();
112 int get_char ();
113 void cat_open ();
114 int find_message ();
115 int find_msg_in_file ();
116 void get_message ();
117 void fatal ();
118 void get_option ();
119
120
121 void main (argc, argv)
122 int argc;
123 char *argv [];
124 {
125     int c;
126
127     get_option(&argc, argv);
128
129     if(pfile == NULL)
130         fatal("Usage: merge [-lang language][-dfile Default.tmsg] Primary.tmsg < File.nls > File \n", 0, 9);
131
132     if(lang != NULL) {
133         setlocale(LC_ALL, lang);
134         /* LC_CTYPE need to be set to make "gencat" command work correctly */
135         sprintf( envvar, "LC_CTYPE=%s", lang );
136         putenv( envvar );
137     } else
138         setlocale(LC_ALL, "");
139
140     cat_open();
141
142     c = get_char ();
143     while (c != EOF) {
144         while (c == '%') {
145             char *s;
146             char *s0;
147
148             for (s = s0 = "|nls-"; *s != 0; s++)
149                 if (c = get_char (), c != *s)
150                     break;
151
152 /* if the string matchs "%|nls-", go to process_message(). */
153             if (*s == 0) {
154                 process_message ();
155                 c = get_char ();
156             }
157             else {
158                 putchar ('%');
159                 while (s0 != s) {
160                     putchar (*s0);
161                     s0++;
162                 }
163             }
164         }
165         putchar (c);
166         c = get_char ();
167     }
168
169     if ( catfile[0] )
170        catclose(catfile[0]);
171
172     if ( catfile[1] )
173        catclose(catfile[1]);
174
175     unlink("./.dt_pfile.cat");
176     unlink("./.dt_dfile.cat");
177
178     exit (0);
179 }
180
181 /*
182  * If the pattern "%|nls-???-###|" is found in the template file, replace it
183  * by big_buff.
184  */
185 void process_message ()
186 {
187     int c;
188     int m = 0;
189
190     while (c = get_char (), c != '-')
191         switch (c)
192         {
193         case EOF: fatal ("Unterminated NLS sequence.\n", crt_line[2]-1, 2);
194         case '\n': fatal ("Unterminated NLS sequence.\n", crt_line[2]-1, 2);
195         default:  fatal ("Bad character in NLS sequence.\n", crt_line[2], 2);
196         case '0': m = m * 10 + 0; break;
197         case '1': m = m * 10 + 1; break;
198         case '2': m = m * 10 + 2; break;
199         case '3': m = m * 10 + 3; break;
200         case '4': m = m * 10 + 4; break;
201         case '5': m = m * 10 + 5; break;
202         case '6': m = m * 10 + 6; break;
203         case '7': m = m * 10 + 7; break;
204         case '8': m = m * 10 + 8; break;
205         case '9': m = m * 10 + 9; break;
206         }
207
208     while (c = get_char (), c != '|')
209         if (c == '\n' || c == EOF)
210             fatal ("Unterminated NLS sequence.\n", crt_line[2]-1, 2);
211
212     if(find_message(m))
213         printf ("%s", big_buff);
214     else {
215         printf ("....Missing message #%d", m);
216         fprintf (stderr, "*** Error: Missing message #%d\n", m);
217     }
218 }
219
220 /*
221  * Get a character from template. Incriment line count if new line is found.
222  */
223 int get_char ()
224 {
225     int c;
226
227     c = getchar();
228     if(c == '\n')
229         crt_line[2]++;
230     return c;
231 }
232
233 /*
234  * Open message files
235  */
236 void cat_open ()
237 {
238     char line[255];
239
240     unlink("./.dt_pfile.cat");
241     unlink("./.dt_dfile.cat");
242
243     if(pfile != NULL)
244     {
245         sprintf(line,"/usr/bin/gencat ./.dt_pfile.cat %s",pfile);
246         if ( system(line) != 0 )
247         {
248            fatal("primary .tmsg file would not gencat\n",0,9);
249         }
250     }
251
252     catfile[0] =  catopen("./.dt_pfile.cat",0);
253
254     if(dfile != NULL)
255     {
256         sprintf(line,"/usr/bin/gencat ./.dt_dfile.cat %s",dfile);
257         if ( system(line) != 0 )
258         {
259            fatal("default .tmsg file would not gencat\n",0,9);
260         }
261
262     }
263
264     catfile[1] = catopen("./.dt_dfile.cat",0);
265
266     /* if all fails */
267     if(catfile[0] == NULL && catfile[1] == NULL)
268         fatal("Can't open message files.\n", 0, 9);
269
270 }
271
272 /*
273  * Search a message by specified number. If found, returns 1 and the message
274  * will be set in big_buff. If not found, returns 0.
275  */
276 int find_message (msg)
277 int msg; /* message number to be searched */
278 {
279     int ret = 0;
280
281     if(catfile[0] != NULL)
282         ret = find_msg_in_file(msg, 0);
283     if(ret == 0 && catfile[1] != NULL)
284         ret = find_msg_in_file(msg, 1);
285     return ret;
286 }
287
288 /*
289  * Search a line starts with the message number in specified file. If found,
290  * the line will be passed to get_message() and returns 1.
291  * If not found, returns 0.
292  */
293 int find_msg_in_file (msg, file)
294 int msg; /* message number to be searched */
295 int file; /* 0: Primary message file, 1: Default message file */
296 {
297         big_buff = catgets(catfile[file],1,msg,"MSG_NOT_FOUND");
298         if ( strcmp(big_buff,"MSG_NOT_FOUND") )
299            return(1);
300         else
301            return(0);
302 }
303
304 /*
305  * Display error message and exit program.
306  *
307  * file == file in which the error found  0: Primary message file 
308  *                                1: Default message file 
309  *                                2: Template file        
310  *                                9: N/A                  
311  */
312 void fatal (char *m, int line, int file)
313 /* file in which the error found  0: Primary message file */
314           /*                                1: Default message file */
315           /*                                2: Template file        */
316           /*                                9: N/A                  */
317 {
318     fprintf (stderr, "*** Fatal: ");
319     fprintf (stderr, "%s", m);
320     switch(file)
321     {
322     case 0:
323         fprintf(stderr, "           [Line %d in Primary message file]\n", line);
324         break;
325     case 1:
326         fprintf(stderr, "           [Line %d in Default message file]\n", line);
327         break;
328     case 2:
329         fprintf(stderr, "           [Line %d in Template file]\n", line);
330     }
331     exit (1);
332 }
333
334 /*
335  * Parse command line options.
336  */
337 void get_option (argc, argv)
338 int *argc;
339 char *argv[];
340 {
341     int i;
342
343     for(i = 1; i < *argc; i++) {
344         if(strcmp(argv[i], "-bs") == 0) {
345             bs = 1;
346         }
347         else if(strcmp(argv[i], "-lang") == 0) {
348             if(argv[i+1] != NULL && strlen(argv[i+1]) > 0) {
349                 lang = (char *)malloc(sizeof(char) * (strlen(argv[i+1]) + 1));
350                 strcpy(lang, argv[i+1]);
351                 i++;
352             }
353         }
354         else if(strcmp(argv[i], "-dfile") == 0) {
355             if(argv[i+1] != NULL && strlen(argv[i+1]) > 0) {
356                 dfile = (char *)malloc(sizeof(char) * (strlen(argv[i+1]) + 1));
357                 strcpy(dfile, argv[i+1]);
358                 i++;
359             }
360         }
361         else {
362             if(strlen(argv[i]) > 0) {
363                 pfile = (char *)malloc(sizeof(char) * (strlen(argv[i]) + 1));
364                 strcpy(pfile, argv[i]);
365             }
366         }
367     }
368 }