]> git.ipfire.org Git - thirdparty/cups.git/blame - ppdc/ppdmerge.cxx
Import CUPS v1.7.1
[thirdparty/cups.git] / ppdc / ppdmerge.cxx
CommitLineData
ac884b6a 1//
61515785 2// "$Id: ppdmerge.cxx 3275 2011-05-20 07:26:13Z msweet $"
ac884b6a
MS
3//
4// PPD file merge utility for the CUPS PPD Compiler.
5//
84315f46 6// Copyright 2007-2011 by Apple Inc.
ac884b6a
MS
7// Copyright 2002-2007 by Easy Software Products.
8//
9// These coded instructions, statements, and computer programs are the
10// property of Apple Inc. and are protected by Federal copyright
11// law. Distribution and use rights are outlined in the file "LICENSE.txt"
12// which should have been included with this file. If this file is
13// file is missing or damaged, see the license at "http://www.cups.org/".
14//
15// Contents:
16//
17// main() - Main entry for the PPD merge utility.
18// ppd_locale() - Return the locale associated with a PPD file.
19// usage() - Show usage and exit.
20//
21
22//
23// Include necessary headers...
24//
25
71e16022 26#include <cups/cups-private.h>
61cf44e2 27#include <cups/ppd-private.h>
ac884b6a 28#include <cups/array.h>
ac884b6a
MS
29
30
31//
32// Local functions...
33//
34
35static const char *ppd_locale(ppd_file_t *ppd);
36static void usage(void);
37
38
39//
40// 'main()' - Main entry for the PPD merge utility.
41//
42
43int // O - Exit status
44main(int argc, // I - Number of command-line arguments
45 char *argv[]) // I - Command-line arguments
46{
47 int i; // Looping var
48 char *opt; // Current option
49 ppd_file_t *ppd; // PPD file
50 cups_array_t *ppds; // Array of PPD files
51 const char *inname, // First input filename
52 *outname; // Output filename (if any)
53 cups_file_t *infile, // Input file
54 *outfile; // Output file
61cf44e2
MS
55 cups_array_t *languages; // Languages in file
56 const char *locale; // Current locale
57 char line[1024]; // Line from file
ac884b6a
MS
58
59
61cf44e2
MS
60 _cupsSetLocale(argv);
61
ac884b6a 62 // Scan the command-line...
61cf44e2
MS
63 inname = NULL;
64 outname = NULL;
65 outfile = NULL;
66 languages = NULL;
67 ppds = cupsArrayNew(NULL, NULL);
ac884b6a
MS
68
69 for (i = 1; i < argc; i ++)
70 if (argv[i][0] == '-')
71 {
72 for (opt = argv[i] + 1; *opt; opt ++)
73 switch (*opt)
74 {
75 case 'o' : // Output file
76 if (outname)
77 usage();
78
79 i ++;
80 if (i >= argc)
81 usage();
82
83 outname = argv[i];
84 break;
85
86 default : // Unknown
87 usage();
88 break;
89 }
90 }
91 else
92 {
61cf44e2 93 // Open and load the PPD file...
ac884b6a
MS
94 if ((infile = cupsFileOpen(argv[i], "r")) == NULL)
95 {
0837b7e8 96 _cupsLangPrintf(stderr, _("%s: Unable to open %s: %s"), "ppdmerge",
61cf44e2
MS
97 argv[i], strerror(errno));
98 return (1);
ac884b6a
MS
99 }
100
101 // Open the PPD file...
102 if ((ppd = ppdOpen2(infile)) == NULL)
103 {
104 ppd_status_t status; // PPD open status
0837b7e8
MS
105 int curline, // Current line
106 linenum; // Line number
88f9aafc
MS
107
108
ac884b6a 109 status = ppdLastError(&linenum);
88f9aafc 110
0837b7e8
MS
111 _cupsLangPrintf(stderr,
112 _("%s: Unable to open PPD file: %s on line %d."),
f0ab5bff 113 "ppdmerge", ppdErrorString(status), linenum);
ac884b6a 114 cupsFileRewind(infile);
88f9aafc 115
ac884b6a 116 line[0] = '\0';
0837b7e8 117 curline = 0;
88f9aafc 118
ac884b6a
MS
119 while (cupsFileGets(infile, line, sizeof(line)))
120 {
0837b7e8
MS
121 curline ++;
122 if (curline >= linenum)
ac884b6a
MS
123 break;
124 }
0837b7e8
MS
125
126 _cupsLangPrintf(stderr, "%d: %s", linenum, line);
127
ac884b6a 128 cupsFileClose(infile);
61cf44e2 129 return (1);
ac884b6a 130 }
88f9aafc 131
ac884b6a 132 // Figure out the locale...
61cf44e2 133 if ((locale = ppd_locale(ppd)) == NULL)
ac884b6a 134 {
61cf44e2 135 _cupsLangPrintf(stderr,
0837b7e8 136 _("ppdmerge: Bad LanguageVersion \"%s\" in %s."),
61cf44e2 137 ppd->lang_version, argv[i]);
ac884b6a
MS
138 cupsFileClose(infile);
139 ppdClose(ppd);
61cf44e2 140 return (1);
ac884b6a 141 }
61cf44e2 142
ac884b6a
MS
143 if (!strcmp(locale, "en") && !inname && !outfile)
144 {
145 // Set the English PPD's filename...
61cf44e2
MS
146 inname = argv[i];
147 languages = _ppdGetLanguages(ppd);
148
ac884b6a 149 if (outname && !strcmp(inname, outname))
88f9aafc 150 {
ac884b6a
MS
151 // Rename input filename so that we don't overwrite it...
152 char bckname[1024]; // Backup filename
88f9aafc
MS
153
154
ac884b6a 155 snprintf(bckname, sizeof(bckname), "%s.bck", inname);
88f9aafc 156
ac884b6a
MS
157 if (rename(inname, bckname))
158 {
61cf44e2 159 _cupsLangPrintf(stderr,
0837b7e8 160 _("ppdmerge: Unable to backup %s to %s - %s"),
61cf44e2 161 inname, bckname, strerror(errno));
ac884b6a
MS
162 return (1);
163 }
ac884b6a 164
61cf44e2 165 inname = bckname;
ac884b6a
MS
166 }
167 }
61cf44e2 168 else if (strcmp(locale, "en"))
ac884b6a
MS
169 {
170 // Save this PPD for later processing...
171 cupsArrayAdd(ppds, ppd);
172 }
173 else
174 {
175 // Don't need this PPD...
0837b7e8 176 _cupsLangPrintf(stderr, _("ppdmerge: Ignoring PPD file %s."),
61cf44e2 177 argv[i]);
ac884b6a
MS
178 ppdClose(ppd);
179 }
88f9aafc 180
ac884b6a
MS
181 // Close and move on...
182 cupsFileClose(infile);
183 }
184
185 // If no PPDs have been loaded, display the program usage message.
186 if (!inname)
187 usage();
61cf44e2
MS
188
189 // Loop through the PPD files we loaded to generate a new language list...
190 if (!languages)
191 languages = cupsArrayNew((cups_array_func_t)strcmp, NULL);
192
193 for (ppd = (ppd_file_t *)cupsArrayFirst(ppds);
194 ppd;
195 ppd = (ppd_file_t *)cupsArrayNext(ppds))
196 {
197 locale = ppd_locale(ppd);
198
199 if (cupsArrayFind(languages, (void *)locale))
200 {
201 // Already have this language, remove the PPD from the list.
202 ppdClose(ppd);
203 cupsArrayRemove(ppds, ppd);
204 }
205 else
206 cupsArrayAdd(languages, (void *)locale);
207 }
208
209 // Copy the English PPD starting with a cupsLanguages line...
210 infile = cupsFileOpen(inname, "r");
211
212 if (outname)
213 {
214 const char *ext = strrchr(outname, '.');
215 if (ext && !strcmp(ext, ".gz"))
216 outfile = cupsFileOpen(outname, "w9");
217 else
218 outfile = cupsFileOpen(outname, "w");
219 }
220 else
221 outfile = cupsFileStdout();
222
223 cupsFileGets(infile, line, sizeof(line));
224 cupsFilePrintf(outfile, "%s\n", line);
225 if ((locale = (char *)cupsArrayFirst(languages)) != NULL)
226 {
227 cupsFilePrintf(outfile, "*cupsLanguages: \"%s", locale);
228 while ((locale = (char *)cupsArrayNext(languages)) != NULL)
229 cupsFilePrintf(outfile, " %s", locale);
230 cupsFilePuts(outfile, "\"\n");
231 }
232
233 while (cupsFileGets(infile, line, sizeof(line)))
234 {
235 if (strncmp(line, "*cupsLanguages:", 15))
236 cupsFilePrintf(outfile, "%s\n", line);
237 }
238
239 // Loop through the other PPD files we loaded to provide the translations...
ac884b6a
MS
240 for (ppd = (ppd_file_t *)cupsArrayFirst(ppds);
241 ppd;
242 ppd = (ppd_file_t *)cupsArrayNext(ppds))
243 {
244 // Output all of the UI text for this language...
245 int j, k, l; // Looping vars
246 ppd_group_t *g; // Option group
247 ppd_option_t *o; // Option
248 ppd_choice_t *c; // Choice
61cf44e2
MS
249 ppd_coption_t *co; // Custom option
250 ppd_cparam_t *cp; // Custom parameter
251 ppd_attr_t *attr; // PPD attribute
252
253 locale = ppd_locale(ppd);
ac884b6a 254
ac884b6a 255 cupsFilePrintf(outfile, "*%% %s localization\n", ppd->lang_version);
ac884b6a
MS
256 cupsFilePrintf(outfile, "*%s.Translation ModelName/%s: \"\"\n", locale,
257 ppd->modelname);
61cf44e2 258
ac884b6a
MS
259 for (j = ppd->num_groups, g = ppd->groups; j > 0; j --, g ++)
260 {
261 cupsFilePrintf(outfile, "*%s.Translation %s/%s: \"\"\n", locale,
262 g->name, g->text);
61cf44e2 263
ac884b6a
MS
264 for (k = g->num_options, o = g->options; k > 0; k --, o ++)
265 {
266 cupsFilePrintf(outfile, "*%s.Translation %s/%s: \"\"\n", locale,
267 o->keyword, o->text);
61cf44e2 268
ac884b6a
MS
269 for (l = o->num_choices, c = o->choices; l > 0; l --, c ++)
270 cupsFilePrintf(outfile, "*%s.%s %s/%s: \"\"\n", locale,
271 o->keyword, c->choice, c->text);
61cf44e2
MS
272
273 if ((co = ppdFindCustomOption(ppd, o->keyword)) != NULL)
274 {
275 snprintf(line, sizeof(line), "Custom%s", o->keyword);
276 attr = ppdFindAttr(ppd, line, "True");
277 cupsFilePrintf(outfile, "*%s.Custom%s True/%s: \"\"\n", locale,
278 o->keyword, attr->text);
279 for (cp = ppdFirstCustomParam(co); cp; cp = ppdNextCustomParam(co))
280 cupsFilePrintf(outfile, "*%s.ParamCustom%s %s/%s: \"\"\n", locale,
281 o->keyword, cp->name, cp->text);
282 }
ac884b6a
MS
283 }
284 }
ac884b6a
MS
285
286 ppdClose(ppd);
287 }
288
289 cupsArrayDelete(ppds);
290
ac884b6a
MS
291 cupsFileClose(outfile);
292
293 // Return with no errors.
294 return (0);
ac884b6a
MS
295}
296
297
298//
299// 'ppd_locale()' - Return the locale associated with a PPD file.
300//
301
302static const char * // O - Locale string
303ppd_locale(ppd_file_t *ppd) // I - PPD file
304{
305 int i, // Looping var
306 vlen; // Length of LanguageVersion string
307 static char locale[255]; // Locale string
308 static struct // LanguageVersion translation table
309 {
310 const char *version, // LanguageVersion string */
311 *language; // Language code */
312 } languages[] =
313 {
dd1abb6b
MS
314 { "chinese", "zh" },
315 { "czech", "cs" },
316 { "danish", "da" },
317 { "dutch", "nl" },
318 { "english", "en" },
319 { "finnish", "fi" },
320 { "french", "fr" },
321 { "german", "de" },
322 { "greek", "el" },
323 { "hungarian", "hu" },
324 { "italian", "it" },
325 { "japanese", "ja" },
326 { "korean", "ko" },
327 { "norwegian", "no" },
328 { "polish", "pl" },
329 { "portuguese", "pt" },
330 { "russian", "ru" },
331 { "simplified chinese", "zh_CN" },
332 { "slovak", "sk" },
333 { "spanish", "es" },
334 { "swedish", "sv" },
335 { "traditional chinese", "zh_TW" },
336 { "turkish", "tr" }
ac884b6a
MS
337 };
338
339
340 for (i = 0; i < (int)(sizeof(languages) / sizeof(languages[0])); i ++)
341 {
342 vlen = strlen(languages[i].version);
343
88f9aafc 344 if (!_cups_strncasecmp(ppd->lang_version, languages[i].version, vlen))
ac884b6a
MS
345 {
346 if (ppd->lang_version[vlen] == '-' ||
347 ppd->lang_version[vlen] == '_')
348 snprintf(locale, sizeof(locale), "%s_%s", languages[i].language,
349 ppd->lang_version + vlen + 1);
350 else
351 strlcpy(locale, languages[i].language, sizeof(locale));
352
353 return (locale);
354 }
355 }
356
357 return (NULL);
358}
359
360//
361// 'usage()' - Show usage and exit.
362//
363
364static void
365usage(void)
366{
0837b7e8
MS
367 _cupsLangPuts(stdout, _("Usage: ppdmerge [options] filename.ppd [ ... "
368 "filenameN.ppd ]"));
369 _cupsLangPuts(stdout, _("Options:"));
84315f46
MS
370 _cupsLangPuts(stdout, _(" -o filename.ppd[.gz] Set output file "
371 "(otherwise stdout)."));
ac884b6a
MS
372
373 exit(1);
374}
375
376
377//
61515785 378// End of "$Id: ppdmerge.cxx 3275 2011-05-20 07:26:13Z msweet $".
ac884b6a 379//