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