]> git.ipfire.org Git - thirdparty/cups.git/blame - locale/po2strings.c
Full sweep of all Clang warnings, plus some bug fixes for incorrect memcpy usage.
[thirdparty/cups.git] / locale / po2strings.c
CommitLineData
bc44d920 1/*
f2d18633 2 * "$Id$"
bc44d920 3 *
7e86f2f6 4 * Convert a GNU gettext .po file to an Apple .strings file.
71e16022 5 *
7e86f2f6 6 * Copyright 2007-2014 by Apple Inc.
71e16022 7 *
7e86f2f6
MS
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/".
bc44d920 13 *
14 * Usage:
15 *
16 * po2strings filename.strings filename.po
17 *
18 * Compile with:
19 *
20 * gcc -o po2strings po2strings.c `cups-config --libs`
bc44d920 21 */
22
71e16022 23#include <cups/cups-private.h>
bc44d920 24
25
26/*
27 * The .strings file format is simple:
28 *
29 * // comment
0837b7e8 30 * "msgid" = "msgstr";
bc44d920 31 *
0837b7e8
MS
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.
bc44d920 50 */
51
bc44d920 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{
745129be 60 int i; /* Looping var */
0837b7e8
MS
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 */
7e86f2f6 70 size_t length; /* Length of combined strings */
745129be 71 int use_msgid; /* Use msgid strings for msgstr? */
bc44d920 72
73
0837b7e8
MS
74 /*
75 * Process command-line arguments...
76 */
745129be 77
0837b7e8
MS
78 pofile = NULL;
79 stringsfile = NULL;
80 use_msgid = 0;
745129be
MS
81
82 for (i = 1; i < argc; i ++)
0837b7e8 83 {
745129be
MS
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 }
0837b7e8
MS
91 else if (!pofile)
92 pofile = argv[i];
93 else if (!stringsfile)
94 stringsfile = argv[i];
745129be
MS
95 else
96 {
97 puts("Usage: po2strings [-m] filename.po filename.strings");
98 return (1);
99 }
0837b7e8 100 }
745129be 101
0837b7e8 102 if (!pofile || !stringsfile)
bc44d920 103 {
745129be 104 puts("Usage: po2strings [-m] filename.po filename.strings");
bc44d920 105 return (1);
106 }
107
108 /*
0837b7e8 109 * Read strings from the .po file and write to the .strings file...
bc44d920 110 */
111
0837b7e8 112 if ((po = cupsFileOpen(pofile, "r")) == NULL)
bc44d920 113 {
0837b7e8 114 perror(pofile);
bc44d920 115 return (1);
116 }
117
0837b7e8 118 if ((strings = cupsFileOpen(stringsfile, "w")) == NULL)
bc44d920 119 {
0837b7e8
MS
120 perror(stringsfile);
121 cupsFileClose(po);
bc44d920 122 return (1);
123 }
124
0837b7e8
MS
125 msgid = msgstr = NULL;
126
127 while (cupsFileGets(po, s, sizeof(s)) != NULL)
bc44d920 128 {
84315f46 129 if (s[0] == '#' && s[1] == '.')
0837b7e8
MS
130 {
131 /*
84315f46 132 * Copy comment string...
0837b7e8 133 */
bc44d920 134
84315f46
MS
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);
0837b7e8 151 }
84315f46 152 else if (s[0] == '#' || !s[0])
0837b7e8
MS
153 {
154 /*
84315f46 155 * Skip blank and file comment lines...
0837b7e8 156 */
bc44d920 157
84315f46 158 continue;
0837b7e8
MS
159 }
160 else
161 {
162 /*
163 * Strip the trailing quote...
164 */
bc44d920 165
0837b7e8
MS
166 if ((ptr = strrchr(s, '\"')) == NULL)
167 continue;
bc44d920 168
0837b7e8 169 *ptr = '\0';
bc44d920 170
0837b7e8
MS
171 /*
172 * Find start of value...
173 */
82cc1f9a 174
0837b7e8
MS
175 if ((ptr = strchr(s, '\"')) == NULL)
176 continue;
bc44d920 177
0837b7e8 178 ptr ++;
bc44d920 179
0837b7e8
MS
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)
84315f46 193 cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
0837b7e8 194 (use_msgid || !*msgstr) ? msgid : msgstr);
82cc1f9a 195 }
0837b7e8 196
82cc1f9a 197 if (msgid)
0837b7e8 198 free(msgid);
82cc1f9a
MS
199
200 if (msgstr)
0837b7e8 201 free(msgstr);
0837b7e8
MS
202
203 msgid = strdup(ptr);
204 msgstr = NULL;
205 }
82cc1f9a 206 else if (s[0] == '\"' && (msgid || msgstr))
0837b7e8
MS
207 {
208 /*
209 * Append to current string...
210 */
211
5a9febac
MS
212 size_t ptrlen = strlen(ptr); /* Length of string */
213
7e86f2f6 214 length = strlen(msgstr ? msgstr : msgid);
0837b7e8
MS
215
216 if ((temp = realloc(msgstr ? msgstr : msgid,
5a9febac 217 length + ptrlen + 1)) == NULL)
0837b7e8 218 {
82cc1f9a
MS
219 free(msgid);
220 if (msgstr)
221 free(msgstr);
0837b7e8
MS
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
5a9febac 236 memcpy(msgstr + length, ptr, ptrlen + 1);
0837b7e8
MS
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
5a9febac 248 memcpy(msgid + length, ptr, ptrlen + 1);
0837b7e8
MS
249 }
250 }
251 else if (!strncmp(s, "msgstr", 6) && msgid)
252 {
253 /*
254 * Set the string...
255 */
256
82cc1f9a
MS
257 if (msgstr)
258 free(msgstr);
259
0837b7e8
MS
260 if ((msgstr = strdup(ptr)) == NULL)
261 {
82cc1f9a 262 free(msgid);
0837b7e8
MS
263 perror("Unable to allocate msgstr");
264 return (1);
265 }
266 }
bc44d920 267 }
0837b7e8
MS
268 }
269
270 if (msgid && msgstr)
271 {
272 if (*msgid)
84315f46 273 cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
0837b7e8 274 (use_msgid || !*msgstr) ? msgid : msgstr);
82cc1f9a 275 }
bc44d920 276
82cc1f9a 277 if (msgid)
0837b7e8 278 free(msgid);
82cc1f9a
MS
279
280 if (msgstr)
0837b7e8 281 free(msgstr);
bc44d920 282
0837b7e8
MS
283 cupsFileClose(po);
284 cupsFileClose(strings);
285
286 return (0);
bc44d920 287}
288
289
290/*
f2d18633 291 * End of "$Id$".
bc44d920 292 */