3
* Copyright (C) 2008 Till Kamppeter <till.kamppeter@gmail.com>
4
* Copyright (C) 2008 Lars Uebernickel <larsuebernickel@gmx.de>
6
* This file is part of foomatic-rip.
8
* Foomatic-rip is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* Foomatic-rip is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU Lesser General Public
19
* License along with this library; if not, write to the
20
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
* Boston, MA 02111-1307, USA.
24
#include "foomaticrip.h"
35
void get_renderer_handle(const dstr_t *prepend, FILE **fd, pid_t *pid);
36
int close_renderer_handle(FILE *rendererhandle, pid_t rendererpid);
38
#define LT_BEGIN_FEATURE 1
39
#define LT_FOOMATIC_RIP_OPTION_SETTING 2
40
int line_type(const char *line)
43
if (startswith(line, "%%BeginFeature:"))
44
return LT_BEGIN_FEATURE;
46
while (*p && isspace(*p)) p++;
47
if (!startswith(p, "%%"))
50
while (*p && isspace(*p)) p++;
51
if (startswith(p, "FoomaticRIPOptionSetting:"))
52
return LT_FOOMATIC_RIP_OPTION_SETTING;
57
/* Next, examine the PostScript job for traces of command-line and
58
JCL options. PPD-aware applications and spoolers stuff option
59
settings directly into the file, they do not necessarily send
60
PPD options by the command line. Also stuff in PostScript code
61
to apply option settings given by the command line and to set
62
the defaults given in the PPD file.
64
Examination strategy: read lines from STDIN until the first
65
%%Page: comment appears and save them as @psheader. This is the
66
page-independent header part of the PostScript file. The
67
PostScript interpreter (renderer) must execute this part once
68
before rendering any assortment of pages. Then pages can be
69
printed in any arbitrary selection or order. All option
70
settings we find here will be collected in the default option
71
set for the RIP command line.
73
Now the pages will be read and sent to the renderer, one after
74
the other. Every page is read into memory until the
75
%%EndPageSetup comment appears (or a certain amount of lines was
76
read). So we can get option settings only valid for this
77
page. If we have such settings we set them in the modified
78
command set for this page.
80
If the renderer is not running yet (first page) we start it with
81
the command line built from the current modified command set and
82
send the first page to it, in the end we leave the renderer
83
running and keep input and output pipes open, so that it can
84
accept further pages. If the renderer is still running from
85
the previous page and the current modified command set is the
86
same as the one for the previous page, we send the page. If
87
the command set is different, we close the renderer, re-start
88
it with the command line built from the new modified command
89
set, send the header again, and then the page.
91
After the last page the trailer (%%Trailer) is sent.
93
The output pipe of this program stays open all the time so that
94
the spooler does not assume that the job has finished when the
95
renderer is re-started.
97
Non DSC-conforming documents will be read until a certain line
98
number is reached. Command line or JCL options inserted later
101
If options are implemented by PostScript code supposed to be
102
stuffed into the job's PostScript data we stuff the code for all
103
these options into our job data, So all default settings made in
104
the PPD file (the user can have edited the PPD file to change
105
them) are taken care of and command line options get also
106
applied. To give priority to settings made by applications we
107
insert the options's code in the beginnings of their respective
108
sections, so that sommething, which is already inserted, gets
109
executed after our code. Missing sections are automatically
110
created. In non-DSC-conforming files we insert the option code
111
in the beginning of the file. This is the same policy as used by
112
the "pstops" filter of CUPS.
114
If CUPS is the spooler, the option settings were already
115
inserted by the "pstops" filter, so we don't insert them
116
again. The only thing we do is correcting settings of numerical
117
options when they were set to a value not available as choice in
118
the PPD file, As "pstops" does not support "real" numerical
119
options, it sees these settings as an invalid choice and stays
120
with the default setting. In this case we correct the setting in
121
the first occurence of the option's code, as this one is the one
122
added by CUPS, later occurences come from applications and
123
should not be touched.
125
If the input is not PostScript (if there is no "%!" after
126
$maxlinestopsstart lines) we will abort the document with an error.
129
/* PostScript sections */
130
#define PS_SECTION_JCLSETUP 1
131
#define PS_SECTION_PROLOG 2
132
#define PS_SECTION_SETUP 3
133
#define PS_SECTION_PAGESETUP 4
135
#define MAX_NON_DSC_LINES_IN_HEADER 1000
136
#define MAX_LINES_FOR_PAGE_OPTIONS 200
142
const char *alreadyread;
146
void _print_ps(stream_t *stream);
148
int stream_next_line(dstr_t *line, stream_t *s)
154
while (s->pos < s->len) {
155
c = s->alreadyread[s->pos++];
162
while ((c = fgetc(s->file)) != EOF) {
171
int print_ps(FILE *file, const char *alreadyread, size_t len, const char *filename)
175
if (file != stdin && (dup2(fileno(file), fileno(stdin)) < 0)) {
176
_log("Could not dup %s to stdin.\n", filename);
182
stream.alreadyread = alreadyread;
188
void _print_ps(stream_t *stream)
192
int maxlines = 1000; /* Maximum number of lines to be read when the
193
documenent is not DSC-conforming.
194
"$maxlines = 0" means that all will be read and
195
examined. If it is discovered that the input
196
file is DSC-conforming, this will be set to 0. */
198
int maxlinestopsstart = 200; /* That many lines are allowed until the
199
"%!" indicating PS comes. These
200
additional lines in the
201
beginning are usually JCL
202
commands. The lines will be
203
ignored by our parsing but
206
int printprevpage = 0; /* We set this when encountering "%%Page:" and the
207
previous page is not printed yet. Then it will
208
be printed and the new page will be prepared in
209
the next run of the loop (we don't read a new
210
line and don't increase the $linect then). */
212
int linect = 0; /* how many lines have we examined */
213
int nonpslines = 0; /* lines before "%!" found yet. */
214
int more_stuff = 1; /* there is more stuff in stdin */
215
int saved = 0; /* DSC line not precessed yet */
216
int isdscjob = 0; /* is the job dsc conforming */
217
int inheader = 1; /* Are we still in the header, before first
218
"%%Page:" comment= */
220
int optionsalsointoheader = 0; /* 1: We are in a "%%BeginSetup...
221
%%EndSetup" section after the first
222
"%%Page:..." line (OpenOffice.org
223
does this and intends the options here
224
apply to the whole document and not
225
only to the current page). We have to
226
add all lines also to the end of the
227
@psheader now and we have to set
228
non-PostScript options also in the
229
"header" optionset. 0: otherwise. */
231
int insertoptions = 1; /* If we find out that a file with a DSC magic
232
string ("%!PS-Adobe-") is not really DSC-
233
conforming, we insert the options directly
234
after the line with the magic string. We use
235
this variable to store the number of the line
236
with the magic string */
238
int prologfound = 0; /* Did we find the
239
"%%BeginProlog...%%EndProlog" section? */
240
int setupfound = 0; /* Did we find the
241
%%BeginSetup...%%EndSetup" section? */
242
int pagesetupfound = 0; /* special page setup handling needed */
244
int inprolog = 0; /* We are between "%%BeginProlog" and "%%EndProlog" */
245
int insetup = 0; /* We are between "%%BeginSetup" and "%%EndSetup" */
246
int infeature = 0; /* We are between "%%BeginFeature" and "%%EndFeature" */
248
int optionreplaced = 0; /* Will be set to 1 when we are in an
249
option ("%%BeginFeature...
250
%%EndFeature") which we have replaced. */
252
int postscriptsection = PS_SECTION_JCLSETUP; /* In which section of the PostScript file
253
are we currently ? */
255
int nondsclines = 0; /* Number of subsequent lines found which are at a
256
non-DSC-conforming place, between the sections
259
int nestinglevel = 0; /* Are we in the main document (0) or in an
260
embedded document bracketed by "%%BeginDocument"
261
and "%%EndDocument" (>0) We do not parse the
262
PostScript in an embedded document. */
264
int inpageheader = 0; /* Are we in the header of a page,
265
between "%%BeginPageSetup" and
266
"%%EndPageSetup" (1) or not (0). */
268
int passthru = 0; /* 0: write data into psfifo,
269
1: pass data directly to the renderer */
271
int lastpassthru = 0; /* State of 'passthru' in previous line
272
(to allow debug output when $passthru
275
int ignorepageheader = 0; /* Will be set to 1 as soon as active
276
code (not between "%%BeginPageSetup"
277
and "%%EndPageSetup") appears after a
278
"%%Page:" comment. In this case
279
"%%BeginPageSetup" and
280
"%%EndPageSetup" is not allowed any
281
more on this page and will be ignored.
282
Will be set to 0 when a new "%%Page:"
285
int optset = optionset("header"); /* Where do the option settings which
289
dstr_t *line = create_dstr();
291
dstr_t *onelinebefore = create_dstr();
292
dstr_t *twolinesbefore = create_dstr();
294
/* The header of the PostScript file, to be send after each start of the renderer */
295
dstr_t *psheader = create_dstr();
297
/* The input FIFO, data which we have pulled from stdin for examination,
298
but not send to the renderer yet */
299
dstr_t *psfifo = create_dstr();
303
int ooo110 = 0; /* Flag to work around an application bug */
305
int currentpage = 0; /* The page which we are currently printing */
312
dstr_t *linesafterlastbeginfeature = create_dstr(); /* All codelines after the last "%%BeginFeature" */
314
char optionname [128];
316
int fromcomposite = 0;
320
double width, height;
322
pid_t rendererpid = 0;
323
FILE *rendererhandle = NULL;
327
dstr_t *tmp = create_dstr();
330
/* We do not parse the PostScript to find Foomatic options, we check
331
only whether we have PostScript. */
335
_log("Reading PostScript input ...\n");
340
if (printprevpage || saved || stream_next_line(line, stream)) {
342
if (linect == nonpslines) {
343
/* In the beginning should be the postscript leader,
344
sometimes after some JCL commands */
345
if ( !(line->data[0] == '%' && line->data[1] == '!') &&
346
!(line->data[1] == '%' && line->data[2] == '!')) /* There can be a Windows control character before "%!" */
349
if (maxlines == nonpslines)
353
if (nonpslines > maxlinestopsstart) {
354
/* This is not a PostScript job, abort it */
355
_log("Job does not start with \"%%!\", is it Postscript?\n");
356
rip_die(EXIT_JOBERR, "Unknown data format.\n");
360
/* Do we have a DSC-conforming document? */
361
if ((line->data[0] == '%' && startswith(line->data, "%!PS-Adobe-")) ||
362
(line->data[1] == '%' && startswith(line->data, "%!PS-Adobe-")))
364
/* Do not stop parsing the document */
368
insertoptions = linect + 1;
369
/* We have written into psfifo before, now we continue in
370
psheader and move over the data which is already in psfifo */
371
dstrcat(psheader, psfifo->data);
374
_log("--> This document is DSC-conforming!\n");
377
/* Job is not DSC-conforming, stick in all PostScript
378
option settings in the beginning */
379
append_prolog_section(line, optset, 1);
380
append_setup_section(line, optset, 1);
381
append_page_setup_section(line, optset, 1);
389
if (startswith(line->data, "%")) {
390
if (startswith(line->data, "%%BeginDocument")) {
391
/* Beginning of an embedded document
392
Note that Adobe Acrobat has a bug and so uses
393
"%%BeginDocument " instead of "%%BeginDocument:" */
395
_log("Embedded document, nesting level now: %d\n", nestinglevel);
397
else if (nestinglevel > 0 && startswith(line->data, "%%EndDocument")) {
398
/* End of an embedded document */
400
_log("End of embedded document, nesting level now: %d\n", nestinglevel);
402
else if (nestinglevel == 0 && startswith(line->data, "%%Creator")) {
403
/* Here we set flags to treat particular bugs of the
404
PostScript produced by certain applications */
405
p = strstr(line->data, "%%Creator") + 9;
406
while (*p && (isspace(*p) || *p == ':')) p++;
407
if (!strcmp(p, "OpenOffice.org")) {
409
while (*p && isspace(*p)) p++;
410
if (sscanf(p, "1.1.%d", &ooo110) == 1) {
411
_log("Document created with OpenOffice.org 1.1.x\n");
414
} else if (!strcmp(p, "StarOffice 8")) {
416
_log("Document created with StarOffice 8\n");
420
else if (nestinglevel == 0 && startswith(line->data, "%%BeginProlog")) {
421
/* Note: Below is another place where a "Prolog" section
422
start will be considered. There we assume start of the
423
"Prolog" if the job is DSC-Conformimg, but an arbitrary
424
comment starting with "%%Begin", but not a comment
425
explicitly treated here, is found. This is done because
426
many "dvips" (TeX/LaTeX) files miss the "%%BeginProlog"
428
Beginning of Prolog */
429
_log("\n-----------\nFound: %%%%BeginProlog\n");
432
postscriptsection = PS_SECTION_PROLOG;
434
/* Insert options for "Prolog" */
436
append_prolog_section(line, optset, 0);
440
else if (nestinglevel == 0 && startswith(line->data, "%%EndProlog")) {
442
_log("Found: %%%%EndProlog\n");
444
insertoptions = linect +1;
446
else if (nestinglevel == 0 && startswith(line->data, "%%BeginSetup")) {
447
/* Beginning of Setup */
448
_log("\n-----------\nFound: %%%%BeginSetup\n");
451
/* We need to distinguish with the $inheader variable
452
here whether we are in the header or on a page, as
453
OpenOffice.org inserts a "%%BeginSetup...%%EndSetup"
454
section after the first "%%Page:..." line and assumes
455
this section to be valid for all pages. */
457
postscriptsection = PS_SECTION_SETUP;
458
/* If there was no "Prolog" but there are
459
options for the "Prolog", push a "Prolog"
460
with these options onto the psfifo here */
463
append_prolog_section(tmp, optset, 1);
464
dstrprepend(line, tmp->data);
467
/* Insert options for "DocumentSetup" or "AnySetup" */
468
if (spooler != SPOOLER_CUPS && !setupfound) {
469
/* For non-CUPS spoolers or no spooler at all,
470
we leave everythnig as it is */
471
append_setup_section(line, optset, 0);
476
/* Found option settings must be stuffed into both
477
the header and the currrent page now. They will
478
be written into both the "header" and the
479
"currentpage" optionsets and the PostScript code
480
lines of this section will not only go into the
481
output stream, but also added to the end of the
482
@psheader, so that they get repeated (to preserve
483
the embedded PostScript option settings) on a
484
restart of the renderer due to command line
486
optionsalsointoheader = 1;
487
_log("\"%%%%BeginSetup\" in page header\n");
490
else if (nestinglevel == 0 && startswith(line->data, "%%EndSetup")) {
492
_log("Found: %%%%EndSetup\n");
495
if (spooler == SPOOLER_CUPS) {
496
/* In case of CUPS, we must insert the
497
accounting stuff just before the
498
%%EndSetup comment in order to leave any
499
EndPage procedures that have been
500
defined by either the pstops filter or
501
the PostScript job itself fully
505
append_setup_section(tmp, optset, 0);
506
dstrprepend(line, tmp->data);
510
insertoptions = linect +1;
513
/* The "%%BeginSetup...%%EndSetup" which
514
OpenOffice.org has inserted after the first
515
"%%Page:..." line ends here, so the following
516
options go only onto the current page again */
517
optionsalsointoheader = 0;
520
else if (nestinglevel == 0 && startswith(line->data, "%%Page:")) {
521
if (!lastpassthru && !inheader) {
522
/* In the last line we were not in passthru mode,
523
so the last page is not printed. Prepare to do
527
_log("New page found but previous not printed, print it now.\n");
530
/* the previous page is printed, so we can prepare
532
_log("\n-----------\nNew page: %s", line->data);
535
/* We consider the beginning of the page already as
536
page setup section, as some apps do not use
537
"%%PageSetup" tags. */
538
postscriptsection = PS_SECTION_PAGESETUP;
540
/* TODO can this be removed?
541
Save PostScript state before beginning the page
542
$line .= "/foomatic-saved-state save def\n"; */
544
/* Here begins a new page */
546
build_commandline(optset, NULL, 0);
547
/* Here we add some stuff which still
548
belongs into the header */
551
/* If there was no "Setup" but there are
552
options for the "Setup", push a "Setup"
553
with these options onto the @psfifo here */
555
append_setup_section(tmp, optset, 1);
558
/* If there was no "Prolog" but there are
559
options for the "Prolog", push a "Prolog"
560
with these options onto the @psfifo here */
562
append_prolog_section(tmp, optset, 1);
565
/* Now we push this into the header */
566
dstrcat(psheader, tmp->data);
568
/* The first page starts, so header ends */
571
/* Option setting should go into the page
572
specific option set now */
573
optset = optionset("currentpage");
576
/* Restore PostScript state after completing the
579
foomatic-saved-state restore
581
/foomatic-saved-state save def
583
Print this directly, so that if we need to
584
restart the renderer for this page due to
585
a command line change this is done under the
586
old instance of the renderer
588
"foomatic-saved-state restore\n"; */
590
/* Save the option settings of the previous page */
591
optionset_copy_values(optionset("currentpage"), optionset("previouspage"));
592
optionset_delete_values(optionset("currentpage"));
594
/* Initialize the option set */
595
optionset_copy_values(optionset("header"), optionset("currentpage"));
597
/* Set the command line options which apply only
599
set_options_for_page(optionset("currentpage"), currentpage);
601
if (spooler == SPOOLER_CUPS) {
602
/* Remove the "notfirst" flag from all options
603
forseen for the "PageSetup" section, because
604
when these are numerical options for CUPS.
605
they have to be set to the correct value
607
for (o = optionlist; o; o = o->next) {
608
if (option_get_section(o ) == SECTION_PAGESETUP)
612
/* Now the page header comes, so buffer the data,
613
because we must perhaps shut down and restart
616
ignorepageheader = 0;
617
optionsalsointoheader = 0;
620
else if (nestinglevel == 0 && !ignorepageheader &&
621
startswith(line->data, "%%BeginPageSetup")) {
622
/* Start of the page header, up to %%EndPageSetup
623
nothing of the page will be drawn, page-specific
624
option settngs (as letter-head paper for page 1)
626
_log("\nFound: %%%%BeginPageSetup\n");
629
postscriptsection = PS_SECTION_PAGESETUP;
630
optionsalsointoheader = (ooo110 && currentpage == 1) ? 1 : 0;
631
/* Insert PostScript option settings
632
(options for section "PageSetup") */
634
append_page_setup_section(line, optset, 0);
638
else if (nestinglevel == 0 && !ignorepageheader &&
639
startswith(line->data, "%%BeginPageSetup")) {
640
/* End of the page header, the page is ready to be printed */
641
_log("Found: %%%%EndPageSetup\n");
642
_log("End of page header\n");
643
/* We cannot for sure say that the page header ends here
644
OpenOffice.org puts (due to a bug) a "%%BeginSetup...
645
%%EndSetup" section after the first "%%Page:...". It
646
is possible that CUPS inserts a "%%BeginPageSetup...
647
%%EndPageSetup" before this section, which means that
648
the options in the "%%BeginSetup...%%EndSetup"
649
section are after the "%%EndPageSetup", so we
650
continue for searching options up to the buffer size
651
limit $maxlinesforpageoptions. */
654
optionsalsointoheader = 0;
656
else if (nestinglevel == 0 && !optionreplaced && (!passthru || !isdscjob) &&
657
((linetype = line_type(line->data)) &&
658
(linetype == LT_BEGIN_FEATURE || linetype == LT_FOOMATIC_RIP_OPTION_SETTING))) {
661
if (linetype == LT_BEGIN_FEATURE) {
662
dstrcpy(tmp, line->data);
663
p = strtok(tmp->data, " \t"); /* %%BeginFeature: */
664
p = strtok(NULL, " \t="); /* Option */
666
strlcpy(optionname, p, 128);
667
p = strtok(NULL, " \t\r\n"); /* value */
669
strlcpy(value, p, 128);
671
else { /* LT_FOOMATIC_RIP_OPTION_SETTING */
672
dstrcpy(tmp, line->data);
673
p = strstr(tmp->data, "FoomaticRIPOptionSetting:");
674
p = strtok(p, " \t"); /* FoomaticRIPOptionSetting */
675
p = strtok(NULL, " \t="); /* Option */
676
strlcpy(optionname, p, 128);
677
p = strtok(NULL, " \t\r\n"); /* value */
678
if (*p == '@') { /* fromcomposite */
684
strlcpy(value, p, 128);
687
/* Mark that we are in a "Feature" section */
688
if (linetype == LT_BEGIN_FEATURE) {
690
dstrclear(linesafterlastbeginfeature);
693
/* OK, we have an option. If it's not a
694
Postscript-style option (ie, it's command-line or
695
JCL) then we should note that fact, since the
696
attribute-to-filter option passing in CUPS is kind of
697
funky, especially wrt boolean options. */
698
_log("Found: %s", line->data);
699
if ((o = find_option(optionname)) &&
700
(o->type != TYPE_NONE)) {
701
_log(" Option: %s=%s%s\n", optionname, fromcomposite ? "From" : "", value);
702
if (spooler == SPOOLER_CUPS &&
703
linetype == LT_BEGIN_FEATURE &&
704
!option_get_value(o, optionset("notfirst")) &&
705
strcmp(option_get_value(o, optset) ?: "", value) != 0 &&
706
(inheader || option_get_section(o) == SECTION_PAGESETUP)) {
708
/* We have the first occurence of an option
709
setting and the spooler is CUPS, so this
710
setting is inserted by "pstops" or
711
"imagetops". The value from the command
712
line was not inserted by "pstops" or
713
"imagetops" so it seems to be not under
714
the choices in the PPD. Possible
717
- "pstops" and "imagetops" ignore settings
718
of numerical or string options which are
719
not one of the choices in the PPD file,
720
and inserts the default value instead.
722
- On the command line an option was applied
723
only to selected pages:
724
"-o <page ranges>:<option>=<values>
725
This is not supported by CUPS, so not
726
taken care of by "pstops".
728
We must fix this here by replacing the
729
setting inserted by "pstops" or "imagetops"
730
with the exact setting given on the command
733
/* $arg->{$optionset} is already
734
range-checked, so do not check again here
735
Insert DSC comment */
736
pdest = (inheader && isdscjob) ? psheader : psfifo;
737
if (option_is_ps_command(o)) {
738
/* PostScript option, insert the code */
740
option_get_command(tmp, o, optset, -1);
741
if (!(val = option_get_value(o, optset)))
744
/* Boolean and enumerated choice options can only be set in the
745
* PageSetup section */
746
if ((inheader && option_is_custom_value(o, val)) || !inheader)
748
if (o->type == TYPE_BOOL)
749
dstrcatf(pdest, "%%%%BeginFeature: *%s %s\n", o->name,
750
val && !strcmp(val, "1") ? "True" : "False");
752
dstrcatf(pdest, "%%%%BeginFeature: *%s %s\n", o->name, val);
754
dstrcatf(pdest, "%s\n", tmp->data);
756
/* We have replaced this option on the FIFO */
760
else { /* Command line or JCL option */
761
val = option_get_value(o, optset);
763
if (!inheader || option_is_custom_value(o, val)) {
764
dstrcatf(pdest, "%%%% FoomaticRIPOptionSetting: %s=%s\n",
765
o->name, val ? val : "");
770
if (optionreplaced) {
771
val = option_get_value(o, optset);
772
_log(" --> Correcting numerical/string option to %s=%s (Command line argument)\n",
773
o->name, val ? val : "");
777
/* Mark that we have already found this option */
779
if (!optionreplaced) {
780
if (o->style != 'G') {
781
/* Controlled by '<Composite>' setting of
782
a member option of a composite option */
784
dstrcpyf(tmp, "From%s", value);
785
strlcpy(value, tmp->data, 128);
788
/* Non PostScript option
789
Check whether it is valid */
790
if (option_set_value(o, optset, value)) {
791
_log("Setting option\n");
792
strlcpy(value, option_get_value(o, optset), 128);
793
if (optionsalsointoheader)
794
option_set_value(o, optionset("header"), value);
795
if (o->type == TYPE_ENUM &&
796
(!strcmp(o->name, "PageSize") || !strcmp(o->name, "PageRegion")) &&
797
startswith(value, "Custom") &&
798
linetype == LT_FOOMATIC_RIP_OPTION_SETTING) {
799
/* Custom Page size */
800
width = height = 0.0;
801
p = linesafterlastbeginfeature->data;
802
while (*p && isspace(*p)) p++;
803
width = strtod(p, &p);
804
while (*p && isspace(*p)) p++;
805
height = strtod(p, &p);
806
if (width && height) {
807
dstrcpyf(tmp, "%s.%fx%f", value, width, height);
808
strlcpy(value, tmp->data, 128);
809
option_set_value(o, optset, value);
810
if (optionsalsointoheader)
811
option_set_value(o, optionset("header"), value);
814
/* For a composite option insert the
815
code from the member options with
816
current setting "From<composite>"
817
The code from the member options
818
is chosen according to the setting
819
of the composite option. */
820
if (option_is_composite(o) && linetype == LT_FOOMATIC_RIP_OPTION_SETTING) {
821
build_commandline(optset, NULL, 0); /* TODO can this be removed? */
823
/* TODO merge section and ps_section */
824
if (postscriptsection == PS_SECTION_JCLSETUP)
825
option_get_command(tmp, o, optset, SECTION_JCLSETUP);
826
else if (postscriptsection == PS_SECTION_PROLOG)
827
option_get_command(tmp, o, optset, SECTION_PROLOG);
828
else if (postscriptsection == PS_SECTION_SETUP)
829
option_get_command(tmp, o, optset, SECTION_DOCUMENTSETUP);
830
else if (postscriptsection == PS_SECTION_PAGESETUP)
831
option_get_command(tmp, o, optset, SECTION_PAGESETUP);
832
dstrcat(line, tmp->data);
836
_log(" --> Invalid option setting found in job\n");
838
else if (fromcomposite) {
839
/* PostScript option, but we have to look up
840
the PostScript code to be inserted from
841
the setting of a composite option, as
842
this option is set to "Controlled by
845
dstrcpyf(tmp, "From%s", value);
846
strlcpy(value, tmp->data, 128);
847
if (option_set_value(o, optset, value)) {
848
_log(" --> Looking up setting in composite option %s\n", value);
849
if (optionsalsointoheader)
850
option_set_value(o, optionset("header"), value);
851
/* update composite options */
852
build_commandline(optset, NULL, 0);
853
/* Substitute PostScript comment by the real code */
854
/* TODO what exactly is the next line doing? */
855
/* dstrcpy(line, o->compositesubst->data); */
858
_log(" --> Invalid option setting found in job\n");
861
/* it is a PostScript style option with
862
the code readily inserted, no option
863
for the renderer command line/JCL to set,
864
no lookup of a composite option needed,
865
so nothing to do here... */
866
_log(" --> Option will be set by PostScript interpreter\n");
870
/* This option is unknown to us, WTF? */
871
_log("Unknown option %s=%s found in the job\n", optionname, value);
873
else if (nestinglevel == 0 && startswith(line->data, "%%EndFeature")) {
876
/* If the option setting was replaced, it ends here,
877
too, and the next option is not necessarily also replaced */
879
dstrclear(linesafterlastbeginfeature);
881
else if (nestinglevel == 0 && isdscjob && !prologfound &&
882
startswith(line->data, "%%Begin")) {
883
/* In some PostScript files (especially when generated
884
by "dvips" of TeX/LaTeX) the "%%BeginProlog" is
885
missing, so assume that it was before the current
886
line (the first line starting with "%%Begin". */
887
_log("Job claims to be DSC-conforming, but \"%%%%BeginProlog\" "
888
"was missing before first line with another"
889
"\"%%%%BeginProlog\" comment (is this a TeX/LaTeX/dvips-generated"
890
" PostScript file?). Assuming start of \"Prolog\" here.\n");
891
/* Beginning of Prolog */
894
/* Insert options for "Prolog" before the current line */
895
dstrcpyf(tmp, "%%%%BeginProlog\n");
896
append_prolog_section(tmp, optset, 0);
897
dstrprepend(line, tmp->data);
900
else if (nestinglevel == 0 && (
901
startswith(line->data, "%RBINumCopies:") ||
902
startswith(line->data, "%%RBINumCopies:"))) {
903
p = strchr(line->data, ':') +1;
904
get_current_job()->rbinumcopies = atoi(p);
905
_log("Found %RBINumCopies: %d\n", get_current_job()->rbinumcopies);
907
else if (startswith(skip_whitespace(line->data), "%") ||
908
startswith(skip_whitespace(line->data), "$"))
909
/* This is an unknown PostScript comment or a blank
910
line, no active code */
914
/* This line is active PostScript code */
916
/* Collect coe in a "%%BeginFeature: ... %%EndFeature"
917
section, to get the values for a custom option
919
dstrcat(linesafterlastbeginfeature, line->data);
922
if (!inprolog && !insetup) {
923
/* Outside the "Prolog" and "Setup" section
924
a correct DSC-conforming document has no
925
active PostScript code, so consider the
926
file as non-DSC-conforming when there are
927
too many of such lines. */
929
if (nondsclines > MAX_NON_DSC_LINES_IN_HEADER) {
930
/* Consider document as not DSC-conforming */
931
_log("This job seems not to be DSC-conforming, "
932
"DSC-comment for next section not found, "
933
"stopping to parse the rest, passing it "
934
"directly to the renderer.\n");
935
/* Stop scanning for further option settings */
938
/* Insert defaults and command line settings in
939
the beginning of the job or after the last valid
943
append_prolog_section(tmp, optset, 1);
945
append_setup_section(tmp, optset, 1);
947
append_page_setup_section(tmp, optset, 1);
948
dstrinsert(psheader, line_start(psheader->data, insertoptions), tmp->data);
956
else if (!inpageheader) {
957
/* PostScript code inside a page, but not between
958
"%%BeginPageSetup" and "%%EndPageSetup", so
959
we are perhaps already drawing onto a page now */
960
if (startswith(onelinebefore->data, "%%Page"))
961
_log("No page header or page header not DSC-conforming\n");
962
/* Stop buffering lines to search for options
963
placed not DSC-conforming */
964
if (line_count(psfifo->data) >= MAX_LINES_FOR_PAGE_OPTIONS) {
965
_log("Stopping search for page header options\n");
967
/* If there comes a page header now, ignore it */
968
ignorepageheader = 1;
969
optionsalsointoheader = 0;
971
/* Insert PostScript option settings (options for the
972
* section "PageSetup" */
973
if (isdscjob && !pagesetupfound) {
974
append_page_setup_section(psfifo, optset, 1);
982
if (lastpassthru != passthru) {
984
_log("Found: %s --> Output goes directly to the renderer now.\n\n", line->data);
986
_log("Found: %s --> Output goes to the FIFO buffer now.\n\n", line->data);
989
/* We are in an option which was replaced, do not output the current line */
993
/* If we are in a "%%BeginSetup...%%EndSetup" section after
994
the first "%%Page:..." and the current line belongs to
995
an option setting, we have to copy the line also to the
997
if (optionsalsointoheader && (infeature || startswith(line->data, "%%EndFeature")))
998
dstrcat(psheader, line->data);
1000
/* Store or send the current line */
1001
if (inheader && isdscjob) {
1002
/* We are still in the PostScript header, collect all lines
1004
dstrcat(psheader, line->data);
1007
if (passthru && isdscjob) {
1008
if (!lastpassthru) {
1010
* We enter passthru mode with this line, so the
1011
* command line can have changed, check it and close
1012
* the renderer if needed
1014
if (rendererpid && !optionset_equal(optionset("currentpage"), optionset("previouspage"), 0)) {
1015
_log("Command line/JCL options changed, restarting renderer\n");
1016
retval = close_renderer_handle(rendererhandle, rendererpid);
1017
if (retval != EXIT_PRINTED)
1018
rip_die(retval, "Error closing renderer\n");
1023
/* Flush psfifo and send line directly to the renderer */
1025
/* No renderer running, start it */
1026
dstrcpy(tmp, psheader->data);
1027
dstrcat(tmp, psfifo->data);
1028
get_renderer_handle(tmp, &rendererhandle, &rendererpid);
1029
/* psfifo is sent out, flush it */
1033
if (!isempty(psfifo->data)) {
1034
/* Send psfifo to renderer */
1035
fwrite(psfifo->data, psfifo->len, 1, rendererhandle);
1040
/* Send line to renderer */
1041
if (!printprevpage) {
1042
fwrite(line->data, line->len, 1, rendererhandle);
1044
while (stream_next_line(line, stream) > 0) {
1045
if (startswith(line->data, "%%")) {
1046
_log("Found: %s", line->data);
1047
_log(" --> Continue DSC parsing now.\n\n");
1052
fwrite(line->data, line->len, 1, rendererhandle);
1059
/* Push the line onto the stack to split up later */
1060
dstrcat(psfifo, line->data);
1071
/* No PostScript header in the whole file? Then it's not
1072
PostScript, convert it.
1073
We open the file converter here when the file has less
1074
lines than the amount which we search for the PostScript
1075
header ($maxlinestopsstart). */
1076
if (linect <= nonpslines) {
1077
/* This is not a PostScript job, abort it */
1078
_log("Job does not start with \"%%!\", is it Postscript?\n");
1079
rip_die(EXIT_JOBERR, "Unknown data format.\n");
1083
lastpassthru = passthru;
1085
if (!ignoreline && !printprevpage) {
1086
dstrcpy(twolinesbefore, onelinebefore->data);
1087
dstrcpy(onelinebefore, line->data);
1090
} while ((maxlines == 0 || linect < maxlines) && more_stuff != 0);
1092
/* Some buffer still containing data? Send it out to the renderer */
1093
if (more_stuff || inheader || !isempty(psfifo->data)) {
1094
/* Flush psfifo and send the remaining data to the renderer, this
1095
only happens with non-DSC-conforming jobs or non-Foomatic PPDs */
1097
_log("Stopped parsing the PostScript data, "
1098
"sending rest directly to the renderer.\n");
1100
_log("Flushing FIFO.\n");
1103
build_commandline(optset, NULL, 0);
1104
/* No page initialized yet? Copy the "header" option set into the
1105
"currentpage" option set, so that the renderer will find the
1106
options settings. */
1107
optionset_copy_values(optionset("header"), optionset("currentpage"));
1108
optset = optionset("currentpage");
1110
/* If not done yet, insert defaults and command line settings
1111
in the beginning of the job or after the last valid section */
1114
append_prolog_section(tmp, optset, 1);
1116
append_setup_section(tmp, optset, 1);
1118
append_page_setup_section(tmp, optset, 1);
1119
dstrinsert(psheader, line_start(psheader->data, insertoptions), tmp->data);
1126
if (rendererpid > 0 && !optionset_equal(optionset("currentpage"), optionset("previouspage"), 0)) {
1127
_log("Command line/JCL options changed, restarting renderer\n");
1128
retval = close_renderer_handle(rendererhandle, rendererpid);
1129
if (retval != EXIT_PRINTED)
1130
rip_die(retval, "Error closing renderer\n");
1135
dstrcpy(tmp, psheader->data);
1136
dstrcat(tmp, psfifo->data);
1137
get_renderer_handle(tmp, &rendererhandle, &rendererpid);
1138
/* We have sent psfifo now */
1143
/* Send psfifo to the renderer */
1144
fwrite(psfifo->data, psfifo->len, 1, rendererhandle);
1148
/* Print the rest of the input data */
1150
while (stream_next_line(tmp, stream))
1151
fwrite(tmp->data, tmp->len, 1, rendererhandle);
1155
/* At every "%%Page:..." comment we have saved the PostScript state
1156
and we have increased the page number. So if the page number is
1157
non-zero we had at least one "%%Page:..." comment and so we have
1158
to give a restore the PostScript state.
1159
if ($currentpage > 0) {
1160
print $rendererhandle "foomatic-saved-state restore\n";
1163
/* Close the renderer */
1165
retval = close_renderer_handle(rendererhandle, rendererpid);
1166
if (retval != EXIT_PRINTED)
1167
rip_die(retval, "Error closing renderer\n");
1172
free_dstr(onelinebefore);
1173
free_dstr(twolinesbefore);
1174
free_dstr(psheader);
1180
* Run the renderer command line (and if defined also the postpipe) and returns
1181
* a file handle for stuffing in the PostScript data.
1183
void get_renderer_handle(const dstr_t *prepend, FILE **fd, pid_t *pid)
1187
dstr_t *cmdline = create_dstr();
1189
/* Build the command line and get the JCL commands */
1190
build_commandline(optionset("currentpage"), cmdline, 0);
1191
massage_gs_commandline(cmdline);
1193
_log("\nStarting renderer with command: \"%s\"\n", cmdline->data);
1194
kid3 = start_process("kid3", exec_kid3, (void *)cmdline->data, &kid3in, NULL);
1196
rip_die(EXIT_PRNERR_NORETRY_BAD_SETTINGS, "Cannot fork for kid3\n");
1198
/* Feed the PostScript header and the FIFO contents */
1200
fwrite(prepend->data, prepend->len, 1, kid3in);
1202
/* We are the parent, return glob to the file handle */
1209
/* Close the renderer process and wait until all kid processes finish */
1210
int close_renderer_handle(FILE *rendererhandle, pid_t rendererpid)
1214
_log("\nClosing renderer\n");
1215
fclose(rendererhandle);
1217
status = wait_for_process(rendererpid);
1218
if (WIFEXITED(status))
1219
return WEXITSTATUS(status);
1221
return EXIT_PRNERR_NORETRY_BAD_SETTINGS;