]>
git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc.cxx
2 // PPD file compiler main entry for the CUPS PPD Compiler.
4 // Copyright 2007-2014 by Apple Inc.
5 // Copyright 2002-2007 by Easy Software Products.
7 // These coded instructions, statements, and computer programs are the
8 // property of Apple Inc. and are protected by Federal copyright
9 // law. Distribution and use rights are outlined in the file "LICENSE.txt"
10 // which should have been included with this file. If this file is
11 // missing or damaged, see the license at "http://www.cups.org/".
15 // Include necessary headers...
18 #include "ppdc-private.h"
21 #include <sys/types.h>
28 static void usage(void);
32 // 'main()' - Main entry for the PPD compiler.
35 int // O - Exit status
36 main(int argc
, // I - Number of command-line arguments
37 char *argv
[]) // I - Command-line arguments
39 int i
, j
; // Looping vars
40 ppdcCatalog
*catalog
; // Message catalog
41 const char *outdir
; // Output directory
42 ppdcSource
*src
; // PPD source file data
43 ppdcDriver
*d
; // Current driver
44 cups_file_t
*fp
; // PPD file
45 char *opt
, // Current option
46 *value
, // Value in option
47 *outname
, // Output filename
51 // Lowercase pcfilename
52 filename
[1024]; // PPD filename
54 do_test
, // Test PPD files
55 single_language
,// Generate single-language files
56 use_model_name
, // Use ModelName for filename
58 ppdcLineEnding le
; // Line ending to use
59 ppdcArray
*locales
; // List of locales
60 cups_array_t
*filenames
; // List of generated filenames
65 // Scan the command-line...
73 src
= new ppdcSource();
76 filenames
= cupsArrayNew((cups_array_func_t
)_cups_strcasecmp
, NULL
);
78 for (i
= 1; i
< argc
; i
++)
79 if (argv
[i
][0] == '-')
81 for (opt
= argv
[i
] + 1; *opt
; opt
++)
84 case 'D' : // Define variable
89 if ((value
= strchr(argv
[i
], '=')) != NULL
)
93 src
->set_variable(argv
[i
], value
);
96 src
->set_variable(argv
[i
], "1");
99 case 'I' : // Include directory...
105 _cupsLangPrintf(stdout
,
106 _("ppdc: Adding include directory \"%s\"."),
109 ppdcSource::add_include(argv
[i
]);
112 case 'c' : // Message catalog...
118 _cupsLangPrintf(stdout
,
119 _("ppdc: Loading messages from \"%s\"."),
123 catalog
= new ppdcCatalog("en");
125 if (catalog
->load_messages(argv
[i
]))
127 _cupsLangPrintf(stderr
,
128 _("ppdc: Unable to load localization file "
129 "\"%s\" - %s"), argv
[i
], strerror(errno
));
134 case 'd' : // Output directory...
140 _cupsLangPrintf(stdout
,
141 _("ppdc: Writing PPD files to directory "
142 "\"%s\"."), argv
[i
]);
147 case 'l' : // Language(s)...
152 if (strchr(argv
[i
], ','))
154 // Comma-delimited list of languages...
155 char temp
[1024], // Copy of language list
156 *start
, // Start of current locale name
157 *end
; // End of current locale name
160 locales
= new ppdcArray();
162 strlcpy(temp
, argv
[i
], sizeof(temp
));
163 for (start
= temp
; *start
; start
= end
)
165 if ((end
= strchr(start
, ',')) != NULL
)
168 end
= start
+ strlen(start
);
171 locales
->add(new ppdcString(start
));
179 _cupsLangPrintf(stdout
,
180 _("ppdc: Loading messages for locale "
181 "\"%s\"."), argv
[i
]);
186 catalog
= new ppdcCatalog(argv
[i
]);
188 if (catalog
->messages
->count
== 0 && strcmp(argv
[i
], "en"))
190 _cupsLangPrintf(stderr
,
191 _("ppdc: Unable to find localization for "
192 "\"%s\" - %s"), argv
[i
], strerror(errno
));
198 case 'm' : // Use ModelName for filename
202 case 't' : // Test PPDs instead of generating them
206 case 'v' : // Be verbose...
210 case 'z' : // Compress files...
214 case '-' : // --option
215 if (!strcmp(opt
, "-lf"))
218 opt
+= strlen(opt
) - 1;
221 else if (!strcmp(opt
, "-cr"))
224 opt
+= strlen(opt
) - 1;
227 else if (!strcmp(opt
, "-crlf"))
230 opt
+= strlen(opt
) - 1;
241 // Open and load the driver info file...
243 _cupsLangPrintf(stdout
,
244 _("ppdc: Loading driver information file \"%s\"."),
247 src
->read_file(argv
[i
]);
251 if (src
->drivers
->count
> 0)
253 // Create the output directory...
254 if (mkdir(outdir
, 0777))
258 _cupsLangPrintf(stderr
,
259 _("ppdc: Unable to create output directory %s: %s"),
260 outdir
, strerror(errno
));
265 // Write PPD files...
266 for (d
= (ppdcDriver
*)src
->drivers
->first();
268 d
= (ppdcDriver
*)src
->drivers
->next())
272 // Test the PPD file for this driver...
273 int pid
, // Process ID
274 fds
[2]; // Pipe file descriptors
279 _cupsLangPrintf(stderr
,
280 _("ppdc: Unable to create output pipes: %s"),
285 if ((pid
= fork()) == 0)
287 // Child process comes here...
293 execlp("cupstestppd", "cupstestppd", "-", (char *)0);
295 _cupsLangPrintf(stderr
,
296 _("ppdc: Unable to execute cupstestppd: %s"),
302 _cupsLangPrintf(stderr
, _("ppdc: Unable to execute cupstestppd: %s"),
308 fp
= cupsFileOpenFd(fds
[1], "w");
312 // Write the PPD file for this driver...
315 if (!_cups_strncasecmp(d
->model_name
->value
, d
->manufacturer
->value
,
316 strlen(d
->manufacturer
->value
)))
318 // Model name already starts with the manufacturer...
319 outname
= d
->model_name
->value
;
323 // Add manufacturer to the front of the model name...
324 snprintf(make_model
, sizeof(make_model
), "%s %s",
325 d
->manufacturer
->value
, d
->model_name
->value
);
326 outname
= make_model
;
329 else if (d
->file_name
)
330 outname
= d
->file_name
->value
;
332 outname
= d
->pc_file_name
->value
;
334 if (strstr(outname
, ".PPD"))
336 // Convert PCFileName to lowercase...
338 outname
[j
] && j
< (int)(sizeof(pcfilename
) - 1);
340 pcfilename
[j
] = (char)tolower(outname
[j
] & 255);
342 pcfilename
[j
] = '\0';
346 // Leave PCFileName as-is...
347 strlcpy(pcfilename
, outname
, sizeof(pcfilename
));
350 // Open the PPD file for writing...
352 snprintf(filename
, sizeof(filename
), "%s/%s.gz", outdir
, pcfilename
);
354 snprintf(filename
, sizeof(filename
), "%s/%s", outdir
, pcfilename
);
356 if (cupsArrayFind(filenames
, filename
))
357 _cupsLangPrintf(stderr
,
358 _("ppdc: Warning - overlapping filename \"%s\"."),
361 cupsArrayAdd(filenames
, strdup(filename
));
363 fp
= cupsFileOpen(filename
, comp
? "w9" : "w");
366 _cupsLangPrintf(stderr
,
367 _("ppdc: Unable to create PPD file \"%s\" - %s."),
368 filename
, strerror(errno
));
373 _cupsLangPrintf(stdout
, _("ppdc: Writing %s."), filename
);
377 * Write the PPD file...
380 ppdcArray
*templocales
= locales
;
382 if (!templocales
&& !single_language
)
384 templocales
= new ppdcArray();
385 for (ppdcCatalog
*tempcatalog
= (ppdcCatalog
*)src
->po_files
->first();
387 tempcatalog
= (ppdcCatalog
*)src
->po_files
->next())
389 tempcatalog
->locale
->retain();
390 templocales
->add(tempcatalog
->locale
);
394 if (d
->write_ppd_file(fp
, catalog
, templocales
, src
, le
))
400 if (templocales
!= locales
)
401 templocales
->release();
409 // Delete the printer driver information...
412 // Message catalog...
416 // Return with no errors.
422 // 'usage()' - Show usage and exit.
428 _cupsLangPuts(stdout
, _("Usage: ppdc [options] filename.drv [ ... "
430 _cupsLangPuts(stdout
, _("Options:"));
431 _cupsLangPuts(stdout
, _(" -D name=value Set named variable to "
433 _cupsLangPuts(stdout
, _(" -I include-dir Add include directory to "
435 _cupsLangPuts(stdout
, _(" -c catalog.po Load the specified "
436 "message catalog."));
437 _cupsLangPuts(stdout
, _(" -d output-dir Specify the output "
439 _cupsLangPuts(stdout
, _(" -l lang[,lang,...] Specify the output "
440 "language(s) (locale)."));
441 _cupsLangPuts(stdout
, _(" -m Use the ModelName value "
442 "as the filename."));
443 _cupsLangPuts(stdout
, _(" -t Test PPDs instead of "
444 "generating them."));
445 _cupsLangPuts(stdout
, _(" -v Be verbose."));
446 _cupsLangPuts(stdout
, _(" -z Compress PPD files using "
448 _cupsLangPuts(stdout
, _(" --cr End lines with CR (Mac "
450 _cupsLangPuts(stdout
, _(" --crlf End lines with CR + LF "
452 _cupsLangPuts(stdout
, _(" --lf End lines with LF "
453 "(UNIX/Linux/macOS)."));