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