]> git.ipfire.org Git - thirdparty/cups.git/blob - ppdc/ppdc.cxx
Merge changes from CUPS 1.4svn-r8492.
[thirdparty/cups.git] / ppdc / ppdc.cxx
1 //
2 // "$Id$"
3 //
4 // PPD file compiler main entry for the CUPS PPD Compiler.
5 //
6 // Copyright 2007-2008 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 compiler.
18 // usage() - Show usage and exit.
19 //
20
21 //
22 // Include necessary headers...
23 //
24
25 #include "ppdc-private.h"
26 #include <unistd.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29
30
31 //
32 // Local functions...
33 //
34
35 static void usage(void);
36
37
38 //
39 // 'main()' - Main entry for the PPD compiler.
40 //
41
42 int // O - Exit status
43 main(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
54 *outname, // Output filename
55 pcfilename[1024],
56 // Lowercase pcfilename
57 filename[1024]; // PPD filename
58 int comp, // Compress
59 do_test, // Test PPD files
60 use_model_name, // Use ModelName for filename
61 verbose; // Verbosity
62 ppdcLineEnding le; // Line ending to use
63 ppdcArray *locales; // List of locales
64
65
66 _cupsSetLocale(argv);
67
68 // Scan the command-line...
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;
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 {
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)
106 _cupsLangPrintf(stdout,
107 _("ppdc: Adding include directory \"%s\"...\n"),
108 argv[i]);
109
110 ppdcSource::add_include(argv[i]);
111 break;
112
113 case 'c' : // Message catalog...
114 i ++;
115 if (i >= argc)
116 usage();
117
118 if (verbose > 1)
119 _cupsLangPrintf(stdout,
120 _("ppdc: Loading messages from \"%s\"...\n"),
121 argv[i]);
122
123 if (!catalog)
124 catalog = new ppdcCatalog("en");
125
126 if (catalog->load_messages(argv[i]))
127 {
128 _cupsLangPrintf(stderr,
129 _("ppdc: Unable to load localization file "
130 "\"%s\" - %s\n"), argv[i], strerror(errno));
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)
141 _cupsLangPrintf(stdout,
142 _("ppdc: Writing PPD files to directory "
143 "\"%s\"...\n"), argv[i]);
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)
178 _cupsLangPrintf(stdout,
179 _("ppdc: Loading messages for locale "
180 "\"%s\"...\n"), argv[i]);
181
182 if (catalog)
183 catalog->release();
184
185 catalog = new ppdcCatalog(argv[i]);
186
187 if (catalog->messages->count == 0)
188 {
189 _cupsLangPrintf(stderr,
190 _("ppdc: Unable to find localization for "
191 "\"%s\" - %s\n"), argv[i], strerror(errno));
192 return (1);
193 }
194 }
195 break;
196
197 case 'm' : // Use ModelName for filename
198 use_model_name = 1;
199 break;
200
201 case 't' : // Test PPDs instead of generating them
202 do_test = 1;
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)
242 _cupsLangPrintf(stdout,
243 _("ppdc: Loading driver information file \"%s\"...\n"),
244 argv[i]);
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 {
257 _cupsLangPrintf(stderr,
258 _("ppdc: Unable to create output directory %s: %s\n"),
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 {
269 if (do_test)
270 {
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 {
278 _cupsLangPrintf(stderr,
279 _("ppdc: Unable to create output pipes: %s\n"),
280 strerror(errno));
281 return (1);
282 }
283
284 if ((pid = fork()) == 0)
285 {
286 // Child process comes here...
287 close(0);
288 dup(fds[0]);
289
290 close(fds[0]);
291 close(fds[1]);
292
293 execlp("cupstestppd", "cupstestppd", "-", (char *)0);
294
295 _cupsLangPrintf(stderr,
296 _("ppdc: Unable to execute cupstestppd: %s\n"),
297 strerror(errno));
298 return (errno);
299 }
300 else if (pid < 0)
301 {
302 _cupsLangPrintf(stderr,
303 _("ppdc: Unable to execute cupstestppd: %s\n"),
304 strerror(errno));
305 return (errno);
306 }
307
308 close(fds[0]);
309 fp = cupsFileOpenFd(fds[1], "w");
310 }
311 else
312 {
313 // Write the PPD file for this driver...
314 if (use_model_name)
315 outname = d->model_name->value;
316 else if (d->file_name)
317 outname = d->file_name->value;
318 else
319 outname = d->pc_file_name->value;
320
321 if (strstr(outname, ".PPD"))
322 {
323 // Convert PCFileName to lowercase...
324 for (j = 0;
325 outname[j] && j < (int)(sizeof(pcfilename) - 1);
326 j ++)
327 pcfilename[j] = tolower(outname[j] & 255);
328
329 pcfilename[j] = '\0';
330 }
331 else
332 {
333 // Leave PCFileName as-is...
334 strlcpy(pcfilename, outname, sizeof(pcfilename));
335 }
336
337 // Open the PPD file for writing...
338 if (comp)
339 snprintf(filename, sizeof(filename), "%s/%s.gz", outdir, pcfilename);
340 else
341 snprintf(filename, sizeof(filename), "%s/%s", outdir, pcfilename);
342
343 fp = cupsFileOpen(filename, comp ? "w9" : "w");
344 if (!fp)
345 {
346 _cupsLangPrintf(stderr,
347 _("ppdc: Unable to create PPD file \"%s\" - %s.\n"),
348 filename, strerror(errno));
349 return (1);
350 }
351
352 if (verbose)
353 _cupsLangPrintf(stdout, _("ppdc: Writing %s...\n"), filename);
354 }
355
356 /*
357 * Write the PPD file...
358 */
359
360 if (d->write_ppd_file(fp, catalog, locales, src, le))
361 {
362 cupsFileClose(fp);
363 return (1);
364 }
365
366 cupsFileClose(fp);
367 }
368 }
369 else
370 usage();
371
372 // Delete the printer driver information...
373 src->release();
374
375 // Message catalog...
376 if (catalog)
377 catalog->release();
378
379 // Return with no errors.
380 return (0);
381 }
382
383
384 //
385 // 'usage()' - Show usage and exit.
386 //
387
388 static void
389 usage(void)
390 {
391 _cupsLangPuts(stdout,
392 _("Usage: ppdc [options] filename.drv [ ... filenameN.drv ]\n"
393 "Options:\n"
394 " -D name=value Set named variable to value.\n"
395 " -I include-dir Add include directory to search "
396 "path.\n"
397 " -c catalog.po Load the specified message catalog.\n"
398 " -d output-dir Specify the output directory.\n"
399 " -l lang[,lang,...] Specify the output language(s) "
400 "(locale).\n"
401 " -m Use the ModelName value as the "
402 "filename.\n"
403 " -t Test PPDs instead of generating "
404 "them.\n"
405 " -v Be verbose (more v's for more "
406 "verbosity).\n"
407 " -z Compress PPD files using GNU zip.\n"
408 " --cr End lines with CR (Mac OS 9).\n"
409 " --crlf End lines with CR + LF (Windows).\n"
410 " --lf End lines with LF (UNIX/Linux/Mac "
411 "OS X).\n"));
412
413 exit(1);
414 }
415
416
417 //
418 // End of "$Id$".
419 //