]> git.ipfire.org Git - thirdparty/cups.git/blame - ppdc/ppdc.cxx
Import changes from CUPS 1.4svn-r8704.
[thirdparty/cups.git] / ppdc / ppdc.cxx
CommitLineData
ac884b6a
MS
1//
2// "$Id$"
3//
4// PPD file compiler main entry for the CUPS PPD Compiler.
5//
61cf44e2 6// Copyright 2007-2008 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 compiler.
18// usage() - Show usage and exit.
19//
20
21//
22// Include necessary headers...
23//
24
38e73f87 25#include "ppdc-private.h"
bdd6c45b 26#include <unistd.h>
ac884b6a
MS
27#include <sys/stat.h>
28#include <sys/types.h>
29
30
31//
32// Local functions...
33//
34
35static void usage(void);
36
37
38//
39// 'main()' - Main entry for the PPD compiler.
40//
41
42int // O - Exit status
43main(int argc, // I - Number of command-line arguments
44 char *argv[]) // I - Command-line arguments
45{
46 int i, j; // Looping vars
47 ppdcCatalog *catalog; // Message catalog
48 const char *outdir; // Output directory
49 ppdcSource *src; // PPD source file data
50 ppdcDriver *d; // Current driver
51 cups_file_t *fp; // PPD file
52 char *opt, // Current option
53 *value, // Value in option
bdd6c45b 54 *outname, // Output filename
ac884b6a
MS
55 pcfilename[1024],
56 // Lowercase pcfilename
57 filename[1024]; // PPD filename
bdd6c45b
MS
58 int comp, // Compress
59 do_test, // Test PPD files
60 use_model_name, // Use ModelName for filename
61 verbose; // Verbosity
ac884b6a 62 ppdcLineEnding le; // Line ending to use
bdd6c45b 63 ppdcArray *locales; // List of locales
ac884b6a
MS
64
65
61cf44e2
MS
66 _cupsSetLocale(argv);
67
ac884b6a 68 // Scan the command-line...
bdd6c45b
MS
69 catalog = NULL;
70 comp = 0;
71 do_test = 0;
72 le = PPDC_LFONLY;
73 locales = NULL;
74 outdir = "ppd";
75 src = new ppdcSource();
76 use_model_name = 0;
77 verbose = 0;
ac884b6a
MS
78
79 for (i = 1; i < argc; i ++)
80 if (argv[i][0] == '-')
81 {
82 for (opt = argv[i] + 1; *opt; opt ++)
83 switch (*opt)
84 {
bdd6c45b
MS
85 case 'D' : // Define variable
86 i ++;
87 if (i >= argc)
88 usage();
89
90 if ((value = strchr(argv[i], '=')) != NULL)
91 {
92 *value++ = '\0';
93
94 src->set_variable(argv[i], value);
95 }
96 else
97 src->set_variable(argv[i], "1");
98 break;
99
100 case 'I' : // Include directory...
101 i ++;
102 if (i >= argc)
103 usage();
104
105 if (verbose > 1)
61cf44e2
MS
106 _cupsLangPrintf(stdout,
107 _("ppdc: Adding include directory \"%s\"...\n"),
108 argv[i]);
bdd6c45b
MS
109
110 ppdcSource::add_include(argv[i]);
111 break;
112
ac884b6a
MS
113 case 'c' : // Message catalog...
114 i ++;
115 if (i >= argc)
116 usage();
117
118 if (verbose > 1)
61cf44e2
MS
119 _cupsLangPrintf(stdout,
120 _("ppdc: Loading messages from \"%s\"...\n"),
121 argv[i]);
ac884b6a
MS
122
123 if (!catalog)
124 catalog = new ppdcCatalog("en");
125
126 if (catalog->load_messages(argv[i]))
127 {
61cf44e2
MS
128 _cupsLangPrintf(stderr,
129 _("ppdc: Unable to load localization file "
130 "\"%s\" - %s\n"), argv[i], strerror(errno));
ac884b6a
MS
131 return (1);
132 }
133 break;
134
135 case 'd' : // Output directory...
136 i ++;
137 if (i >= argc)
138 usage();
139
140 if (verbose > 1)
61cf44e2
MS
141 _cupsLangPrintf(stdout,
142 _("ppdc: Writing PPD files to directory "
143 "\"%s\"...\n"), argv[i]);
ac884b6a
MS
144
145 outdir = argv[i];
146 break;
147
148 case 'l' : // Language(s)...
149 i ++;
150 if (i >= argc)
151 usage();
152
153 if (strchr(argv[i], ','))
154 {
155 // Comma-delimited list of languages...
156 char temp[1024], // Copy of language list
157 *start, // Start of current locale name
158 *end; // End of current locale name
159
160
161 locales = new ppdcArray();
162
163 strlcpy(temp, argv[i], sizeof(temp));
164 for (start = temp; *start; start = end)
165 {
166 if ((end = strchr(start, ',')) != NULL)
167 *end++ = '\0';
168 else
169 end = start + strlen(start);
170
171 if (end > start)
172 locales->add(new ppdcString(start));
173 }
174 }
175 else
176 {
177 if (verbose > 1)
61cf44e2
MS
178 _cupsLangPrintf(stdout,
179 _("ppdc: Loading messages for locale "
180 "\"%s\"...\n"), argv[i]);
ac884b6a
MS
181
182 if (catalog)
e4572d57 183 catalog->release();
ac884b6a
MS
184
185 catalog = new ppdcCatalog(argv[i]);
186
187 if (catalog->messages->count == 0)
188 {
61cf44e2
MS
189 _cupsLangPrintf(stderr,
190 _("ppdc: Unable to find localization for "
191 "\"%s\" - %s\n"), argv[i], strerror(errno));
ac884b6a
MS
192 return (1);
193 }
194 }
195 break;
196
bdd6c45b
MS
197 case 'm' : // Use ModelName for filename
198 use_model_name = 1;
199 break;
ac884b6a 200
bdd6c45b
MS
201 case 't' : // Test PPDs instead of generating them
202 do_test = 1;
ac884b6a
MS
203 break;
204
205 case 'v' : // Be verbose...
206 verbose ++;
207 break;
208
209 case 'z' : // Compress files...
210 comp = 1;
211 break;
212
213 case '-' : // --option
214 if (!strcmp(opt, "-lf"))
215 {
216 le = PPDC_LFONLY;
217 opt += strlen(opt) - 1;
218 break;
219 }
220 else if (!strcmp(opt, "-cr"))
221 {
222 le = PPDC_CRONLY;
223 opt += strlen(opt) - 1;
224 break;
225 }
226 else if (!strcmp(opt, "-crlf"))
227 {
228 le = PPDC_CRLF;
229 opt += strlen(opt) - 1;
230 break;
231 }
232
233 default : // Unknown
234 usage();
235 break;
236 }
237 }
238 else
239 {
240 // Open and load the driver info file...
241 if (verbose > 1)
61cf44e2
MS
242 _cupsLangPrintf(stdout,
243 _("ppdc: Loading driver information file \"%s\"...\n"),
244 argv[i]);
ac884b6a
MS
245
246 src->read_file(argv[i]);
247 }
248
249
250 if (src->drivers->count > 0)
251 {
252 // Create the output directory...
253 if (mkdir(outdir, 0777))
254 {
255 if (errno != EEXIST)
256 {
61cf44e2
MS
257 _cupsLangPrintf(stderr,
258 _("ppdc: Unable to create output directory %s: %s\n"),
ac884b6a
MS
259 outdir, strerror(errno));
260 return (1);
261 }
262 }
263
264 // Write PPD files...
265 for (d = (ppdcDriver *)src->drivers->first();
266 d;
267 d = (ppdcDriver *)src->drivers->next())
268 {
bdd6c45b 269 if (do_test)
ac884b6a 270 {
bdd6c45b
MS
271 // Test the PPD file for this driver...
272 int pid, // Process ID
273 fds[2]; // Pipe file descriptors
274
275
276 if (pipe(fds))
277 {
61cf44e2
MS
278 _cupsLangPrintf(stderr,
279 _("ppdc: Unable to create output pipes: %s\n"),
280 strerror(errno));
bdd6c45b
MS
281 return (1);
282 }
283
284 if ((pid = fork()) == 0)
285 {
286 // Child process comes here...
97c9a8d7 287 dup2(fds[0], 0);
bdd6c45b
MS
288
289 close(fds[0]);
290 close(fds[1]);
291
292 execlp("cupstestppd", "cupstestppd", "-", (char *)0);
293
61cf44e2
MS
294 _cupsLangPrintf(stderr,
295 _("ppdc: Unable to execute cupstestppd: %s\n"),
296 strerror(errno));
bdd6c45b
MS
297 return (errno);
298 }
299 else if (pid < 0)
300 {
61cf44e2
MS
301 _cupsLangPrintf(stderr,
302 _("ppdc: Unable to execute cupstestppd: %s\n"),
303 strerror(errno));
bdd6c45b
MS
304 return (errno);
305 }
ac884b6a 306
bdd6c45b
MS
307 close(fds[0]);
308 fp = cupsFileOpenFd(fds[1], "w");
ac884b6a
MS
309 }
310 else
311 {
bdd6c45b
MS
312 // Write the PPD file for this driver...
313 if (use_model_name)
314 outname = d->model_name->value;
315 else if (d->file_name)
316 outname = d->file_name->value;
317 else
318 outname = d->pc_file_name->value;
319
320 if (strstr(outname, ".PPD"))
321 {
322 // Convert PCFileName to lowercase...
323 for (j = 0;
324 outname[j] && j < (int)(sizeof(pcfilename) - 1);
325 j ++)
326 pcfilename[j] = tolower(outname[j] & 255);
ac884b6a 327
bdd6c45b
MS
328 pcfilename[j] = '\0';
329 }
330 else
331 {
332 // Leave PCFileName as-is...
333 strlcpy(pcfilename, outname, sizeof(pcfilename));
334 }
ac884b6a 335
bdd6c45b
MS
336 // Open the PPD file for writing...
337 if (comp)
338 snprintf(filename, sizeof(filename), "%s/%s.gz", outdir, pcfilename);
339 else
340 snprintf(filename, sizeof(filename), "%s/%s", outdir, pcfilename);
341
342 fp = cupsFileOpen(filename, comp ? "w9" : "w");
343 if (!fp)
344 {
61cf44e2
MS
345 _cupsLangPrintf(stderr,
346 _("ppdc: Unable to create PPD file \"%s\" - %s.\n"),
347 filename, strerror(errno));
bdd6c45b
MS
348 return (1);
349 }
350
351 if (verbose)
61cf44e2 352 _cupsLangPrintf(stdout, _("ppdc: Writing %s...\n"), filename);
ac884b6a
MS
353 }
354
bdd6c45b
MS
355 /*
356 * Write the PPD file...
357 */
ac884b6a 358
97c9a8d7
MS
359 ppdcArray *templocales = locales;
360
361 if (!templocales)
362 {
363 templocales = new ppdcArray();
364 for (ppdcCatalog *tempcatalog = (ppdcCatalog *)src->po_files->first();
365 tempcatalog;
366 tempcatalog = (ppdcCatalog *)src->po_files->next())
367 {
368 tempcatalog->locale->retain();
369 templocales->add(tempcatalog->locale);
370 }
371 }
372
373 if (d->write_ppd_file(fp, catalog, templocales, src, le))
ac884b6a
MS
374 {
375 cupsFileClose(fp);
376 return (1);
377 }
378
97c9a8d7
MS
379 if (templocales != locales)
380 templocales->release();
381
ac884b6a
MS
382 cupsFileClose(fp);
383 }
384 }
385 else
386 usage();
387
388 // Delete the printer driver information...
e4572d57 389 src->release();
ac884b6a
MS
390
391 // Message catalog...
392 if (catalog)
e4572d57 393 catalog->release();
ac884b6a
MS
394
395 // Return with no errors.
396 return (0);
397}
398
399
400//
401// 'usage()' - Show usage and exit.
402//
403
404static void
405usage(void)
406{
61cf44e2
MS
407 _cupsLangPuts(stdout,
408 _("Usage: ppdc [options] filename.drv [ ... filenameN.drv ]\n"
409 "Options:\n"
410 " -D name=value Set named variable to value.\n"
411 " -I include-dir Add include directory to search "
412 "path.\n"
413 " -c catalog.po Load the specified message catalog.\n"
414 " -d output-dir Specify the output directory.\n"
415 " -l lang[,lang,...] Specify the output language(s) "
416 "(locale).\n"
417 " -m Use the ModelName value as the "
418 "filename.\n"
419 " -t Test PPDs instead of generating "
420 "them.\n"
421 " -v Be verbose (more v's for more "
422 "verbosity).\n"
423 " -z Compress PPD files using GNU zip.\n"
424 " --cr End lines with CR (Mac OS 9).\n"
425 " --crlf End lines with CR + LF (Windows).\n"
426 " --lf End lines with LF (UNIX/Linux/Mac "
427 "OS X).\n"));
ac884b6a
MS
428
429 exit(1);
430}
431
432
433//
434// End of "$Id$".
435//