insfilter.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright (c) 1998-1999 by Sun Microsystems, Inc.
* All rights reserved.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */
#include "assert.h"
#include "string.h"
#include "errno.h"
#include "stdlib.h"
#include "lp.h"
#include "filters.h"
#include "regex.h"
typedef struct PARM {
char *keyword;
unsigned short flags;
char **pvalue;
} PARM;
static struct S {
char *printer;
} S;
#if defined(__STDC__)
int (*)(), void *);
#else
static int searchlist_t();
static int instantiate();
static int check_pipeline();
static char *build_pipe();
#endif
/*
* Table of recognized keywords, with info. about them.
*/
#define NFIXED 4
/* These must be the first NFIXED, and in this order */
PARM_LENGTH, FPARM_LENGTH, 0,
PARM_WIDTH, FPARM_WIDTH, 0,
PARM_FORM, FPARM_FORM, 0,
0, 0, 0,
};
/*
* insfilter()
*/
#if defined(__STDC__)
char **pipes,
char *input_type,
char *output_type,
char *printer_type,
char *printer,
char **parms,
unsigned short *flagsp
)
#else
char **pipes,
*printer,
**parms;
unsigned short *flagsp;
#endif
{
/*
* If the filters have't been loaded yet, do so now.
* We'll load the standard table, but the caller can override
* this by first calling "loadfilters()" with the appropriate
* filter table name.
*/
return (fl_none);
/*
* Allocate and initialize space to hold additional
* information about each item in "parms".
* THIS SPACE MUST BE FREED BEFORE EXITING THIS ROUTINE!
*/
{
register int n;
register char ** p;
for (n = 0, p = parms; *p; n++, p++)
;
n /= 2;
return (fl_none);
}
/*
* Load the parameter list with the fixed ``type''
* parameters. Mark them as used (if appropriate)
* so we don't pick them up from the callers list.
*/
else
pp++;
}
/*
* Copy each parameter from the caller supplied list
* to another list, adding information gathered from
* the keyword table. Note that some keywords should
* be given only once; additional occurrances in the
* caller's list will be ignored.
*/
for (p = parms; *p; p += 2)
else
pp++;
break;
}
}
/*
* Preview the list of filters, to rule out those that
* can't possibly work.
*/
{
else if (printer_type &&
!searchlist_t(&(S.printer_type),
pf->printer_types))
}
}
/*
* Find a pipeline that will convert the input-type to the
* output-type and map the parameters as well.
*/
check_pipeline, S.parms)) {
goto Return;
}
if (!pipes) {
goto Return;
} else {
/*
* Found a pipeline, so now build it.
*/
/*
* Split pipeline after last slow filter.
* "pipeline" will point to first filter in slow
* pipe, "pfastf" will point to first filter in
* fast pipe.
*/
}
if (pslowf) {
} else
pipes[0] = 0;
if (pfastf) {
} else
pipes[1] = 0;
/*
* Check for the oops case.
*/
}
return (ret);
}
/*
* searchlist_t() - SEARCH (TYPE *) LIST FOR ITEM
*/
static int
#if defined(__STDC__)
)
#else
#endif
{
return (1);
else
return (0);
}
static int
#if defined(__STDC__)
)
#else
#endif
{
return (0);
/*
* This is a linear search--we believe that the lists
* will be short.
*/
return (1);
list++;
}
return (0);
}
/*
*/
/*
* The "instantiate()" routine is the meat of the "insfilter()"
* algorithm. It is given an input-type and output-type and finds a
* filter-pipline that will convert the input-type into the
* output-type. Since the filter-pipeline must meet other criteria,
* a function "verify" is also given, along with the set of criteria;
* these are used by "instantiate()" to verify a filter-pipeline.
*
* The filter-pipeline is built up and returned in "pipeline".
* Conceptually this is just a list of filters, with the pipeline to
* be constructed by simply concatenating the filter simple-commmands
* (after filling in option templates) in the order found in the
* list. What is used in the routine, though, is a pair of linked
* lists, one list forming the ``right-half'' of the pipeline, the
* other forming the ``left-half''. The pipeline is then the two
* lists taken together.
*
* The "instantiate()" routine looks for a single filter that matches
* the input-type and output-type and satisfies the criteria. If one
* is found, it is added to the end of the ``left-half'' list (it
* could be added to the beginning of the ``right-half'' list with no
* problem). The two lists are linked together to form one linked
* list, which is passed, along with the set of criteria, to the
* "verify" routine to check the filter-pipeline. If it passes the
* check, the work is done.
*
* If a single filter is not found, "instantiate()" examines all
* pairs of filters where one in the pair can accept the input-type
* and the other can produce the output-type. For each of these, it
* calls itself again to find a filter that can join the pair
* together--one that accepts as input the output-type of the first
* in the pair, and produces as output the input-type of the second
* in the pair. This joining filter may be a single filter or may
* be a filter-pipeline. "instantiate()" checks for the trivial case
* where the input-type is the output-type; with trivial cases it
* links the two lists without adding a filter and checks it with
* "verify".
*/
/*
* instantiate()
*/
/*
* A PIPELIST is what is passed to each recursive call to "instantiate()".
* It contains a pointer to the end of the ``left-list'', a pointer to the
* head of the ``right-list'', and a pointer to the head of the left-list.
* The latter is passed to "verify". The end of the right-list (and thus
* the end of the entire list when left and right are joined) is the
* filter with a null ``next'' pointer.
*/
typedef struct PIPELIST {
} PIPELIST;
#if defined(__STDC__)
int (*)(_FILTER *, void *), void *);
#else
static int _instantiate();
#endif
static int peg;
static int
#if defined(__STDC__)
void *criteria
)
#else
*output;
int (*verify)();
char *criteria;
#endif
{
PIPELIST p;
int ret;
peg = 0;
return (ret);
}
#define LEAVE(Y) if (!Y) { \
register _FILTER *f; \
CLEAR(f); \
return (0); \
} else \
return (1)
static int
#if defined(__STDC__)
void *criteria
)
#else
*outputp;
int (*verify)();
char *criteria;
#endif
{
register _FILTER *prev_lhead;
register _FILTER *prev_ltail;
/*
* Must be first ``statement'' after declarations.
*/
ENTER();
/*
* We're done when we've added filters on the left and right
* that let us connect the left and right directly; i.e. when
* the output of the left is the same type as the input of the
* right. HOWEVER, there must be at least one filter involved,
* to allow the filter feature to be used for handling modes,
* pages, copies, etc. not just FILTERING data.
*/
/*
* Getting here means that we must have a left and right
* pipeline. Why? For "pp->lhead" to be non-zero it
* must have been set below. The first place below
* doesn't set the right pipeline, but it also doesn't
* get us here (at least not directly). The only
* place we can get to here again is the second place
* "pp->phead" is set, and THAT sets the right pipeline.
*/
LEAVE(1);
else
LEAVE(0);
}
/*
* Each time we search the list of filters, we examine
* them in the order given and stop searching when a filter
* that meets the needs is found. If the list is ordered with
* fast filters before slow filters, then fast filters will
* be chosen over otherwise-equal filters.
*/
/*
* See if there's a single filter that will work.
* Just in case we can't find one, mark those that
* will work as left- or right-filters, to save time
* later.
*
* type would be needed if the filter was used.
* This record will be complete (both input and output
* recorded) IF the single filter works. Otherwise,
* only the input, for the left possible filters,
* and the output, for the right possible filters,
* will be recorded. Thus, we'll have to record the
* missing types later.
*/
{
continue;
}
}
else
LEAVE(1);
}
}
}
/*
* Try all DISJOINT pairs of left- and right-filters; recursively
* call this function to find a filter that will connect
* them (it might be a ``null'' filter).
*/
{
continue;
continue;
else
/*
* Try all the possible output types of
* the left filter with all the possible
* input types of the right filter. If
* we find a combo. that works, record
* the output and input types for the
* respective filters.
*/
llist++)
criteria)) {
LEAVE(1);
}
}
}
}
LEAVE(0);
}
/*
* check_pipeline() - CHECK THAT PIPELINE HANDLES MODES, PAGE-LIST
*/
static int
#if defined(__STDC__)
)
#else
#endif
{
register int fail;
continue;
continue;
goto Okay;
}
fail = 1;
continue;
Okay:;
}
return (fail? 0 : 1);
}
/*
* build_filter() - CONSTRUCT PIPELINE FROM LINKED LIST OF FILTERS
*/
#if defined(__STDC__)
unsigned short *);
#else
static size_t build_simple_cmd();
#endif
static char *
#if defined(__STDC__)
unsigned short *fp
)
#else
unsigned short *fp;
#endif
{
register size_t n;
char *p; /* NOT register */
char *ret;
/*
* This is a two-pass routine. In the first pass we add
* up how much space is needed for the pipeline, in the second
* pass we allocate the space and construct the pipeline.
*/
return (0);
}
return (ret);
}
/*
* build_simple_cmd()
*/
static size_t
#if defined(__STDC__)
char **pp,
unsigned short *flagsp
)
#else
char **pp;
unsigned short *flagsp;
#endif
{
if (pp) {
}
} else
ncount = 0;
return (ncount);
continue;
continue;
/*
* INPUT and OUTPUT are those for *this* filter,
* not for the entire pipeline.
*/
if (pp)
*(*pp)++ = ' ';
ncount++;
/*
* Difficulty here due to the two pass
* nature of this code. The first pass
* just counts the number of bytes; if
* we mark the once-only parms as being
* used, then we don't pick them up the
* second time through. We could get
* difficult and mark them temporarily,
* but that's hard. So on the first pass
* we don't mark the flags. The only
* problem is an estimate too high.
*/
}
}
}
return (ncount);
}