localized/util/merge.h: include string.h and fix up some warnings
[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 <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 #if defined(USL) || defined(__uxp__)
246         sprintf(line,"/usr/bin/gencat -m ./.dt_pfile.cat %s",pfile);
247 #else
248         sprintf(line,"/usr/bin/gencat ./.dt_pfile.cat %s",pfile);
249 #endif
250         if ( system(line) != 0 )
251         {
252            fatal("primary .tmsg file would not gencat\n",0,9);
253         }
254     }
255
256     catfile[0] =  catopen("./.dt_pfile.cat",0);
257
258     if(dfile != NULL)
259     {
260 #if defined(USL) || defined(__uxp__)
261         sprintf(line,"/usr/bin/gencat -m ./.dt_dfile.cat %s",dfile);
262 #else
263         sprintf(line,"/usr/bin/gencat ./.dt_dfile.cat %s",dfile);
264 #endif
265         if ( system(line) != 0 )
266         {
267            fatal("default .tmsg file would not gencat\n",0,9);
268         }
269
270     }
271
272     catfile[1] = catopen("./.dt_dfile.cat",0);
273
274     /* if all fails */
275     if(catfile[0] == NULL && catfile[1] == NULL)
276         fatal("Can't open message files.\n", 0, 9);
277
278 }
279
280 /*
281  * Search a message by specified number. If found, returns 1 and the message
282  * will be set in big_buff. If not found, returns 0.
283  */
284 int find_message (msg)
285 int msg; /* message number to be searched */
286 {
287     int ret = 0;
288
289     if(catfile[0] != NULL)
290         ret = find_msg_in_file(msg, 0);
291     if(ret == 0 && catfile[1] != NULL)
292         ret = find_msg_in_file(msg, 1);
293     return ret;
294 }
295
296 /*
297  * Search a line starts with the message number in specified file. If found,
298  * the line will be passed to get_message() and returns 1.
299  * If not found, returns 0.
300  */
301 int find_msg_in_file (msg, file)
302 int msg; /* message number to be searched */
303 int file; /* 0: Primary message file, 1: Default message file */
304 {
305         big_buff = catgets(catfile[file],1,msg,"MSG_NOT_FOUND");
306         if ( strcmp(big_buff,"MSG_NOT_FOUND") )
307            return(1);
308         else
309            return(0);
310 }
311
312 /*
313  * Display error message and exit program.
314  *
315  * file == file in which the error found  0: Primary message file 
316  *                                1: Default message file 
317  *                                2: Template file        
318  *                                9: N/A                  
319  */
320 void fatal (char *m, int line, int file)
321 /* file in which the error found  0: Primary message file */
322           /*                                1: Default message file */
323           /*                                2: Template file        */
324           /*                                9: N/A                  */
325 {
326     fprintf (stderr, "*** Fatal: ");
327     fprintf (stderr, "%s", m);
328     switch(file)
329     {
330     case 0:
331         fprintf(stderr, "           [Line %d in Primary message file]\n", line);
332         break;
333     case 1:
334         fprintf(stderr, "           [Line %d in Default message file]\n", line);
335         break;
336     case 2:
337         fprintf(stderr, "           [Line %d in Template file]\n", line);
338     }
339     exit (1);
340 }
341
342 /*
343  * Parse command line options.
344  */
345 void get_option (argc, argv)
346 int *argc;
347 char *argv[];
348 {
349     int i;
350
351     for(i = 1; i < *argc; i++) {
352         if(strcmp(argv[i], "-bs") == 0) {
353             bs = 1;
354         }
355         else if(strcmp(argv[i], "-lang") == 0) {
356             if(argv[i+1] != NULL && strlen(argv[i+1]) > 0) {
357                 lang = (char *)malloc(sizeof(char) * (strlen(argv[i+1]) + 1));
358                 strcpy(lang, argv[i+1]);
359                 i++;
360             }
361         }
362         else if(strcmp(argv[i], "-dfile") == 0) {
363             if(argv[i+1] != NULL && strlen(argv[i+1]) > 0) {
364                 dfile = (char *)malloc(sizeof(char) * (strlen(argv[i+1]) + 1));
365                 strcpy(dfile, argv[i+1]);
366                 i++;
367             }
368         }
369         else {
370             if(strlen(argv[i]) > 0) {
371                 pfile = (char *)malloc(sizeof(char) * (strlen(argv[i]) + 1));
372                 strcpy(pfile, argv[i]);
373             }
374         }
375     }
376 }