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