#include "ppdc-private.h"
#include <cups/globals.h>
#include <limits.h>
#include <math.h>
#include <unistd.h>
#include <cups/raster.h>
#include "data/epson.h"
#include "data/escp.h"
#include "data/hp.h"
#include "data/label.h"
#include "data/pcl.h"
#ifndef WIN32
# include <sys/utsname.h>
#endif // !WIN32
ppdcArray *ppdcSource::includes = 0;
const char *ppdcSource::driver_types[] =
{
"custom",
"ps",
"escp",
"pcl",
"label",
"epson",
"hp"
};
ppdcSource::ppdcSource(const char *f, cups_file_t *ffp) : ppdcShared()
{
PPDC_NEW;
filename = new ppdcString(f);
base_fonts = new ppdcArray();
drivers = new ppdcArray();
po_files = new ppdcArray();
sizes = new ppdcArray();
vars = new ppdcArray();
cond_state = PPDC_COND_NORMAL;
cond_current = cond_stack;
cond_stack[0] = PPDC_COND_NORMAL;
#define MAKE_STRING(x) #x
vars->add(new ppdcVariable("CUPS_VERSION", MAKE_STRING(CUPS_VERSION)));
vars->add(new ppdcVariable("CUPS_VERSION_MAJOR", MAKE_STRING(CUPS_VERSION_MAJOR)));
vars->add(new ppdcVariable("CUPS_VERSION_MINOR", MAKE_STRING(CUPS_VERSION_MINOR)));
vars->add(new ppdcVariable("CUPS_VERSION_PATCH", MAKE_STRING(CUPS_VERSION_PATCH)));
#ifdef WIN32
vars->add(new ppdcVariable("PLATFORM_NAME", "Windows"));
vars->add(new ppdcVariable("PLATFORM_ARCH", "X86"));
#else
struct utsname name;
if (!uname(&name))
{
vars->add(new ppdcVariable("PLATFORM_NAME", name.sysname));
vars->add(new ppdcVariable("PLATFORM_ARCH", name.machine));
}
else
{
vars->add(new ppdcVariable("PLATFORM_NAME", "unknown"));
vars->add(new ppdcVariable("PLATFORM_ARCH", "unknown"));
}
#endif // WIN32
if (f)
read_file(f, ffp);
}
ppdcSource::~ppdcSource()
{
PPDC_DELETE;
filename->release();
base_fonts->release();
drivers->release();
po_files->release();
sizes->release();
vars->release();
}
void
ppdcSource::add_include(const char *d) {
if (!d)
return;
if (!includes)
includes = new ppdcArray();
includes->add(new ppdcString(d));
}
ppdcDriver * ppdcSource::find_driver(const char *f) {
ppdcDriver *d;
for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
if (!strcasecmp(f, d->pc_file_name->value))
return (d);
return (NULL);
}
char * ppdcSource::find_include(
const char *f, const char *base, char *n, int nlen) {
ppdcString *dir; char temp[1024], *ptr;
if (!f || !*f || !n || nlen < 2)
return (0);
if (*f == '<')
{
strlcpy(temp, f + 1, sizeof(temp));
ptr = temp + strlen(temp) - 1;
if (*ptr != '>')
{
_cupsLangPrintf(stderr,
_("ppdc: Invalid #include/#po filename \"%s\"!\n"), n);
return (0);
}
*ptr = '\0';
f = temp;
}
else
{
if (base && *base && f[0] != '/')
snprintf(n, nlen, "%s/%s", base, f);
else
strlcpy(n, f, nlen);
if (!access(n, 0))
return (n);
else if (*f == '/')
{
return (0);
}
}
if (includes)
{
for (dir = (ppdcString *)includes->first(); dir; dir = (ppdcString *)includes->next())
{
snprintf(n, nlen, "%s/%s", dir->value, f);
if (!access(n, 0))
return (n);
}
}
_cups_globals_t *cg = _cupsGlobals();
snprintf(n, nlen, "%s/ppdc/%s", cg->cups_datadir, f);
if (!access(n, 0))
return (n);
snprintf(n, nlen, "%s/po/%s", cg->cups_datadir, f);
if (!access(n, 0))
return (n);
else
return (0);
}
ppdcCatalog * ppdcSource::find_po(const char *l) {
ppdcCatalog *cat;
for (cat = (ppdcCatalog *)po_files->first();
cat;
cat = (ppdcCatalog *)po_files->next())
if (!strcasecmp(l, cat->locale->value))
return (cat);
return (NULL);
}
ppdcMediaSize * ppdcSource::find_size(const char *s) {
ppdcMediaSize *m;
for (m = (ppdcMediaSize *)sizes->first(); m; m = (ppdcMediaSize *)sizes->next())
if (!strcasecmp(s, m->name->value))
return (m);
return (NULL);
}
ppdcVariable * ppdcSource::find_variable(const char *n){
ppdcVariable *v;
for (v = (ppdcVariable *)vars->first(); v; v = (ppdcVariable *)vars->next())
if (!strcasecmp(n, v->name->value))
return (v);
return (NULL);
}
ppdcAttr * ppdcSource::get_attr(ppdcFile *fp, bool loc) {
char name[1024], selector[1024], *text, value[1024];
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name after %s on line %d of %s!\n"),
loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
return (0);
}
if (!get_token(fp, selector, sizeof(selector)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected selector after %s on line %d of %s!\n"),
loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
return (0);
}
if ((text = strchr(selector, '/')) != NULL)
*text++ = '\0';
if (!get_token(fp, value, sizeof(value)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected value after %s on line %d of %s!\n"),
loc ? "LocAttribute" : "Attribute", fp->line, fp->filename);
return (0);
}
return (new ppdcAttr(name, selector, text, value, loc));
}
int ppdcSource::get_boolean(ppdcFile *fp) {
char buffer[256];
if (!get_token(fp, buffer, sizeof(buffer)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected boolean value on line %d of %s.\n"),
fp->line, fp->filename);
return (-1);
}
if (!strcasecmp(buffer, "on") ||
!strcasecmp(buffer, "yes") ||
!strcasecmp(buffer, "true"))
return (1);
else if (!strcasecmp(buffer, "off") ||
!strcasecmp(buffer, "no") ||
!strcasecmp(buffer, "false"))
return (0);
else
{
_cupsLangPrintf(stderr,
_("ppdc: Bad boolean value (%s) on line %d of %s.\n"),
buffer, fp->line, fp->filename);
return (-1);
}
}
ppdcChoice * ppdcSource::get_choice(ppdcFile *fp) {
char name[1024], *text, code[10240];
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected choice name/text on line %d of %s.\n"),
fp->line, fp->filename);
return (NULL);
}
if ((text = strchr(name, '/')) != NULL)
*text++ = '\0';
else
text = name;
if (!get_token(fp, code, sizeof(code)))
{
_cupsLangPrintf(stderr, _("ppdc: Expected choice code on line %d of %s.\n"),
fp->line, fp->filename);
return (NULL);
}
return (new ppdcChoice(name, text, code));
}
ppdcChoice * ppdcSource::get_color_model(ppdcFile *fp)
{
char name[1024], *text, temp[256]; int color_space, color_order, compression;
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name/text combination for ColorModel on "
"line %d of %s!\n"), fp->line, fp->filename);
return (NULL);
}
if ((text = strchr(name, '/')) != NULL)
*text++ = '\0';
else
text = name;
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected colorspace for ColorModel on line %d of "
"%s!\n"), fp->line, fp->filename);
return (NULL);
}
if ((color_space = get_color_space(temp)) < 0)
color_space = get_integer(temp);
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected color order for ColorModel on line %d of "
"%s!\n"), fp->line, fp->filename);
return (NULL);
}
if ((color_order = get_color_order(temp)) < 0)
color_order = get_integer(temp);
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected compression for ColorModel on line %d of "
"%s!\n"), fp->line, fp->filename);
return (NULL);
}
compression = get_integer(temp);
snprintf(temp, sizeof(temp),
"<</cupsColorSpace %d/cupsColorOrder %d/cupsCompression %d>>"
"setpagedevice",
color_space, color_order, compression);
return (new ppdcChoice(name, text, temp));
}
int ppdcSource::get_color_order(
const char *co) {
if (!strcasecmp(co, "chunked") ||
!strcasecmp(co, "chunky"))
return (CUPS_ORDER_CHUNKED);
else if (!strcasecmp(co, "banded"))
return (CUPS_ORDER_BANDED);
else if (!strcasecmp(co, "planar"))
return (CUPS_ORDER_PLANAR);
else
return (-1);
}
ppdcProfile * ppdcSource::get_color_profile(
ppdcFile *fp) {
char resolution[1024], *media_type; int i; float g, d, m[9];
if (!get_token(fp, resolution, sizeof(resolution)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected resolution/mediatype following "
"ColorProfile on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
if ((media_type = strchr(resolution, '/')) != NULL)
*media_type++ = '\0';
else
media_type = resolution;
g = get_float(fp);
d = get_float(fp);
for (i = 0; i < 9; i ++)
m[i] = get_float(fp);
return (new ppdcProfile(resolution, media_type, g, d, m));
}
int ppdcSource::get_color_space(
const char *cs) {
if (!strcasecmp(cs, "w"))
return (CUPS_CSPACE_W);
else if (!strcasecmp(cs, "rgb"))
return (CUPS_CSPACE_RGB);
else if (!strcasecmp(cs, "rgba"))
return (CUPS_CSPACE_RGBA);
else if (!strcasecmp(cs, "k"))
return (CUPS_CSPACE_K);
else if (!strcasecmp(cs, "cmy"))
return (CUPS_CSPACE_CMY);
else if (!strcasecmp(cs, "ymc"))
return (CUPS_CSPACE_YMC);
else if (!strcasecmp(cs, "cmyk"))
return (CUPS_CSPACE_CMYK);
else if (!strcasecmp(cs, "ymck"))
return (CUPS_CSPACE_YMCK);
else if (!strcasecmp(cs, "kcmy"))
return (CUPS_CSPACE_KCMY);
else if (!strcasecmp(cs, "kcmycm"))
return (CUPS_CSPACE_KCMYcm);
else if (!strcasecmp(cs, "gmck"))
return (CUPS_CSPACE_GMCK);
else if (!strcasecmp(cs, "gmcs"))
return (CUPS_CSPACE_GMCS);
else if (!strcasecmp(cs, "white"))
return (CUPS_CSPACE_WHITE);
else if (!strcasecmp(cs, "gold"))
return (CUPS_CSPACE_GOLD);
else if (!strcasecmp(cs, "silver"))
return (CUPS_CSPACE_SILVER);
else if (!strcasecmp(cs, "CIEXYZ"))
return (CUPS_CSPACE_CIEXYZ);
else if (!strcasecmp(cs, "CIELab"))
return (CUPS_CSPACE_CIELab);
else if (!strcasecmp(cs, "RGBW"))
return (CUPS_CSPACE_RGBW);
else if (!strcasecmp(cs, "ICC1"))
return (CUPS_CSPACE_ICC1);
else if (!strcasecmp(cs, "ICC2"))
return (CUPS_CSPACE_ICC2);
else if (!strcasecmp(cs, "ICC3"))
return (CUPS_CSPACE_ICC3);
else if (!strcasecmp(cs, "ICC4"))
return (CUPS_CSPACE_ICC4);
else if (!strcasecmp(cs, "ICC5"))
return (CUPS_CSPACE_ICC5);
else if (!strcasecmp(cs, "ICC6"))
return (CUPS_CSPACE_ICC6);
else if (!strcasecmp(cs, "ICC7"))
return (CUPS_CSPACE_ICC7);
else if (!strcasecmp(cs, "ICC8"))
return (CUPS_CSPACE_ICC8);
else if (!strcasecmp(cs, "ICC9"))
return (CUPS_CSPACE_ICC9);
else if (!strcasecmp(cs, "ICCA"))
return (CUPS_CSPACE_ICCA);
else if (!strcasecmp(cs, "ICCB"))
return (CUPS_CSPACE_ICCB);
else if (!strcasecmp(cs, "ICCC"))
return (CUPS_CSPACE_ICCC);
else if (!strcasecmp(cs, "ICCD"))
return (CUPS_CSPACE_ICCD);
else if (!strcasecmp(cs, "ICCE"))
return (CUPS_CSPACE_ICCE);
else if (!strcasecmp(cs, "ICCF"))
return (CUPS_CSPACE_ICCF);
else
return (-1);
}
ppdcConstraint * ppdcSource::get_constraint(ppdcFile *fp){
char temp[1024], *ptr, *option1, *choice1, *option2, *choice2;
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected constraints string for UIConstraints on "
"line %d of %s!\n"), fp->line, fp->filename);
return (NULL);
}
for (ptr = temp; isspace(*ptr); ptr ++);
if (*ptr != '*')
{
_cupsLangPrintf(stderr,
_("ppdc: Option constraint must *name on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
option1 = ptr;
for (; *ptr && !isspace(*ptr); ptr ++);
for (; isspace(*ptr); *ptr++ = '\0');
if (*ptr != '*')
{
choice1 = ptr;
for (; *ptr && !isspace(*ptr); ptr ++);
for (; isspace(*ptr); *ptr++ = '\0');
}
else
choice1 = NULL;
if (*ptr != '*')
{
_cupsLangPrintf(stderr,
_("ppdc: Expected two option names on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
option2 = ptr;
for (; *ptr && !isspace(*ptr); ptr ++);
for (; isspace(*ptr); *ptr++ = '\0');
if (*ptr)
choice2 = ptr;
else
choice2 = NULL;
return (new ppdcConstraint(option1, choice1, option2, choice2));
}
ppdcMediaSize * ppdcSource::get_custom_size(ppdcFile *fp)
{
char name[1024], *text, size_code[10240], region_code[10240]; float width, length, left, bottom, right, top;
if (!get_token(fp, name, sizeof(name)))
return (NULL);
if ((text = strchr(name, '/')) != NULL)
*text++ = '\0';
else
text = name;
if ((width = get_measurement(fp)) < 0.0f)
return (NULL);
if ((length = get_measurement(fp)) < 0.0f)
return (NULL);
if ((left = get_measurement(fp)) < 0.0f)
return (NULL);
if ((bottom = get_measurement(fp)) < 0.0f)
return (NULL);
if ((right = get_measurement(fp)) < 0.0f)
return (NULL);
if ((top = get_measurement(fp)) < 0.0f)
return (NULL);
if (!get_token(fp, size_code, sizeof(size_code)))
return (NULL);
if (!get_token(fp, region_code, sizeof(region_code)))
return (NULL);
return (new ppdcMediaSize(name, text, width, length, left, bottom,
right, top, size_code, region_code));
}
void
ppdcSource::get_duplex(ppdcFile *fp, ppdcDriver *d) {
char temp[256]; ppdcAttr *attr; ppdcGroup *g; ppdcOption *o;
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected duplex type after Duplex on line %d of "
"%s!\n"), fp->line, fp->filename);
return;
}
if (cond_state)
return;
if (!strcasecmp(temp, "none") || !strcasecmp(temp, "false") ||
!strcasecmp(temp, "no") || !strcasecmp(temp, "off"))
{
g = d->find_group("General");
if ((o = g->find_option("Duplex")) != NULL)
g->options->remove(o);
for (attr = (ppdcAttr *)d->attrs->first();
attr;
attr = (ppdcAttr *)d->attrs->next())
if (!strcmp(attr->name->value, "cupsFlipDuplex"))
{
d->attrs->remove(attr);
break;
}
}
else if (!strcasecmp(temp, "normal") || !strcasecmp(temp, "true") ||
!strcasecmp(temp, "yes") || !strcasecmp(temp, "on") ||
!strcasecmp(temp, "flip") || !strcasecmp(temp, "rotated") ||
!strcasecmp(temp, "manualtumble"))
{
g = d->find_group("General");
o = g->find_option("Duplex");
if (!o)
{
o = new ppdcOption(PPDC_PICKONE, "Duplex", "2-Sided Printing",
!strcasecmp(temp, "flip") ? PPDC_SECTION_PAGE :
PPDC_SECTION_ANY, 10.0f);
o->add_choice(new ppdcChoice("None", "Off (1-Sided)",
"<</Duplex false>>setpagedevice"));
o->add_choice(new ppdcChoice("DuplexNoTumble", "Long-Edge (Portrait)",
"<</Duplex true/Tumble false>>setpagedevice"));
o->add_choice(new ppdcChoice("DuplexTumble", "Short-Edge (Landscape)",
"<</Duplex true/Tumble true>>setpagedevice"));
g->add_option(o);
}
for (attr = (ppdcAttr *)d->attrs->first();
attr;
attr = (ppdcAttr *)d->attrs->next())
if (!strcmp(attr->name->value, "cupsFlipDuplex"))
{
if (strcasecmp(temp, "flip"))
d->attrs->remove(attr);
break;
}
if (!strcasecmp(temp, "flip") && !attr)
d->add_attr(new ppdcAttr("cupsFlipDuplex", NULL, NULL, "true"));
for (attr = (ppdcAttr *)d->attrs->first();
attr;
attr = (ppdcAttr *)d->attrs->next())
if (!strcmp(attr->name->value, "cupsBackSide"))
{
d->attrs->remove(attr);
break;
}
if (!strcasecmp(temp, "flip"))
d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Flipped"));
else if (!strcasecmp(temp, "rotated"))
d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Rotated"));
else if (!strcasecmp(temp, "manualtumble"))
d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "ManualTumble"));
else
d->add_attr(new ppdcAttr("cupsBackSide", NULL, NULL, "Normal"));
}
else
_cupsLangPrintf(stderr,
_("ppdc: Unknown duplex type \"%s\" on line %d of %s!\n"),
temp, fp->line, fp->filename);
}
ppdcFilter * ppdcSource::get_filter(ppdcFile *fp) {
char type[1024], program[1024], *ptr; int cost;
if (!get_token(fp, type, sizeof(type)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected a filter definition on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
if ((ptr = strchr(type, ' ')) != NULL)
{
*ptr++ = '\0';
cost = strtol(ptr, &ptr, 10);
while (isspace(*ptr))
ptr ++;
strcpy(program, ptr);
}
else
{
cost = get_integer(fp);
if (!get_token(fp, program, sizeof(program)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected a program name on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
}
if (!type[0])
{
_cupsLangPrintf(stderr,
_("ppdc: Invalid empty MIME type for filter on line %d of "
"%s!\n"), fp->line, fp->filename);
return (NULL);
}
if (cost < 0 || cost > 200)
{
_cupsLangPrintf(stderr,
_("ppdc: Invalid cost for filter on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
if (!program[0])
{
_cupsLangPrintf(stderr,
_("ppdc: Invalid empty program name for filter on line %d "
"of %s!\n"), fp->line, fp->filename);
return (NULL);
}
return (new ppdcFilter(type, program, cost));
}
float ppdcSource::get_float(ppdcFile *fp) {
char temp[256], *ptr; float val;
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr, _("ppdc: Expected real number on line %d of %s!\n"),
fp->line, fp->filename);
return (-1.0f);
}
val = (float)strtod(temp, &ptr);
if (*ptr)
{
_cupsLangPrintf(stderr,
_("ppdc: Unknown trailing characters in real number \"%s\" "
"on line %d of %s!\n"), temp, fp->line, fp->filename);
return (-1.0f);
}
else
return (val);
}
ppdcFont * ppdcSource::get_font(ppdcFile *fp) {
char name[256], encoding[256], version[256], charset[256], temp[256]; ppdcFontStatus status;
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name after Font on line %d of %s!\n"),
fp->line, fp->filename);
return (0);
}
if (!strcmp(name, "*"))
{
encoding[0] = '\0';
version[0] = '\0';
charset[0] = '\0';
status = PPDC_FONT_ROM;
}
else
{
if (!get_token(fp, encoding, sizeof(encoding)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected encoding after Font on line %d of "
"%s!\n"), fp->line, fp->filename);
return (0);
}
if (!get_token(fp, version, sizeof(version)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected version after Font on line %d of "
"%s!\n"), fp->line, fp->filename);
return (0);
}
if (!get_token(fp, charset, sizeof(charset)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected charset after Font on line %d of "
"%s!\n"), fp->line, fp->filename);
return (0);
}
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected status after Font on line %d of %s!\n"),
fp->line, fp->filename);
return (0);
}
if (!strcasecmp(temp, "ROM"))
status = PPDC_FONT_ROM;
else if (!strcasecmp(temp, "Disk"))
status = PPDC_FONT_DISK;
else
{
_cupsLangPrintf(stderr,
_("ppdc: Bad status keyword %s on line %d of %s!\n"),
temp, fp->line, fp->filename);
return (0);
}
}
return (new ppdcFont(name, encoding, version, charset, status));
}
ppdcChoice * ppdcSource::get_generic(ppdcFile *fp, const char *keyword,
const char *tattr,
const char *nattr)
{
char name[1024], *text, command[256]; int val;
if (nattr)
val = get_integer(fp);
else
val = 0;
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name/text after %s on line %d of %s!\n"),
keyword, fp->line, fp->filename);
return (NULL);
}
if ((text = strchr(name, '/')) != NULL)
*text++ = '\0';
else
text = name;
if (nattr)
{
if (tattr)
snprintf(command, sizeof(command),
"<</%s(%s)/%s %d>>setpagedevice",
tattr, name, nattr, val);
else
snprintf(command, sizeof(command),
"<</%s %d>>setpagedevice",
nattr, val);
}
else
snprintf(command, sizeof(command),
"<</%s(%s)>>setpagedevice",
tattr, name);
return (new ppdcChoice(name, text, command));
}
ppdcGroup * ppdcSource::get_group(ppdcFile *fp, ppdcDriver *d) {
char name[1024], *text; ppdcGroup *g;
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected group name/text on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
if ((text = strchr(name, '/')) != NULL)
*text++ = '\0';
else
text = name;
if ((g = d->find_group(name)) == NULL)
{
g = new ppdcGroup(name, text);
}
return (g);
}
ppdcOption * ppdcSource::get_installable(ppdcFile *fp)
{
char name[1024], *text; ppdcOption *o;
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name/text after Installable on line %d "
"of %s!\n"), fp->line, fp->filename);
return (NULL);
}
if ((text = strchr(name, '/')) != NULL)
*text++ = '\0';
else
text = name;
o = new ppdcOption(PPDC_BOOLEAN, name, text, PPDC_SECTION_ANY, 10.0f);
o->add_choice(new ppdcChoice("False", "Not Installed", ""));
o->add_choice(new ppdcChoice("True", "Installed", ""));
return (o);
}
#define PPDC_XX -1 // Bad
#define PPDC_EQ 0 // ==
#define PPDC_NE 1 // !=
#define PPDC_LT 2 // <
#define PPDC_LE 3 // <=
#define PPDC_GT 4 // >
#define PPDC_GE 5 // >=
int ppdcSource::get_integer(const char *v) {
long val; long temp, temp2; char *newv, ch; ppdcVariable *var; int compop;
if (!v)
return (-1);
if (isdigit(*v & 255) || *v == '-' || *v == '+')
{
val = strtol(v, (char **)&v, 0);
if (*v || val == LONG_MIN)
return (-1);
else
return ((int)val);
}
else if (*v == '(')
{
v ++;
val = 0;
while (*v && *v != ')')
{
while (*v && isspace(*v & 255))
v ++;
if (!*v || *v == ')')
break;
if (isdigit(*v & 255) || *v == '-' || *v == '+')
{
temp = strtol(v, &newv, 0);
if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
temp == LONG_MIN)
return (-1);
}
else
{
for (newv = (char *)v + 1;
*newv && (isalnum(*newv & 255) || *newv == '_');
newv ++);
ch = *newv;
*newv = '\0';
if ((var = find_variable(v)) != NULL)
{
if (!var->value || !var->value->value || !var->value->value[0])
temp = 0;
else if (isdigit(var->value->value[0] & 255) ||
var->value->value[0] == '-' ||
var->value->value[0] == '+')
temp = strtol(var->value->value, NULL, 0);
else
temp = 1;
}
else
temp = 0;
*newv = ch;
while (isspace(*newv & 255))
newv ++;
if (!strncmp(newv, "==", 2))
{
compop = PPDC_EQ;
newv += 2;
}
else if (!strncmp(newv, "!=", 2))
{
compop = PPDC_NE;
newv += 2;
}
else if (!strncmp(newv, "<=", 2))
{
compop = PPDC_LE;
newv += 2;
}
else if (*newv == '<')
{
compop = PPDC_LT;
newv ++;
}
else if (!strncmp(newv, ">=", 2))
{
compop = PPDC_GE;
newv += 2;
}
else if (*newv == '>')
{
compop = PPDC_GT;
newv ++;
}
else
compop = PPDC_XX;
if (compop != PPDC_XX)
{
while (isspace(*newv & 255))
newv ++;
if (*newv == ')' || !*newv)
return (-1);
if (isdigit(*newv & 255) || *newv == '-' || *newv == '+')
{
temp2 = strtol(newv, &newv, 0);
if (!*newv || newv == v || !(isspace(*newv) || *newv == ')') ||
temp == LONG_MIN)
return (-1);
}
else
{
for (v = newv, newv ++;
*newv && (isalnum(*newv & 255) || *newv == '_');
newv ++);
ch = *newv;
*newv = '\0';
if ((var = find_variable(v)) != NULL)
{
if (!var->value || !var->value->value || !var->value->value[0])
temp2 = 0;
else if (isdigit(var->value->value[0] & 255) ||
var->value->value[0] == '-' ||
var->value->value[0] == '+')
temp2 = strtol(var->value->value, NULL, 0);
else
temp2 = 1;
}
else
temp2 = 0;
*newv = ch;
}
switch (compop)
{
case PPDC_EQ :
temp = temp == temp2;
break;
case PPDC_NE :
temp = temp != temp2;
break;
case PPDC_LT :
temp = temp < temp2;
break;
case PPDC_LE :
temp = temp <= temp2;
break;
case PPDC_GT :
temp = temp > temp2;
break;
case PPDC_GE :
temp = temp >= temp2;
break;
}
}
}
val |= temp;
v = newv;
}
if (*v == ')' && !v[1])
return ((int)val);
else
return (-1);
}
else if ((var = find_variable(v)) != NULL)
{
return (var->value->value && var->value->value[0] &&
strcmp(var->value->value, "0"));
}
else
{
return (-1);
}
}
int ppdcSource::get_integer(ppdcFile *fp) {
char temp[1024];
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr, _("ppdc: Expected integer on line %d of %s!\n"),
fp->line, fp->filename);
return (-1);
}
else
return (get_integer(temp));
}
float ppdcSource::get_measurement(ppdcFile *fp)
{
char buffer[256], *ptr; float val;
if (!get_token(fp, buffer, sizeof(buffer)))
return (-1.0f);
val = (float)strtod(buffer, &ptr);
if (!strcasecmp(ptr, "mm"))
val *= 72.0f / 25.4f;
else if (!strcasecmp(ptr, "cm"))
val *= 72.0f / 2.54f;
else if (!strcasecmp(ptr, "m"))
val *= 72.0f / 0.0254f;
else if (!strcasecmp(ptr, "in"))
val *= 72.0f;
else if (!strcasecmp(ptr, "ft"))
val *= 72.0f * 12.0f;
else if (strcasecmp(ptr, "pt") && *ptr)
return (-1.0f);
return (val);
}
ppdcOption * ppdcSource::get_option(ppdcFile *fp, ppdcDriver *d, ppdcGroup *g) {
char name[1024], *text, type[256]; ppdcOptType ot; ppdcOptSection section; float order; ppdcOption *o; ppdcGroup *mg;
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected option name/text on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
if ((text = strchr(name, '/')) != NULL)
*text++ = '\0';
else
text = name;
if (!get_token(fp, type, sizeof(type)))
{
_cupsLangPrintf(stderr, _("ppdc: Expected option type on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
if (!strcasecmp(type, "boolean"))
ot = PPDC_BOOLEAN;
else if (!strcasecmp(type, "pickone"))
ot = PPDC_PICKONE;
else if (!strcasecmp(type, "pickmany"))
ot = PPDC_PICKMANY;
else
{
_cupsLangPrintf(stderr,
_("ppdc: Invalid option type \"%s\" on line %d of %s!\n"),
type, fp->line, fp->filename);
return (NULL);
}
if (!get_token(fp, type, sizeof(type)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected option section on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
if (!strcasecmp(type, "AnySetup"))
section = PPDC_SECTION_ANY;
else if (!strcasecmp(type, "DocumentSetup"))
section = PPDC_SECTION_DOCUMENT;
else if (!strcasecmp(type, "ExitServer"))
section = PPDC_SECTION_EXIT;
else if (!strcasecmp(type, "JCLSetup"))
section = PPDC_SECTION_JCL;
else if (!strcasecmp(type, "PageSetup"))
section = PPDC_SECTION_PAGE;
else if (!strcasecmp(type, "Prolog"))
section = PPDC_SECTION_PROLOG;
else
{
_cupsLangPrintf(stderr,
_("ppdc: Invalid option section \"%s\" on line %d of "
"%s!\n"), type, fp->line, fp->filename);
return (NULL);
}
order = get_float(fp);
if ((o = d->find_option_group(name, &mg)) == NULL)
{
o = new ppdcOption(ot, name, text, section, order);
}
else if (o->type != ot)
{
_cupsLangPrintf(stderr,
_("ppdc: Option %s redefined with a different type on line "
"%d of %s!\n"), name, fp->line, fp->filename);
return (NULL);
}
else if (g != mg)
{
_cupsLangPrintf(stderr,
_("ppdc: Option %s defined in two different groups on line "
"%d of %s!\n"), name, fp->line, fp->filename);
return (NULL);
}
return (o);
}
ppdcCatalog * ppdcSource::get_po(ppdcFile *fp) {
char locale[32], poname[1024], basedir[1024], *baseptr, pofilename[1024]; ppdcCatalog *cat;
if (!get_token(fp, locale, sizeof(locale)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected locale after #po on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
if (!get_token(fp, poname, sizeof(poname)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected filename after #po %s on line %d of "
"%s!\n"), locale, fp->line, fp->filename);
return (NULL);
}
if (find_po(locale))
{
_cupsLangPrintf(stderr,
_("ppdc: Duplicate #po for locale %s on line %d of %s!\n"),
locale, fp->line, fp->filename);
return (NULL);
}
strlcpy(basedir, fp->filename, sizeof(basedir));
if ((baseptr = strrchr(basedir, '/')) != NULL)
*baseptr = '\0';
else
strcpy(basedir, ".");
pofilename[0] = '\0';
if (!poname[0] ||
find_include(poname, basedir, pofilename, sizeof(pofilename)))
{
cat = new ppdcCatalog(locale, pofilename);
cat->filename->release();
cat->filename = new ppdcString(poname);
return (cat);
}
else
{
_cupsLangPrintf(stderr,
_("ppdc: Unable to find #po file %s on line %d of %s!\n"),
poname, fp->line, fp->filename);
return (NULL);
}
}
ppdcChoice * ppdcSource::get_resolution(ppdcFile *fp){
char name[1024], *text, temp[256], command[256], *commptr; int xdpi, ydpi, color_order, color_space, compression, depth, row_count, row_feed, row_step;
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected override field after Resolution on line "
"%d of %s!\n"), fp->line, fp->filename);
return (NULL);
}
color_order = get_color_order(temp);
color_space = get_color_space(temp);
compression = get_integer(temp);
depth = get_integer(fp);
row_count = get_integer(fp);
row_feed = get_integer(fp);
row_step = get_integer(fp);
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name/text after Resolution on line %d of "
"%s!\n"), fp->line, fp->filename);
return (NULL);
}
if ((text = strchr(name, '/')) != NULL)
*text++ = '\0';
else
text = name;
switch (sscanf(name, "%dx%d", &xdpi, &ydpi))
{
case 0 :
_cupsLangPrintf(stderr,
_("ppdc: Bad resolution name \"%s\" on line %d of "
"%s!\n"), name, fp->line, fp->filename);
break;
case 1 :
ydpi = xdpi;
break;
}
snprintf(command, sizeof(command),
"<</HWResolution[%d %d]/cupsBitsPerColor %d/cupsRowCount %d"
"/cupsRowFeed %d/cupsRowStep %d",
xdpi, ydpi, depth, row_count, row_feed, row_step);
commptr = command + strlen(command);
if (color_order >= 0)
{
snprintf(commptr, sizeof(command) - (commptr - command),
"/cupsColorOrder %d", color_order);
commptr += strlen(commptr);
}
if (color_space >= 0)
{
snprintf(commptr, sizeof(command) - (commptr - command),
"/cupsColorSpace %d", color_space);
commptr += strlen(commptr);
}
if (compression >= 0)
{
snprintf(commptr, sizeof(command) - (commptr - command),
"/cupsCompression %d", compression);
commptr += strlen(commptr);
}
snprintf(commptr, sizeof(command) - (commptr - command), ">>setpagedevice");
return (new ppdcChoice(name, text, command));
}
ppdcProfile * ppdcSource::get_simple_profile(ppdcFile *fp)
{
char resolution[1024], *media_type; float m[9]; float kd, rd, g; float red, green, blue; float yellow; float color;
if (!get_token(fp, resolution, sizeof(resolution)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected resolution/mediatype following "
"SimpleColorProfile on line %d of %s!\n"),
fp->line, fp->filename);
return (NULL);
}
if ((media_type = strchr(resolution, '/')) != NULL)
*media_type++ = '\0';
else
media_type = resolution;
kd = get_float(fp);
yellow = get_float(fp);
rd = get_float(fp);
g = get_float(fp);
red = get_float(fp);
green = get_float(fp);
blue = get_float(fp);
color = 0.5f * rd / kd - kd;
m[0] = 1.0f; m[1] = color + blue; m[2] = color - green; m[3] = color - blue; m[4] = 1.0f; m[5] = color + red; m[6] = yellow * (color + green); m[7] = yellow * (color - red); m[8] = yellow;
if (m[1] > 0.0f)
{
m[3] -= m[1];
m[1] = 0.0f;
}
else if (m[3] > 0.0f)
{
m[1] -= m[3];
m[3] = 0.0f;
}
if (m[2] > 0.0f)
{
m[6] -= m[2];
m[2] = 0.0f;
}
else if (m[6] > 0.0f)
{
m[2] -= m[6];
m[6] = 0.0f;
}
if (m[5] > 0.0f)
{
m[7] -= m[5];
m[5] = 0.0f;
}
else if (m[7] > 0.0f)
{
m[5] -= m[7];
m[7] = 0.0f;
}
return (new ppdcProfile(resolution, media_type, g, kd, m));
}
ppdcMediaSize * ppdcSource::get_size(ppdcFile *fp) {
char name[1024], *text; float width, length;
if (!get_token(fp, name, sizeof(name)))
return (NULL);
if ((text = strchr(name, '/')) != NULL)
*text++ = '\0';
else
text = name;
if ((width = get_measurement(fp)) < 0.0f)
return (NULL);
if ((length = get_measurement(fp)) < 0.0f)
return (NULL);
return (new ppdcMediaSize(name, text, width, length, 0.0f, 0.0f, 0.0f, 0.0f));
}
char * ppdcSource::get_token(ppdcFile *fp, char *buffer, int buflen) {
char *bufptr, *bufend; int ch, nextch, quote, empty, startline; char name[256], *nameptr; ppdcVariable *var;
bufptr = buffer;
bufend = buffer + buflen - 1;
quote = 0;
startline = 0;
empty = 1;
while ((ch = fp->get()) != EOF)
{
if (isspace(ch) && !quote)
{
if (empty)
continue;
else
break;
}
else if (ch == '$')
{
empty = 0;
for (nameptr = name; (ch = fp->peek()) != EOF;)
{
if (!isalnum(ch) && ch != '_')
break;
else if (nameptr < (name + sizeof(name) - 1))
*nameptr++ = fp->get();
}
if (nameptr == name)
{
if (ch == '$')
{
if (bufptr < bufend)
*bufptr++ = fp->get();
}
else
{
_cupsLangPrintf(stderr,
_("ppdc: Bad variable substitution ($%c) on line %d "
"of %s.\n"), ch, fp->line, fp->filename);
if (bufptr < bufend)
*bufptr++ = '$';
}
}
else
{
*nameptr = '\0';
var = find_variable(name);
if (var)
{
strlcpy(bufptr, var->value->value, bufend - bufptr + 1);
bufptr += strlen(bufptr);
}
else
{
if (!(cond_state & PPDC_COND_SKIP))
_cupsLangPrintf(stderr,
_("ppdc: Undefined variable (%s) on line %d of "
"%s.\n"), name, fp->line, fp->filename);
snprintf(bufptr, bufend - bufptr + 1, "$%s", name);
bufptr += strlen(bufptr);
}
}
}
else if (ch == '/' && !quote)
{
nextch = fp->peek();
if (nextch == '*')
{
fp->get();
ch = fp->get();
while ((nextch = fp->get()) != EOF)
{
if (ch == '*' && nextch == '/')
break;
ch = nextch;
}
if (nextch == EOF)
break;
}
else if (nextch == '/')
{
while ((nextch = fp->get()) != EOF)
if (nextch == '\n')
break;
if (nextch == EOF)
break;
}
else
{
empty = 0;
if (bufptr < bufend)
*bufptr++ = ch;
}
}
else if (ch == '\'' || ch == '\"')
{
empty = 0;
if (quote == ch)
{
quote = 0;
}
else if (quote)
{
if (bufptr < bufend)
*bufptr++ = ch;
}
else
{
startline = fp->line;
quote = ch;
}
}
else if ((ch == '(' || ch == '<') && !quote)
{
empty = 0;
quote = ch;
startline = fp->line;
if (bufptr < bufend)
*bufptr++ = ch;
}
else if ((ch == ')' && quote == '(') || (ch == '>' && quote == '<'))
{
quote = 0;
if (bufptr < bufend)
*bufptr++ = ch;
}
else if (ch == '\\')
{
empty = 0;
if ((ch = fp->get()) == EOF)
break;
if (bufptr < bufend)
*bufptr++ = ch;
}
else if (bufptr < bufend)
{
empty = 0;
*bufptr++ = ch;
if ((ch == '{' || ch == '}') && !quote)
break;
}
}
if (quote)
{
_cupsLangPrintf(stderr,
_("ppdc: Unterminated string starting with %c on line %d "
"of %s!\n"), quote, startline, fp->filename);
return (NULL);
}
if (empty)
return (NULL);
else
{
*bufptr = '\0';
return (buffer);
}
}
ppdcVariable * ppdcSource::get_variable(ppdcFile *fp) {
char name[1024], value[1024];
if (!get_token(fp, name, sizeof(name)))
return (NULL);
if (!get_token(fp, value, sizeof(value)))
return (NULL);
return (set_variable(name, value));
}
int ppdcSource::quotef(cups_file_t *fp, const char *format, ...) {
va_list ap; int bytes; char sign, size, type; const char *bufformat; int width, prec; char tformat[100]; char *s; int slen; int i;
if (!fp || !format)
return (-1);
va_start(ap, format);
bytes = 0;
while (*format)
{
if (*format == '%')
{
bufformat = format;
format ++;
if (*format == '%')
{
cupsFilePutChar(fp, *format++);
bytes ++;
continue;
}
else if (strchr(" -+#\'", *format))
sign = *format++;
else
sign = 0;
width = 0;
while (isdigit(*format))
width = width * 10 + *format++ - '0';
if (*format == '.')
{
format ++;
prec = 0;
while (isdigit(*format))
prec = prec * 10 + *format++ - '0';
}
else
prec = -1;
if (*format == 'l' && format[1] == 'l')
{
size = 'L';
format += 2;
}
else if (*format == 'h' || *format == 'l' || *format == 'L')
size = *format++;
if (!*format)
break;
type = *format++;
switch (type)
{
case 'E' : case 'G' :
case 'e' :
case 'f' :
case 'g' :
if ((format - bufformat + 1) > (int)sizeof(tformat))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
bytes += cupsFilePrintf(fp, tformat, va_arg(ap, double));
break;
case 'B' : case 'X' :
case 'b' :
case 'd' :
case 'i' :
case 'o' :
case 'u' :
case 'x' :
if ((format - bufformat + 1) > (int)sizeof(tformat))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
bytes += cupsFilePrintf(fp, tformat, va_arg(ap, int));
break;
case 'p' : if ((format - bufformat + 1) > (int)sizeof(tformat))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
bytes += cupsFilePrintf(fp, tformat, va_arg(ap, void *));
break;
case 'c' : if (width <= 1)
{
bytes ++;
cupsFilePutChar(fp, va_arg(ap, int));
}
else
{
cupsFileWrite(fp, va_arg(ap, char *), width);
bytes += width;
}
break;
case 's' : if ((s = va_arg(ap, char *)) == NULL)
s = (char *)"(nil)";
slen = strlen(s);
if (slen > width && prec != width)
width = slen;
if (slen > width)
slen = width;
if (sign != '-')
{
for (i = width - slen; i > 0; i --, bytes ++)
cupsFilePutChar(fp, ' ');
}
for (i = slen; i > 0; i --, s ++, bytes ++)
{
if (*s == '\\' || *s == '\"')
{
cupsFilePutChar(fp, '\\');
bytes ++;
}
cupsFilePutChar(fp, *s);
}
if (sign == '-')
{
for (i = width - slen; i > 0; i --, bytes ++)
cupsFilePutChar(fp, ' ');
}
break;
}
}
else
{
cupsFilePutChar(fp, *format++);
bytes ++;
}
}
va_end(ap);
return (bytes);
}
void
ppdcSource::read_file(const char *f, cups_file_t *ffp) {
ppdcFile *fp = new ppdcFile(f, ffp);
scan_file(fp);
delete fp;
if (cond_current != cond_stack)
_cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"!\n"), f);
}
void
ppdcSource::scan_file(ppdcFile *fp, ppdcDriver *td, bool inc) {
ppdcDriver *d; ppdcGroup *g, *mg, *general, *install; ppdcOption *o; ppdcChoice *c; char temp[256], *ptr; int isdefault;
if (inc && td)
{
d = td;
d->retain();
}
else
d = new ppdcDriver(td);
if ((general = d->find_group("General")) == NULL)
{
general = new ppdcGroup("General", NULL);
d->add_group(general);
}
if ((install = d->find_group("InstallableOptions")) == NULL)
{
install = new ppdcGroup("InstallableOptions", "Installable Options");
d->add_group(install);
}
o = 0;
g = general;
while (get_token(fp, temp, sizeof(temp)))
{
if (temp[0] == '*')
{
isdefault = 1;
for (ptr = temp; ptr[1]; ptr ++)
*ptr = ptr[1];
*ptr = '\0';
}
else
{
isdefault = 0;
}
if (!strcasecmp(temp, "}"))
{
break;
}
else if (!strcasecmp(temp, "{"))
{
scan_file(fp, d);
}
else if (!strcasecmp(temp, "#if"))
{
if ((cond_current - cond_stack) >= 100)
{
_cupsLangPrintf(stderr,
_("ppdc: Too many nested #if's on line %d of %s!\n"),
fp->line, fp->filename);
break;
}
cond_current ++;
if (get_integer(fp) > 0)
*cond_current = PPDC_COND_SATISFIED;
else
{
*cond_current = PPDC_COND_SKIP;
cond_state |= PPDC_COND_SKIP;
}
}
else if (!strcasecmp(temp, "#elif"))
{
if (cond_current == cond_stack)
{
_cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
fp->line, fp->filename);
break;
}
if (*cond_current & PPDC_COND_SATISFIED)
{
get_integer(fp);
*cond_current |= PPDC_COND_SKIP;
}
else if (get_integer(fp) > 0)
{
*cond_current |= PPDC_COND_SATISFIED;
*cond_current &= ~PPDC_COND_SKIP;
}
else
*cond_current |= PPDC_COND_SKIP;
int *cond_temp = cond_current;
cond_state = PPDC_COND_NORMAL;
while (cond_temp > cond_stack)
if (*cond_temp & PPDC_COND_SKIP)
{
cond_state = PPDC_COND_SKIP;
break;
}
else
cond_temp --;
}
else if (!strcasecmp(temp, "#else"))
{
if (cond_current == cond_stack)
{
_cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
fp->line, fp->filename);
break;
}
if (*cond_current & PPDC_COND_SATISFIED)
*cond_current |= PPDC_COND_SKIP;
else
{
*cond_current |= PPDC_COND_SATISFIED;
*cond_current &= ~PPDC_COND_SKIP;
}
int *cond_temp = cond_current;
cond_state = PPDC_COND_NORMAL;
while (cond_temp > cond_stack)
if (*cond_temp & PPDC_COND_SKIP)
{
cond_state = PPDC_COND_SKIP;
break;
}
else
cond_temp --;
}
else if (!strcasecmp(temp, "#endif"))
{
if (cond_current == cond_stack)
{
_cupsLangPrintf(stderr, _("ppdc: Missing #if on line %d of %s!\n"),
fp->line, fp->filename);
break;
}
cond_current --;
int *cond_temp = cond_current;
cond_state = PPDC_COND_NORMAL;
while (cond_temp > cond_stack)
if (*cond_temp & PPDC_COND_SKIP)
{
cond_state = PPDC_COND_SKIP;
break;
}
else
cond_temp --;
}
else if (!strcasecmp(temp, "#define"))
{
get_variable(fp);
}
else if (!strcasecmp(temp, "#include"))
{
char basedir[1024], *baseptr, inctemp[1024], incname[1024]; ppdcFile *incfile; int *old_current = cond_current;
if (!get_token(fp, inctemp, sizeof(inctemp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected include filename on line %d of "
"%s!\n"), fp->line, fp->filename);
break;
}
if (cond_state)
continue;
strlcpy(basedir, fp->filename, sizeof(basedir));
if ((baseptr = strrchr(basedir, '/')) != NULL)
*baseptr = '\0';
else
strcpy(basedir, ".");
if (find_include(inctemp, basedir, incname, sizeof(incname)))
{
incfile = new ppdcFile(incname);
scan_file(incfile, d, true);
delete incfile;
if (cond_current != old_current)
_cupsLangPrintf(stderr, _("ppdc: Missing #endif at end of \"%s\"!\n"),
incname);
}
else
{
_cupsLangPrintf(stderr,
_("ppdc: Unable to find include file \"%s\" on line %d "
"of %s!\n"), inctemp, fp->line, fp->filename);
break;
}
}
else if (!strcasecmp(temp, "#media"))
{
ppdcMediaSize *m;
m = get_size(fp);
if (m)
{
if (cond_state)
m->release();
else
sizes->add(m);
}
}
else if (!strcasecmp(temp, "#po"))
{
ppdcCatalog *cat;
cat = get_po(fp);
if (cat)
{
if (cond_state)
cat->release();
else
po_files->add(cat);
}
}
else if (!strcasecmp(temp, "Attribute") ||
!strcasecmp(temp, "LocAttribute"))
{
ppdcAttr *a;
a = get_attr(fp, !strcasecmp(temp, "LocAttribute"));
if (a)
{
if (cond_state)
a->release();
else
d->add_attr(a);
}
}
else if (!strcasecmp(temp, "Choice"))
{
c = get_choice(fp);
if (!c)
break;
if (cond_state)
{
c->release();
continue;
}
if (!o)
{
_cupsLangPrintf(stderr,
_("ppdc: Choice found on line %d of %s with no "
"Option!\n"), fp->line, fp->filename);
break;
}
o->add_choice(c);
if (isdefault)
o->set_defchoice(c);
}
else if (!strcasecmp(temp, "ColorDevice"))
{
if (cond_state)
get_boolean(fp);
else
d->color_device = get_boolean(fp);
}
else if (!strcasecmp(temp, "ColorModel"))
{
c = get_color_model(fp);
if (!c)
continue;
if (cond_state)
{
c->release();
continue;
}
if ((o = d->find_option("ColorModel")) == NULL)
{
o = new ppdcOption(PPDC_PICKONE, "ColorModel", "Color Mode", PPDC_SECTION_ANY, 10.0f);
g = general;
g->add_option(o);
}
o->add_choice(c);
if (isdefault)
o->set_defchoice(c);
o = NULL;
}
else if (!strcasecmp(temp, "ColorProfile"))
{
ppdcProfile *p;
p = get_color_profile(fp);
if (p)
{
if (cond_state)
p->release();
else
d->profiles->add(p);
}
}
else if (!strcasecmp(temp, "Copyright"))
{
char copytemp[8192], *copyptr, *copyend;
if (!get_token(fp, copytemp, sizeof(temp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected string after Copyright on line %d "
"of %s!\n"), fp->line, fp->filename);
break;
}
if (cond_state)
continue;
for (copyptr = copytemp; copyptr; copyptr = copyend)
{
if ((copyend = strchr(copyptr, '\n')) != NULL)
*copyend++ = '\0';
d->copyright->add(new ppdcString(copyptr));
}
}
else if (!strcasecmp(temp, "CustomMedia"))
{
ppdcMediaSize *m;
m = get_custom_size(fp);
if (cond_state)
{
m->release();
continue;
}
if (m)
d->sizes->add(m);
if (isdefault)
d->set_default_size(m);
}
else if (!strcasecmp(temp, "Cutter"))
{
int have_cutter;
have_cutter = get_boolean(fp);
if (have_cutter <= 0 || cond_state)
continue;
if ((o = d->find_option("CutMedia")) == NULL)
{
o = new ppdcOption(PPDC_BOOLEAN, "CutMedia", "Cut Media", PPDC_SECTION_ANY, 10.0f);
g = general;
g->add_option(o);
c = new ppdcChoice("False", NULL, "<</CutMedia 0>>setpagedevice");
o->add_choice(c);
o->set_defchoice(c);
c = new ppdcChoice("True", NULL, "<</CutMedia 4>>setpagedevice");
o->add_choice(c);
}
o = NULL;
}
else if (!strcasecmp(temp, "Darkness"))
{
c = get_generic(fp, "Darkness", NULL, "cupsCompression");
if (!c)
continue;
if (cond_state)
{
c->release();
continue;
}
if ((o = d->find_option_group("cupsDarkness", &mg)) == NULL)
{
o = new ppdcOption(PPDC_PICKONE, "cupsDarkness", "Darkness", PPDC_SECTION_ANY, 10.0f);
g = general;
g->add_option(o);
}
else if (mg != general)
{
_cupsLangPrintf(stderr,
_("ppdc: Option %s defined in two different groups on "
"line %d of %s!\n"), "cupsDarkness", fp->line,
fp->filename);
c->release();
continue;
}
o->add_choice(c);
if (isdefault)
o->set_defchoice(c);
o = NULL;
}
else if (!strcasecmp(temp, "DriverType"))
{
int i;
if (!get_token(fp, temp, sizeof(temp)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected driver type keyword following "
"DriverType on line %d of %s!\n"),
fp->line, fp->filename);
continue;
}
if (cond_state)
continue;
for (i = 0; i < (int)(sizeof(driver_types) / sizeof(driver_types[0])); i ++)
if (!strcasecmp(temp, driver_types[i]))
break;
if (i < (int)(sizeof(driver_types) / sizeof(driver_types[0])))
d->type = (ppdcDrvType)i;
else if (!strcasecmp(temp, "dymo"))
d->type = PPDC_DRIVER_LABEL;
else
_cupsLangPrintf(stderr,
_("ppdc: Unknown driver type %s on line %d of %s!\n"),
temp, fp->line, fp->filename);
}
else if (!strcasecmp(temp, "Duplex"))
get_duplex(fp, d);
else if (!strcasecmp(temp, "Filter"))
{
ppdcFilter *f;
f = get_filter(fp);
if (f)
{
if (cond_state)
f->release();
else
d->filters->add(f);
}
}
else if (!strcasecmp(temp, "Finishing"))
{
c = get_generic(fp, "Finishing", "OutputType", NULL);
if (!c)
continue;
if (cond_state)
{
c->release();
continue;
}
if ((o = d->find_option_group("cupsFinishing", &mg)) == NULL)
{
o = new ppdcOption(PPDC_PICKONE, "cupsFinishing", "Finishing", PPDC_SECTION_ANY, 10.0f);
g = general;
g->add_option(o);
}
else if (mg != general)
{
_cupsLangPrintf(stderr,
_("ppdc: Option %s defined in two different groups on "
"line %d of %s!\n"), "cupsFinishing", fp->line,
fp->filename);
c->release();
continue;
}
o->add_choice(c);
if (isdefault)
o->set_defchoice(c);
o = NULL;
}
else if (!strcasecmp(temp, "Font") ||
!strcasecmp(temp, "#font"))
{
ppdcFont *f;
f = get_font(fp);
if (f)
{
if (cond_state)
f->release();
else
{
if (!strcasecmp(temp, "#font"))
base_fonts->add(f);
else
d->add_font(f);
if (isdefault)
d->set_default_font(f);
}
}
}
else if (!strcasecmp(temp, "Group"))
{
ppdcGroup *tempg = get_group(fp, d);
if (!tempg)
break;
if (cond_state)
{
if (!d->find_group(tempg->name->value))
tempg->release();
}
else
{
if (!d->find_group(tempg->name->value))
d->add_group(tempg);
g = tempg;
}
}
else if (!strcasecmp(temp, "HWMargins"))
{
d->left_margin = get_measurement(fp);
d->bottom_margin = get_measurement(fp);
d->right_margin = get_measurement(fp);
d->top_margin = get_measurement(fp);
}
else if (!strcasecmp(temp, "InputSlot"))
{
c = get_generic(fp, "InputSlot", NULL, "MediaPosition");
if (!c)
continue;
if (cond_state)
{
c->release();
continue;
}
if ((o = d->find_option_group("InputSlot", &mg)) == NULL)
{
o = new ppdcOption(PPDC_PICKONE, "InputSlot", "Media Source",
PPDC_SECTION_ANY, 10.0f);
g = general;
g->add_option(o);
}
else if (mg != general)
{
_cupsLangPrintf(stderr,
_("ppdc: Option %s defined in two different groups on "
"line %d of %s!\n"), "InputSlot", fp->line,
fp->filename);
c->release();
continue;
}
o->add_choice(c);
if (isdefault)
o->set_defchoice(c);
o = NULL;
}
else if (!strcasecmp(temp, "Installable"))
{
o = get_installable(fp);
if (o)
{
if (cond_state)
o->release();
else
install->add_option(o);
o = NULL;
}
}
else if (!strcasecmp(temp, "ManualCopies"))
{
if (cond_state)
get_boolean(fp);
else
d->manual_copies = get_boolean(fp);
}
else if (!strcasecmp(temp, "Manufacturer"))
{
char name[256];
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name after Manufacturer on line %d "
"of %s!\n"), fp->line, fp->filename);
break;
}
if (!cond_state)
d->set_manufacturer(name);
}
else if (!strcasecmp(temp, "MaxSize"))
{
if (cond_state)
{
get_measurement(fp);
get_measurement(fp);
}
else
{
d->max_width = get_measurement(fp);
d->max_length = get_measurement(fp);
}
}
else if (!strcasecmp(temp, "MediaSize"))
{
char name[41]; ppdcMediaSize *m, *dm;
if (get_token(fp, name, sizeof(name)) == NULL)
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name after MediaSize on line %d of "
"%s!\n"), fp->line, fp->filename);
break;
}
if (cond_state)
continue;
m = find_size(name);
if (!m)
{
_cupsLangPrintf(stderr,
_("ppdc: Unknown media size \"%s\" on line %d of "
"%s!\n"), name, fp->line, fp->filename);
break;
}
dm = new ppdcMediaSize(m->name->value, m->text->value,
m->width, m->length, d->left_margin,
d->bottom_margin, d->right_margin,
d->top_margin);
d->sizes->add(dm);
if (isdefault)
d->set_default_size(dm);
}
else if (!strcasecmp(temp, "MediaType"))
{
c = get_generic(fp, "MediaType", "MediaType", "cupsMediaType");
if (!c)
continue;
if (cond_state)
{
c->release();
continue;
}
if ((o = d->find_option_group("MediaType", &mg)) == NULL)
{
o = new ppdcOption(PPDC_PICKONE, "MediaType", "Media Type",
PPDC_SECTION_ANY, 10.0f);
g = general;
g->add_option(o);
}
else if (mg != general)
{
_cupsLangPrintf(stderr,
_("ppdc: Option %s defined in two different groups on "
"line %d of %s!\n"), "MediaType", fp->line,
fp->filename);
c->release();
continue;
}
o->add_choice(c);
if (isdefault)
o->set_defchoice(c);
o = NULL;
}
else if (!strcasecmp(temp, "MinSize"))
{
if (cond_state)
{
get_measurement(fp);
get_measurement(fp);
}
else
{
d->min_width = get_measurement(fp);
d->min_length = get_measurement(fp);
}
}
else if (!strcasecmp(temp, "ModelName"))
{
char name[256];
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name after ModelName on line %d of "
"%s!\n"), fp->line, fp->filename);
break;
}
if (!cond_state)
d->set_model_name(name);
}
else if (!strcasecmp(temp, "ModelNumber"))
{
if (cond_state)
get_integer(fp);
else
d->model_number = get_integer(fp);
}
else if (!strcasecmp(temp, "Option"))
{
ppdcOption *tempo = get_option(fp, d, g);
if (!tempo)
break;
if (cond_state)
{
if (!g->find_option(tempo->name->value))
tempo->release();
}
else
{
if (!g->find_option(tempo->name->value))
g->add_option(tempo);
o = tempo;
}
}
else if (!strcasecmp(temp, "FileName"))
{
char name[256];
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name after FileName on line %d of "
"%s!\n"), fp->line, fp->filename);
break;
}
if (!cond_state)
d->set_file_name(name);
}
else if (!strcasecmp(temp, "PCFileName"))
{
char name[256];
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected name after PCFileName on line %d of "
"%s!\n"), fp->line, fp->filename);
break;
}
if (!cond_state)
d->set_pc_file_name(name);
}
else if (!strcasecmp(temp, "Resolution"))
{
c = get_resolution(fp);
if (!c)
continue;
if (cond_state)
{
c->release();
continue;
}
if ((o = d->find_option_group("Resolution", &mg)) == NULL)
{
o = new ppdcOption(PPDC_PICKONE, "Resolution", NULL, PPDC_SECTION_ANY,
10.0f);
g = general;
g->add_option(o);
}
else if (mg != general)
{
_cupsLangPrintf(stderr,
_("ppdc: Option %s defined in two different groups on "
"line %d of %s!\n"), "Resolution", fp->line,
fp->filename);
c->release();
continue;
}
o->add_choice(c);
if (isdefault)
o->set_defchoice(c);
o = NULL;
}
else if (!strcasecmp(temp, "SimpleColorProfile"))
{
ppdcProfile *p;
p = get_simple_profile(fp);
if (p)
{
if (cond_state)
p->release();
else
d->profiles->add(p);
}
}
else if (!strcasecmp(temp, "Throughput"))
{
if (cond_state)
get_integer(fp);
else
d->throughput = get_integer(fp);
}
else if (!strcasecmp(temp, "UIConstraints"))
{
ppdcConstraint *con;
con = get_constraint(fp);
if (con)
{
if (cond_state)
con->release();
else
d->constraints->add(con);
}
}
else if (!strcasecmp(temp, "VariablePaperSize"))
{
if (cond_state)
get_boolean(fp);
else
d->variable_paper_size = get_boolean(fp);
}
else if (!strcasecmp(temp, "Version"))
{
char name[256];
if (!get_token(fp, name, sizeof(name)))
{
_cupsLangPrintf(stderr,
_("ppdc: Expected string after Version on line %d of "
"%s!\n"), fp->line, fp->filename);
break;
}
if (!cond_state)
d->set_version(name);
}
else
{
_cupsLangPrintf(stderr,
_("ppdc: Unknown token \"%s\" seen on line %d of %s!\n"),
temp, fp->line, fp->filename);
break;
}
}
if (!inc)
{
if (!d->pc_file_name || !d->model_name || !d->manufacturer || !d->version ||
!d->sizes->count)
{
d->release();
}
else
{
drivers->add(d);
}
}
else if (inc && td)
td->release();
}
ppdcVariable * ppdcSource::set_variable(
const char *name, const char *value) {
ppdcVariable *v;
v = find_variable(name);
if (v)
{
v->set_value(value);
}
else
{
v = new ppdcVariable(name, value);
vars->add(v);
}
return (v);
}
int ppdcSource::write_file(const char *f) {
cups_file_t *fp; char bckname[1024]; ppdcDriver *d; ppdcString *st; ppdcAttr *a; ppdcConstraint *co; ppdcFilter *fi; ppdcFont *fo; ppdcGroup *g; ppdcOption *o; ppdcChoice *ch; ppdcProfile *p; ppdcMediaSize *si; float left, bottom, right, top; int dtused[PPDC_DRIVER_MAX];
snprintf(bckname, sizeof(bckname), "%s.bck", f);
rename(f, bckname);
fp = cupsFileOpen(f, "w");
if (!fp)
{
rename(bckname, f);
return (-1);
}
cupsFilePuts(fp, "// CUPS PPD Compiler " CUPS_SVERSION "\n\n");
cupsFilePuts(fp, "// Include necessary files...\n");
cupsFilePuts(fp, "#include <font.defs>\n");
cupsFilePuts(fp, "#include <media.defs>\n");
memset(dtused, 0, sizeof(dtused));
for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
if (d->type > PPDC_DRIVER_PS && !dtused[d->type])
{
cupsFilePrintf(fp, "#include <%s.h>\n", driver_types[d->type]);
dtused[d->type] = 1;
}
for (d = (ppdcDriver *)drivers->first(); d; d = (ppdcDriver *)drivers->next())
{
cupsFilePrintf(fp, "\n// %s %s\n", d->manufacturer->value,
d->model_name->value);
cupsFilePuts(fp, "{\n");
for (st = (ppdcString *)d->copyright->first();
st;
st = (ppdcString *)d->copyright->next())
quotef(fp, " Copyright \"%s\"\n", st->value);
if (d->manufacturer && d->manufacturer->value)
quotef(fp, " Manufacturer \"%s\"\n", d->manufacturer->value);
if (d->model_name->value)
quotef(fp, " ModelName \"%s\"\n", d->model_name->value);
if (d->file_name && d->file_name->value)
quotef(fp, " FileName \"%s\"\n", d->file_name->value);
if (d->pc_file_name && d->pc_file_name->value)
quotef(fp, " PCFileName \"%s\"\n", d->pc_file_name->value);
if (d->version && d->version->value)
quotef(fp, " Version \"%s\"\n", d->version->value);
cupsFilePrintf(fp, " DriverType %s\n", driver_types[d->type]);
if (d->model_number)
{
switch (d->type)
{
case PPDC_DRIVER_ESCP :
cupsFilePuts(fp, " ModelNumber (");
if (d->model_number & ESCP_DOTMATRIX)
cupsFilePuts(fp, " $ESCP_DOTMATRIX");
if (d->model_number & ESCP_MICROWEAVE)
cupsFilePuts(fp, " $ESCP_MICROWEAVE");
if (d->model_number & ESCP_STAGGER)
cupsFilePuts(fp, " $ESCP_STAGGER");
if (d->model_number & ESCP_ESCK)
cupsFilePuts(fp, " $ESCP_ESCK");
if (d->model_number & ESCP_EXT_UNITS)
cupsFilePuts(fp, " $ESCP_EXT_UNITS");
if (d->model_number & ESCP_EXT_MARGINS)
cupsFilePuts(fp, " $ESCP_EXT_MARGINS");
if (d->model_number & ESCP_USB)
cupsFilePuts(fp, " $ESCP_USB");
if (d->model_number & ESCP_PAGE_SIZE)
cupsFilePuts(fp, " $ESCP_PAGE_SIZE");
if (d->model_number & ESCP_RASTER_ESCI)
cupsFilePuts(fp, " $ESCP_RASTER_ESCI");
if (d->model_number & ESCP_REMOTE)
cupsFilePuts(fp, " $ESCP_REMOTE");
cupsFilePuts(fp, ")\n");
break;
case PPDC_DRIVER_PCL :
cupsFilePuts(fp, " ModelNumber (");
if (d->model_number & PCL_PAPER_SIZE)
cupsFilePuts(fp, " $PCL_PAPER_SIZE");
if (d->model_number & PCL_INKJET)
cupsFilePuts(fp, " $PCL_INKJET");
if (d->model_number & PCL_RASTER_END_COLOR)
cupsFilePuts(fp, " $PCL_RASTER_END_COLOR");
if (d->model_number & PCL_RASTER_CID)
cupsFilePuts(fp, " $PCL_RASTER_CID");
if (d->model_number & PCL_RASTER_CRD)
cupsFilePuts(fp, " $PCL_RASTER_CRD");
if (d->model_number & PCL_RASTER_SIMPLE)
cupsFilePuts(fp, " $PCL_RASTER_SIMPLE");
if (d->model_number & PCL_RASTER_RGB24)
cupsFilePuts(fp, " $PCL_RASTER_RGB24");
if (d->model_number & PCL_PJL)
cupsFilePuts(fp, " $PCL_PJL");
if (d->model_number & PCL_PJL_PAPERWIDTH)
cupsFilePuts(fp, " $PCL_PJL_PAPERWIDTH");
if (d->model_number & PCL_PJL_HPGL2)
cupsFilePuts(fp, " $PCL_PJL_HPGL2");
if (d->model_number & PCL_PJL_PCL3GUI)
cupsFilePuts(fp, " $PCL_PJL_PCL3GUI");
if (d->model_number & PCL_PJL_RESOLUTION)
cupsFilePuts(fp, " $PCL_PJL_RESOLUTION");
cupsFilePuts(fp, ")\n");
break;
case PPDC_DRIVER_LABEL :
cupsFilePuts(fp, " ModelNumber ");
switch (d->model_number)
{
case DYMO_3x0 :
cupsFilePuts(fp, "$DYMO_3x0\n");
break;
case ZEBRA_EPL_LINE :
cupsFilePuts(fp, "$ZEBRA_EPL_LINE\n");
break;
case ZEBRA_EPL_PAGE :
cupsFilePuts(fp, "$ZEBRA_EPL_PAGE\n");
break;
case ZEBRA_ZPL :
cupsFilePuts(fp, "$ZEBRA_ZPL\n");
break;
case ZEBRA_CPCL :
cupsFilePuts(fp, "$ZEBRA_CPCL\n");
break;
case INTELLITECH_PCL :
cupsFilePuts(fp, "$INTELLITECH_PCL\n");
break;
default :
cupsFilePrintf(fp, "%d\n", d->model_number);
break;
}
break;
case PPDC_DRIVER_EPSON :
cupsFilePuts(fp, " ModelNumber ");
switch (d->model_number)
{
case EPSON_9PIN :
cupsFilePuts(fp, "$EPSON_9PIN\n");
break;
case EPSON_24PIN :
cupsFilePuts(fp, "$EPSON_24PIN\n");
break;
case EPSON_COLOR :
cupsFilePuts(fp, "$EPSON_COLOR\n");
break;
case EPSON_PHOTO :
cupsFilePuts(fp, "$EPSON_PHOTO\n");
break;
case EPSON_ICOLOR :
cupsFilePuts(fp, "$EPSON_ICOLOR\n");
break;
case EPSON_IPHOTO :
cupsFilePuts(fp, "$EPSON_IPHOTO\n");
break;
default :
cupsFilePrintf(fp, "%d\n", d->model_number);
break;
}
break;
case PPDC_DRIVER_HP :
cupsFilePuts(fp, " ModelNumber ");
switch (d->model_number)
{
case HP_LASERJET :
cupsFilePuts(fp, "$HP_LASERJET\n");
break;
case HP_DESKJET :
cupsFilePuts(fp, "$HP_DESKJET\n");
break;
case HP_DESKJET2 :
cupsFilePuts(fp, "$HP_DESKJET2\n");
break;
default :
cupsFilePrintf(fp, "%d\n", d->model_number);
break;
}
cupsFilePuts(fp, ")\n");
break;
default :
cupsFilePrintf(fp, " ModelNumber %d\n", d->model_number);
break;
}
}
if (d->manual_copies)
cupsFilePuts(fp, " ManualCopies Yes\n");
if (d->color_device)
cupsFilePuts(fp, " ColorDevice Yes\n");
if (d->throughput)
cupsFilePrintf(fp, " Throughput %d\n", d->throughput);
for (a = (ppdcAttr *)d->attrs->first();
a;
a = (ppdcAttr *)d->attrs->next())
if (a->text->value && a->text->value[0])
quotef(fp, " Attribute \"%s\" \"%s/%s\" \"%s\"\n",
a->name->value, a->selector->value ? a->selector->value : "",
a->text->value, a->value->value ? a->value->value : "");
else
quotef(fp, " Attribute \"%s\" \"%s\" \"%s\"\n",
a->name->value, a->selector->value ? a->selector->value : "",
a->value->value ? a->value->value : "");
for (co = (ppdcConstraint *)d->constraints->first();
co;
co = (ppdcConstraint *)d->constraints->next())
{
if (co->option1->value[0] == '*')
cupsFilePrintf(fp, " UIConstraints \"%s %s", co->option1->value,
co->choice1->value ? co->choice1->value : "");
else
cupsFilePrintf(fp, " UIConstraints \"*%s %s", co->option1->value,
co->choice1->value ? co->choice1->value : "");
if (co->option2->value[0] == '*')
cupsFilePrintf(fp, " %s %s\"\n", co->option2->value,
co->choice2->value ? co->choice2->value : "");
else
cupsFilePrintf(fp, " *%s %s\"\n", co->option2->value,
co->choice2->value ? co->choice2->value : "");
}
for (fi = (ppdcFilter *)d->filters->first();
fi;
fi = (ppdcFilter *)d->filters->next())
cupsFilePrintf(fp, " Filter \"%s %d %s\"\n",
fi->mime_type->value, fi->cost, fi->program->value);
for (fo = (ppdcFont *)d->fonts->first();
fo;
fo = (ppdcFont *)d->fonts->next())
if (!strcmp(fo->name->value, "*"))
cupsFilePuts(fp, " Font *\n");
else
cupsFilePrintf(fp, " Font \"%s\" \"%s\" \"%s\" \"%s\" %s\n",
fo->name->value, fo->encoding->value,
fo->version->value, fo->charset->value,
fo->status == PPDC_FONT_ROM ? "ROM" : "Disk");
for (g = (ppdcGroup *)d->groups->first();
g;
g = (ppdcGroup *)d->groups->next())
{
if (g->options->count == 0)
continue;
if (g->text->value && g->text->value[0])
quotef(fp, " Group \"%s/%s\"\n", g->name->value, g->text->value);
else
cupsFilePrintf(fp, " Group \"%s\"\n", g->name->value);
for (o = (ppdcOption *)g->options->first();
o;
o = (ppdcOption *)g->options->next())
{
if (o->choices->count == 0)
continue;
if (o->text->value && o->text->value[0])
quotef(fp, " Option \"%s/%s\"", o->name->value, o->text->value);
else
cupsFilePrintf(fp, " Option \"%s\"", o->name->value);
cupsFilePrintf(fp, " %s %s %.1f\n",
o->type == PPDC_BOOLEAN ? "Boolean" :
o->type == PPDC_PICKONE ? "PickOne" : "PickMany",
o->section == PPDC_SECTION_ANY ? "AnySetup" :
o->section == PPDC_SECTION_DOCUMENT ? "DocumentSetup" :
o->section == PPDC_SECTION_EXIT ? "ExitServer" :
o->section == PPDC_SECTION_JCL ? "JCLSetup" :
o->section == PPDC_SECTION_PAGE ? "PageSetup" :
"Prolog",
o->order);
for (ch = (ppdcChoice *)o->choices->first();
ch;
ch = (ppdcChoice *)o->choices->next())
{
if (ch->text->value && ch->text->value[0])
quotef(fp, " %sChoice \"%s/%s\" \"%s\"\n",
o->defchoice == ch->name ? "*" : "",
ch->name->value, ch->text->value,
ch->code->value ? ch->code->value : "");
else
quotef(fp, " %sChoice \"%s\" \"%s\"\n",
o->defchoice == ch->name ? "*" : "",
ch->name->value,
ch->code->value ? ch->code->value : "");
}
}
}
for (p = (ppdcProfile *)d->profiles->first();
p;
p = (ppdcProfile *)d->profiles->next())
cupsFilePrintf(fp, " ColorProfile \"%s/%s\" %.3f %.3f "
"%.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f %.3f\n",
p->resolution->value, p->media_type->value,
p->density, p->gamma,
p->profile[0], p->profile[1], p->profile[2],
p->profile[3], p->profile[4], p->profile[5],
p->profile[6], p->profile[7], p->profile[8]);
left = 0.0;
bottom = 0.0;
right = 0.0;
top = 0.0;
for (si = (ppdcMediaSize *)d->sizes->first();
si;
si = (ppdcMediaSize *)d->sizes->next())
if (si->size_code->value && si->region_code->value)
{
quotef(fp, " %sCustomMedia \"%s/%s\" %.2f %.2f %.2f %.2f %.2f %.2f \"%s\" \"%s\"\n",
si->name == d->default_size ? "*" : "", si->name->value,
si->text->value, si->width, si->length, si->left, si->bottom,
si->right, si->top, si->size_code->value,
si->region_code->value);
}
else
{
if (fabs(left - si->left) > 0.1 ||
fabs(bottom - si->bottom) > 0.1 ||
fabs(right - si->right) > 0.1 ||
fabs(top - si->top) > 0.1)
{
cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
si->left, si->bottom, si->right, si->top);
left = si->left;
bottom = si->bottom;
right = si->right;
top = si->top;
}
cupsFilePrintf(fp, " %sMediaSize %s\n",
si->name == d->default_size ? "*" : "",
si->name->value);
}
if (d->variable_paper_size)
{
cupsFilePuts(fp, " VariablePaperSize Yes\n");
if (fabs(left - d->left_margin) > 0.1 ||
fabs(bottom - d->bottom_margin) > 0.1 ||
fabs(right - d->right_margin) > 0.1 ||
fabs(top - d->top_margin) > 0.1)
{
cupsFilePrintf(fp, " HWMargins %.2f %.2f %.2f %.2f\n",
d->left_margin, d->bottom_margin, d->right_margin,
d->top_margin);
}
cupsFilePrintf(fp, " MinSize %.2f %.2f\n", d->min_width, d->min_length);
cupsFilePrintf(fp, " MaxSize %.2f %.2f\n", d->max_width, d->max_length);
}
cupsFilePuts(fp, "}\n");
}
cupsFileClose(fp);
return (0);
}