1/*
2 * "$Id: po2strings.c 11093 2013-07-03 20:48:42Z msweet $"
3 *
4 *   Convert a GNU gettext .po file to an Apple .strings file.
5 *
6 *   Copyright 2007-2012 by Apple Inc.
7 *
8 *   These coded instructions, statements, and computer programs are the
9 *   property of Apple Inc. and are protected by Federal copyright
10 *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
11 *   which should have been included with this file.  If this file is
12 *   file is missing or damaged, see the license at "http://www.cups.org/".
13 *
14 * Usage:
15 *
16 *   po2strings filename.strings filename.po
17 *
18 * Compile with:
19 *
20 *   gcc -o po2strings po2strings.c `cups-config --libs`
21 *
22 * Contents:
23 *
24 *   main() - Convert .po file to .strings.
25 */
26
27#include <cups/cups-private.h>
28
29
30/*
31 * The .strings file format is simple:
32 *
33 * // comment
34 * "msgid" = "msgstr";
35 *
36 * The GNU gettext .po format is also fairly simple:
37 *
38 *     #. comment
39 *     msgid "some text"
40 *     msgstr "localized text"
41 *
42 * The comment, msgid, and msgstr text can span multiple lines using the form:
43 *
44 *     #. comment
45 *     #. more comments
46 *     msgid ""
47 *     "some long text"
48 *     msgstr ""
49 *     "localized text spanning "
50 *     "multiple lines"
51 *
52 * Both the msgid and msgstr strings use standard C quoting for special
53 * characters like newline and the double quote character.
54 */
55
56/*
57 *   main() - Convert .po file to .strings.
58 */
59
60int					/* O - Exit code */
61main(int  argc,				/* I - Number of command-line args */
62     char *argv[])			/* I - Command-line arguments */
63{
64  int			i;		/* Looping var */
65  const char		*pofile,	/* .po filename */
66			*stringsfile;	/* .strings filename */
67  cups_file_t		*po,		/* .po file */
68			*strings;	/* .strings file */
69  char			s[4096],	/* String buffer */
70			*ptr,		/* Pointer into buffer */
71			*temp,		/* New string */
72			*msgid,		/* msgid string */
73			*msgstr;	/* msgstr string */
74  int			length;		/* Length of combined strings */
75  int			use_msgid;	/* Use msgid strings for msgstr? */
76
77
78 /*
79  * Process command-line arguments...
80  */
81
82  pofile      = NULL;
83  stringsfile = NULL;
84  use_msgid   = 0;
85
86  for (i = 1; i < argc; i ++)
87  {
88    if (!strcmp(argv[i], "-m"))
89      use_msgid = 1;
90    else if (argv[i][0] == '-')
91    {
92      puts("Usage: po2strings [-m] filename.po filename.strings");
93      return (1);
94    }
95    else if (!pofile)
96      pofile = argv[i];
97    else if (!stringsfile)
98      stringsfile = argv[i];
99    else
100    {
101      puts("Usage: po2strings [-m] filename.po filename.strings");
102      return (1);
103    }
104  }
105
106  if (!pofile || !stringsfile)
107  {
108    puts("Usage: po2strings [-m] filename.po filename.strings");
109    return (1);
110  }
111
112 /*
113  * Read strings from the .po file and write to the .strings file...
114  */
115
116  if ((po = cupsFileOpen(pofile, "r")) == NULL)
117  {
118    perror(pofile);
119    return (1);
120  }
121
122  if ((strings = cupsFileOpen(stringsfile, "w")) == NULL)
123  {
124    perror(stringsfile);
125    cupsFileClose(po);
126    return (1);
127  }
128
129  msgid = msgstr = NULL;
130
131  while (cupsFileGets(po, s, sizeof(s)) != NULL)
132  {
133    if (s[0] == '#' && s[1] == '.')
134    {
135     /*
136      * Copy comment string...
137      */
138
139      if (msgid && msgstr)
140      {
141       /*
142        * First output the last localization string...
143	*/
144
145	if (*msgid)
146	  cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
147			 (use_msgid || !*msgstr) ? msgid : msgstr);
148
149	free(msgid);
150	free(msgstr);
151	msgid = msgstr = NULL;
152      }
153
154      cupsFilePrintf(strings, "//%s\n", s + 2);
155    }
156    else if (s[0] == '#' || !s[0])
157    {
158     /*
159      * Skip blank and file comment lines...
160      */
161
162      continue;
163    }
164    else
165    {
166     /*
167      * Strip the trailing quote...
168      */
169
170      if ((ptr = strrchr(s, '\"')) == NULL)
171	continue;
172
173      *ptr = '\0';
174
175     /*
176      * Find start of value...
177      */
178
179      if ((ptr = strchr(s, '\"')) == NULL)
180	continue;
181
182      ptr ++;
183
184     /*
185      * Create or add to a message...
186      */
187
188      if (!strncmp(s, "msgid", 5))
189      {
190       /*
191	* Output previous message as needed...
192	*/
193
194        if (msgid && msgstr)
195	{
196	  if (*msgid)
197            cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
198	                   (use_msgid || !*msgstr) ? msgid : msgstr);
199	}
200
201	if (msgid)
202	  free(msgid);
203
204	if (msgstr)
205	  free(msgstr);
206
207        msgid  = strdup(ptr);
208	msgstr = NULL;
209      }
210      else if (s[0] == '\"' && (msgid || msgstr))
211      {
212       /*
213	* Append to current string...
214	*/
215
216        size_t ptrlen = strlen(ptr);	/* Length of string */
217
218	length = (int)strlen(msgstr ? msgstr : msgid);
219
220	if ((temp = realloc(msgstr ? msgstr : msgid,
221			    length + ptrlen + 1)) == NULL)
222	{
223	  free(msgid);
224	  if (msgstr)
225	    free(msgstr);
226	  perror("Unable to allocate string");
227	  return (1);
228	}
229
230	if (msgstr)
231	{
232	 /*
233	  * Copy the new portion to the end of the msgstr string - safe
234	  * to use strcpy because the buffer is allocated to the correct
235	  * size...
236	  */
237
238	  msgstr = temp;
239
240	  memcpy(msgstr + length, ptr, ptrlen + 1);
241	}
242	else
243	{
244	 /*
245	  * Copy the new portion to the end of the msgid string - safe
246	  * to use strcpy because the buffer is allocated to the correct
247	  * size...
248	  */
249
250	  msgid = temp;
251
252	  memcpy(msgid + length, ptr, ptrlen + 1);
253	}
254      }
255      else if (!strncmp(s, "msgstr", 6) && msgid)
256      {
257       /*
258	* Set the string...
259	*/
260
261        if (msgstr)
262          free(msgstr);
263
264	if ((msgstr = strdup(ptr)) == NULL)
265	{
266	  free(msgid);
267	  perror("Unable to allocate msgstr");
268	  return (1);
269	}
270      }
271    }
272  }
273
274  if (msgid && msgstr)
275  {
276    if (*msgid)
277      cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
278		     (use_msgid || !*msgstr) ? msgid : msgstr);
279  }
280
281  if (msgid)
282    free(msgid);
283
284  if (msgstr)
285    free(msgstr);
286
287  cupsFileClose(po);
288  cupsFileClose(strings);
289
290  return (0);
291}
292
293
294/*
295 * End of "$Id: po2strings.c 11093 2013-07-03 20:48:42Z msweet $".
296 */
297