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