]>
Commit | Line | Data |
---|---|---|
ac884b6a MS |
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" | |
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 | ||
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 | |
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 | ||
66 | // Scan the command-line... | |
bdd6c45b MS |
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; | |
ac884b6a MS |
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 | { | |
bdd6c45b MS |
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 | ||
ac884b6a MS |
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 | ||
bdd6c45b MS |
189 | case 'm' : // Use ModelName for filename |
190 | use_model_name = 1; | |
191 | break; | |
ac884b6a | 192 | |
bdd6c45b MS |
193 | case 't' : // Test PPDs instead of generating them |
194 | do_test = 1; | |
ac884b6a MS |
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 | { | |
bdd6c45b | 258 | if (do_test) |
ac884b6a | 259 | { |
bdd6c45b MS |
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 | } | |
ac884b6a | 293 | |
bdd6c45b MS |
294 | close(fds[0]); |
295 | fp = cupsFileOpenFd(fds[1], "w"); | |
ac884b6a MS |
296 | } |
297 | else | |
298 | { | |
bdd6c45b MS |
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); | |
ac884b6a | 314 | |
bdd6c45b MS |
315 | pcfilename[j] = '\0'; |
316 | } | |
317 | else | |
318 | { | |
319 | // Leave PCFileName as-is... | |
320 | strlcpy(pcfilename, outname, sizeof(pcfilename)); | |
321 | } | |
ac884b6a | 322 | |
bdd6c45b MS |
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); | |
ac884b6a MS |
339 | } |
340 | ||
bdd6c45b MS |
341 | /* |
342 | * Write the PPD file... | |
343 | */ | |
ac884b6a MS |
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)."); | |
bdd6c45b MS |
383 | puts(" -m Use the ModelName value as the filename."); |
384 | puts(" -t Test PPDs instead of generating them."); | |
ac884b6a MS |
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 | // |