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