1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate *
4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate * with the License.
8*7c478bd9Sstevel@tonic-gate *
9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate *
14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */
24*7c478bd9Sstevel@tonic-gate
25*7c478bd9Sstevel@tonic-gate
26*7c478bd9Sstevel@tonic-gate /*
27*7c478bd9Sstevel@tonic-gate * Copyright (c) 1998-1999 by Sun Microsystems, Inc.
28*7c478bd9Sstevel@tonic-gate * All rights reserved.
29*7c478bd9Sstevel@tonic-gate */
30*7c478bd9Sstevel@tonic-gate
31*7c478bd9Sstevel@tonic-gate /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
32*7c478bd9Sstevel@tonic-gate
33*7c478bd9Sstevel@tonic-gate #include "assert.h"
34*7c478bd9Sstevel@tonic-gate #include "string.h"
35*7c478bd9Sstevel@tonic-gate #include "errno.h"
36*7c478bd9Sstevel@tonic-gate #include "stdlib.h"
37*7c478bd9Sstevel@tonic-gate
38*7c478bd9Sstevel@tonic-gate #include "lp.h"
39*7c478bd9Sstevel@tonic-gate #include "filters.h"
40*7c478bd9Sstevel@tonic-gate
41*7c478bd9Sstevel@tonic-gate #include "regex.h"
42*7c478bd9Sstevel@tonic-gate
43*7c478bd9Sstevel@tonic-gate
44*7c478bd9Sstevel@tonic-gate #define MATCH(PT, PM) (STREQU((PT)->pattern, PATT_STAR) || \
45*7c478bd9Sstevel@tonic-gate match((PT)->re, *((PM)->pvalue)))
46*7c478bd9Sstevel@tonic-gate
47*7c478bd9Sstevel@tonic-gate
48*7c478bd9Sstevel@tonic-gate typedef struct PARM {
49*7c478bd9Sstevel@tonic-gate char *keyword;
50*7c478bd9Sstevel@tonic-gate unsigned short flags;
51*7c478bd9Sstevel@tonic-gate char **pvalue;
52*7c478bd9Sstevel@tonic-gate } PARM;
53*7c478bd9Sstevel@tonic-gate
54*7c478bd9Sstevel@tonic-gate #define X_MUST 0x0800 /* Pipeline MUST use this parm */
55*7c478bd9Sstevel@tonic-gate #define X_FIRST 0x1000 /* Use parm only in 1st cmd of pipeline */
56*7c478bd9Sstevel@tonic-gate #define X_FIXED 0x2000 /* Get value from elsewhere, not parms */
57*7c478bd9Sstevel@tonic-gate #define X_MANY 0x4000 /* Several values allowed for parm */
58*7c478bd9Sstevel@tonic-gate #define X_USED 0x8000 /* Used already, don't use again */
59*7c478bd9Sstevel@tonic-gate
60*7c478bd9Sstevel@tonic-gate static struct S {
61*7c478bd9Sstevel@tonic-gate TYPE input_type;
62*7c478bd9Sstevel@tonic-gate TYPE output_type;
63*7c478bd9Sstevel@tonic-gate TYPE printer_type;
64*7c478bd9Sstevel@tonic-gate char *printer;
65*7c478bd9Sstevel@tonic-gate PARM *parms;
66*7c478bd9Sstevel@tonic-gate } S;
67*7c478bd9Sstevel@tonic-gate
68*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
69*7c478bd9Sstevel@tonic-gate
70*7c478bd9Sstevel@tonic-gate static int searchlist_t(TYPE *, TYPE *);
71*7c478bd9Sstevel@tonic-gate static int instantiate(_FILTER **, TYPE *, TYPE *,
72*7c478bd9Sstevel@tonic-gate int (*)(), void *);
73*7c478bd9Sstevel@tonic-gate static int check_pipeline(_FILTER *, PARM *);
74*7c478bd9Sstevel@tonic-gate static char *build_pipe(_FILTER *, PARM *, unsigned short *);
75*7c478bd9Sstevel@tonic-gate #else
76*7c478bd9Sstevel@tonic-gate
77*7c478bd9Sstevel@tonic-gate static int searchlist_t();
78*7c478bd9Sstevel@tonic-gate static int instantiate();
79*7c478bd9Sstevel@tonic-gate static int check_pipeline();
80*7c478bd9Sstevel@tonic-gate static char *build_pipe();
81*7c478bd9Sstevel@tonic-gate
82*7c478bd9Sstevel@tonic-gate #endif
83*7c478bd9Sstevel@tonic-gate
84*7c478bd9Sstevel@tonic-gate /*
85*7c478bd9Sstevel@tonic-gate * Table of recognized keywords, with info. about them.
86*7c478bd9Sstevel@tonic-gate */
87*7c478bd9Sstevel@tonic-gate
88*7c478bd9Sstevel@tonic-gate #define NFIXED 4
89*7c478bd9Sstevel@tonic-gate
90*7c478bd9Sstevel@tonic-gate static PARM parmtable[] = {
91*7c478bd9Sstevel@tonic-gate
92*7c478bd9Sstevel@tonic-gate /* These must be the first NFIXED, and in this order */
93*7c478bd9Sstevel@tonic-gate PARM_INPUT, X_FIXED, &S.input_type.name,
94*7c478bd9Sstevel@tonic-gate PARM_OUTPUT, X_FIXED, &S.output_type.name,
95*7c478bd9Sstevel@tonic-gate PARM_TERM, X_FIXED, &S.printer_type.name,
96*7c478bd9Sstevel@tonic-gate PARM_PRINTER, X_FIXED, &S.printer,
97*7c478bd9Sstevel@tonic-gate
98*7c478bd9Sstevel@tonic-gate PARM_CPI, FPARM_CPI, 0,
99*7c478bd9Sstevel@tonic-gate PARM_LPI, FPARM_LPI, 0,
100*7c478bd9Sstevel@tonic-gate PARM_LENGTH, FPARM_LENGTH, 0,
101*7c478bd9Sstevel@tonic-gate PARM_WIDTH, FPARM_WIDTH, 0,
102*7c478bd9Sstevel@tonic-gate PARM_PAGES, FPARM_PAGES | X_FIRST | X_MUST, 0,
103*7c478bd9Sstevel@tonic-gate PARM_CHARSET, FPARM_CHARSET, 0,
104*7c478bd9Sstevel@tonic-gate PARM_FORM, FPARM_FORM, 0,
105*7c478bd9Sstevel@tonic-gate PARM_COPIES, FPARM_COPIES | X_FIRST, 0,
106*7c478bd9Sstevel@tonic-gate PARM_MODES, FPARM_MODES | X_MANY | X_MUST, 0,
107*7c478bd9Sstevel@tonic-gate 0, 0, 0,
108*7c478bd9Sstevel@tonic-gate };
109*7c478bd9Sstevel@tonic-gate
110*7c478bd9Sstevel@tonic-gate /*
111*7c478bd9Sstevel@tonic-gate * insfilter()
112*7c478bd9Sstevel@tonic-gate */
113*7c478bd9Sstevel@tonic-gate
114*7c478bd9Sstevel@tonic-gate FILTERTYPE
115*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
insfilter(char ** pipes,char * input_type,char * output_type,char * printer_type,char * printer,char ** parms,unsigned short * flagsp)116*7c478bd9Sstevel@tonic-gate insfilter(
117*7c478bd9Sstevel@tonic-gate char **pipes,
118*7c478bd9Sstevel@tonic-gate char *input_type,
119*7c478bd9Sstevel@tonic-gate char *output_type,
120*7c478bd9Sstevel@tonic-gate char *printer_type,
121*7c478bd9Sstevel@tonic-gate char *printer,
122*7c478bd9Sstevel@tonic-gate char **parms,
123*7c478bd9Sstevel@tonic-gate unsigned short *flagsp
124*7c478bd9Sstevel@tonic-gate )
125*7c478bd9Sstevel@tonic-gate #else
126*7c478bd9Sstevel@tonic-gate insfilter(pipes, input_type, output_type, printer_type, printer, parms, flagsp)
127*7c478bd9Sstevel@tonic-gate char **pipes,
128*7c478bd9Sstevel@tonic-gate *input_type,
129*7c478bd9Sstevel@tonic-gate *output_type,
130*7c478bd9Sstevel@tonic-gate *printer_type,
131*7c478bd9Sstevel@tonic-gate *printer,
132*7c478bd9Sstevel@tonic-gate **parms;
133*7c478bd9Sstevel@tonic-gate unsigned short *flagsp;
134*7c478bd9Sstevel@tonic-gate #endif
135*7c478bd9Sstevel@tonic-gate {
136*7c478bd9Sstevel@tonic-gate _FILTER *pipeline;
137*7c478bd9Sstevel@tonic-gate
138*7c478bd9Sstevel@tonic-gate FILTERTYPE ret;
139*7c478bd9Sstevel@tonic-gate
140*7c478bd9Sstevel@tonic-gate
141*7c478bd9Sstevel@tonic-gate S.input_type.name = input_type;
142*7c478bd9Sstevel@tonic-gate S.input_type.info = isterminfo(input_type);
143*7c478bd9Sstevel@tonic-gate S.output_type.name = output_type;
144*7c478bd9Sstevel@tonic-gate S.output_type.info = isterminfo(output_type);
145*7c478bd9Sstevel@tonic-gate S.printer_type.name = printer_type;
146*7c478bd9Sstevel@tonic-gate S.printer_type.info = isterminfo(printer_type);
147*7c478bd9Sstevel@tonic-gate S.printer = printer;
148*7c478bd9Sstevel@tonic-gate
149*7c478bd9Sstevel@tonic-gate /*
150*7c478bd9Sstevel@tonic-gate * If the filters have't been loaded yet, do so now.
151*7c478bd9Sstevel@tonic-gate * We'll load the standard table, but the caller can override
152*7c478bd9Sstevel@tonic-gate * this by first calling "loadfilters()" with the appropriate
153*7c478bd9Sstevel@tonic-gate * filter table name.
154*7c478bd9Sstevel@tonic-gate */
155*7c478bd9Sstevel@tonic-gate if (!filters && loadfilters((char *)0) == -1)
156*7c478bd9Sstevel@tonic-gate return (fl_none);
157*7c478bd9Sstevel@tonic-gate
158*7c478bd9Sstevel@tonic-gate /*
159*7c478bd9Sstevel@tonic-gate * Allocate and initialize space to hold additional
160*7c478bd9Sstevel@tonic-gate * information about each item in "parms".
161*7c478bd9Sstevel@tonic-gate * THIS SPACE MUST BE FREED BEFORE EXITING THIS ROUTINE!
162*7c478bd9Sstevel@tonic-gate */
163*7c478bd9Sstevel@tonic-gate {
164*7c478bd9Sstevel@tonic-gate register int n;
165*7c478bd9Sstevel@tonic-gate
166*7c478bd9Sstevel@tonic-gate register PARM * pp;
167*7c478bd9Sstevel@tonic-gate register PARM * ppt;
168*7c478bd9Sstevel@tonic-gate
169*7c478bd9Sstevel@tonic-gate register char ** p;
170*7c478bd9Sstevel@tonic-gate
171*7c478bd9Sstevel@tonic-gate
172*7c478bd9Sstevel@tonic-gate
173*7c478bd9Sstevel@tonic-gate for (n = 0, p = parms; *p; n++, p++)
174*7c478bd9Sstevel@tonic-gate ;
175*7c478bd9Sstevel@tonic-gate n /= 2;
176*7c478bd9Sstevel@tonic-gate n += NFIXED; /* for fixed parms (in/out/printer types) */
177*7c478bd9Sstevel@tonic-gate
178*7c478bd9Sstevel@tonic-gate if (!(S.parms = (PARM *)Malloc((n + 1) * sizeof (PARM)))) {
179*7c478bd9Sstevel@tonic-gate errno = ENOMEM;
180*7c478bd9Sstevel@tonic-gate return (fl_none);
181*7c478bd9Sstevel@tonic-gate }
182*7c478bd9Sstevel@tonic-gate
183*7c478bd9Sstevel@tonic-gate for (ppt = parmtable; ppt->keyword; ppt++)
184*7c478bd9Sstevel@tonic-gate ppt->flags &= ~X_USED;
185*7c478bd9Sstevel@tonic-gate
186*7c478bd9Sstevel@tonic-gate /*
187*7c478bd9Sstevel@tonic-gate * Load the parameter list with the fixed ``type''
188*7c478bd9Sstevel@tonic-gate * parameters. Mark them as used (if appropriate)
189*7c478bd9Sstevel@tonic-gate * so we don't pick them up from the callers list.
190*7c478bd9Sstevel@tonic-gate */
191*7c478bd9Sstevel@tonic-gate pp = S.parms;
192*7c478bd9Sstevel@tonic-gate for (ppt = parmtable; ppt < parmtable + NFIXED; ppt++) {
193*7c478bd9Sstevel@tonic-gate pp->keyword = ppt->keyword;
194*7c478bd9Sstevel@tonic-gate pp->flags = ppt->flags;
195*7c478bd9Sstevel@tonic-gate if (ppt->flags & X_FIXED)
196*7c478bd9Sstevel@tonic-gate pp->pvalue = ppt->pvalue;
197*7c478bd9Sstevel@tonic-gate else
198*7c478bd9Sstevel@tonic-gate pp->pvalue = parms + 1;
199*7c478bd9Sstevel@tonic-gate if (!(ppt->flags & X_MANY))
200*7c478bd9Sstevel@tonic-gate ppt->flags |= X_USED;
201*7c478bd9Sstevel@tonic-gate pp++;
202*7c478bd9Sstevel@tonic-gate }
203*7c478bd9Sstevel@tonic-gate
204*7c478bd9Sstevel@tonic-gate /*
205*7c478bd9Sstevel@tonic-gate * Copy each parameter from the caller supplied list
206*7c478bd9Sstevel@tonic-gate * to another list, adding information gathered from
207*7c478bd9Sstevel@tonic-gate * the keyword table. Note that some keywords should
208*7c478bd9Sstevel@tonic-gate * be given only once; additional occurrances in the
209*7c478bd9Sstevel@tonic-gate * caller's list will be ignored.
210*7c478bd9Sstevel@tonic-gate */
211*7c478bd9Sstevel@tonic-gate for (p = parms; *p; p += 2)
212*7c478bd9Sstevel@tonic-gate for (ppt = parmtable; ppt->keyword; ppt++)
213*7c478bd9Sstevel@tonic-gate if (STREQU(*p, ppt->keyword) &&
214*7c478bd9Sstevel@tonic-gate !(ppt->flags & X_USED)) {
215*7c478bd9Sstevel@tonic-gate
216*7c478bd9Sstevel@tonic-gate pp->keyword = ppt->keyword;
217*7c478bd9Sstevel@tonic-gate pp->flags = ppt->flags;
218*7c478bd9Sstevel@tonic-gate if (ppt->flags & X_FIXED)
219*7c478bd9Sstevel@tonic-gate pp->pvalue = ppt->pvalue;
220*7c478bd9Sstevel@tonic-gate else
221*7c478bd9Sstevel@tonic-gate pp->pvalue = p + 1;
222*7c478bd9Sstevel@tonic-gate
223*7c478bd9Sstevel@tonic-gate if (!(ppt->flags & X_MANY))
224*7c478bd9Sstevel@tonic-gate ppt->flags |= X_USED;
225*7c478bd9Sstevel@tonic-gate
226*7c478bd9Sstevel@tonic-gate pp++;
227*7c478bd9Sstevel@tonic-gate break;
228*7c478bd9Sstevel@tonic-gate
229*7c478bd9Sstevel@tonic-gate }
230*7c478bd9Sstevel@tonic-gate
231*7c478bd9Sstevel@tonic-gate pp->keyword = 0;
232*7c478bd9Sstevel@tonic-gate
233*7c478bd9Sstevel@tonic-gate }
234*7c478bd9Sstevel@tonic-gate
235*7c478bd9Sstevel@tonic-gate /*
236*7c478bd9Sstevel@tonic-gate * Preview the list of filters, to rule out those that
237*7c478bd9Sstevel@tonic-gate * can't possibly work.
238*7c478bd9Sstevel@tonic-gate */
239*7c478bd9Sstevel@tonic-gate {
240*7c478bd9Sstevel@tonic-gate register _FILTER * pf;
241*7c478bd9Sstevel@tonic-gate
242*7c478bd9Sstevel@tonic-gate for (pf = filters; pf->name; pf++) {
243*7c478bd9Sstevel@tonic-gate
244*7c478bd9Sstevel@tonic-gate pf->mark = FL_CLEAR;
245*7c478bd9Sstevel@tonic-gate
246*7c478bd9Sstevel@tonic-gate if (printer && !searchlist(printer, pf->printers))
247*7c478bd9Sstevel@tonic-gate pf->mark = FL_SKIP;
248*7c478bd9Sstevel@tonic-gate
249*7c478bd9Sstevel@tonic-gate else if (printer_type &&
250*7c478bd9Sstevel@tonic-gate !searchlist_t(&(S.printer_type),
251*7c478bd9Sstevel@tonic-gate pf->printer_types))
252*7c478bd9Sstevel@tonic-gate pf->mark = FL_SKIP;
253*7c478bd9Sstevel@tonic-gate
254*7c478bd9Sstevel@tonic-gate }
255*7c478bd9Sstevel@tonic-gate }
256*7c478bd9Sstevel@tonic-gate
257*7c478bd9Sstevel@tonic-gate /*
258*7c478bd9Sstevel@tonic-gate * Find a pipeline that will convert the input-type to the
259*7c478bd9Sstevel@tonic-gate * output-type and map the parameters as well.
260*7c478bd9Sstevel@tonic-gate */
261*7c478bd9Sstevel@tonic-gate if (!instantiate(&pipeline, &S.input_type, &S.output_type,
262*7c478bd9Sstevel@tonic-gate check_pipeline, S.parms)) {
263*7c478bd9Sstevel@tonic-gate ret = fl_none;
264*7c478bd9Sstevel@tonic-gate goto Return;
265*7c478bd9Sstevel@tonic-gate }
266*7c478bd9Sstevel@tonic-gate
267*7c478bd9Sstevel@tonic-gate if (!pipes) {
268*7c478bd9Sstevel@tonic-gate ret = fl_both;
269*7c478bd9Sstevel@tonic-gate goto Return;
270*7c478bd9Sstevel@tonic-gate
271*7c478bd9Sstevel@tonic-gate } else {
272*7c478bd9Sstevel@tonic-gate register _FILTER * pf;
273*7c478bd9Sstevel@tonic-gate register _FILTER * pfastf; /* first in fast pipe */
274*7c478bd9Sstevel@tonic-gate register _FILTER * pslowf; /* last in slow pipe */
275*7c478bd9Sstevel@tonic-gate
276*7c478bd9Sstevel@tonic-gate /*
277*7c478bd9Sstevel@tonic-gate * Found a pipeline, so now build it.
278*7c478bd9Sstevel@tonic-gate */
279*7c478bd9Sstevel@tonic-gate
280*7c478bd9Sstevel@tonic-gate /*
281*7c478bd9Sstevel@tonic-gate * Split pipeline after last slow filter.
282*7c478bd9Sstevel@tonic-gate * "pipeline" will point to first filter in slow
283*7c478bd9Sstevel@tonic-gate * pipe, "pfastf" will point to first filter in
284*7c478bd9Sstevel@tonic-gate * fast pipe.
285*7c478bd9Sstevel@tonic-gate */
286*7c478bd9Sstevel@tonic-gate for (pf = pfastf = pipeline, pslowf = 0; pf; pf = pf->next)
287*7c478bd9Sstevel@tonic-gate if (pf->type == fl_slow) {
288*7c478bd9Sstevel@tonic-gate pslowf = pf;
289*7c478bd9Sstevel@tonic-gate pfastf = pf->next;
290*7c478bd9Sstevel@tonic-gate }
291*7c478bd9Sstevel@tonic-gate
292*7c478bd9Sstevel@tonic-gate if (pslowf) {
293*7c478bd9Sstevel@tonic-gate assert(pslowf != pfastf);
294*7c478bd9Sstevel@tonic-gate pslowf->next = 0;
295*7c478bd9Sstevel@tonic-gate pipes[0] = build_pipe(pipeline, S.parms, flagsp);
296*7c478bd9Sstevel@tonic-gate ret = fl_slow;
297*7c478bd9Sstevel@tonic-gate } else
298*7c478bd9Sstevel@tonic-gate pipes[0] = 0;
299*7c478bd9Sstevel@tonic-gate
300*7c478bd9Sstevel@tonic-gate if (pfastf) {
301*7c478bd9Sstevel@tonic-gate pipes[1] = build_pipe(pfastf, S.parms, flagsp);
302*7c478bd9Sstevel@tonic-gate ret = fl_fast;
303*7c478bd9Sstevel@tonic-gate } else
304*7c478bd9Sstevel@tonic-gate pipes[1] = 0;
305*7c478bd9Sstevel@tonic-gate
306*7c478bd9Sstevel@tonic-gate if (pslowf && pfastf)
307*7c478bd9Sstevel@tonic-gate ret = fl_both;
308*7c478bd9Sstevel@tonic-gate
309*7c478bd9Sstevel@tonic-gate /*
310*7c478bd9Sstevel@tonic-gate * Check for the oops case.
311*7c478bd9Sstevel@tonic-gate */
312*7c478bd9Sstevel@tonic-gate if (pslowf && !pipes[0] || pfastf && !pipes[1])
313*7c478bd9Sstevel@tonic-gate ret = fl_none;
314*7c478bd9Sstevel@tonic-gate
315*7c478bd9Sstevel@tonic-gate }
316*7c478bd9Sstevel@tonic-gate
317*7c478bd9Sstevel@tonic-gate Return: Free((char *)S.parms);
318*7c478bd9Sstevel@tonic-gate
319*7c478bd9Sstevel@tonic-gate return (ret);
320*7c478bd9Sstevel@tonic-gate }
321*7c478bd9Sstevel@tonic-gate
322*7c478bd9Sstevel@tonic-gate /*
323*7c478bd9Sstevel@tonic-gate * searchlist_t() - SEARCH (TYPE *) LIST FOR ITEM
324*7c478bd9Sstevel@tonic-gate */
325*7c478bd9Sstevel@tonic-gate
326*7c478bd9Sstevel@tonic-gate static int
327*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
typematch(TYPE * type1,TYPE * type2)328*7c478bd9Sstevel@tonic-gate typematch(
329*7c478bd9Sstevel@tonic-gate TYPE *type1,
330*7c478bd9Sstevel@tonic-gate TYPE *type2
331*7c478bd9Sstevel@tonic-gate )
332*7c478bd9Sstevel@tonic-gate #else
333*7c478bd9Sstevel@tonic-gate typematch(type1, type2)
334*7c478bd9Sstevel@tonic-gate TYPE *type1, *type2;
335*7c478bd9Sstevel@tonic-gate #endif
336*7c478bd9Sstevel@tonic-gate {
337*7c478bd9Sstevel@tonic-gate if (STREQU(type1->name, NAME_ANY) || STREQU(type2->name, NAME_ANY) ||
338*7c478bd9Sstevel@tonic-gate STREQU(type1->name, type2->name) ||
339*7c478bd9Sstevel@tonic-gate (STREQU(type1->name, NAME_TERMINFO) && type2->info) ||
340*7c478bd9Sstevel@tonic-gate (STREQU(type2->name, NAME_TERMINFO) && type1->info))
341*7c478bd9Sstevel@tonic-gate return (1);
342*7c478bd9Sstevel@tonic-gate else
343*7c478bd9Sstevel@tonic-gate return (0);
344*7c478bd9Sstevel@tonic-gate }
345*7c478bd9Sstevel@tonic-gate
346*7c478bd9Sstevel@tonic-gate static int
347*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
searchlist_t(TYPE * itemp,TYPE * list)348*7c478bd9Sstevel@tonic-gate searchlist_t(
349*7c478bd9Sstevel@tonic-gate TYPE *itemp,
350*7c478bd9Sstevel@tonic-gate TYPE *list
351*7c478bd9Sstevel@tonic-gate )
352*7c478bd9Sstevel@tonic-gate #else
353*7c478bd9Sstevel@tonic-gate searchlist_t(itemp, list)
354*7c478bd9Sstevel@tonic-gate TYPE *itemp;
355*7c478bd9Sstevel@tonic-gate register TYPE *list;
356*7c478bd9Sstevel@tonic-gate #endif
357*7c478bd9Sstevel@tonic-gate {
358*7c478bd9Sstevel@tonic-gate if (!list || !list->name)
359*7c478bd9Sstevel@tonic-gate return (0);
360*7c478bd9Sstevel@tonic-gate
361*7c478bd9Sstevel@tonic-gate /*
362*7c478bd9Sstevel@tonic-gate * This is a linear search--we believe that the lists
363*7c478bd9Sstevel@tonic-gate * will be short.
364*7c478bd9Sstevel@tonic-gate */
365*7c478bd9Sstevel@tonic-gate while (list->name) {
366*7c478bd9Sstevel@tonic-gate if (typematch(itemp, list))
367*7c478bd9Sstevel@tonic-gate return (1);
368*7c478bd9Sstevel@tonic-gate list++;
369*7c478bd9Sstevel@tonic-gate }
370*7c478bd9Sstevel@tonic-gate return (0);
371*7c478bd9Sstevel@tonic-gate }
372*7c478bd9Sstevel@tonic-gate
373*7c478bd9Sstevel@tonic-gate /*
374*7c478bd9Sstevel@tonic-gate * instantiate() - CREATE FILTER-PIPELINE KNOWING INPUT/OUTPUT TYPES
375*7c478bd9Sstevel@tonic-gate */
376*7c478bd9Sstevel@tonic-gate
377*7c478bd9Sstevel@tonic-gate /*
378*7c478bd9Sstevel@tonic-gate * The "instantiate()" routine is the meat of the "insfilter()"
379*7c478bd9Sstevel@tonic-gate * algorithm. It is given an input-type and output-type and finds a
380*7c478bd9Sstevel@tonic-gate * filter-pipline that will convert the input-type into the
381*7c478bd9Sstevel@tonic-gate * output-type. Since the filter-pipeline must meet other criteria,
382*7c478bd9Sstevel@tonic-gate * a function "verify" is also given, along with the set of criteria;
383*7c478bd9Sstevel@tonic-gate * these are used by "instantiate()" to verify a filter-pipeline.
384*7c478bd9Sstevel@tonic-gate *
385*7c478bd9Sstevel@tonic-gate * The filter-pipeline is built up and returned in "pipeline".
386*7c478bd9Sstevel@tonic-gate * Conceptually this is just a list of filters, with the pipeline to
387*7c478bd9Sstevel@tonic-gate * be constructed by simply concatenating the filter simple-commmands
388*7c478bd9Sstevel@tonic-gate * (after filling in option templates) in the order found in the
389*7c478bd9Sstevel@tonic-gate * list. What is used in the routine, though, is a pair of linked
390*7c478bd9Sstevel@tonic-gate * lists, one list forming the ``right-half'' of the pipeline, the
391*7c478bd9Sstevel@tonic-gate * other forming the ``left-half''. The pipeline is then the two
392*7c478bd9Sstevel@tonic-gate * lists taken together.
393*7c478bd9Sstevel@tonic-gate *
394*7c478bd9Sstevel@tonic-gate * The "instantiate()" routine looks for a single filter that matches
395*7c478bd9Sstevel@tonic-gate * the input-type and output-type and satisfies the criteria. If one
396*7c478bd9Sstevel@tonic-gate * is found, it is added to the end of the ``left-half'' list (it
397*7c478bd9Sstevel@tonic-gate * could be added to the beginning of the ``right-half'' list with no
398*7c478bd9Sstevel@tonic-gate * problem). The two lists are linked together to form one linked
399*7c478bd9Sstevel@tonic-gate * list, which is passed, along with the set of criteria, to the
400*7c478bd9Sstevel@tonic-gate * "verify" routine to check the filter-pipeline. If it passes the
401*7c478bd9Sstevel@tonic-gate * check, the work is done.
402*7c478bd9Sstevel@tonic-gate *
403*7c478bd9Sstevel@tonic-gate * If a single filter is not found, "instantiate()" examines all
404*7c478bd9Sstevel@tonic-gate * pairs of filters where one in the pair can accept the input-type
405*7c478bd9Sstevel@tonic-gate * and the other can produce the output-type. For each of these, it
406*7c478bd9Sstevel@tonic-gate * calls itself again to find a filter that can join the pair
407*7c478bd9Sstevel@tonic-gate * together--one that accepts as input the output-type of the first
408*7c478bd9Sstevel@tonic-gate * in the pair, and produces as output the input-type of the second
409*7c478bd9Sstevel@tonic-gate * in the pair. This joining filter may be a single filter or may
410*7c478bd9Sstevel@tonic-gate * be a filter-pipeline. "instantiate()" checks for the trivial case
411*7c478bd9Sstevel@tonic-gate * where the input-type is the output-type; with trivial cases it
412*7c478bd9Sstevel@tonic-gate * links the two lists without adding a filter and checks it with
413*7c478bd9Sstevel@tonic-gate * "verify".
414*7c478bd9Sstevel@tonic-gate */
415*7c478bd9Sstevel@tonic-gate
416*7c478bd9Sstevel@tonic-gate /*
417*7c478bd9Sstevel@tonic-gate * instantiate()
418*7c478bd9Sstevel@tonic-gate */
419*7c478bd9Sstevel@tonic-gate
420*7c478bd9Sstevel@tonic-gate /*
421*7c478bd9Sstevel@tonic-gate * A PIPELIST is what is passed to each recursive call to "instantiate()".
422*7c478bd9Sstevel@tonic-gate * It contains a pointer to the end of the ``left-list'', a pointer to the
423*7c478bd9Sstevel@tonic-gate * head of the ``right-list'', and a pointer to the head of the left-list.
424*7c478bd9Sstevel@tonic-gate * The latter is passed to "verify". The end of the right-list (and thus
425*7c478bd9Sstevel@tonic-gate * the end of the entire list when left and right are joined) is the
426*7c478bd9Sstevel@tonic-gate * filter with a null ``next'' pointer.
427*7c478bd9Sstevel@tonic-gate */
428*7c478bd9Sstevel@tonic-gate typedef struct PIPELIST {
429*7c478bd9Sstevel@tonic-gate _FILTER * lhead;
430*7c478bd9Sstevel@tonic-gate _FILTER * ltail;
431*7c478bd9Sstevel@tonic-gate _FILTER * rhead;
432*7c478bd9Sstevel@tonic-gate } PIPELIST;
433*7c478bd9Sstevel@tonic-gate
434*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
435*7c478bd9Sstevel@tonic-gate static int _instantiate(PIPELIST *, TYPE *, TYPE *,
436*7c478bd9Sstevel@tonic-gate int (*)(_FILTER *, void *), void *);
437*7c478bd9Sstevel@tonic-gate #else
438*7c478bd9Sstevel@tonic-gate static int _instantiate();
439*7c478bd9Sstevel@tonic-gate #endif
440*7c478bd9Sstevel@tonic-gate
441*7c478bd9Sstevel@tonic-gate static int peg;
442*7c478bd9Sstevel@tonic-gate
443*7c478bd9Sstevel@tonic-gate static int
444*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
instantiate(_FILTER ** pline,TYPE * input,TYPE * output,int (* verify)(_FILTER *,void *),void * criteria)445*7c478bd9Sstevel@tonic-gate instantiate(
446*7c478bd9Sstevel@tonic-gate _FILTER **pline,
447*7c478bd9Sstevel@tonic-gate TYPE *input,
448*7c478bd9Sstevel@tonic-gate TYPE *output,
449*7c478bd9Sstevel@tonic-gate int (*verify)(_FILTER *, void *),
450*7c478bd9Sstevel@tonic-gate void *criteria
451*7c478bd9Sstevel@tonic-gate )
452*7c478bd9Sstevel@tonic-gate #else
453*7c478bd9Sstevel@tonic-gate instantiate(pline, input, output, verify, criteria)
454*7c478bd9Sstevel@tonic-gate _FILTER **pline;
455*7c478bd9Sstevel@tonic-gate TYPE *input,
456*7c478bd9Sstevel@tonic-gate *output;
457*7c478bd9Sstevel@tonic-gate int (*verify)();
458*7c478bd9Sstevel@tonic-gate char *criteria;
459*7c478bd9Sstevel@tonic-gate #endif
460*7c478bd9Sstevel@tonic-gate {
461*7c478bd9Sstevel@tonic-gate PIPELIST p;
462*7c478bd9Sstevel@tonic-gate int ret;
463*7c478bd9Sstevel@tonic-gate
464*7c478bd9Sstevel@tonic-gate peg = 0;
465*7c478bd9Sstevel@tonic-gate p.lhead = p.ltail = p.rhead = 0;
466*7c478bd9Sstevel@tonic-gate ret = _instantiate(&p, input, output, verify, criteria);
467*7c478bd9Sstevel@tonic-gate *pline = p.lhead;
468*7c478bd9Sstevel@tonic-gate return (ret);
469*7c478bd9Sstevel@tonic-gate }
470*7c478bd9Sstevel@tonic-gate
471*7c478bd9Sstevel@tonic-gate #define ENTER() int our_tag; our_tag = ++peg;
472*7c478bd9Sstevel@tonic-gate
473*7c478bd9Sstevel@tonic-gate #define LEAVE(Y) if (!Y) { \
474*7c478bd9Sstevel@tonic-gate register _FILTER *f; \
475*7c478bd9Sstevel@tonic-gate for (f = filters; f->name; f++) \
476*7c478bd9Sstevel@tonic-gate CLEAR(f); \
477*7c478bd9Sstevel@tonic-gate return (0); \
478*7c478bd9Sstevel@tonic-gate } else \
479*7c478bd9Sstevel@tonic-gate return (1)
480*7c478bd9Sstevel@tonic-gate
481*7c478bd9Sstevel@tonic-gate #define MARK(F, M) (((F)->mark |= M), (F)->level = our_tag)
482*7c478bd9Sstevel@tonic-gate
483*7c478bd9Sstevel@tonic-gate #define CLEAR(F) if ((F)->level == our_tag) \
484*7c478bd9Sstevel@tonic-gate (F)->level = 0, (F)->mark = FL_CLEAR
485*7c478bd9Sstevel@tonic-gate
486*7c478bd9Sstevel@tonic-gate #define CHECK(F, M) (((F)->mark & M) && (F)->level == our_tag)
487*7c478bd9Sstevel@tonic-gate
488*7c478bd9Sstevel@tonic-gate #define USED(F) ((F)->mark)
489*7c478bd9Sstevel@tonic-gate
490*7c478bd9Sstevel@tonic-gate static int
491*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
_instantiate(PIPELIST * pp,TYPE * inputp,TYPE * outputp,int (* verify)(_FILTER *,void *),void * criteria)492*7c478bd9Sstevel@tonic-gate _instantiate(
493*7c478bd9Sstevel@tonic-gate PIPELIST *pp,
494*7c478bd9Sstevel@tonic-gate TYPE *inputp,
495*7c478bd9Sstevel@tonic-gate TYPE *outputp,
496*7c478bd9Sstevel@tonic-gate int (*verify)(_FILTER *, void *),
497*7c478bd9Sstevel@tonic-gate void *criteria
498*7c478bd9Sstevel@tonic-gate )
499*7c478bd9Sstevel@tonic-gate #else
500*7c478bd9Sstevel@tonic-gate _instantiate(pp, inputp, outputp, verify, criteria)
501*7c478bd9Sstevel@tonic-gate PIPELIST *pp;
502*7c478bd9Sstevel@tonic-gate TYPE *inputp,
503*7c478bd9Sstevel@tonic-gate *outputp;
504*7c478bd9Sstevel@tonic-gate int (*verify)();
505*7c478bd9Sstevel@tonic-gate char *criteria;
506*7c478bd9Sstevel@tonic-gate #endif
507*7c478bd9Sstevel@tonic-gate {
508*7c478bd9Sstevel@tonic-gate register _FILTER *prev_lhead;
509*7c478bd9Sstevel@tonic-gate register _FILTER *prev_ltail;
510*7c478bd9Sstevel@tonic-gate
511*7c478bd9Sstevel@tonic-gate
512*7c478bd9Sstevel@tonic-gate /*
513*7c478bd9Sstevel@tonic-gate * Must be first ``statement'' after declarations.
514*7c478bd9Sstevel@tonic-gate */
515*7c478bd9Sstevel@tonic-gate ENTER();
516*7c478bd9Sstevel@tonic-gate
517*7c478bd9Sstevel@tonic-gate /*
518*7c478bd9Sstevel@tonic-gate * We're done when we've added filters on the left and right
519*7c478bd9Sstevel@tonic-gate * that let us connect the left and right directly; i.e. when
520*7c478bd9Sstevel@tonic-gate * the output of the left is the same type as the input of the
521*7c478bd9Sstevel@tonic-gate * right. HOWEVER, there must be at least one filter involved,
522*7c478bd9Sstevel@tonic-gate * to allow the filter feature to be used for handling modes,
523*7c478bd9Sstevel@tonic-gate * pages, copies, etc. not just FILTERING data.
524*7c478bd9Sstevel@tonic-gate */
525*7c478bd9Sstevel@tonic-gate if (typematch(inputp, outputp) && pp->lhead) {
526*7c478bd9Sstevel@tonic-gate
527*7c478bd9Sstevel@tonic-gate /*
528*7c478bd9Sstevel@tonic-gate * Getting here means that we must have a left and right
529*7c478bd9Sstevel@tonic-gate * pipeline. Why? For "pp->lhead" to be non-zero it
530*7c478bd9Sstevel@tonic-gate * must have been set below. The first place below
531*7c478bd9Sstevel@tonic-gate * doesn't set the right pipeline, but it also doesn't
532*7c478bd9Sstevel@tonic-gate * get us here (at least not directly). The only
533*7c478bd9Sstevel@tonic-gate * place we can get to here again is the second place
534*7c478bd9Sstevel@tonic-gate * "pp->phead" is set, and THAT sets the right pipeline.
535*7c478bd9Sstevel@tonic-gate */
536*7c478bd9Sstevel@tonic-gate pp->ltail->next = pp->rhead;
537*7c478bd9Sstevel@tonic-gate if ((*verify)(pp->lhead, criteria))
538*7c478bd9Sstevel@tonic-gate LEAVE(1);
539*7c478bd9Sstevel@tonic-gate else
540*7c478bd9Sstevel@tonic-gate LEAVE(0);
541*7c478bd9Sstevel@tonic-gate
542*7c478bd9Sstevel@tonic-gate }
543*7c478bd9Sstevel@tonic-gate
544*7c478bd9Sstevel@tonic-gate /*
545*7c478bd9Sstevel@tonic-gate * Each time we search the list of filters, we examine
546*7c478bd9Sstevel@tonic-gate * them in the order given and stop searching when a filter
547*7c478bd9Sstevel@tonic-gate * that meets the needs is found. If the list is ordered with
548*7c478bd9Sstevel@tonic-gate * fast filters before slow filters, then fast filters will
549*7c478bd9Sstevel@tonic-gate * be chosen over otherwise-equal filters.
550*7c478bd9Sstevel@tonic-gate */
551*7c478bd9Sstevel@tonic-gate
552*7c478bd9Sstevel@tonic-gate /*
553*7c478bd9Sstevel@tonic-gate * See if there's a single filter that will work.
554*7c478bd9Sstevel@tonic-gate * Just in case we can't find one, mark those that
555*7c478bd9Sstevel@tonic-gate * will work as left- or right-filters, to save time
556*7c478bd9Sstevel@tonic-gate * later.
557*7c478bd9Sstevel@tonic-gate *
558*7c478bd9Sstevel@tonic-gate * Also, record exactly *which* input/output
559*7c478bd9Sstevel@tonic-gate * type would be needed if the filter was used.
560*7c478bd9Sstevel@tonic-gate * This record will be complete (both input and output
561*7c478bd9Sstevel@tonic-gate * recorded) IF the single filter works. Otherwise,
562*7c478bd9Sstevel@tonic-gate * only the input, for the left possible filters,
563*7c478bd9Sstevel@tonic-gate * and the output, for the right possible filters,
564*7c478bd9Sstevel@tonic-gate * will be recorded. Thus, we'll have to record the
565*7c478bd9Sstevel@tonic-gate * missing types later.
566*7c478bd9Sstevel@tonic-gate */
567*7c478bd9Sstevel@tonic-gate {
568*7c478bd9Sstevel@tonic-gate register _FILTER * pf;
569*7c478bd9Sstevel@tonic-gate
570*7c478bd9Sstevel@tonic-gate
571*7c478bd9Sstevel@tonic-gate for (pf = filters; pf->name; pf++) {
572*7c478bd9Sstevel@tonic-gate
573*7c478bd9Sstevel@tonic-gate if (USED(pf))
574*7c478bd9Sstevel@tonic-gate continue;
575*7c478bd9Sstevel@tonic-gate
576*7c478bd9Sstevel@tonic-gate if (searchlist_t(inputp, pf->input_types)) {
577*7c478bd9Sstevel@tonic-gate MARK(pf, FL_LEFT);
578*7c478bd9Sstevel@tonic-gate pf->inputp = inputp;
579*7c478bd9Sstevel@tonic-gate }
580*7c478bd9Sstevel@tonic-gate if (searchlist_t(outputp, pf->output_types)) {
581*7c478bd9Sstevel@tonic-gate MARK(pf, FL_RIGHT);
582*7c478bd9Sstevel@tonic-gate pf->outputp = outputp;
583*7c478bd9Sstevel@tonic-gate }
584*7c478bd9Sstevel@tonic-gate
585*7c478bd9Sstevel@tonic-gate if (CHECK(pf, FL_LEFT) && CHECK(pf, FL_RIGHT)) {
586*7c478bd9Sstevel@tonic-gate prev_lhead = pp->lhead;
587*7c478bd9Sstevel@tonic-gate prev_ltail = pp->ltail;
588*7c478bd9Sstevel@tonic-gate
589*7c478bd9Sstevel@tonic-gate if (!pp->lhead)
590*7c478bd9Sstevel@tonic-gate pp->lhead = pf;
591*7c478bd9Sstevel@tonic-gate else
592*7c478bd9Sstevel@tonic-gate pp->ltail->next = pf;
593*7c478bd9Sstevel@tonic-gate (pp->ltail = pf)->next = pp->rhead;
594*7c478bd9Sstevel@tonic-gate
595*7c478bd9Sstevel@tonic-gate if ((*verify)(pp->lhead, criteria))
596*7c478bd9Sstevel@tonic-gate LEAVE(1);
597*7c478bd9Sstevel@tonic-gate
598*7c478bd9Sstevel@tonic-gate if ((pp->ltail = prev_ltail))
599*7c478bd9Sstevel@tonic-gate pp->ltail->next = 0;
600*7c478bd9Sstevel@tonic-gate pp->lhead = prev_lhead;
601*7c478bd9Sstevel@tonic-gate
602*7c478bd9Sstevel@tonic-gate }
603*7c478bd9Sstevel@tonic-gate
604*7c478bd9Sstevel@tonic-gate }
605*7c478bd9Sstevel@tonic-gate }
606*7c478bd9Sstevel@tonic-gate
607*7c478bd9Sstevel@tonic-gate /*
608*7c478bd9Sstevel@tonic-gate * Try all DISJOINT pairs of left- and right-filters; recursively
609*7c478bd9Sstevel@tonic-gate * call this function to find a filter that will connect
610*7c478bd9Sstevel@tonic-gate * them (it might be a ``null'' filter).
611*7c478bd9Sstevel@tonic-gate */
612*7c478bd9Sstevel@tonic-gate {
613*7c478bd9Sstevel@tonic-gate register _FILTER * pfl;
614*7c478bd9Sstevel@tonic-gate register _FILTER * pfr;
615*7c478bd9Sstevel@tonic-gate
616*7c478bd9Sstevel@tonic-gate register TYPE * llist;
617*7c478bd9Sstevel@tonic-gate register TYPE * rlist;
618*7c478bd9Sstevel@tonic-gate
619*7c478bd9Sstevel@tonic-gate
620*7c478bd9Sstevel@tonic-gate for (pfl = filters; pfl->name; pfl++) {
621*7c478bd9Sstevel@tonic-gate
622*7c478bd9Sstevel@tonic-gate if (!CHECK(pfl, FL_LEFT))
623*7c478bd9Sstevel@tonic-gate continue;
624*7c478bd9Sstevel@tonic-gate
625*7c478bd9Sstevel@tonic-gate for (pfr = filters; pfr->name; pfr++) {
626*7c478bd9Sstevel@tonic-gate
627*7c478bd9Sstevel@tonic-gate if (pfr == pfl || !CHECK(pfr, FL_RIGHT))
628*7c478bd9Sstevel@tonic-gate continue;
629*7c478bd9Sstevel@tonic-gate
630*7c478bd9Sstevel@tonic-gate prev_lhead = pp->lhead;
631*7c478bd9Sstevel@tonic-gate prev_ltail = pp->ltail;
632*7c478bd9Sstevel@tonic-gate
633*7c478bd9Sstevel@tonic-gate if (!pp->lhead)
634*7c478bd9Sstevel@tonic-gate pp->lhead = pfl;
635*7c478bd9Sstevel@tonic-gate else
636*7c478bd9Sstevel@tonic-gate pp->ltail->next = pfl;
637*7c478bd9Sstevel@tonic-gate (pp->ltail = pfl)->next = 0;
638*7c478bd9Sstevel@tonic-gate
639*7c478bd9Sstevel@tonic-gate pfr->next = pp->rhead;
640*7c478bd9Sstevel@tonic-gate pp->rhead = pfr;
641*7c478bd9Sstevel@tonic-gate
642*7c478bd9Sstevel@tonic-gate /*
643*7c478bd9Sstevel@tonic-gate * Try all the possible output types of
644*7c478bd9Sstevel@tonic-gate * the left filter with all the possible
645*7c478bd9Sstevel@tonic-gate * input types of the right filter. If
646*7c478bd9Sstevel@tonic-gate * we find a combo. that works, record
647*7c478bd9Sstevel@tonic-gate * the output and input types for the
648*7c478bd9Sstevel@tonic-gate * respective filters.
649*7c478bd9Sstevel@tonic-gate */
650*7c478bd9Sstevel@tonic-gate for (llist = pfl->output_types; llist->name;
651*7c478bd9Sstevel@tonic-gate llist++)
652*7c478bd9Sstevel@tonic-gate for (rlist = pfr->input_types;
653*7c478bd9Sstevel@tonic-gate rlist->name; rlist++)
654*7c478bd9Sstevel@tonic-gate if (_instantiate(pp, llist,
655*7c478bd9Sstevel@tonic-gate rlist, verify,
656*7c478bd9Sstevel@tonic-gate criteria)) {
657*7c478bd9Sstevel@tonic-gate pfl->outputp = llist;
658*7c478bd9Sstevel@tonic-gate pfr->inputp = rlist;
659*7c478bd9Sstevel@tonic-gate LEAVE(1);
660*7c478bd9Sstevel@tonic-gate }
661*7c478bd9Sstevel@tonic-gate pp->rhead = pfr->next;
662*7c478bd9Sstevel@tonic-gate if ((pp->ltail = prev_ltail))
663*7c478bd9Sstevel@tonic-gate pp->ltail->next = 0;
664*7c478bd9Sstevel@tonic-gate pp->lhead = prev_lhead;
665*7c478bd9Sstevel@tonic-gate
666*7c478bd9Sstevel@tonic-gate }
667*7c478bd9Sstevel@tonic-gate
668*7c478bd9Sstevel@tonic-gate }
669*7c478bd9Sstevel@tonic-gate }
670*7c478bd9Sstevel@tonic-gate
671*7c478bd9Sstevel@tonic-gate LEAVE(0);
672*7c478bd9Sstevel@tonic-gate }
673*7c478bd9Sstevel@tonic-gate
674*7c478bd9Sstevel@tonic-gate /*
675*7c478bd9Sstevel@tonic-gate * check_pipeline() - CHECK THAT PIPELINE HANDLES MODES, PAGE-LIST
676*7c478bd9Sstevel@tonic-gate */
677*7c478bd9Sstevel@tonic-gate
678*7c478bd9Sstevel@tonic-gate static int
679*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
check_pipeline(_FILTER * pipeline,PARM * parms)680*7c478bd9Sstevel@tonic-gate check_pipeline(
681*7c478bd9Sstevel@tonic-gate _FILTER *pipeline,
682*7c478bd9Sstevel@tonic-gate PARM *parms
683*7c478bd9Sstevel@tonic-gate )
684*7c478bd9Sstevel@tonic-gate #else
685*7c478bd9Sstevel@tonic-gate check_pipeline(pipeline, parms)
686*7c478bd9Sstevel@tonic-gate _FILTER *pipeline;
687*7c478bd9Sstevel@tonic-gate PARM *parms;
688*7c478bd9Sstevel@tonic-gate #endif
689*7c478bd9Sstevel@tonic-gate {
690*7c478bd9Sstevel@tonic-gate register PARM *pm;
691*7c478bd9Sstevel@tonic-gate
692*7c478bd9Sstevel@tonic-gate register _FILTER *pf;
693*7c478bd9Sstevel@tonic-gate
694*7c478bd9Sstevel@tonic-gate register TEMPLATE *pt;
695*7c478bd9Sstevel@tonic-gate
696*7c478bd9Sstevel@tonic-gate register int fail;
697*7c478bd9Sstevel@tonic-gate
698*7c478bd9Sstevel@tonic-gate
699*7c478bd9Sstevel@tonic-gate for (fail = 0, pm = parms; !fail && pm->keyword; pm++) {
700*7c478bd9Sstevel@tonic-gate
701*7c478bd9Sstevel@tonic-gate if (!(pm->flags & X_MUST))
702*7c478bd9Sstevel@tonic-gate continue;
703*7c478bd9Sstevel@tonic-gate
704*7c478bd9Sstevel@tonic-gate for (pf = pipeline; pf; pf = pf->next) {
705*7c478bd9Sstevel@tonic-gate
706*7c478bd9Sstevel@tonic-gate if (!(pt = pf->templates))
707*7c478bd9Sstevel@tonic-gate continue;
708*7c478bd9Sstevel@tonic-gate
709*7c478bd9Sstevel@tonic-gate for (; pt->keyword; pt++)
710*7c478bd9Sstevel@tonic-gate if (STREQU(pt->keyword, pm->keyword) &&
711*7c478bd9Sstevel@tonic-gate pt->result && MATCH(pt, pm))
712*7c478bd9Sstevel@tonic-gate goto Okay;
713*7c478bd9Sstevel@tonic-gate
714*7c478bd9Sstevel@tonic-gate }
715*7c478bd9Sstevel@tonic-gate fail = 1;
716*7c478bd9Sstevel@tonic-gate continue;
717*7c478bd9Sstevel@tonic-gate
718*7c478bd9Sstevel@tonic-gate Okay:;
719*7c478bd9Sstevel@tonic-gate
720*7c478bd9Sstevel@tonic-gate }
721*7c478bd9Sstevel@tonic-gate
722*7c478bd9Sstevel@tonic-gate return (fail? 0 : 1);
723*7c478bd9Sstevel@tonic-gate }
724*7c478bd9Sstevel@tonic-gate
725*7c478bd9Sstevel@tonic-gate /*
726*7c478bd9Sstevel@tonic-gate * build_filter() - CONSTRUCT PIPELINE FROM LINKED LIST OF FILTERS
727*7c478bd9Sstevel@tonic-gate */
728*7c478bd9Sstevel@tonic-gate
729*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
730*7c478bd9Sstevel@tonic-gate static size_t build_simple_cmd(char **, _FILTER *, PARM *,
731*7c478bd9Sstevel@tonic-gate unsigned short *);
732*7c478bd9Sstevel@tonic-gate #else
733*7c478bd9Sstevel@tonic-gate static size_t build_simple_cmd();
734*7c478bd9Sstevel@tonic-gate #endif
735*7c478bd9Sstevel@tonic-gate
736*7c478bd9Sstevel@tonic-gate static char *
737*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
build_pipe(_FILTER * pipeline,PARM * parms,unsigned short * fp)738*7c478bd9Sstevel@tonic-gate build_pipe(
739*7c478bd9Sstevel@tonic-gate _FILTER *pipeline,
740*7c478bd9Sstevel@tonic-gate PARM *parms,
741*7c478bd9Sstevel@tonic-gate unsigned short *fp
742*7c478bd9Sstevel@tonic-gate )
743*7c478bd9Sstevel@tonic-gate #else
744*7c478bd9Sstevel@tonic-gate build_pipe(pipeline, parms, fp)
745*7c478bd9Sstevel@tonic-gate _FILTER *pipeline;
746*7c478bd9Sstevel@tonic-gate PARM *parms;
747*7c478bd9Sstevel@tonic-gate unsigned short *fp;
748*7c478bd9Sstevel@tonic-gate #endif
749*7c478bd9Sstevel@tonic-gate {
750*7c478bd9Sstevel@tonic-gate register _FILTER *pf;
751*7c478bd9Sstevel@tonic-gate
752*7c478bd9Sstevel@tonic-gate register size_t nchars;
753*7c478bd9Sstevel@tonic-gate register size_t n;
754*7c478bd9Sstevel@tonic-gate
755*7c478bd9Sstevel@tonic-gate char *p; /* NOT register */
756*7c478bd9Sstevel@tonic-gate char *ret;
757*7c478bd9Sstevel@tonic-gate
758*7c478bd9Sstevel@tonic-gate
759*7c478bd9Sstevel@tonic-gate /*
760*7c478bd9Sstevel@tonic-gate * This is a two-pass routine. In the first pass we add
761*7c478bd9Sstevel@tonic-gate * up how much space is needed for the pipeline, in the second
762*7c478bd9Sstevel@tonic-gate * pass we allocate the space and construct the pipeline.
763*7c478bd9Sstevel@tonic-gate */
764*7c478bd9Sstevel@tonic-gate
765*7c478bd9Sstevel@tonic-gate for (nchars = 0, pf = pipeline; pf; pf = pf->next)
766*7c478bd9Sstevel@tonic-gate if ((n = build_simple_cmd((char **)0, pf, parms, fp)) > 0)
767*7c478bd9Sstevel@tonic-gate nchars += n + 1; /* +1 for '|' or ending null */
768*7c478bd9Sstevel@tonic-gate
769*7c478bd9Sstevel@tonic-gate if (!(ret = p = Malloc(nchars))) {
770*7c478bd9Sstevel@tonic-gate errno = ENOMEM;
771*7c478bd9Sstevel@tonic-gate return (0);
772*7c478bd9Sstevel@tonic-gate }
773*7c478bd9Sstevel@tonic-gate
774*7c478bd9Sstevel@tonic-gate for (pf = pipeline; pf; pf = pf->next, *p++ = (pf? '|' : 0))
775*7c478bd9Sstevel@tonic-gate (void) build_simple_cmd(&p, pf, parms, fp);
776*7c478bd9Sstevel@tonic-gate
777*7c478bd9Sstevel@tonic-gate return (ret);
778*7c478bd9Sstevel@tonic-gate }
779*7c478bd9Sstevel@tonic-gate
780*7c478bd9Sstevel@tonic-gate /*
781*7c478bd9Sstevel@tonic-gate * build_simple_cmd()
782*7c478bd9Sstevel@tonic-gate */
783*7c478bd9Sstevel@tonic-gate
784*7c478bd9Sstevel@tonic-gate static size_t
785*7c478bd9Sstevel@tonic-gate #if defined(__STDC__)
build_simple_cmd(char ** pp,_FILTER * pf,PARM * parms,unsigned short * flagsp)786*7c478bd9Sstevel@tonic-gate build_simple_cmd(
787*7c478bd9Sstevel@tonic-gate char **pp,
788*7c478bd9Sstevel@tonic-gate _FILTER *pf,
789*7c478bd9Sstevel@tonic-gate PARM *parms,
790*7c478bd9Sstevel@tonic-gate unsigned short *flagsp
791*7c478bd9Sstevel@tonic-gate )
792*7c478bd9Sstevel@tonic-gate #else
793*7c478bd9Sstevel@tonic-gate build_simple_cmd(pp, pf, parms, flagsp)
794*7c478bd9Sstevel@tonic-gate char **pp;
795*7c478bd9Sstevel@tonic-gate _FILTER *pf;
796*7c478bd9Sstevel@tonic-gate PARM *parms;
797*7c478bd9Sstevel@tonic-gate unsigned short *flagsp;
798*7c478bd9Sstevel@tonic-gate #endif
799*7c478bd9Sstevel@tonic-gate {
800*7c478bd9Sstevel@tonic-gate register size_t ncount;
801*7c478bd9Sstevel@tonic-gate
802*7c478bd9Sstevel@tonic-gate register TEMPLATE *pt;
803*7c478bd9Sstevel@tonic-gate
804*7c478bd9Sstevel@tonic-gate register PARM *pm;
805*7c478bd9Sstevel@tonic-gate
806*7c478bd9Sstevel@tonic-gate
807*7c478bd9Sstevel@tonic-gate if (pf->command) {
808*7c478bd9Sstevel@tonic-gate ncount = strlen(pf->command);
809*7c478bd9Sstevel@tonic-gate if (pp) {
810*7c478bd9Sstevel@tonic-gate strcpy (*pp, pf->command);
811*7c478bd9Sstevel@tonic-gate *pp += ncount;
812*7c478bd9Sstevel@tonic-gate }
813*7c478bd9Sstevel@tonic-gate } else
814*7c478bd9Sstevel@tonic-gate ncount = 0;
815*7c478bd9Sstevel@tonic-gate
816*7c478bd9Sstevel@tonic-gate if (!pf->templates)
817*7c478bd9Sstevel@tonic-gate return (ncount);
818*7c478bd9Sstevel@tonic-gate
819*7c478bd9Sstevel@tonic-gate for (pm = parms; pm->keyword; pm++) {
820*7c478bd9Sstevel@tonic-gate
821*7c478bd9Sstevel@tonic-gate if ((pm->flags & X_USED) || !*(pm->pvalue))
822*7c478bd9Sstevel@tonic-gate continue;
823*7c478bd9Sstevel@tonic-gate
824*7c478bd9Sstevel@tonic-gate for (pt = pf->templates; pt->keyword; pt++) {
825*7c478bd9Sstevel@tonic-gate
826*7c478bd9Sstevel@tonic-gate if (!STREQU(pt->keyword, pm->keyword) || !pt->result)
827*7c478bd9Sstevel@tonic-gate continue;
828*7c478bd9Sstevel@tonic-gate
829*7c478bd9Sstevel@tonic-gate /*
830*7c478bd9Sstevel@tonic-gate * INPUT and OUTPUT are those for *this* filter,
831*7c478bd9Sstevel@tonic-gate * not for the entire pipeline.
832*7c478bd9Sstevel@tonic-gate */
833*7c478bd9Sstevel@tonic-gate if (STREQU(pt->keyword, PARM_INPUT))
834*7c478bd9Sstevel@tonic-gate pm->pvalue = &(pf->inputp->name);
835*7c478bd9Sstevel@tonic-gate else if (STREQU(pt->keyword, PARM_OUTPUT))
836*7c478bd9Sstevel@tonic-gate pm->pvalue = &(pf->outputp->name);
837*7c478bd9Sstevel@tonic-gate
838*7c478bd9Sstevel@tonic-gate if (MATCH(pt, pm)) {
839*7c478bd9Sstevel@tonic-gate if (pp)
840*7c478bd9Sstevel@tonic-gate *(*pp)++ = ' ';
841*7c478bd9Sstevel@tonic-gate ncount++;
842*7c478bd9Sstevel@tonic-gate
843*7c478bd9Sstevel@tonic-gate ncount += replace(pp, pt->result,
844*7c478bd9Sstevel@tonic-gate *(pm->pvalue), pt->nbra);
845*7c478bd9Sstevel@tonic-gate
846*7c478bd9Sstevel@tonic-gate /*
847*7c478bd9Sstevel@tonic-gate * Difficulty here due to the two pass
848*7c478bd9Sstevel@tonic-gate * nature of this code. The first pass
849*7c478bd9Sstevel@tonic-gate * just counts the number of bytes; if
850*7c478bd9Sstevel@tonic-gate * we mark the once-only parms as being
851*7c478bd9Sstevel@tonic-gate * used, then we don't pick them up the
852*7c478bd9Sstevel@tonic-gate * second time through. We could get
853*7c478bd9Sstevel@tonic-gate * difficult and mark them temporarily,
854*7c478bd9Sstevel@tonic-gate * but that's hard. So on the first pass
855*7c478bd9Sstevel@tonic-gate * we don't mark the flags. The only
856*7c478bd9Sstevel@tonic-gate * problem is an estimate too high.
857*7c478bd9Sstevel@tonic-gate */
858*7c478bd9Sstevel@tonic-gate if (pp && pm->flags & X_FIRST)
859*7c478bd9Sstevel@tonic-gate pm->flags |= X_USED;
860*7c478bd9Sstevel@tonic-gate
861*7c478bd9Sstevel@tonic-gate *flagsp |= pm->flags;
862*7c478bd9Sstevel@tonic-gate
863*7c478bd9Sstevel@tonic-gate }
864*7c478bd9Sstevel@tonic-gate }
865*7c478bd9Sstevel@tonic-gate }
866*7c478bd9Sstevel@tonic-gate
867*7c478bd9Sstevel@tonic-gate return (ncount);
868*7c478bd9Sstevel@tonic-gate }
869