]>
Commit | Line | Data |
---|---|---|
90a24de4 | 1 | /* |
e8fda7b9 | 2 | * "$Id: ppd.c,v 1.7 1999/03/01 20:51:53 mike Exp $" |
90a24de4 | 3 | * |
3a193f5e | 4 | * PPD file routines for the Common UNIX Printing System (CUPS). |
90a24de4 | 5 | * |
3a193f5e | 6 | * Copyright 1997-1999 by Easy Software Products, all rights reserved. |
90a24de4 | 7 | * |
3a193f5e | 8 | * These coded instructions, statements, and computer programs are the |
9 | * property of Easy Software Products and are protected by Federal | |
10 | * copyright law. Distribution and use rights are outlined in the file | |
11 | * "LICENSE.txt" which should have been included with this file. If this | |
12 | * file is missing or damaged please contact Easy Software Products | |
13 | * at: | |
14 | * | |
15 | * Attn: CUPS Licensing Information | |
90a24de4 | 16 | * Easy Software Products |
17 | * 44145 Airport View Drive, Suite 204 | |
18 | * Hollywood, Maryland 20636-3111 USA | |
19 | * | |
20 | * Voice: (301) 373-9603 | |
21 | * EMail: cups-info@cups.org | |
22 | * WWW: http://www.cups.org | |
23 | * | |
2b85e375 | 24 | * PostScript is a trademark of Adobe Systems, Inc. |
25 | * | |
90a24de4 | 26 | * Contents: |
27 | * | |
2b85e375 | 28 | * ppdClose() - Free all memory used by the PPD file. |
29 | * ppd_free_group() - Free a single UI group. | |
30 | * ppd_free_option() - Free a single option. | |
31 | * ppdOpen() - Read a PPD file into memory. | |
32 | * ppdOpenFd() - Read a PPD file into memory. | |
33 | * ppdOpenFile() - Read a PPD file into memory. | |
34 | * ppd_read() - Read a line from a PPD file, skipping comment lines | |
35 | * as necessary. | |
90a24de4 | 36 | */ |
37 | ||
38 | /* | |
39 | * Include necessary headers. | |
40 | */ | |
41 | ||
2b85e375 | 42 | #include "ppd.h" |
3b960317 | 43 | #include <stdlib.h> |
2456b740 | 44 | #include <ctype.h> |
3b960317 | 45 | #include "string.h" |
2b85e375 | 46 | |
47 | ||
48 | /* | |
49 | * Definitions... | |
50 | */ | |
51 | ||
3b960317 | 52 | #if defined(WIN32) || defined(__EMX__) |
2b85e375 | 53 | # define READ_BINARY "rb" /* Open a binary file for reading */ |
54 | # define WRITE_BINARY "wb" /* Open a binary file for writing */ | |
55 | #else | |
56 | # define READ_BINARY "r" /* Open a binary file for reading */ | |
57 | # define WRITE_BINARY "w" /* Open a binary file for writing */ | |
3b960317 | 58 | #endif /* WIN32 || __EMX__ */ |
2b85e375 | 59 | |
60 | #define PPD_KEYWORD 1 /* Line contained a keyword */ | |
61 | #define PPD_OPTION 2 /* Line contained an option name */ | |
62 | #define PPD_TEXT 4 /* Line contained human-readable text */ | |
63 | #define PPD_STRING 8 /* Line contained a string or code */ | |
64 | ||
65 | ||
66 | /* | |
67 | * Local functions... | |
68 | */ | |
69 | ||
70 | static int ppd_read(FILE *fp, char *keyword, char *option, | |
71 | unsigned char *text, unsigned char **string); | |
72 | static void ppd_decode(unsigned char *string); | |
73 | static void ppd_free_group(ppd_group_t *group); | |
74 | static void ppd_free_option(ppd_option_t *option); | |
75 | ||
76 | ||
77 | /* | |
78 | * 'ppdClose()' - Free all memory used by the PPD file. | |
79 | */ | |
80 | ||
81 | void | |
82 | ppdClose(ppd_file_t *ppd) /* I - PPD file record */ | |
83 | { | |
84 | int i; /* Looping var */ | |
85 | ppd_emul_t *emul; /* Current emulation */ | |
86 | ppd_group_t *group; /* Current group */ | |
87 | ppd_option_t *option; /* Current option */ | |
88 | char **font; /* Current font */ | |
89 | ||
90 | ||
91 | /* | |
92 | * Range check the PPD file record... | |
93 | */ | |
94 | ||
95 | if (ppd == NULL) | |
96 | return; | |
97 | ||
98 | /* | |
99 | * Free all strings at the top level... | |
100 | */ | |
101 | ||
102 | free(ppd->lang_encoding); | |
103 | free(ppd->lang_version); | |
104 | free(ppd->modelname); | |
105 | free(ppd->ttrasterizer); | |
106 | free(ppd->manufacturer); | |
107 | free(ppd->product); | |
108 | free(ppd->nickname); | |
109 | free(ppd->shortnickname); | |
110 | ||
111 | /* | |
112 | * Free any emulations... | |
113 | */ | |
114 | ||
115 | if (ppd->num_emulations > 0) | |
116 | { | |
117 | for (i = ppd->num_emulations, emul = ppd->emulations; i > 0; i --, emul ++) | |
118 | { | |
119 | free(emul->start); | |
120 | free(emul->stop); | |
e8fda7b9 | 121 | } |
2b85e375 | 122 | |
123 | free(ppd->emulations); | |
e8fda7b9 | 124 | } |
2b85e375 | 125 | |
126 | /* | |
127 | * Free any JCLs... | |
128 | */ | |
129 | ||
130 | if (ppd->num_jcls > 0) | |
131 | { | |
132 | for (i = ppd->num_jcls, option = ppd->jcls; i > 0; i --, option ++) | |
133 | ppd_free_option(option); | |
134 | ||
135 | free(ppd->jcls); | |
e8fda7b9 | 136 | } |
2b85e375 | 137 | |
138 | /* | |
139 | * Free any UI groups, subgroups, and options... | |
140 | */ | |
141 | ||
142 | if (ppd->num_groups > 0) | |
143 | { | |
144 | for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) | |
145 | ppd_free_group(group); | |
146 | ||
147 | free(ppd->groups); | |
e8fda7b9 | 148 | } |
2b85e375 | 149 | |
150 | /* | |
151 | * Free any Non-UI options... | |
152 | */ | |
153 | ||
154 | if (ppd->num_nonuis > 0) | |
155 | { | |
156 | for (i = ppd->num_nonuis, option = ppd->nonuis; i > 0; i --, option ++) | |
157 | ppd_free_option(option); | |
158 | ||
159 | free(ppd->nonuis); | |
e8fda7b9 | 160 | } |
2b85e375 | 161 | |
162 | /* | |
163 | * Free any page sizes... | |
164 | */ | |
165 | ||
166 | if (ppd->num_sizes > 0) | |
167 | free(ppd->sizes); | |
168 | ||
169 | /* | |
170 | * Free any constraints... | |
171 | */ | |
172 | ||
173 | if (ppd->num_consts > 0) | |
174 | free(ppd->consts); | |
175 | ||
176 | /* | |
177 | * Free any fonts... | |
178 | */ | |
179 | ||
180 | if (ppd->num_fonts > 0) | |
181 | { | |
182 | for (i = ppd->num_fonts, font = ppd->fonts; i > 0; i --, font ++) | |
183 | free(*font); | |
184 | ||
185 | free(ppd->fonts); | |
e8fda7b9 | 186 | } |
2b85e375 | 187 | |
188 | /* | |
189 | * Free the whole record... | |
190 | */ | |
191 | ||
192 | free(ppd); | |
193 | } | |
194 | ||
195 | ||
196 | /* | |
197 | * 'ppd_free_group()' - Free a single UI group. | |
198 | */ | |
199 | ||
200 | static void | |
201 | ppd_free_group(ppd_group_t *group) /* I - Group to free */ | |
202 | { | |
203 | int i; /* Looping var */ | |
204 | ppd_option_t *option; /* Current option */ | |
205 | ppd_group_t *subgroup; /* Current sub-group */ | |
206 | ||
207 | ||
208 | if (group->num_options > 0) | |
209 | { | |
210 | for (i = group->num_options, option = group->options; | |
211 | i > 0; | |
212 | i --, option ++) | |
213 | ppd_free_option(option); | |
214 | ||
215 | free(group->options); | |
e8fda7b9 | 216 | } |
2b85e375 | 217 | |
218 | if (group->num_subgroups > 0) | |
219 | { | |
220 | for (i = group->num_subgroups, subgroup = group->subgroups; | |
221 | i > 0; | |
222 | i --, subgroup ++) | |
223 | ppd_free_group(subgroup); | |
224 | ||
225 | free(group->subgroups); | |
e8fda7b9 | 226 | } |
2b85e375 | 227 | } |
228 | ||
229 | ||
230 | /* | |
231 | * 'ppd_free_option()' - Free a single option. | |
232 | */ | |
233 | ||
234 | static void | |
235 | ppd_free_option(ppd_option_t *option) /* I - Option to free */ | |
236 | { | |
237 | int i; /* Looping var */ | |
238 | ppd_choice_t *choice; /* Current choice */ | |
239 | ||
240 | ||
241 | if (option->num_choices > 0) | |
242 | { | |
243 | for (i = option->num_choices, choice = option->choices; | |
244 | i > 0; | |
245 | i --, choice ++) | |
246 | free(choice->code); | |
247 | ||
248 | free(option->choices); | |
e8fda7b9 | 249 | } |
2b85e375 | 250 | } |
251 | ||
252 | ||
253 | /* | |
254 | * 'ppdOpen()' - Read a PPD file into memory. | |
255 | */ | |
256 | ||
257 | ppd_file_t * /* O - PPD file record */ | |
258 | ppdOpen(FILE *fp) /* I - File to read from */ | |
259 | { | |
260 | int i; /* Looping var */ | |
8c1333e2 | 261 | int count; /* Temporary count */ |
2b85e375 | 262 | ppd_file_t *ppd; /* PPD file record */ |
263 | ppd_group_t *group, /* Current group */ | |
264 | *subgroup; /* Current sub-group */ | |
265 | ppd_option_t *option; /* Current option */ | |
266 | ppd_choice_t *choice; /* Current choice */ | |
267 | ppd_const_t *constraint; /* Current constraint */ | |
268 | ppd_size_t *size; /* Current page size */ | |
269 | int mask; /* Line data mask */ | |
270 | char keyword[41], /* Keyword from file */ | |
271 | name[41]; /* Option from file */ | |
272 | unsigned char text[81], /* Human-readable text from file */ | |
273 | *string; /* Code/text from file */ | |
8c1333e2 | 274 | char *sptr, /* Pointer into string */ |
275 | *nameptr; /* Pointer into name */ | |
2b85e375 | 276 | float order; /* Order dependency number */ |
277 | ppd_section_t section; /* Order dependency section */ | |
278 | ||
279 | ||
280 | /* | |
281 | * Range check input... | |
282 | */ | |
283 | ||
284 | if (fp == NULL) | |
285 | return (NULL); | |
286 | ||
287 | /* | |
288 | * Grab the first line and make sure it reads '*PPD-Adobe: "major.minor"'... | |
289 | */ | |
290 | ||
291 | mask = ppd_read(fp, keyword, name, text, &string); | |
292 | ||
293 | if (mask == 0 || | |
294 | strcmp(keyword, "PPD-Adobe") != 0 || | |
295 | string == NULL || string[0] != '4') | |
296 | { | |
297 | /* | |
298 | * Either this is not a PPD file, or it is not a 4.x PPD file. | |
299 | */ | |
300 | ||
301 | if (string != NULL) | |
302 | free(string); | |
303 | ||
304 | return (NULL); | |
e8fda7b9 | 305 | } |
2b85e375 | 306 | |
307 | if (string != NULL) | |
308 | free(string); | |
309 | ||
310 | /* | |
311 | * Allocate memory for the PPD file record... | |
312 | */ | |
313 | ||
314 | if ((ppd = calloc(sizeof(ppd_file_t), 1)) == NULL) | |
315 | return (NULL); | |
316 | ||
317 | ppd->language_level = 1; | |
318 | ppd->color_device = 0; | |
319 | ppd->colorspace = PPD_CS_GRAY; | |
320 | ppd->landscape = 90; | |
321 | ||
322 | /* | |
323 | * Read lines from the PPD file and add them to the file record... | |
324 | */ | |
325 | ||
326 | group = NULL; | |
327 | subgroup = NULL; | |
328 | option = NULL; | |
329 | choice = NULL; | |
330 | ||
331 | while ((mask = ppd_read(fp, keyword, name, text, &string)) != 0) | |
332 | { | |
333 | #ifdef DEBUG | |
334 | printf("mask = %x, keyword = \"%s\"", mask, keyword); | |
335 | ||
336 | if (name[0] != '\0') | |
337 | printf(", name = \"%s\"", name); | |
338 | ||
339 | if (text[0] != '\0') | |
340 | printf(", text = \"%s\"", text); | |
341 | ||
342 | if (string != NULL) | |
343 | { | |
8c1333e2 | 344 | if (strlen((char *)string) > 40) |
2b85e375 | 345 | printf(", string = %08x", string); |
346 | else | |
347 | printf(", string = \"%s\"", string); | |
e8fda7b9 | 348 | } |
2b85e375 | 349 | |
350 | puts(""); | |
351 | #endif /* DEBUG */ | |
352 | ||
353 | if (strcmp(keyword, "LanguageLevel") == 0) | |
8c1333e2 | 354 | ppd->language_level = atoi((char *)string); |
2b85e375 | 355 | else if (strcmp(keyword, "LanguageEncoding") == 0) |
356 | { | |
8c1333e2 | 357 | ppd->lang_encoding = (char *)string; |
2b85e375 | 358 | string = NULL; /* Don't free this string below */ |
359 | } | |
360 | else if (strcmp(keyword, "LanguageVersion") == 0) | |
361 | { | |
8c1333e2 | 362 | ppd->lang_version = (char *)string; |
2b85e375 | 363 | string = NULL; /* Don't free this string below */ |
364 | } | |
365 | else if (strcmp(keyword, "Manufacturer") == 0) | |
366 | { | |
367 | ppd->manufacturer = string; | |
368 | string = NULL; /* Don't free this string below */ | |
369 | } | |
370 | else if (strcmp(keyword, "ModelName") == 0) | |
371 | { | |
8c1333e2 | 372 | ppd->modelname = (char *)string; |
2b85e375 | 373 | string = NULL; /* Don't free this string below */ |
374 | } | |
375 | else if (strcmp(keyword, "NickName") == 0) | |
376 | { | |
377 | ppd->nickname = string; | |
378 | string = NULL; /* Don't free this string below */ | |
379 | } | |
380 | else if (strcmp(keyword, "Product") == 0) | |
381 | { | |
382 | ppd->product = string; | |
383 | string = NULL; /* Don't free this string below */ | |
384 | } | |
385 | else if (strcmp(keyword, "ShortNickName") == 0) | |
386 | { | |
387 | ppd->shortnickname = string; | |
388 | string = NULL; /* Don't free this string below */ | |
389 | } | |
390 | else if (strcmp(keyword, "TTRasterizer") == 0) | |
391 | { | |
8c1333e2 | 392 | ppd->ttrasterizer = (char *)string; |
2b85e375 | 393 | string = NULL; /* Don't free this string below */ |
394 | } | |
395 | else if (strcmp(keyword, "JCLBegin") == 0) | |
396 | { | |
397 | ppd_decode(string); /* Decode quoted string */ | |
398 | ppd->jcl_begin = string; | |
399 | string = NULL; /* Don't free this string below */ | |
400 | } | |
401 | else if (strcmp(keyword, "JCLEnd") == 0) | |
402 | { | |
403 | ppd_decode(string); /* Decode quoted string */ | |
404 | ppd->jcl_end = string; | |
405 | string = NULL; /* Don't free this string below */ | |
406 | } | |
407 | else if (strcmp(keyword, "JCLToPSInterpreter") == 0) | |
408 | { | |
409 | ppd_decode(string); /* Decode quoted string */ | |
410 | ppd->jcl_ps = string; | |
411 | string = NULL; /* Don't free this string below */ | |
412 | } | |
413 | else if (strcmp(keyword, "AccurateScreensSupport") == 0) | |
8c1333e2 | 414 | ppd->accurate_screens = strcmp((char *)string, "True") == 0; |
2b85e375 | 415 | else if (strcmp(keyword, "ColorDevice") == 0) |
8c1333e2 | 416 | ppd->color_device = strcmp((char *)string, "True") == 0; |
2b85e375 | 417 | else if (strcmp(keyword, "ContoneOnly") == 0) |
8c1333e2 | 418 | ppd->contone_only = strcmp((char *)string, "True") == 0; |
2b85e375 | 419 | else if (strcmp(keyword, "DefaultColorSpace") == 0) |
420 | { | |
8c1333e2 | 421 | if (strcmp((char *)string, "CMY") == 0) |
2b85e375 | 422 | ppd->colorspace = PPD_CS_CMY; |
8c1333e2 | 423 | else if (strcmp((char *)string, "CMYK") == 0) |
2b85e375 | 424 | ppd->colorspace = PPD_CS_CMYK; |
8c1333e2 | 425 | else if (strcmp((char *)string, "RGB") == 0) |
2b85e375 | 426 | ppd->colorspace = PPD_CS_RGB; |
427 | else | |
428 | ppd->colorspace = PPD_CS_GRAY; | |
429 | } | |
430 | else if (strcmp(keyword, "LandscapeOrientation") == 0) | |
431 | { | |
8c1333e2 | 432 | if (strcmp((char *)string, "Minus90") == 0) |
2b85e375 | 433 | ppd->landscape = -90; |
434 | else | |
435 | ppd->landscape = 90; | |
436 | } | |
8c1333e2 | 437 | else if (strcmp(keyword, "Emulators") == 0) |
438 | { | |
439 | for (count = 1, sptr = (char *)string; sptr != NULL;) | |
440 | if ((sptr = strchr(sptr, ' ')) != NULL) | |
441 | { | |
442 | count ++; | |
443 | while (*sptr == ' ') | |
444 | sptr ++; | |
e8fda7b9 | 445 | } |
8c1333e2 | 446 | |
447 | ppd->num_emulations = count; | |
448 | ppd->emulations = calloc(sizeof(ppd_emul_t), count); | |
449 | ||
450 | for (i = 0, sptr = (char *)string; i < count; i ++) | |
451 | { | |
452 | for (nameptr = ppd->emulations[i].name; *sptr != '\0' && *sptr != ' ';) | |
453 | *nameptr ++ = *sptr ++; | |
454 | ||
455 | *nameptr = '\0'; | |
456 | ||
457 | while (*sptr == ' ') | |
458 | sptr ++; | |
459 | } | |
460 | } | |
461 | else if (strncmp(keyword, "StartEmulator_", 14) == 0) | |
462 | { | |
463 | ppd_decode(string); | |
464 | ||
465 | for (i = 0; i < ppd->num_emulations; i ++) | |
466 | if (strcmp(keyword + 14, ppd->emulations[i].name) == 0) | |
467 | { | |
468 | ppd->emulations[i].start = string; | |
469 | string = NULL; | |
470 | } | |
471 | } | |
472 | else if (strncmp(keyword, "StopEmulator_", 13) == 0) | |
473 | { | |
474 | ppd_decode(string); | |
475 | ||
476 | for (i = 0; i < ppd->num_emulations; i ++) | |
477 | if (strcmp(keyword + 13, ppd->emulations[i].name) == 0) | |
478 | { | |
479 | ppd->emulations[i].stop = string; | |
480 | string = NULL; | |
481 | } | |
482 | } | |
483 | else if (strcmp(keyword, "JobPatchFile") == 0) | |
484 | { | |
485 | if (ppd->patches == NULL) | |
486 | { | |
487 | ppd->patches = string; | |
488 | string = NULL; | |
489 | } | |
490 | else | |
491 | { | |
492 | ppd->patches = realloc(ppd->patches, strlen((char *)ppd->patches) + | |
493 | strlen((char *)string) + 1); | |
494 | ||
495 | strcpy((char *)ppd->patches + strlen((char *)ppd->patches), | |
496 | (char *)string); | |
497 | } | |
498 | } | |
2b85e375 | 499 | else if (strcmp(keyword, "OpenUI") == 0) |
500 | { | |
501 | /* | |
502 | * Add an option record to the current sub-group, group, or file... | |
503 | */ | |
504 | ||
505 | if (name[0] == '*') | |
506 | strcpy(name, name + 1); | |
507 | ||
508 | if (string == NULL) | |
509 | { | |
510 | ppdClose(ppd); | |
511 | return (NULL); | |
e8fda7b9 | 512 | } |
2b85e375 | 513 | |
514 | if (subgroup != NULL) | |
515 | { | |
516 | if (subgroup->num_options == 0) | |
517 | option = malloc(sizeof(ppd_option_t)); | |
518 | else | |
519 | option = realloc(subgroup->options, | |
520 | (subgroup->num_options + 1) * sizeof(ppd_option_t)); | |
521 | ||
522 | if (option == NULL) | |
523 | { | |
524 | ppdClose(ppd); | |
525 | free(string); | |
526 | return (NULL); | |
e8fda7b9 | 527 | } |
2b85e375 | 528 | |
529 | subgroup->options = option; | |
530 | option += subgroup->num_options; | |
531 | subgroup->num_options ++; | |
532 | } | |
533 | else if (group != NULL) | |
534 | { | |
535 | if (group->num_options == 0) | |
536 | option = malloc(sizeof(ppd_option_t)); | |
537 | else | |
538 | option = realloc(group->options, | |
539 | (group->num_options + 1) * sizeof(ppd_option_t)); | |
540 | ||
541 | if (option == NULL) | |
542 | { | |
543 | ppdClose(ppd); | |
544 | free(string); | |
545 | return (NULL); | |
e8fda7b9 | 546 | } |
2b85e375 | 547 | |
548 | group->options = option; | |
549 | option += group->num_options; | |
550 | group->num_options ++; | |
551 | } | |
8c1333e2 | 552 | else if (strcmp(name, "Collate") != 0 && |
553 | strcmp(name, "Duplex") != 0 && | |
2b85e375 | 554 | strcmp(name, "InputSlot") != 0 && |
555 | strcmp(name, "ManualFeed") != 0 && | |
556 | strcmp(name, "MediaType") != 0 && | |
557 | strcmp(name, "MediaColor") != 0 && | |
8c1333e2 | 558 | strcmp(name, "MediaWeight") != 0 && |
559 | strcmp(name, "OutputBin") != 0 && | |
560 | strcmp(name, "OutputMode") != 0 && | |
561 | strcmp(name, "OutputOrder") != 0 && | |
562 | strcmp(name, "PageSize") != 0 && | |
563 | strcmp(name, "PageRegion") != 0) | |
2b85e375 | 564 | { |
565 | for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++) | |
8c1333e2 | 566 | if (strcmp((char *)group->text, "Printer") == 0) |
2b85e375 | 567 | break; |
568 | ||
569 | if (i <= 0) | |
570 | { | |
571 | if (ppd->num_groups == 0) | |
572 | group = malloc(sizeof(ppd_group_t)); | |
573 | else | |
574 | group = realloc(ppd->groups, | |
575 | (ppd->num_groups + 1) * sizeof(ppd_group_t)); | |
576 | ||
577 | if (group == NULL) | |
578 | { | |
579 | ppdClose(ppd); | |
580 | free(string); | |
581 | return (NULL); | |
e8fda7b9 | 582 | } |
2b85e375 | 583 | |
584 | ppd->groups = group; | |
585 | group += ppd->num_groups; | |
586 | ppd->num_groups ++; | |
587 | ||
588 | memset(group, 0, sizeof(ppd_group_t)); | |
589 | ||
8c1333e2 | 590 | strcpy((char *)group->text, "Printer"); |
e8fda7b9 | 591 | } |
2b85e375 | 592 | |
593 | if (group->num_options == 0) | |
594 | option = malloc(sizeof(ppd_option_t)); | |
595 | else | |
596 | option = realloc(group->options, | |
597 | (group->num_options + 1) * sizeof(ppd_option_t)); | |
598 | ||
599 | if (option == NULL) | |
600 | { | |
601 | ppdClose(ppd); | |
602 | free(string); | |
603 | return (NULL); | |
e8fda7b9 | 604 | } |
2b85e375 | 605 | |
606 | group->options = option; | |
607 | option += group->num_options; | |
608 | group->num_options ++; | |
609 | group = NULL; | |
610 | } | |
611 | else | |
612 | { | |
613 | if (ppd->num_options == 0) | |
614 | option = malloc(sizeof(ppd_option_t)); | |
615 | else | |
616 | option = realloc(ppd->options, | |
617 | (ppd->num_options + 1) * sizeof(ppd_option_t)); | |
618 | ||
619 | if (option == NULL) | |
620 | { | |
621 | ppdClose(ppd); | |
622 | free(string); | |
623 | return (NULL); | |
e8fda7b9 | 624 | } |
2b85e375 | 625 | |
626 | ppd->options = option; | |
627 | option += ppd->num_options; | |
628 | ppd->num_options ++; | |
e8fda7b9 | 629 | } |
2b85e375 | 630 | |
631 | /* | |
632 | * Now fill in the initial information for the option... | |
633 | */ | |
634 | ||
635 | memset(option, 0, sizeof(ppd_option_t)); | |
636 | ||
8c1333e2 | 637 | if (strcmp((char *)string, "PickMany") == 0) |
2b85e375 | 638 | option->ui = PPD_UI_PICKMANY; |
8c1333e2 | 639 | else if (strcmp((char *)string, "Boolean") == 0) |
2b85e375 | 640 | option->ui = PPD_UI_BOOLEAN; |
641 | else | |
642 | option->ui = PPD_UI_PICKONE; | |
643 | ||
644 | strcpy(option->keyword, name); | |
8c1333e2 | 645 | strcpy((char *)option->text, (char *)text); |
2b85e375 | 646 | |
647 | option->section = PPD_ORDER_ANY; | |
648 | } | |
649 | else if (strcmp(keyword, "JCLOpenUI") == 0) | |
650 | { | |
651 | /* | |
652 | * Add an option record to the current JCLs... | |
653 | */ | |
654 | ||
655 | if (name[0] == '*') | |
656 | strcpy(name, name + 1); | |
657 | ||
658 | if (ppd->num_jcls == 0) | |
659 | option = malloc(sizeof(ppd_option_t)); | |
660 | else | |
661 | option = realloc(ppd->jcls, | |
662 | (ppd->num_jcls + 1) * sizeof(ppd_option_t)); | |
663 | ||
664 | if (option == NULL) | |
665 | { | |
666 | ppdClose(ppd); | |
667 | free(string); | |
668 | return (NULL); | |
e8fda7b9 | 669 | } |
2b85e375 | 670 | |
671 | ppd->jcls = option; | |
672 | option += ppd->num_jcls; | |
673 | ppd->num_jcls ++; | |
674 | ||
675 | /* | |
676 | * Now fill in the initial information for the option... | |
677 | */ | |
678 | ||
679 | memset(option, 0, sizeof(ppd_option_t)); | |
680 | ||
8c1333e2 | 681 | if (strcmp((char *)string, "PickMany") == 0) |
2b85e375 | 682 | option->ui = PPD_UI_PICKMANY; |
8c1333e2 | 683 | else if (strcmp((char *)string, "Boolean") == 0) |
2b85e375 | 684 | option->ui = PPD_UI_BOOLEAN; |
685 | else | |
686 | option->ui = PPD_UI_PICKONE; | |
687 | ||
688 | strcpy(option->keyword, name); | |
8c1333e2 | 689 | strcpy((char *)option->text, (char *)text); |
2b85e375 | 690 | |
691 | option->section = PPD_ORDER_JCL; | |
692 | } | |
693 | else if (strcmp(keyword, "CloseUI") == 0 || | |
694 | strcmp(keyword, "JCLCloseUI") == 0) | |
695 | option = NULL; | |
696 | else if (strcmp(keyword, "OpenGroup") == 0) | |
697 | { | |
698 | /* | |
699 | * Open a new group... | |
700 | */ | |
701 | ||
702 | if (group != NULL) | |
703 | { | |
704 | ppdClose(ppd); | |
705 | free(string); | |
706 | return (NULL); | |
e8fda7b9 | 707 | } |
2b85e375 | 708 | |
8c1333e2 | 709 | if (strchr((char *)string, '/') != NULL) /* Just show human readable text */ |
710 | strcpy((char *)string, strchr((char *)string, '/') + 1); | |
2b85e375 | 711 | |
712 | if (ppd->num_groups == 0) | |
713 | group = malloc(sizeof(ppd_group_t)); | |
714 | else | |
715 | group = realloc(ppd->groups, | |
716 | (ppd->num_groups + 1) * sizeof(ppd_group_t)); | |
717 | ||
718 | if (group == NULL) | |
719 | { | |
720 | ppdClose(ppd); | |
721 | free(string); | |
722 | return (NULL); | |
e8fda7b9 | 723 | } |
2b85e375 | 724 | |
725 | ppd->groups = group; | |
726 | group += ppd->num_groups; | |
727 | ppd->num_groups ++; | |
728 | ||
729 | memset(group, 0, sizeof(ppd_group_t)); | |
730 | ||
8c1333e2 | 731 | strcpy((char *)group->text, (char *)string); |
2b85e375 | 732 | } |
733 | else if (strcmp(keyword, "CloseGroup") == 0) | |
734 | group = NULL; | |
735 | else if (strcmp(keyword, "OpenSubGroup") == 0) | |
736 | { | |
737 | /* | |
738 | * Open a new sub-group... | |
739 | */ | |
740 | ||
741 | if (group == NULL || subgroup != NULL) | |
742 | { | |
743 | ppdClose(ppd); | |
744 | free(string); | |
745 | return (NULL); | |
e8fda7b9 | 746 | } |
2b85e375 | 747 | |
748 | if (group->num_subgroups == 0) | |
749 | subgroup = malloc(sizeof(ppd_group_t)); | |
750 | else | |
751 | subgroup = realloc(group->subgroups, | |
752 | (group->num_subgroups + 1) * sizeof(ppd_group_t)); | |
753 | ||
754 | if (subgroup == NULL) | |
755 | { | |
756 | ppdClose(ppd); | |
757 | free(string); | |
758 | return (NULL); | |
e8fda7b9 | 759 | } |
2b85e375 | 760 | |
761 | group->subgroups = subgroup; | |
762 | subgroup += group->num_subgroups; | |
763 | group->num_subgroups ++; | |
764 | ||
765 | memset(subgroup, 0, sizeof(ppd_group_t)); | |
766 | ||
8c1333e2 | 767 | strcpy((char *)subgroup->text, (char *)string); |
2b85e375 | 768 | } |
769 | else if (strcmp(keyword, "CloseSubGroup") == 0) | |
770 | subgroup = NULL; | |
771 | else if (strcmp(keyword, "OrderDependency") == 0 || | |
772 | strcmp(keyword, "NonUIOrderDependency") == 0) | |
773 | { | |
8c1333e2 | 774 | if (sscanf((char *)string, "%f%s%s", &order, name, keyword) != 3) |
2b85e375 | 775 | { |
776 | ppdClose(ppd); | |
777 | free(string); | |
778 | return (NULL); | |
e8fda7b9 | 779 | } |
2b85e375 | 780 | |
781 | if (keyword[0] == '*') | |
782 | strcpy(keyword, keyword + 1); | |
783 | ||
784 | if (strcmp(name, "ExitServer") == 0) | |
785 | section = PPD_ORDER_EXIT; | |
786 | else if (strcmp(name, "Prolog") == 0) | |
787 | section = PPD_ORDER_PROLOG; | |
788 | else if (strcmp(name, "DocumentSetup") == 0) | |
789 | section = PPD_ORDER_DOCUMENT; | |
790 | else if (strcmp(name, "PageSetup") == 0) | |
791 | section = PPD_ORDER_PAGE; | |
792 | else if (strcmp(name, "JCLSetup") == 0) | |
793 | section = PPD_ORDER_JCL; | |
794 | else | |
795 | section = PPD_ORDER_ANY; | |
796 | ||
797 | if (option == NULL) | |
798 | { | |
799 | /* | |
800 | * Only valid for Non-UI options... | |
801 | */ | |
802 | ||
803 | for (i = 0; i < ppd->num_nonuis; i ++) | |
804 | if (strcmp(keyword, ppd->nonuis[i].keyword) == 0) | |
805 | { | |
806 | ppd->nonuis[i].section = section; | |
807 | ppd->nonuis[i].order = order; | |
808 | break; | |
e8fda7b9 | 809 | } |
2b85e375 | 810 | } |
811 | else | |
812 | { | |
813 | option->section = section; | |
814 | option->order = order; | |
e8fda7b9 | 815 | } |
2b85e375 | 816 | } |
817 | else if (strncmp(keyword, "Default", 7) == 0) | |
818 | { | |
819 | if (option == NULL) | |
820 | { | |
821 | /* | |
822 | * Only valid for Non-UI options... | |
823 | */ | |
824 | ||
825 | for (i = 0; i < ppd->num_nonuis; i ++) | |
826 | if (strcmp(keyword + 7, ppd->nonuis[i].keyword) == 0) | |
827 | { | |
8c1333e2 | 828 | strcpy(ppd->nonuis[i].defchoice, (char *)string); |
2b85e375 | 829 | break; |
e8fda7b9 | 830 | } |
2b85e375 | 831 | } |
832 | else | |
8c1333e2 | 833 | strcpy(option->defchoice, (char *)string); |
2b85e375 | 834 | } |
835 | else if (strcmp(keyword, "UIConstraints") == 0 || | |
836 | strcmp(keyword, "NonUIConstraints") == 0) | |
837 | { | |
838 | if (ppd->num_consts == 0) | |
839 | constraint = calloc(sizeof(ppd_const_t), 1); | |
840 | else | |
841 | constraint = realloc(ppd->consts, | |
842 | (ppd->num_consts + 1) * sizeof(ppd_const_t)); | |
843 | ||
844 | if (constraint == NULL) | |
845 | { | |
846 | ppdClose(ppd); | |
847 | free(string); | |
848 | return (NULL); | |
e8fda7b9 | 849 | } |
2b85e375 | 850 | |
851 | ppd->consts = constraint; | |
852 | constraint += ppd->num_consts; | |
853 | ppd->num_consts ++; | |
854 | ||
8c1333e2 | 855 | switch (sscanf((char *)string, "%s%s%s%s", constraint->option1, |
856 | constraint->choice1, constraint->option2, | |
857 | constraint->choice2)) | |
2b85e375 | 858 | { |
859 | case 0 : /* Error */ | |
860 | case 1 : /* Error */ | |
861 | ppdClose(ppd); | |
862 | free(string); | |
863 | break; | |
864 | ||
8c1333e2 | 865 | case 2 : /* Two options... */ |
2b85e375 | 866 | if (constraint->option1[0] == '*') |
8c1333e2 | 867 | strcpy(constraint->option1, constraint->option1 + 1); |
868 | ||
869 | if (constraint->choice1[0] == '*') | |
870 | strcpy(constraint->option2, constraint->choice1 + 1); | |
2b85e375 | 871 | else |
8c1333e2 | 872 | strcpy(constraint->option2, constraint->choice1); |
2b85e375 | 873 | |
8c1333e2 | 874 | constraint->choice1[0] = '\0'; |
875 | constraint->choice2[0] = '\0'; | |
2b85e375 | 876 | break; |
877 | ||
8c1333e2 | 878 | case 3 : /* Two options, one choice... */ |
2b85e375 | 879 | if (constraint->option1[0] == '*') |
8c1333e2 | 880 | strcpy(constraint->option1, constraint->option1 + 1); |
881 | ||
882 | if (constraint->choice1[0] == '*') | |
2b85e375 | 883 | { |
8c1333e2 | 884 | strcpy(constraint->option2, constraint->choice1 + 1); |
885 | constraint->choice1[0] = '\0'; | |
2b85e375 | 886 | } |
8c1333e2 | 887 | else if (constraint->option2[0] == '*') |
888 | strcpy(constraint->option2, constraint->option2 + 1); | |
2b85e375 | 889 | |
8c1333e2 | 890 | constraint->choice2[0] = '\0'; |
2b85e375 | 891 | break; |
892 | ||
8c1333e2 | 893 | case 4 : /* Two options, two choices... */ |
894 | if (constraint->option1[0] == '*') | |
895 | strcpy(constraint->option1, constraint->option1 + 1); | |
2b85e375 | 896 | |
8c1333e2 | 897 | if (constraint->option2[0] == '*') |
898 | strcpy(constraint->option2, constraint->option2 + 1); | |
2b85e375 | 899 | break; |
e8fda7b9 | 900 | } |
2b85e375 | 901 | } |
902 | else if (strcmp(keyword, "PaperDimension") == 0) | |
903 | { | |
904 | if ((size = ppdPageSize(ppd, name)) != NULL) | |
8c1333e2 | 905 | sscanf((char *)string, "%f%f", &(size->width), &(size->length)); |
2b85e375 | 906 | } |
907 | else if (strcmp(keyword, "ImageableArea") == 0) | |
908 | { | |
909 | if ((size = ppdPageSize(ppd, name)) != NULL) | |
8c1333e2 | 910 | sscanf((char *)string, "%f%f%f%f", &(size->left), &(size->bottom), |
2b85e375 | 911 | &(size->right), &(size->top)); |
912 | } | |
913 | else if (option != NULL && | |
914 | (mask & (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) == | |
915 | (PPD_KEYWORD | PPD_OPTION | PPD_STRING)) | |
916 | { | |
917 | if (strcmp(keyword, "PageSize") == 0) | |
918 | { | |
919 | /* | |
920 | * Add a page size... | |
921 | */ | |
922 | ||
923 | if (ppd->num_sizes == 0) | |
924 | size = malloc(sizeof(ppd_size_t)); | |
925 | else | |
926 | size = realloc(ppd->sizes, sizeof(ppd_size_t) * (ppd->num_sizes + 1)); | |
927 | ||
928 | if (size == NULL) | |
929 | { | |
930 | ppdClose(ppd); | |
931 | free(string); | |
932 | return (NULL); | |
e8fda7b9 | 933 | } |
2b85e375 | 934 | |
935 | ppd->sizes = size; | |
936 | size += ppd->num_sizes; | |
937 | ppd->num_sizes ++; | |
938 | ||
939 | memset(size, 0, sizeof(ppd_size_t)); | |
940 | ||
941 | strcpy(size->name, name); | |
e8fda7b9 | 942 | } |
2b85e375 | 943 | |
944 | /* | |
945 | * Add the option choice... | |
946 | */ | |
947 | ||
948 | if (option->num_choices == 0) | |
949 | choice = malloc(sizeof(ppd_choice_t)); | |
950 | else | |
951 | choice = realloc(option->choices, | |
952 | sizeof(ppd_choice_t) * (option->num_choices + 1)); | |
953 | ||
954 | if (choice == NULL) | |
955 | { | |
956 | ppdClose(ppd); | |
957 | free(string); | |
958 | return (NULL); | |
e8fda7b9 | 959 | } |
2b85e375 | 960 | |
961 | option->choices = choice; | |
962 | choice += option->num_choices; | |
963 | option->num_choices ++; | |
964 | ||
965 | memset(choice, 0, sizeof(ppd_choice_t)); | |
966 | ||
8c1333e2 | 967 | choice->option = (void *)option; |
968 | strcpy(choice->choice, name); | |
2b85e375 | 969 | |
8c1333e2 | 970 | if (mask & PPD_TEXT) |
971 | strcpy((char *)choice->text, (char *)text); | |
2b85e375 | 972 | else if (strcmp(name, "True") == 0) |
8c1333e2 | 973 | strcpy((char *)choice->text, "Yes"); |
2b85e375 | 974 | else if (strcmp(name, "False") == 0) |
8c1333e2 | 975 | strcpy((char *)choice->text, "No"); |
2b85e375 | 976 | else |
8c1333e2 | 977 | strcpy((char *)choice->text, name); |
2b85e375 | 978 | |
979 | if (strncmp(keyword, "JCL", 3) == 0) | |
980 | ppd_decode(string); /* Decode quoted string */ | |
981 | ||
982 | choice->code = string; | |
983 | string = NULL; /* Don't free this string below */ | |
e8fda7b9 | 984 | } |
2b85e375 | 985 | |
986 | if (string != NULL) | |
987 | free(string); | |
e8fda7b9 | 988 | } |
2b85e375 | 989 | |
990 | #ifdef DEBUG | |
991 | if (!feof(fp)) | |
992 | printf("Premature EOF at %d...\n", ftell(fp)); | |
993 | #endif /* DEBUG */ | |
994 | ||
995 | return (ppd); | |
996 | } | |
997 | ||
998 | ||
999 | /* | |
1000 | * 'ppdOpenFd()' - Read a PPD file into memory. | |
1001 | */ | |
1002 | ||
1003 | ppd_file_t * /* O - PPD file record */ | |
1004 | ppdOpenFd(int fd) /* I - File to read from */ | |
1005 | { | |
1006 | FILE *fp; /* File pointer */ | |
1007 | ppd_file_t *ppd; /* PPD file record */ | |
1008 | ||
1009 | ||
1010 | /* | |
1011 | * Range check input... | |
1012 | */ | |
1013 | ||
1014 | if (fd < 0) | |
1015 | return (NULL); | |
1016 | ||
1017 | /* | |
1018 | * Try to open the file and parse it... | |
1019 | */ | |
1020 | ||
1021 | if ((fp = fdopen(fd, "r")) != NULL) | |
1022 | { | |
1023 | setbuf(fp, NULL); | |
1024 | ||
1025 | ppd = ppdOpen(fp); | |
1026 | ||
1027 | free(fp); | |
1028 | } | |
1029 | else | |
1030 | ppd = NULL; | |
1031 | ||
1032 | return (ppd); | |
1033 | } | |
1034 | ||
1035 | ||
1036 | /* | |
1037 | * 'ppdOpenFile()' - Read a PPD file into memory. | |
1038 | */ | |
1039 | ||
1040 | ppd_file_t * /* O - PPD file record */ | |
1041 | ppdOpenFile(char *filename) /* I - File to read from */ | |
1042 | { | |
1043 | FILE *fp; /* File pointer */ | |
1044 | ppd_file_t *ppd; /* PPD file record */ | |
1045 | ||
1046 | ||
1047 | /* | |
1048 | * Range check input... | |
1049 | */ | |
1050 | ||
1051 | if (filename == NULL) | |
1052 | return (NULL); | |
1053 | ||
1054 | /* | |
1055 | * Try to open the file and parse it... | |
1056 | */ | |
1057 | ||
1058 | if ((fp = fopen(filename, "r")) != NULL) | |
1059 | { | |
1060 | ppd = ppdOpen(fp); | |
1061 | ||
1062 | fclose(fp); | |
1063 | } | |
1064 | else | |
1065 | ppd = NULL; | |
1066 | ||
1067 | return (ppd); | |
1068 | } | |
1069 | ||
1070 | ||
1071 | /* | |
1072 | * 'ppd_read()' - Read a line from a PPD file, skipping comment lines as | |
1073 | * necessary. | |
1074 | */ | |
1075 | ||
1076 | static int /* O - Bitmask of fields read */ | |
1077 | ppd_read(FILE *fp, /* I - File to read from */ | |
1078 | char *keyword,/* O - Keyword from line */ | |
1079 | char *option, /* O - Option from line */ | |
1080 | unsigned char *text, /* O - Human-readable text from line */ | |
1081 | unsigned char **string)/* O - Code/string data */ | |
1082 | { | |
1083 | int ch, /* Character from file */ | |
1084 | endquote, /* Waiting for an end quote */ | |
1085 | mask; /* Mask to be returned */ | |
1086 | char *keyptr, /* Keyword pointer */ | |
1087 | *optptr; /* Option pointer */ | |
1088 | unsigned char *textptr, /* Text pointer */ | |
1089 | *strptr; /* Pointer into string */ | |
1090 | unsigned char *lineptr, /* Current position in line buffer */ | |
1091 | line[262144]; /* Line buffer (256k) */ | |
1092 | ||
1093 | ||
1094 | /* | |
1095 | * Range check everything... | |
1096 | */ | |
1097 | ||
1098 | if (fp == NULL || keyword == NULL || option == NULL || text == NULL || | |
1099 | string == NULL) | |
1100 | return (0); | |
1101 | ||
1102 | /* | |
1103 | * Now loop until we have a valid line... | |
1104 | */ | |
1105 | ||
1106 | do | |
1107 | { | |
1108 | /* | |
1109 | * Read the line... | |
1110 | */ | |
1111 | ||
1112 | lineptr = line; | |
1113 | endquote = 0; | |
1114 | ||
1115 | while ((ch = getc(fp)) != EOF && | |
1116 | (lineptr - line) < (sizeof(line) - 1)) | |
1117 | { | |
1118 | if (ch == '\r' || ch == '\n') | |
1119 | { | |
1120 | /* | |
1121 | * Line feed or carriage return... | |
1122 | */ | |
1123 | ||
1124 | if (lineptr == line) /* Skip blank lines */ | |
1125 | continue; | |
1126 | ||
1127 | if (ch == '\r') | |
1128 | { | |
1129 | /* | |
1130 | * Check for a trailing line feed... | |
1131 | */ | |
1132 | ||
1133 | if ((ch = getc(fp)) == EOF) | |
1134 | break; | |
1135 | if (ch != 0x0a) | |
1136 | ungetc(ch, fp); | |
e8fda7b9 | 1137 | } |
2b85e375 | 1138 | |
1139 | *lineptr++ = '\n'; | |
1140 | ||
1141 | if (!endquote) /* Continue for multi-line text */ | |
1142 | break; | |
1143 | } | |
1144 | else | |
1145 | { | |
1146 | /* | |
1147 | * Any other character... | |
1148 | */ | |
1149 | ||
1150 | *lineptr++ = ch; | |
1151 | ||
1152 | if (ch == '\"') | |
1153 | endquote = !endquote; | |
e8fda7b9 | 1154 | } |
1155 | } | |
2b85e375 | 1156 | |
1157 | if (lineptr > line && lineptr[-1] == '\n') | |
1158 | lineptr --; | |
1159 | ||
1160 | *lineptr = '\0'; | |
1161 | ||
1162 | if (ch == EOF && lineptr == line) | |
1163 | return (0); | |
1164 | ||
1165 | /* | |
1166 | * Now parse it... | |
1167 | */ | |
1168 | ||
1169 | mask = 0; | |
1170 | lineptr = line + 1; | |
1171 | ||
1172 | keyword[0] = '\0'; | |
1173 | option[0] = '\0'; | |
1174 | text[0] = '\0'; | |
1175 | *string = NULL; | |
1176 | ||
1177 | if (line[0] != '*') /* All lines start with an asterisk */ | |
1178 | continue; | |
1179 | ||
8c1333e2 | 1180 | if (strncmp((char *)line, "*%", 2) == 0 || /* Comment line */ |
1181 | strncmp((char *)line, "*?", 2) == 0 || /* Query line */ | |
1182 | strcmp((char *)line, "*End") == 0) /* End of multi-line string */ | |
2b85e375 | 1183 | continue; |
1184 | ||
1185 | /* | |
1186 | * Get a keyword... | |
1187 | */ | |
1188 | ||
1189 | keyptr = keyword; | |
1190 | ||
1191 | while (*lineptr != '\0' && *lineptr != ':' && !isspace(*lineptr) && | |
1192 | (keyptr - keyword) < 40) | |
1193 | *keyptr++ = *lineptr++; | |
1194 | ||
1195 | *keyptr = '\0'; | |
1196 | mask |= PPD_KEYWORD; | |
1197 | ||
1198 | if (*lineptr == ' ' || *lineptr == '\t') | |
1199 | { | |
1200 | /* | |
1201 | * Get an option name... | |
1202 | */ | |
1203 | ||
1204 | while (*lineptr == ' ' || *lineptr == '\t') | |
1205 | lineptr ++; | |
1206 | ||
1207 | optptr = option; | |
1208 | ||
1209 | while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':' && | |
1210 | *lineptr != '/' && (optptr - option) < 40) | |
1211 | *optptr++ = *lineptr++; | |
1212 | ||
1213 | *optptr = '\0'; | |
1214 | mask |= PPD_OPTION; | |
1215 | ||
1216 | if (*lineptr == '/') | |
1217 | { | |
1218 | /* | |
1219 | * Get human-readable text... | |
1220 | */ | |
1221 | ||
1222 | lineptr ++; | |
1223 | ||
1224 | textptr = text; | |
1225 | ||
1226 | while (*lineptr != '\0' && *lineptr != '\n' && *lineptr != ':' && | |
1227 | (textptr - text) < 80) | |
1228 | *textptr++ = *lineptr++; | |
1229 | ||
1230 | *textptr = '\0'; | |
1231 | ppd_decode(text); | |
1232 | ||
1233 | mask |= PPD_TEXT; | |
e8fda7b9 | 1234 | } |
1235 | } | |
2b85e375 | 1236 | |
1237 | if (*lineptr == ':') | |
1238 | { | |
1239 | /* | |
1240 | * Get string... | |
1241 | */ | |
1242 | ||
8c1333e2 | 1243 | *string = malloc(strlen((char *)lineptr)); |
2b85e375 | 1244 | |
1245 | while (*lineptr == ':' || isspace(*lineptr)) | |
1246 | lineptr ++; | |
1247 | ||
1248 | strptr = *string; | |
1249 | ||
1250 | while (*lineptr != '\0') | |
1251 | { | |
1252 | if (*lineptr != '\"') | |
1253 | *strptr++ = *lineptr++; | |
1254 | else | |
1255 | lineptr ++; | |
e8fda7b9 | 1256 | } |
2b85e375 | 1257 | |
1258 | *strptr = '\0'; | |
1259 | mask |= PPD_STRING; | |
e8fda7b9 | 1260 | } |
2b85e375 | 1261 | } |
1262 | while (mask == 0); | |
1263 | ||
1264 | return (mask); | |
1265 | } | |
1266 | ||
1267 | ||
1268 | /* | |
1269 | * 'ppd_decode()' - Decode a string value... | |
1270 | */ | |
1271 | ||
1272 | static void | |
1273 | ppd_decode(unsigned char *string) /* I - String to decode */ | |
1274 | { | |
1275 | unsigned char *inptr, /* Input pointer */ | |
1276 | *outptr; /* Output pointer */ | |
1277 | ||
1278 | ||
1279 | inptr = string; | |
1280 | outptr = string; | |
1281 | ||
1282 | while (*inptr != '\0') | |
1283 | if (*inptr == '<' && isxdigit(inptr[1])) | |
1284 | { | |
1285 | /* | |
1286 | * Convert hex to 8-bit values... | |
1287 | */ | |
1288 | ||
1289 | inptr ++; | |
1290 | while (isxdigit(*inptr)) | |
1291 | { | |
1292 | if (isalpha(*inptr)) | |
1293 | *outptr = (tolower(*inptr) - 'a' + 10) << 16; | |
1294 | else | |
1295 | *outptr = (*inptr - '0') << 16; | |
1296 | ||
1297 | inptr ++; | |
1298 | ||
1299 | if (isalpha(*inptr)) | |
1300 | *outptr |= tolower(*inptr) - 'a' + 10; | |
1301 | else | |
1302 | *outptr |= *inptr - '0'; | |
1303 | ||
1304 | inptr ++; | |
1305 | outptr ++; | |
e8fda7b9 | 1306 | } |
2b85e375 | 1307 | |
1308 | while (*inptr != '>' && *inptr != '\0') | |
1309 | inptr ++; | |
1310 | while (*inptr == '>') | |
1311 | inptr ++; | |
1312 | } | |
1313 | else | |
1314 | *outptr++ = *inptr++; | |
1315 | ||
1316 | *outptr = '\0'; | |
1317 | } | |
1318 | ||
1319 | ||
90a24de4 | 1320 | |
1321 | ||
1322 | /* | |
e8fda7b9 | 1323 | * End of "$Id: ppd.c,v 1.7 1999/03/01 20:51:53 mike Exp $". |
90a24de4 | 1324 | */ |