]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/ppd.c
Implemented language specific stuff.
[thirdparty/cups.git] / cups / ppd.c
CommitLineData
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
70static int ppd_read(FILE *fp, char *keyword, char *option,
71 unsigned char *text, unsigned char **string);
72static void ppd_decode(unsigned char *string);
73static void ppd_free_group(ppd_group_t *group);
74static void ppd_free_option(ppd_option_t *option);
75
76
77/*
78 * 'ppdClose()' - Free all memory used by the PPD file.
79 */
80
81void
82ppdClose(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
200static void
201ppd_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
234static void
235ppd_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
257ppd_file_t * /* O - PPD file record */
258ppdOpen(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
1003ppd_file_t * /* O - PPD file record */
1004ppdOpenFd(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
1040ppd_file_t * /* O - PPD file record */
1041ppdOpenFile(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
1076static int /* O - Bitmask of fields read */
1077ppd_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
1272static void
1273ppd_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 */