/* * Foomatic Perl Data * ------------------ * * Compute the Foomatic Perl data structures out of the * printer/driver combo XML file or overview XML file as generated * by foomatic-combo-xml.c. Compute also a Perl data structure from * printer and driver entries of the Fommatic database. * * The Foomatic Perl data structure for the printer/driver combos is * the basis for all spooler-specific config files and PPD files and * also the data structure used by the filter Perl scripts. * * The other Perl data structures are used by the Foomatic Perl library * to do the database operations provided by its API. * * This program is based on the libxml2 and this is a retianol way to * make a C data structure from a single XML file. This structure is then * converted to Perl * * Copyright 2001 by Till Kamppeter * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA * */ /* Compilable with (depending on installed packages): gcc `xml2-config --cflags` -lxml2 -o foomatic-perl-data \ foomatic-perl-data.c or gcc `xml-config --cflags` -lxml -o foomatic-perl-data \ foomatic-perl-data.c */ #include #include #include /* * This program should compile and run indifferently with libxml-1.8.8 + * and libxml2-2.1.0 + * Check the COMPAT comments below */ /* * COMPAT using "xml-config --cflags" to get the include path this will * work with both (on distros with both xml1 and xml2 "xml2-config". */ #include #include #define DEBUG(x) printf(x) /* * an xmlChar * is really an UTF8 encoded char string (0 terminated) */ /* * Records for the unprintable margins data */ typedef struct marginRecord { xmlChar *pagesize; xmlChar *unit; xmlChar *absolute; xmlChar *left; xmlChar *right; xmlChar *top; xmlChar *bottom; } marginRecord, *marginRecordPtr; typedef struct margins { int num_marginRecords; marginRecordPtr *marginRecords; } margins, *marginsPtr; /* For driver list in printer XML, for ready-made PPDs or user-contributed printer entry */ typedef struct printerDrvEntry { xmlChar *name; xmlChar const *comment; xmlChar *ppd; /* functionality exceptions */ xmlChar *excmaxresx; xmlChar *excmaxresy; xmlChar *exccolor; xmlChar *exctext; xmlChar *exclineart; xmlChar *excgraphics; xmlChar *excphoto; xmlChar *excload; xmlChar *excspeed; } printerDrvEntry, *printerDrvEntryPtr; /* * Records for the data of a printer/driver combo */ typedef struct choice { xmlChar const *value; xmlChar const *comment; xmlChar *idx; xmlChar *driverval; } choice, *choicePtr; typedef struct arg { xmlChar const *name; xmlChar const *name_false; xmlChar const *comment; xmlChar *idx; xmlChar *option_type; xmlChar *style; xmlChar *substyle; xmlChar *spot; xmlChar *order; xmlChar *section; xmlChar *grouppath; xmlChar *proto; xmlChar *required; xmlChar *min_value; xmlChar *max_value; xmlChar *max_length; xmlChar *allowed_chars; xmlChar *allowed_regexp; xmlChar const *default_value; /* Choices for enumerated options */ int num_choices; choicePtr *choices; } arg, *argPtr; typedef struct comboData { /* Printer */ xmlChar *id; xmlChar *make; xmlChar *model; xmlChar *pcmodel; xmlChar *ppdurl; /* Printer properties */ xmlChar *color; xmlChar *ascii; xmlChar *pjl; xmlChar *printerppdentry; marginsPtr printermargins; /* Printer auto-detection */ xmlChar *general_ieee; xmlChar *general_mfg; xmlChar *general_mdl; xmlChar *general_des; xmlChar *general_cmd; xmlChar *par_ieee; xmlChar *par_mfg; xmlChar *par_mdl; xmlChar *par_des; xmlChar *par_cmd; xmlChar *usb_ieee; xmlChar *usb_mfg; xmlChar *usb_mdl; xmlChar *usb_des; xmlChar *usb_cmd; xmlChar *snmp_ieee; xmlChar *snmp_mfg; xmlChar *snmp_mdl; xmlChar *snmp_des; xmlChar *snmp_cmd; xmlChar *recdriver; /* Driver list in printer XML file (for ready-made PPD links) */ int num_drivers; printerDrvEntryPtr *drivers; /* Driver */ xmlChar *driver; xmlChar *driver_group; xmlChar *pcdriver; xmlChar *driver_type; xmlChar const *driver_comment; xmlChar *url; xmlChar *driver_obsolete; xmlChar const *supplier; xmlChar *manufacturersupplied; xmlChar const *license; xmlChar *licensetext; xmlChar *origlicensetext; xmlChar *licenselink; xmlChar *origlicenselink; xmlChar *free; xmlChar *patents; int num_supportcontacts; xmlChar const **supportcontacts; xmlChar **supportcontacturls; xmlChar **supportcontactlevels; xmlChar const *shortdescription; xmlChar *locales; int num_packages; xmlChar **packageurls; xmlChar **packagescopes; xmlChar **packagefingerprints; xmlChar *drvmaxresx; xmlChar *drvmaxresy; xmlChar *drvcolor; xmlChar *text; xmlChar *lineart; xmlChar *graphics; xmlChar *photo; xmlChar *load; xmlChar *speed; xmlChar *excmaxresx; xmlChar *excmaxresy; xmlChar *exccolor; xmlChar *exctext; xmlChar *exclineart; xmlChar *excgraphics; xmlChar *excphoto; xmlChar *excload; xmlChar *excspeed; int num_requires; xmlChar **requires; xmlChar **requiresversion; xmlChar *cmd; xmlChar *cmd_pdf; xmlChar *nopjl; xmlChar *nopageaccounting; xmlChar *driverppdentry; xmlChar *comboppdentry; marginsPtr drivermargins; marginsPtr combomargins; /* Driver options */ int num_args; argPtr *args; xmlChar *maxspot; } comboData, *comboDataPtr; /* * Record for a Foomatic printer entry */ typedef struct printerLanguage { xmlChar *name; xmlChar *level; } printerLanguage, *printerLanguagePtr; typedef struct printerEntry { xmlChar *id; xmlChar *make; xmlChar *model; /* Printer properties */ xmlChar *printer_type; xmlChar *color; xmlChar *maxxres; xmlChar *maxyres; xmlChar const *refill; xmlChar *ascii; xmlChar *pjl; xmlChar *printerppdentry; marginsPtr printermargins; /* Printer auto-detection */ xmlChar *general_ieee; xmlChar *general_mfg; xmlChar *general_mdl; xmlChar *general_des; xmlChar *general_cmd; xmlChar *par_ieee; xmlChar *par_mfg; xmlChar *par_mdl; xmlChar *par_des; xmlChar *par_cmd; xmlChar *usb_ieee; xmlChar *usb_mfg; xmlChar *usb_mdl; xmlChar *usb_des; xmlChar *usb_cmd; xmlChar *snmp_ieee; xmlChar *snmp_mfg; xmlChar *snmp_mdl; xmlChar *snmp_des; xmlChar *snmp_cmd; /* Misc items */ xmlChar *functionality; xmlChar *driver; xmlChar *unverified; xmlChar *noxmlentry; xmlChar *url; xmlChar *contriburl; xmlChar *ppdurl; xmlChar const *comment; /* Page Description Languages */ int num_languages; printerLanguagePtr *languages; /* Drivers (for user-contributed printer entries and for ready-made PPD links) */ int num_drivers; printerDrvEntryPtr *drivers; } printerEntry, *printerEntryPtr; /* * Records for a Foomatic driver entry */ typedef struct drvPrnEntry { xmlChar *id; xmlChar const *comment; /* functionality exceptions */ xmlChar *excmaxresx; xmlChar *excmaxresy; xmlChar *exccolor; xmlChar *exctext; xmlChar *exclineart; xmlChar *excgraphics; xmlChar *excphoto; xmlChar *excload; xmlChar *excspeed; } drvPrnEntry, *drvPrnEntryPtr; typedef struct driverEntry { xmlChar *id; xmlChar *name; xmlChar *group; xmlChar *url; xmlChar *driver_obsolete; xmlChar const *supplier; xmlChar *manufacturersupplied; xmlChar const *license; xmlChar *licensetext; xmlChar *origlicensetext; xmlChar *licenselink; xmlChar *origlicenselink; xmlChar *free; xmlChar *patents; int num_supportcontacts; xmlChar const **supportcontacts; xmlChar **supportcontacturls; xmlChar **supportcontactlevels; xmlChar const *shortdescription; xmlChar *locales; int num_packages; xmlChar **packageurls; xmlChar **packagescopes; xmlChar **packagefingerprints; xmlChar *maxresx; xmlChar *maxresy; xmlChar *color; xmlChar *text; xmlChar *lineart; xmlChar *graphics; xmlChar *photo; xmlChar *load; xmlChar *speed; int num_requires; xmlChar **requires; xmlChar **requiresversion; xmlChar *driver_type; xmlChar *cmd; xmlChar *cmd_pdf; xmlChar *driverppdentry; marginsPtr drivermargins; xmlChar const *comment; int num_printers; drvPrnEntryPtr *printers; } driverEntry, *driverEntryPtr; /* * Records for the data of the overview */ typedef struct ppdFile { xmlChar *driver; xmlChar *filename; } ppdFile, *ppdFilePtr; typedef struct overviewPrinter { /* General info */ xmlChar *id; xmlChar *make; xmlChar *model; xmlChar *functionality; xmlChar *unverified; xmlChar *noxmlentry; /* Printer auto-detection */ xmlChar *general_ieee; xmlChar *general_mfg; xmlChar *general_mdl; xmlChar *general_des; xmlChar *general_cmd; xmlChar *par_ieee; xmlChar *par_mfg; xmlChar *par_mdl; xmlChar *par_des; xmlChar *par_cmd; xmlChar *usb_ieee; xmlChar *usb_mfg; xmlChar *usb_mdl; xmlChar *usb_des; xmlChar *usb_cmd; xmlChar *snmp_ieee; xmlChar *snmp_mfg; xmlChar *snmp_mdl; xmlChar *snmp_des; xmlChar *snmp_cmd; /* Drivers */ xmlChar *driver; int num_drivers; printerDrvEntryPtr *drivers; /* PPD files */ int num_ppdfiles; ppdFilePtr *ppdfiles; } overviewPrinter, *overviewPrinterPtr; typedef struct overview { int num_overviewDrivers; driverEntryPtr *overviewDrivers; int num_overviewPrinters; overviewPrinterPtr *overviewPrinters; } overview, *overviewPtr; /* * Function to quote "'" and "\" in a string */ static xmlChar* /* O - String with quoted "'" */ perlquote(xmlChar *str) { /* I - Original string */ xmlChar *dest, *s; int offset = 0; if (str == NULL) return NULL; dest = xmlStrdup(str); while ((s = (xmlChar *)xmlStrchr((const xmlChar *)(dest + offset), (xmlChar)'\'')) || (s = (xmlChar *)xmlStrchr((const xmlChar *)(dest + offset), (xmlChar)'\\'))) { offset = s - dest; dest = (xmlChar *)realloc((xmlChar *)dest, sizeof(xmlChar) * (xmlStrlen(dest) + 2)); s = dest + offset; memmove(s + 1, s, xmlStrlen(dest) + 1 - offset); *s = '\\'; offset += 2; } return(dest); } /* * Functions to read out localized text, choosing the translation into the * desired language. Reads also simple text without language tags, for * backward compatibility for the case that a not yet localized database * field gets localized. The second function is especially for license text. * It returns always the English (original) version in addition and allows * links to text files as alternative to the text itself, as often license text * has to be in its own file. */ xmlChar const sc_locale_C [] = "C", sc_locale_POSIX [] = "POSIX"; static void getLocalizedText(xmlDocPtr doc, /* I - The whole data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ xmlChar const **ret, /* O - Text which was selected by the language */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ cur1 = node->xmlChildrenNode; if (xmlStrcasecmp(cur1->name, sc_locale_C) && xmlStrcasecmp(cur1->name, sc_locale_POSIX)) { while (cur1 != NULL) { /* Exact match of locale ID */ if ((!xmlStrcasecmp(cur1->name, language))) { *ret = xmlStrdup (perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1))); if (debug) fprintf (stderr, " Localized text with full locale ID matched (%s):\n\n%s\n\n", language, *ret); return; } cur1 = cur1->next; } cur1 = node->xmlChildrenNode; while (cur1 != NULL) { /* Fall back to match only the two-character language code */ if ((!xmlStrncasecmp(cur1->name, language, 2))) { *ret = xmlStrdup (perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1))); if (debug) fprintf (stderr, " Localized text with only language ID matched (%s):\n\n%s\n\n", language, *ret); return; } cur1 = cur1->next; } cur1 = node->xmlChildrenNode; } while (cur1 != NULL) { /* Fall back to English */ if ((!xmlStrncasecmp(cur1->name, (const xmlChar *) "en", 2))) { *ret = xmlStrdup (perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1))); if (debug) fprintf(stderr, " English text:\n\n%s\n\n", *ret); return; } cur1 = cur1->next; } cur1 = node->xmlChildrenNode; /* Fall back to non-localized text (allows backward compatibility if deciding on localizing a database item later */ *ret = xmlStrdup(perlquote(xmlNodeListGetString(doc, cur1, 1))); if (debug) fprintf(stderr, " Non-localized text:\n\n%s\n\n", *ret); } static void getLocalizedLicenseText(xmlDocPtr doc, /* I - The whole data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ xmlChar **text, /* O - Text which was selected by the language */ xmlChar **origtext, /* O - Original text in English */ xmlChar **link, /* O - Link which was selected by the language */ xmlChar **origlink, /* O - Link to original text in English */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ int localizedtextfound = 0; cur1 = node->xmlChildrenNode; if (xmlStrcasecmp(cur1->name, sc_locale_C) && xmlStrcasecmp(cur1->name, sc_locale_POSIX)) { while (cur1 != NULL) { /* Exact match of locale ID */ if ((!xmlStrcasecmp(cur1->name, language))) { *link = xmlGetProp(cur1, (const xmlChar *) "url"); if (*link == NULL) { *text = xmlStrdup (perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1))); if (debug) fprintf (stderr, " Localized text with full locale ID matched (%s):\n\n%s\n\n", language, *text); } else { if (debug) fprintf (stderr, " Link to localized text with full locale ID matched (%s):\n\n%s\n\n", language, *link); } localizedtextfound = 1; break; } cur1 = cur1->next; } if (localizedtextfound == 0) { cur1 = node->xmlChildrenNode; while (cur1 != NULL) { /* Fall back to match only the two-character language code */ if ((!xmlStrncasecmp(cur1->name, language, 2))) { *link = xmlGetProp(cur1, (const xmlChar *) "url"); if (*link == NULL) { *text = xmlStrdup (perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1))); if (debug) fprintf (stderr, " Localized text with only language ID matched (%s):\n\n%s\n\n", language, *text); } else { if (debug) fprintf (stderr, " Link to localized text with only language ID matched (%s):\n\n%s\n\n", language, *link); } localizedtextfound = 1; break; } cur1 = cur1->next; } } } cur1 = node->xmlChildrenNode; while (cur1 != NULL) { /* Fall back to English and/or extract original, English text/link */ if ((!xmlStrncasecmp(cur1->name, (const xmlChar *) "en", 2))) { *origlink = xmlGetProp(cur1, (const xmlChar *) "url"); if (*origlink == NULL) { *origtext = xmlStrdup (perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1))); if (debug) fprintf(stderr, " Original English text:\n\n%s\n\n", *origtext); if (localizedtextfound == 0) { *text = *origtext; if (debug) fprintf(stderr, " No localization, using original English text\n"); } } else { if (debug) fprintf(stderr, " Link to original English text:\n\n%s\n\n", *origlink); if (localizedtextfound == 0) { *link = *origlink; if (debug) fprintf(stderr, " No localization, using original English link\n"); } } return; } cur1 = cur1->next; } cur1 = node->xmlChildrenNode; /* Fall back to non-localized text (allows backward compatibility if deciding on localizing a database item later */ *link = xmlGetProp(cur1, (const xmlChar *) "url"); if (*link == NULL) { *text = xmlStrdup(perlquote(xmlNodeListGetString(doc, cur1, 1))); *origtext = *text; if (debug) fprintf(stderr, " Non-localized text:\n\n%s\n\n", *text); } else { *origlink = *link; if (debug) fprintf(stderr, " Link to non-localized text:\n\n%s\n\n", *link); } } /* * Functions to fill in the unprintable margin data structure with the * data parsed from the XML input */ static void parseMarginEntry(xmlDocPtr doc, /* I - The whole combo data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ int entrytype, /* I - 0: General, 1: Page size exzception */ marginsPtr ret, /* O - C data structure of Foomatic overview */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ xmlChar *pagesize; marginRecordPtr marginRec; /* Allocate memory for the margin record */ ret->num_marginRecords ++; ret->marginRecords = (marginRecordPtr *)realloc ((marginRecordPtr *)(ret->marginRecords), sizeof(marginRecordPtr) * ret->num_marginRecords); marginRec = (marginRecordPtr) malloc(sizeof(marginRecord)); if (marginRec == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } ret->marginRecords[ret->num_marginRecords-1] = marginRec; memset(marginRec, 0, sizeof(marginRecord)); /* Initialization of entries */ marginRec->pagesize = NULL; marginRec->unit = NULL; marginRec->absolute = NULL; marginRec->left = NULL; marginRec->right = NULL; marginRec->top = NULL; marginRec->bottom = NULL; /* Get page size */ if (entrytype > 0) { pagesize = xmlGetProp(node, (const xmlChar *) "PageSize"); if (pagesize != NULL) { marginRec->pagesize = perlquote(pagesize); if (debug) fprintf(stderr, " Margins for page size %s\n", marginRec->pagesize); } else { fprintf(stderr,"Page size missing!\n"); xmlFreeDoc(doc); exit(1); } } else { if (debug) fprintf(stderr, " General Margins\n"); } /* Go through subnodes */ cur1 = node->xmlChildrenNode; while (cur1 != NULL) { if ((!xmlStrcmp(cur1->name, (const xmlChar *) "unit"))) { marginRec->unit = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Unit: %s\n", marginRec->unit); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "absolute"))) { marginRec->absolute = (xmlChar *)"1"; perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Absolute values\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "relative"))) { marginRec->absolute = (xmlChar *)"0"; perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Relative values\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "left"))) { marginRec->left = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Left margin: %s\n", marginRec->left); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "right"))) { marginRec->right = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Right margin: %s\n", marginRec->right); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "top"))) { marginRec->top = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Top margin: %s\n", marginRec->top); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "bottom"))) { marginRec->bottom = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Bottom margin: %s\n", marginRec->bottom); } cur1 = cur1->next; } } static void parseMargins(xmlDocPtr doc, /* I - The whole combo data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ marginsPtr *ret, /* O - C data structure of Foomatic overview */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ /* Allocate memory for the margins data structure */ *ret = (marginsPtr) malloc(sizeof(margins)); if (*ret == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } memset(*ret, 0, sizeof(margins)); /* Initialization of entries */ (*ret)->num_marginRecords = 0; (*ret)->marginRecords = NULL; if (debug) fprintf(stderr, " Unprintable margins\n"); /* Go through subnodes */ cur1 = node->xmlChildrenNode; while (cur1 != NULL) { if ((!xmlStrcmp(cur1->name, (const xmlChar *) "general"))) { parseMarginEntry(doc, cur1, 0, *ret, language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "exception"))) { parseMarginEntry(doc, cur1, 1, *ret, language, debug); } cur1 = cur1->next; } } /* * Function to fill in the Foomatic overview data structure with the * data parsed from the XML input */ static void parseOverviewPrinter(xmlDocPtr doc, /* I - The whole combo data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ overviewPtr ret, /* O - C data structure of Foomatic overview */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ xmlNodePtr cur2; /* Another XML node pointer */ xmlNodePtr cur3; /* Another XML node pointer */ xmlNodePtr cur4; /* Another XML node pointer */ xmlChar *id; /* Full printer ID, with "printer/" */ xmlChar *charset; xmlChar *drivername; overviewPrinterPtr printer; printerDrvEntryPtr dentry; /* An entry for a driver supporting this printer */ ppdFilePtr ppd; int driverfound; int i, j; /* Allocate memory for the printer */ ret->num_overviewPrinters ++; ret->overviewPrinters = (overviewPrinterPtr *)realloc ((overviewPrinterPtr *)(ret->overviewPrinters), sizeof(overviewPrinterPtr) * ret->num_overviewPrinters); printer = (overviewPrinterPtr) malloc(sizeof(overviewPrinter)); if (printer == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } ret->overviewPrinters[ret->num_overviewPrinters-1] = printer; memset(printer, 0, sizeof(overviewPrinter)); /* Initialization of entries */ printer->id = NULL; printer->make = NULL; printer->model = NULL; printer->functionality = (xmlChar *)"X"; printer->unverified = NULL; printer->noxmlentry = NULL; printer->general_ieee = NULL; printer->general_mfg = NULL; printer->general_mdl = NULL; printer->general_des = NULL; printer->general_cmd = NULL; printer->par_ieee = NULL; printer->par_mfg = NULL; printer->par_mdl = NULL; printer->par_des = NULL; printer->par_cmd = NULL; printer->usb_ieee = NULL; printer->usb_mfg = NULL; printer->usb_mdl = NULL; printer->usb_des = NULL; printer->usb_cmd = NULL; printer->snmp_ieee = NULL; printer->snmp_mfg = NULL; printer->snmp_mdl = NULL; printer->snmp_des = NULL; printer->snmp_cmd = NULL; printer->driver = NULL; printer->num_drivers = 0; printer->drivers = NULL; printer->num_ppdfiles = 0; printer->ppdfiles = NULL; /* Go through subnodes */ cur1 = node->xmlChildrenNode; while (cur1 != NULL) { if ((!xmlStrcmp(cur1->name, (const xmlChar *) "id"))) { printer->id = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer ID: %s\n", printer->id); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "make"))) { printer->make = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer Manufacturer: %s\n", printer->make); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "model"))) { printer->model = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer Model: %s\n", printer->model); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "functionality"))) { printer->functionality = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer Functionality: %s\n", printer->functionality); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "unverified"))) { printer->unverified = (xmlChar *)"1"; if (debug) fprintf(stderr, " Printer entry is unverified\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "noxmlentry"))) { printer->noxmlentry = (xmlChar *)"1"; if (debug) fprintf(stderr, " Printer XML entry does not exist in the database\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "driver"))) { printer->driver = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Recommended driver: %s\n", printer->driver); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "drivers"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "driver"))) { drivername = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); driverfound = 0; for (i = 0; i < printer->num_drivers; i++) { dentry = printer->drivers[i]; if ((dentry->name != NULL) && (!xmlStrcmp(drivername, dentry->name))) { driverfound = 1; break; } } if (!driverfound) { printer->num_drivers ++; printer->drivers = (printerDrvEntryPtr *) realloc((printerDrvEntryPtr *)printer->drivers, sizeof(printerDrvEntryPtr) * printer->num_drivers); dentry = (printerDrvEntryPtr) malloc(sizeof(printerDrvEntry)); if (dentry == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } printer->drivers[printer->num_drivers-1] = dentry; memset(dentry, 0, sizeof(printerDrvEntry)); dentry->name = NULL; dentry->comment = NULL; dentry->ppd = NULL; dentry->excmaxresx = NULL; dentry->excmaxresy = NULL; dentry->exccolor = NULL; dentry->exctext = NULL; dentry->exclineart = NULL; dentry->excgraphics = NULL; dentry->excphoto = NULL; dentry->excload = NULL; dentry->excspeed = NULL; } dentry->name = drivername; if (debug) fprintf(stderr, " Printer works with: %s\n", dentry->name); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "driverfunctionalityexceptions"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "driverfunctionalityexception"))) { drivername = NULL; dentry = NULL; cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "driver"))) { drivername = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Functionality exceptions for driver: %s\n", drivername); if ((dentry != NULL) && (dentry->name == NULL)) { dentry->name = drivername; /* Check whether there is already an entry for this driver and delete this old entry */ for (i = 0; i < printer->num_drivers - 1; i++) { if ((printer->drivers[i]->name != NULL) && (!xmlStrcmp(drivername, printer->drivers[i]->name))) { for (j = i + 1; j < printer->num_drivers; j++) printer->drivers[j - 1] = printer->drivers[j]; printer->num_drivers --; printer->drivers = (printerDrvEntryPtr *) realloc((printerDrvEntryPtr *)printer->drivers, sizeof(printerDrvEntryPtr) * printer->num_drivers); break; } } } } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "functionality"))) { driverfound = 0; dentry = NULL; if (drivername != NULL) { for (i = 0; i < printer->num_drivers; i++) { dentry = printer->drivers[i]; if ((dentry->name != NULL) && (!xmlStrcmp(drivername, dentry->name))) { driverfound = 1; break; } } } if (!driverfound) { printer->num_drivers ++; printer->drivers = (printerDrvEntryPtr *) realloc((printerDrvEntryPtr *)printer->drivers, sizeof(printerDrvEntryPtr) * printer->num_drivers); dentry = (printerDrvEntryPtr) malloc(sizeof(printerDrvEntry)); if (dentry == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } printer->drivers[printer->num_drivers-1] = dentry; memset(dentry, 0, sizeof(printerDrvEntry)); dentry->name = NULL; dentry->comment = NULL; dentry->ppd = NULL; dentry->excmaxresx = NULL; dentry->excmaxresy = NULL; dentry->exccolor = NULL; dentry->exctext = NULL; dentry->exclineart = NULL; dentry->excgraphics = NULL; dentry->excphoto = NULL; dentry->excload = NULL; dentry->excspeed = NULL; } dentry->name = drivername; if (drivername != NULL) { if (debug) fprintf(stderr, " Functionality exceptions for driver: %s\n", dentry->name); } cur4 = cur3->xmlChildrenNode; while (cur4 != NULL) { if ((!xmlStrcmp(cur4->name, (const xmlChar *) "maxresx"))) { dentry->excmaxresx = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Maximum X resolution: %s\n", dentry->excmaxresx); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "maxresy"))) { dentry->excmaxresy = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Maximum Y resolution: %s\n", dentry->excmaxresy); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "monochrome"))) { dentry->exccolor = (xmlChar *)"0"; if (debug) fprintf(stderr, " Color: %s\n", dentry->exccolor); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "color"))) { dentry->exccolor = (xmlChar *)"1"; if (debug) fprintf(stderr, " Color: %s\n", dentry->exccolor); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "text"))) { dentry->exctext = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Support level for text: %s\n", dentry->exctext); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "lineart"))) { dentry->exclineart = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Support level for line art: %s\n", dentry->exclineart); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "graphics"))) { dentry->excgraphics = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Support level for graphics: %s\n", dentry->excgraphics); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "photo"))) { dentry->excphoto = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Support level for photos: %s\n", dentry->excphoto); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "load"))) { dentry->excload = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Expected relative system load: %s\n", dentry->excload); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "speed"))) { dentry->excspeed = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Expected relative driver speed: %s\n", dentry->excspeed); } cur4 = cur4->next; } } cur3 = cur3->next; } } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "ppds"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ppd"))) { printer->num_ppdfiles ++; printer->ppdfiles = (ppdFilePtr *) realloc((ppdFilePtr *)printer->ppdfiles, sizeof(ppdFilePtr) * printer->num_ppdfiles); ppd = (ppdFilePtr) malloc(sizeof(ppdFile)); if (ppd == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } printer->ppdfiles[printer->num_ppdfiles-1] = ppd; memset(ppd, 0, sizeof(ppdFile)); ppd->driver = NULL; ppd->filename = NULL; if (debug) fprintf(stderr, " Available ready-made PPD file:\n"); cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "driver"))) { ppd->driver = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " For driver: %s\n", ppd->driver); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ppdfile"))) { ppd->filename = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " File name: %s\n", ppd->filename); } cur3 = cur3->next; } } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "autodetect"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "general"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (general):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { printer->general_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", printer->general_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { printer->general_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", printer->general_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { printer->general_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", printer->general_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { printer->general_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", printer->general_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { printer->general_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", printer->general_cmd); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "parallel"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (parallel port):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { printer->par_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", printer->par_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { printer->par_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", printer->par_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { printer->par_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", printer->par_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { printer->par_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", printer->par_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { printer->par_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", printer->par_cmd); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "usb"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (USB):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { printer->usb_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", printer->usb_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { printer->usb_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", printer->usb_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { printer->usb_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", printer->usb_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { printer->usb_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", printer->usb_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { printer->usb_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", printer->usb_cmd); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "snmp"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (SNMP):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { printer->snmp_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", printer->snmp_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { printer->snmp_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", printer->snmp_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { printer->snmp_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", printer->snmp_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { printer->snmp_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", printer->snmp_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { printer->snmp_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", printer->snmp_cmd); } cur3 = cur3->next; } } cur2 = cur2->next; } } cur1 = cur1->next; } } /* * Functions to fill in the printer/driver combo data structure with the * data parsed from the XML input */ static void parseComboPrinter(xmlDocPtr doc, /* I - The whole combo data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ comboDataPtr ret, /* O - C data structure of Foomatic combo */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ xmlNodePtr cur2; /* Another XML node pointer */ xmlNodePtr cur3; /* Another XML node pointer */ xmlNodePtr cur4; /* Another XML node pointer */ xmlChar *id; /* Full printer ID, with "printer/" */ xmlChar *charset; xmlChar *dname; /* Name of a driver supporting this printer */ xmlChar *dppd; /* Ready-made PPD supporting this printer */ printerDrvEntryPtr dentry; /* An entry for a driver supporting this printer */ /* Initialization of entries */ ret->id = NULL; ret->make = NULL; ret->model = NULL; ret->pcmodel = NULL; ret->ppdurl = NULL; ret->color = (xmlChar *)"0"; ret->pjl = (xmlChar *)"undef"; ret->ascii = (xmlChar *)"0"; ret->printerppdentry = NULL; ret->printermargins = NULL; ret->general_ieee = NULL; ret->general_mfg = NULL; ret->general_mdl = NULL; ret->general_des = NULL; ret->general_cmd = NULL; ret->par_ieee = NULL; ret->par_mfg = NULL; ret->par_mdl = NULL; ret->par_des = NULL; ret->par_cmd = NULL; ret->usb_ieee = NULL; ret->usb_mfg = NULL; ret->usb_mdl = NULL; ret->usb_des = NULL; ret->usb_cmd = NULL; ret->snmp_ieee = NULL; ret->snmp_mfg = NULL; ret->snmp_mdl = NULL; ret->snmp_des = NULL; ret->snmp_cmd = NULL; ret->recdriver = NULL; ret->num_drivers = 0; ret->drivers = NULL; /* Get printer ID */ id = xmlGetProp(node, (const xmlChar *) "id"); if (id == NULL) { fprintf(stderr, "No printer ID found\n"); return; } ret->id = perlquote(id + 8); if (debug) fprintf(stderr, " Printer ID: %s\n", ret->id); /* Go through subnodes */ cur1 = node->xmlChildrenNode; while (cur1 != NULL) { if ((!xmlStrcmp(cur1->name, (const xmlChar *) "make"))) { ret->make = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer Manufacturer: %s\n", ret->make); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "model"))) { ret->model = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer Model: %s\n", ret->model); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "driver"))) { ret->recdriver = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Recommended driver: %s\n", ret->recdriver); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "drivers"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "driver"))) { ret->num_drivers ++; ret->drivers = (printerDrvEntryPtr *) realloc((printerDrvEntryPtr *)ret->drivers, sizeof(printerDrvEntryPtr) * ret->num_drivers); dentry = (printerDrvEntryPtr) malloc(sizeof(printerDrvEntry)); if (dentry == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } ret->drivers[ret->num_drivers-1] = dentry; memset(dentry, 0, sizeof(printerDrvEntry)); dentry->name = NULL; dentry->comment = NULL; dentry->ppd = NULL; dentry->excmaxresx = NULL; dentry->excmaxresy = NULL; dentry->exccolor = NULL; dentry->exctext = NULL; dentry->exclineart = NULL; dentry->excgraphics = NULL; dentry->excphoto = NULL; dentry->excload = NULL; dentry->excspeed = NULL; if (debug) fprintf(stderr, " Printer supported by drivers:\n"); cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "id"))) { dname = xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); dentry->name = perlquote(dname); if (debug) fprintf(stderr, " Name: %s\n", dentry->name); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ppd"))) { dppd = xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); dentry->ppd = perlquote(dppd); if (debug) fprintf(stderr, " Ready-made PPD: %s\n", dentry->ppd); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "functionality"))) { cur4 = cur3->xmlChildrenNode; while (cur4 != NULL) { if ((!xmlStrcmp(cur4->name, (const xmlChar *) "maxresx"))) { dentry->excmaxresx = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Maximum X resolution: %s\n", dentry->excmaxresx); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "maxresy"))) { dentry->excmaxresy = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Maximum Y resolution: %s\n", dentry->excmaxresy); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "monochrome"))) { dentry->exccolor = (xmlChar *)"0"; if (debug) fprintf(stderr, " Color: %s\n", dentry->exccolor); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "color"))) { dentry->exccolor = (xmlChar *)"1"; if (debug) fprintf(stderr, " Color: %s\n", dentry->exccolor); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "text"))) { dentry->exctext = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Support level for text: %s\n", dentry->exctext); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "lineart"))) { dentry->exclineart = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Support level for line art: %s\n", dentry->exclineart); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "graphics"))) { dentry->excgraphics = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Support level for graphics: %s\n", dentry->excgraphics); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "photo"))) { dentry->excphoto = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Support level for photos: %s\n", dentry->excphoto); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "load"))) { dentry->excload = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Expected relative system load: %s\n", dentry->excload); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "speed"))) { dentry->excspeed = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Expected relative driver speed: %s\n", dentry->excspeed); } cur4 = cur4->next; } } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "comments"))) { if (debug) fprintf(stderr, " Comments:\n"); getLocalizedText(doc, cur3, &(dentry->comment), language, debug); } cur3 = cur3->next; } } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "ppdentry"))) { ret->printerppdentry = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Extra lines for PPD file:\n%s\n", ret->printerppdentry); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "pcmodel"))) { ret->pcmodel = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Model part for PC filename in PPD: %s\n", ret->pcmodel); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "lang"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "postscript"))) { cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ppd"))) { ret->ppdurl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " URL for the PPD for this printer: %s\n", ret->ppdurl); } cur3 = cur3->next; } } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "mechanism"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "color"))) { ret->color = (xmlChar *)"1"; if (debug) fprintf(stderr, " Color printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "margins"))) { parseMargins(doc, cur2, &(ret->printermargins), language, debug); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "lang"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "pjl"))) { ret->pjl = (xmlChar *)"''"; if (debug) fprintf(stderr, " Printer supports PJL\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "text"))) { cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "charset"))) { charset = xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); if ((!xmlStrcmp(charset, (const xmlChar *) "us-ascii")) || (!xmlStrcmp(charset, (const xmlChar *) "iso-8859-1")) || (!xmlStrcmp(charset, (const xmlChar *) "iso-8859-15"))) { ret->ascii = (xmlChar *)"1"; if (debug) fprintf(stderr, " Printer prints plain text\n"); } } cur3 = cur3->next; } } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "autodetect"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "general"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (general):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { ret->general_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", ret->general_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { ret->general_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", ret->general_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { ret->general_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", ret->general_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { ret->general_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", ret->general_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { ret->general_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", ret->general_cmd); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "parallel"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (parallel port):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { ret->par_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", ret->par_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { ret->par_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", ret->par_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { ret->par_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", ret->par_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { ret->par_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", ret->par_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { ret->par_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", ret->par_cmd); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "usb"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (USB):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { ret->usb_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", ret->usb_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { ret->usb_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", ret->usb_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { ret->usb_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", ret->usb_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { ret->usb_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", ret->usb_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { ret->usb_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", ret->usb_cmd); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "snmp"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (SNMP):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { ret->snmp_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", ret->snmp_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { ret->snmp_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", ret->snmp_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { ret->snmp_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", ret->snmp_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { ret->snmp_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", ret->snmp_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { ret->snmp_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", ret->snmp_cmd); } cur3 = cur3->next; } } cur2 = cur2->next; } } cur1 = cur1->next; } } static void parseComboDriver(xmlDocPtr doc, /* I - The whole combo data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ comboDataPtr ret, /* O - C data structure of Foomatic combo */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ xmlNodePtr cur2; /* Another XML node pointer */ xmlNodePtr cur3; /* Another XML node pointer */ xmlNodePtr cur4; /* Another XML node pointer */ xmlChar *id; /* Full driver ID, with "driver/" */ xmlChar *level, *version, *scope, *fingerprint; xmlChar *url; /* Initialization of entries */ ret->driver = NULL; ret->driver_group = NULL; ret->driver_type = NULL; ret->driver_comment = NULL; ret->url = NULL; ret->supplier = NULL; ret->driver_obsolete = NULL; ret->manufacturersupplied = NULL; ret->license = NULL; ret->licensetext = NULL; ret->origlicensetext = NULL; ret->licenselink = NULL; ret->origlicenselink = NULL; ret->free = NULL; ret->patents = NULL; ret->num_supportcontacts = 0; ret->supportcontacts = NULL; ret->supportcontacturls = NULL; ret->supportcontactlevels = NULL; ret->shortdescription = NULL; ret->locales = NULL; ret->num_packages = 0; ret->packageurls = NULL; ret->packagescopes = NULL; ret->packagefingerprints = NULL; ret->drvmaxresx = NULL; ret->drvmaxresy = NULL; ret->drvcolor = NULL; ret->text = NULL; ret->lineart = NULL; ret->graphics = NULL; ret->photo = NULL; ret->load = NULL; ret->speed = NULL; ret->excmaxresx = NULL; ret->excmaxresy = NULL; ret->exccolor = NULL; ret->exctext = NULL; ret->exclineart = NULL; ret->excgraphics = NULL; ret->excphoto = NULL; ret->excload = NULL; ret->excspeed = NULL; ret->num_requires = 0; ret->requires = NULL; ret->requiresversion = NULL; ret->cmd = NULL; ret->cmd_pdf = NULL; ret->nopjl = (xmlChar *)"0"; ret->nopageaccounting = (xmlChar *)"0"; ret->driverppdentry = NULL; ret->comboppdentry = NULL; ret->drivermargins = NULL; ret->combomargins = NULL; /* Get driver ID */ id = xmlGetProp(node, (const xmlChar *) "id"); if (id == NULL) { fprintf(stderr, "No driver ID found\n"); return; } ret->driver = perlquote(id + 7); if (debug) fprintf(stderr, " Driver ID: %s\n", ret->driver); /* Go through subnodes */ cur1 = node->xmlChildrenNode; while (cur1 != NULL) { if ((!xmlStrcmp(cur1->name, (const xmlChar *) "driver"))) { ret->driver = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver name: %s\n", ret->driver); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "group"))) { ret->driver_group = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver group (for localization): %s\n", ret->driver_group); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "pcdriver"))) { ret->pcdriver = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver part of PC file name in PPD: %s\n", ret->pcdriver); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "url"))) { ret->url = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver URL: %s\n", ret->url); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "obsolete"))) { ret->driver_obsolete = xmlGetProp(cur1, (const xmlChar *) "replace"); if (ret->driver_obsolete == NULL) { if (debug) fprintf(stderr, " No replacement driver found!\n"); ret->driver_obsolete = (xmlChar *)"1"; } if (debug) fprintf(stderr, " Driver is obsolete: %s\n", ret->driver_obsolete); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "supplier"))) { if (debug) fprintf(stderr, " Driver supplier:\n"); getLocalizedText(doc, cur1, &(ret->supplier), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "manufacturersupplied"))) { ret->manufacturersupplied = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if ((ret->manufacturersupplied == NULL) || (ret->manufacturersupplied[0] == '\0')) ret->manufacturersupplied = (xmlChar *)"1"; if (debug) fprintf(stderr, " Driver supplied by manufacturer: %s\n", ret->manufacturersupplied); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "thirdpartysupplied"))) { ret->manufacturersupplied = (xmlChar *)"0"; if (debug) fprintf(stderr, " Driver supplied by a third party\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "license"))) { if (debug) fprintf(stderr, " Driver license:\n"); getLocalizedText(doc, cur1, &(ret->license), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "licensetext"))) { if (debug) fprintf(stderr, " Driver license text:\n"); getLocalizedLicenseText(doc, cur1, &(ret->licensetext), &(ret->origlicensetext), &(ret->licenselink), &(ret->origlicenselink), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "freesoftware"))) { ret->free = (xmlChar *)"1"; if (debug) fprintf(stderr, " Driver is free software\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "nonfreesoftware"))) { ret->free = (xmlChar *)"0"; if (debug) fprintf(stderr, " Driver is not free software\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "patents"))) { ret->patents = (xmlChar *)"1"; if (debug) fprintf(stderr, " There are patents applying to this driver's code\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "nopatents"))) { ret->patents = (xmlChar *)"0"; if (debug) fprintf(stderr, " There are no patents applying to this driver's code\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "supportcontacts"))) { cur2 = cur1->xmlChildrenNode; if (debug) fprintf(stderr, " Driver support contacts:\n"); while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "supportcontact"))) { ret->num_supportcontacts ++; ret->supportcontacts = (xmlChar const **) realloc((xmlChar **)ret->supportcontacts, sizeof(xmlChar *) * ret->num_supportcontacts); ret->supportcontacturls = (xmlChar **) realloc((xmlChar **)ret->supportcontacturls, sizeof(xmlChar *) * ret->num_supportcontacts); ret->supportcontactlevels = (xmlChar **) realloc((xmlChar **)ret->supportcontactlevels, sizeof(xmlChar *) * ret->num_supportcontacts); level = xmlGetProp(cur2, (const xmlChar *) "level"); if (level == NULL) { level = (xmlChar *)"Unknown"; } url = xmlGetProp(cur2, (const xmlChar *) "url"); ret->supportcontactlevels[ret->num_supportcontacts - 1] = level; ret->supportcontacturls[ret->num_supportcontacts - 1] = url; getLocalizedText (doc, cur2, &(ret->supportcontacts[ret->num_supportcontacts - 1]), language, debug); if (debug) fprintf(stderr, " %s (%s):\n %s\n", ret->supportcontacts[ret->num_supportcontacts - 1], ret->supportcontactlevels[ret->num_supportcontacts - 1], ret->supportcontacturls[ret->num_supportcontacts - 1]); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "shortdescription"))) { if (debug) fprintf(stderr, " Driver short description:\n"); getLocalizedText(doc, cur1, &(ret->shortdescription), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "locales"))) { ret->locales = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver list of locales: %s\n", ret->locales); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "packages"))) { cur2 = cur1->xmlChildrenNode; if (debug) fprintf(stderr, " Driver downloadable packages:\n"); while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "package"))) { ret->num_packages ++; ret->packageurls = (xmlChar **) realloc((xmlChar **)ret->packageurls, sizeof(xmlChar *) * ret->num_packages); ret->packagescopes = (xmlChar **) realloc((xmlChar **)ret->packagescopes, sizeof(xmlChar *) * ret->num_packages); scope = xmlGetProp(cur2, (const xmlChar *) "scope"); ret->packagefingerprints = (xmlChar **) realloc((xmlChar **)ret->packagefingerprints, sizeof(xmlChar *) * ret->num_packages); fingerprint = xmlGetProp(cur2, (const xmlChar *) "fingerprint"); ret->packageurls[ret->num_packages - 1] = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); ret->packagescopes[ret->num_packages - 1] = perlquote(scope); ret->packagefingerprints[ret->num_packages - 1] = perlquote(fingerprint); if (debug) fprintf(stderr, " %s (%s), key fingerprint on %s\n", ret->packageurls[ret->num_packages - 1], ret->packagescopes[ret->num_packages - 1], ret->packagefingerprints[ret->num_packages - 1]); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "functionality"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "maxresx"))) { ret->drvmaxresx = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Max X resolution: %s\n", ret->drvmaxresx); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "maxresy"))) { ret->drvmaxresy = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Max Y resolution: %s\n", ret->drvmaxresy); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "color"))) { ret->drvcolor = (xmlChar *)"1"; if (debug) fprintf(stderr, " Driver functionality: Color\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "monochrome"))) { ret->drvcolor = (xmlChar *)"0"; if (debug) fprintf(stderr, " Driver functionality: Monochrome\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "text"))) { ret->text = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Text support rating: %s\n", ret->text); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "lineart"))) { ret->lineart = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Line art support rating: %s\n", ret->lineart); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "graphics"))) { ret->graphics = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Graphics support rating: %s\n", ret->graphics); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "photo"))) { ret->photo = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Photo support rating: %s\n", ret->photo); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "load"))) { ret->load = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: System load rating: %s\n", ret->load); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "speed"))) { ret->speed = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Speed rating: %s\n", ret->speed); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "execution"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "requires"))) { ret->num_requires ++; ret->requires = (xmlChar **) realloc((xmlChar **)ret->requires, sizeof(xmlChar *) * ret->num_requires); ret->requiresversion = (xmlChar **) realloc((xmlChar **)ret->requiresversion, sizeof(xmlChar *) * ret->num_requires); version = xmlGetProp(cur2, (const xmlChar *) "version"); ret->requires[ret->num_requires - 1] = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); ret->requiresversion[ret->num_requires - 1] = perlquote(version); if (debug) /* an explicit brace for GCC thought police */ { if (!version) fprintf(stderr, " Driver requires driver: %s\n", ret->requires[ret->num_requires - 1]); else fprintf(stderr, " Driver requires driver: %s (%s)\n", ret->requires[ret->num_requires - 1], ret->requiresversion[ret->num_requires - 1]); } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "cups"))) { ret->driver_type = (xmlChar *)"C"; if (debug) fprintf(stderr, " Driver type: CUPS Raster\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ijs"))) { ret->driver_type = (xmlChar *)"I"; if (debug) fprintf(stderr, " Driver type: IJS\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "opvp"))) { ret->driver_type = (xmlChar *)"V"; if (debug) fprintf(stderr, " Driver type: OpenPrinting Vector\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ghostscript"))) { ret->driver_type = (xmlChar *)"G"; if (debug) fprintf(stderr, " Driver type: Ghostscript built-in\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "filter"))) { ret->driver_type = (xmlChar *)"F"; if (debug) fprintf(stderr, " Driver type: Filter\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "uniprint"))) { ret->driver_type = (xmlChar *)"U"; if (debug) fprintf(stderr, " Driver type: Ghostscript Uniprint\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "postscript"))) { ret->driver_type = (xmlChar *)"P"; if (debug) fprintf(stderr, " Driver type: PostScript\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "nopjl"))) { ret->nopjl = (xmlChar *)"1"; if (debug) fprintf(stderr, " Driver suppresses PJL options\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "nopageaccounting"))) { ret->nopageaccounting = (xmlChar *)"1"; if (debug) fprintf(stderr, " Driver suppresses CUPS page accounting\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "prototype"))) { ret->cmd = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver command line:\n\n %s\n\n", ret->cmd); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "prototype_pdf"))) { ret->cmd_pdf = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver PDF command line:\n\n %s\n\n", ret->cmd_pdf); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ppdentry"))) { ret->driverppdentry = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Extra lines for PPD file:\n%s\n", ret->driverppdentry); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "margins"))) { parseMargins(doc, cur2, &(ret->drivermargins), language, debug); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "comments"))) { if (debug) fprintf(stderr, " Driver Comment:\n"); getLocalizedText(doc, cur1, &(ret->driver_comment), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "printers"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "printer"))) { cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ppdentry"))) { ret->comboppdentry = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Extra lines for PPD file:\n%s\n", ret->comboppdentry); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "margins"))) { parseMargins(doc, cur3, &(ret->combomargins), language, debug); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "functionality"))) { cur4 = cur3->xmlChildrenNode; while (cur4 != NULL) { if ((!xmlStrcmp(cur4->name, (const xmlChar *) "maxresx"))) { ret->excmaxresx = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Combo exception: Maximum X resolution: %s\n", ret->excmaxresx); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "maxresy"))) { ret->excmaxresy = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Combo exception: Maximum Y resolution: %s\n", ret->excmaxresy); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "monochrome"))) { ret->exccolor = (xmlChar *)"0"; if (debug) fprintf(stderr, " Combo exception: Color: %s\n", ret->exccolor); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "color"))) { ret->exccolor = (xmlChar *)"1"; if (debug) fprintf(stderr, " Combo exception: Color: %s\n", ret->exccolor); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "text"))) { ret->exctext = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Combo exception: Support level for text: %s\n", ret->exctext); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "lineart"))) { ret->exclineart = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Combo exception: Support level for line art: %s\n", ret->exclineart); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "graphics"))) { ret->excgraphics = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Combo exception: Support level for graphics: %s\n", ret->excgraphics); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "photo"))) { ret->excphoto = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Combo exception: Support level for photos: %s\n", ret->excphoto); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "load"))) { ret->excload = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Combo exception: Expected relative system load: %s\n", ret->excload); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "speed"))) { ret->excspeed = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Combo exception: Expected relative driver speed: %s\n", ret->excspeed); } cur4 = cur4->next; } } cur3 = cur3->next; } } cur2 = cur2->next; } } cur1 = cur1->next; } } static void parseChoices(xmlDocPtr doc, /* I - The whole combo data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ argPtr option, /* O - C data structure of Foomatic option */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ xmlNodePtr cur2; /* Another XML node pointer */ xmlNodePtr cur3; /* Another XML node pointer */ xmlChar *id; /* Full choice ID, with "ev/" */ choicePtr enum_val; /* Data structure for the choice currently parsed */ /* Initialization of entries */ option->num_choices = 0; option->choices = NULL; /* Go through the choice nodes */ cur1 = node->xmlChildrenNode; while (cur1 != NULL) { if ((!xmlStrcmp(cur1->name, (const xmlChar *) "enum_val"))) { /* Allocate memory for the option */ option->num_choices ++; option->choices = (choicePtr *)realloc((choicePtr *)(option->choices), sizeof(choicePtr) * option->num_choices); enum_val = (choicePtr) malloc(sizeof(arg)); if (enum_val == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } option->choices[option->num_choices-1] = enum_val; memset(enum_val, 0, sizeof(choice)); /* Initialization of entries */ enum_val->value = NULL; enum_val->comment = NULL; enum_val->idx = NULL; enum_val->driverval = NULL; /* Get option ID */ id = xmlGetProp(cur1, (const xmlChar *) "id"); if (id == NULL) { fprintf(stderr, "No choice ID found\n"); return; } enum_val->idx = perlquote(id); if (debug) fprintf(stderr, " Choice ID: %s\n", enum_val->idx); /* Go through subnodes */ cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ev_shortname"))) { if (debug) fprintf(stderr, " Choice short name (do not translate):\n"); getLocalizedText (doc, cur2, &(enum_val->value), sc_locale_C, debug); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ev_longname"))) { if (debug) fprintf(stderr, " Choice long name:\n"); getLocalizedText(doc, cur2, &(enum_val->comment), language, debug); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ev_driverval"))) { enum_val->driverval = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " String to insert at %%s: %s\n", enum_val->driverval); } cur2 = cur2->next; } } cur1 = cur1->next; } } static void parseOptions(xmlDocPtr doc, /* I - The whole combo data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ comboDataPtr ret, /* O - C data structure of Foomatic combo */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ xmlNodePtr cur2; /* Another XML node pointer */ xmlNodePtr cur3; /* Another XML node pointer */ xmlChar *id, /* Full option ID, with "opt/" */ *option_type; /* Option type */ argPtr option;/* Data structure for the option currently parsed */ /* Initialization of entries */ ret->num_args = 0; ret->args = NULL; ret->maxspot = (xmlChar *)"A"; /* Go through the option nodes */ cur1 = node->xmlChildrenNode; while (cur1 != NULL) { if ((!xmlStrcmp(cur1->name, (const xmlChar *) "option"))) { /* Allocate memory for the option */ ret->num_args ++; ret->args = (argPtr *)realloc((argPtr *)(ret->args), sizeof(argPtr) * ret->num_args); option = (argPtr) malloc(sizeof(arg)); if (option == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } ret->args[ret->num_args-1] = option; memset(option, 0, sizeof(arg)); /* Initialization of entries */ option->name = NULL; option->name_false = NULL; option->comment = NULL; option->idx = NULL; option->option_type = NULL; option->style = NULL; option->substyle= NULL; option->spot = NULL; option->order = NULL; option->section = NULL; option->grouppath = NULL; option->proto = NULL; option->required = NULL; option->min_value = NULL; option->max_value = NULL; option->max_length = NULL; option->allowed_chars = NULL; option->allowed_regexp = NULL; option->default_value = NULL; option->num_choices = 0; option->choices = NULL; /* Get option ID */ id = xmlGetProp(cur1, (const xmlChar *) "id"); if (id == NULL) { fprintf(stderr, "No option ID found\n"); return; } option->idx = perlquote(id); if (debug) fprintf(stderr, " Option ID: %s\n", option->idx); /* Get option type */ option_type = xmlGetProp(cur1, (const xmlChar *) "type"); if (option_type == NULL) { fprintf(stderr, "No option type found\n"); return; } option->option_type = perlquote(option_type); if (debug) fprintf(stderr, " Option type: %s\n", option->option_type); /* Go through subnodes */ cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_shortname"))) { if (debug) fprintf(stderr, " Option short name (do not translate):\n"); getLocalizedText(doc, cur2, &(option->name), sc_locale_C, debug); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_shortname_false"))) { if (debug) fprintf(stderr, " Option short name if false (do not translate):\n"); getLocalizedText(doc, cur2, &(option->name_false), sc_locale_C, debug); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_longname"))) { if (debug) fprintf(stderr, " Option long name:\n"); getLocalizedText(doc, cur2, &(option->comment), language, debug); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_execution"))) { cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_substitution"))) { option->style = (xmlChar *)"C"; option->substyle = NULL; if (debug) fprintf(stderr, " Option style: Command line Substitution\n"); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_postscript"))) { option->style = (xmlChar *)"G"; option->substyle = NULL; if (debug) fprintf(stderr, " Option style: PostScript code\n"); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_pjl"))) { option->style = (xmlChar *)"J"; option->substyle = NULL; if (debug) fprintf(stderr, " Option style: PJL command\n"); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_composite"))) { option->style = (xmlChar *)"X"; option->substyle = NULL; if (debug) fprintf(stderr, " Option style: Composite option\n"); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_forced_composite"))) { option->style = (xmlChar *)"X"; option->substyle = (xmlChar *)"F"; if (debug) fprintf(stderr, " Option style: Forced composite option\n"); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_spot"))) { option->spot = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Command line insertion spot: %%%s\n", option->spot); if ((xmlStrcmp(option->spot, ret->maxspot) > 0)) { ret->maxspot = option->spot; } } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_order"))) { option->order = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Command line insertion order: %s\n", option->order); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_section"))) { option->section = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Section in PostScript file: %s\n", option->section); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_group"))) { option->grouppath = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Option Group: %s\n", option->grouppath); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_proto"))) { option->proto = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Code to insert: %s\n", option->proto); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "arg_required"))) { option->required = (xmlChar *)"1"; if (debug) fprintf(stderr, " This option is required\n"); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_min"))) { option->min_value = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Minimum value: %s\n", option->min_value); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_max"))) { option->max_value = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Maximum value: %s\n", option->max_value); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_maxlength"))) { option->max_length = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Maximum string length: %s\n", option->max_length); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_allowedchars"))) { option->allowed_chars = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Allowed characters in string: %s\n", option->allowed_chars); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_allowedregexp"))) { option->allowed_regexp = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " String must match Perl regexp: %s\n", option->allowed_regexp); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "arg_defval"))) { option->default_value = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Default: %s\n", option->default_value); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "enum_vals"))) { if (debug) fprintf(stderr, " --> Parsing choice data\n"); parseChoices(doc, cur2, option, language, debug); } cur2 = cur2->next; } } cur1 = cur1->next; } if (debug) fprintf(stderr, " Last command line insertion spot: %%%s\n", ret->maxspot); } /* * Functions to fill in the printer and driver data structures with the * data parsed from the XML input */ static void parsePrinterEntry(xmlDocPtr doc, /* I - The whole printer data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ printerEntryPtr ret, /* O - C data structure of Foomatic printer entry */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ xmlNodePtr cur2; /* Another XML node pointer */ xmlNodePtr cur3; /* Another XML node pointer */ xmlNodePtr cur4; /* Another XML node pointer */ xmlChar *id; /* Full printer ID, with "printer/" */ xmlChar *dname; /* Name of a driver supporting this printer */ xmlChar *dppd; /* Ready-made PPD supporting this printer */ printerLanguagePtr lentry; /* An entry for a language used by this printer */ printerDrvEntryPtr dentry; /* An entry for a driver supporting this printer */ /* Initialization of entries */ ret->id = NULL; ret->make = NULL; ret->model = NULL; ret->printer_type = NULL; ret->color = (xmlChar *)"0"; ret->maxxres = NULL; ret->maxyres = NULL; ret->printerppdentry = NULL; ret->printermargins = NULL; ret->refill = NULL; ret->ascii = NULL; ret->pjl = (xmlChar *)"0"; ret->general_ieee = NULL; ret->general_mfg = NULL; ret->general_mdl = NULL; ret->general_des = NULL; ret->general_cmd = NULL; ret->par_ieee = NULL; ret->par_mfg = NULL; ret->par_mdl = NULL; ret->par_des = NULL; ret->par_cmd = NULL; ret->usb_ieee = NULL; ret->usb_mfg = NULL; ret->usb_mdl = NULL; ret->usb_des = NULL; ret->usb_cmd = NULL; ret->snmp_ieee = NULL; ret->snmp_mfg = NULL; ret->snmp_mdl = NULL; ret->snmp_des = NULL; ret->snmp_cmd = NULL; ret->functionality = (xmlChar *)"X"; ret->driver = NULL; ret->unverified = (xmlChar *)"0"; ret->noxmlentry = (xmlChar *)"0"; ret->url = NULL; ret->contriburl = NULL; ret->comment = NULL; ret->ppdurl = NULL; ret->num_languages = 0; ret->languages = NULL; ret->num_drivers = 0; ret->drivers = NULL; /* Get printer ID */ id = xmlGetProp(node, (const xmlChar *) "id"); if (id == NULL) { fprintf(stderr, "No printer ID found\n"); return; } ret->id = perlquote(id + 8); if (debug) fprintf(stderr, " Printer ID: %s\n", ret->id); /* Go through subnodes */ cur1 = node->xmlChildrenNode; while (cur1 != NULL) { if ((!xmlStrcmp(cur1->name, (const xmlChar *) "make"))) { ret->make = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer Manufacturer: %s\n", ret->make); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "model"))) { ret->model = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer Model: %s\n", ret->model); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "mechanism"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "inkjet"))) { ret->printer_type = (xmlChar *)"inkjet"; if (debug) fprintf(stderr, " Inkjet printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "laser"))) { ret->printer_type = (xmlChar *)"laser"; if (debug) fprintf(stderr, " Laser printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "impact"))) { ret->printer_type = (xmlChar *)"impact"; if (debug) fprintf(stderr, " Impact printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "dotmatrix"))) { ret->printer_type = (xmlChar *)"dotmatrix"; if (debug) fprintf(stderr, " Dot matrix printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "led"))) { ret->printer_type = (xmlChar *)"led"; if (debug) fprintf(stderr, " LED printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "sublimation"))) { ret->printer_type = (xmlChar *)"sublimation"; if (debug) fprintf(stderr, " Dye sublimation printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "transfer"))) { ret->printer_type = (xmlChar *)"transfer"; if (debug) fprintf(stderr, " Thermal transfer printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "color"))) { ret->color = (xmlChar *)"1"; if (debug) fprintf(stderr, " Color printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "monochrome"))) { ret->color = (xmlChar *)"0"; if (debug) fprintf(stderr, " Monochrome printer\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "resolution"))) { cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "dpi"))) { cur4 = cur3->xmlChildrenNode; while (cur4 != NULL) { if ((!xmlStrcmp(cur4->name, (const xmlChar *) "x"))) { ret->maxxres = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Maximum X resolution: %s\n", ret->maxxres); } else if ((!xmlStrcmp(cur4->name,(const xmlChar *) "y"))) { ret->maxyres = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Maximum Y resolution: %s\n", ret->maxyres); } cur4 = cur4->next; } } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "margins"))) { parseMargins(doc, cur2, &(ret->printermargins), language, debug); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "consumables"))) { cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "comments"))) { if (debug) fprintf(stderr, " Consumables:\n"); getLocalizedText(doc, cur3, &(ret->refill), language, debug); } cur3 = cur3->next; } } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "lang"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "pjl"))) { ret->pjl = (xmlChar *)"1"; if (debug) fprintf(stderr, " Printer supports PJL\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "text"))) { cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "charset"))) { ret->ascii = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer prints plain text: %s\n", ret->ascii); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "postscript"))) { cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ppd"))) { ret->ppdurl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " URL for the PPD for this printer: %s\n", ret->ppdurl); } cur3 = cur3->next; } } if ((xmlStrcmp(cur2->name, (const xmlChar *) "pjl")) && (xmlStrcmp(cur2->name, (const xmlChar *) "text")) && (xmlStrcmp(cur2->name, (const xmlChar *) "comment"))) { ret->num_languages ++; ret->languages = (printerLanguagePtr *) realloc((printerLanguagePtr *)ret->languages, sizeof(printerLanguagePtr) * ret->num_languages); lentry = (printerLanguagePtr) malloc(sizeof(printerLanguage)); if (lentry == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } ret->languages[ret->num_languages-1] = lentry; memset(lentry, 0, sizeof(printerLanguage)); lentry->name = perlquote((xmlChar *)(cur2->name)); lentry->level = perlquote(xmlGetProp(cur2, (const xmlChar *) "level")); if (lentry->level == NULL) lentry->level = (xmlChar *) ""; if (debug) fprintf(stderr, " Printer understands PDL: %s Level %s\n", lentry->name, lentry->level); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "autodetect"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "general"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (general):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { ret->general_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", ret->general_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { ret->general_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", ret->general_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { ret->general_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", ret->general_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { ret->general_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", ret->general_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { ret->general_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", ret->general_cmd); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "parallel"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (parallel port):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { ret->par_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", ret->par_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { ret->par_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", ret->par_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { ret->par_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", ret->par_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { ret->par_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", ret->par_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { ret->par_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", ret->par_cmd); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "usb"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (USB):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { ret->usb_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", ret->usb_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { ret->usb_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", ret->usb_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { ret->usb_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", ret->usb_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { ret->usb_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", ret->usb_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { ret->usb_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", ret->usb_cmd); } cur3 = cur3->next; } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "snmp"))) { cur3 = cur2->xmlChildrenNode; if (debug) fprintf(stderr, " Printer auto-detection info (SNMP):\n"); while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ieee1284"))) { ret->snmp_ieee = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " IEEE1284: %s\n", ret->snmp_ieee); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "manufacturer"))) { ret->snmp_mfg = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MFG: %s\n", ret->snmp_mfg); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "model"))) { ret->snmp_mdl = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " MDL: %s\n", ret->snmp_mdl); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "description"))) { ret->snmp_des = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " DES: %s\n", ret->snmp_des); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "commandset"))) { ret->snmp_cmd = perlquote(xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " CMD: %s\n", ret->snmp_cmd); } cur3 = cur3->next; } } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "functionality"))) { ret->functionality = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer Functionality: %s\n", ret->functionality); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "driver"))) { ret->driver = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Recommended driver: %s\n", ret->driver); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "ppdentry"))) { ret->printerppdentry = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Extra lines for PPD file:\n%s\n", ret->printerppdentry); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "unverified"))) { ret->unverified = (xmlChar *)"1"; if (debug) fprintf(stderr, " Printer entry is unverified\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "noxmlentry"))) { ret->noxmlentry = (xmlChar *)"1"; if (debug) fprintf(stderr, " Printer XML entry does not exist in the database\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "url"))) { ret->url = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer URL: %s\n", ret->url); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "contrib_url"))) { ret->contriburl = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Contributed URL: %s\n", ret->contriburl); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "comments"))) { if (debug) fprintf(stderr, " Comment:\n"); getLocalizedText(doc, cur1, &(ret->comment), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "drivers"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "driver"))) { ret->num_drivers ++; ret->drivers = (printerDrvEntryPtr *) realloc((printerDrvEntryPtr *)ret->drivers, sizeof(printerDrvEntryPtr) * ret->num_drivers); dentry = (printerDrvEntryPtr) malloc(sizeof(printerDrvEntry)); if (dentry == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } ret->drivers[ret->num_drivers-1] = dentry; memset(dentry, 0, sizeof(printerDrvEntry)); dentry->name = NULL; dentry->comment = NULL; dentry->ppd = NULL; dentry->excmaxresx = NULL; dentry->excmaxresy = NULL; dentry->exccolor = NULL; dentry->exctext = NULL; dentry->exclineart = NULL; dentry->excgraphics = NULL; dentry->excphoto = NULL; dentry->excload = NULL; dentry->excspeed = NULL; if (debug) fprintf(stderr, " Printer supported by drivers:\n"); cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "id"))) { dname = xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); dentry->name = perlquote(dname); if (debug) fprintf(stderr, " Name: %s\n", dentry->name); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "ppd"))) { dppd = xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); dentry->ppd = perlquote(dppd); if (debug) fprintf(stderr, " Ready-made PPD: %s\n", dentry->ppd); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "comments"))) { if (debug) fprintf(stderr, " Comment:\n"); getLocalizedText(doc, cur3, &(dentry->comment), language, debug); } cur3 = cur3->next; } } cur2 = cur2->next; } } cur1 = cur1->next; } } static void parseDriverEntry(xmlDocPtr doc, /* I - The whole driver data tree */ xmlNodePtr node, /* I - Node of XML tree to work on */ driverEntryPtr ret, /* O - C data structure of Foomatic driver entry */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlNodePtr cur1; /* XML node currently worked on */ xmlNodePtr cur2; /* Another XML node pointer */ xmlNodePtr cur3; /* Another XML node pointer */ xmlNodePtr cur4; /* Another XML node pointer */ xmlChar *id; /* Full driver ID, with "driver/" */ drvPrnEntryPtr entry; /* An entry for a printer supported by this driver*/ xmlChar *url, *level, *version, *scope, *fingerprint; /* Initialization of entries */ ret->id = NULL; ret->name = NULL; ret->group = NULL; ret->url = NULL; ret->driver_obsolete = NULL; ret->supplier = NULL; ret->manufacturersupplied = NULL; ret->license = NULL; ret->licensetext = NULL; ret->origlicensetext = NULL; ret->licenselink = NULL; ret->origlicenselink = NULL; ret->free = NULL; ret->patents = NULL; ret->num_supportcontacts = 0; ret->supportcontacts = NULL; ret->supportcontacturls = NULL; ret->supportcontactlevels = NULL; ret->shortdescription = NULL; ret->locales = NULL; ret->num_packages = 0; ret->packageurls = NULL; ret->packagescopes = NULL; ret->packagefingerprints = NULL; ret->maxresx = NULL; ret->maxresy = NULL; ret->color = NULL; ret->text = NULL; ret->lineart = NULL; ret->graphics = NULL; ret->photo = NULL; ret->load = NULL; ret->speed = NULL; ret->num_requires = 0; ret->requires = NULL; ret->requiresversion = NULL; ret->driver_type = NULL; ret->cmd = NULL; ret->cmd_pdf = NULL; ret->driverppdentry = NULL; ret->drivermargins = NULL; ret->comment = NULL; ret->num_printers = 0; ret->printers = NULL; /* Get driver ID */ id = xmlGetProp(node, (const xmlChar *) "id"); if (id == NULL) { fprintf(stderr, "No driver ID found\n"); return; } ret->id = perlquote(id + 7); if (debug) fprintf(stderr, " Driver ID: %s\n", ret->id); /* Go through subnodes */ cur1 = node->xmlChildrenNode; while (cur1 != NULL) { if ((!xmlStrcmp(cur1->name, (const xmlChar *) "name"))) { ret->name = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver name: %s\n", ret->name); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "group"))) { ret->group = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver group (for localization): %s\n", ret->group); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "url"))) { ret->url = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver URL: %s\n", ret->url); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "obsolete"))) { ret->driver_obsolete = xmlGetProp(cur1, (const xmlChar *) "replace"); if (ret->driver_obsolete == NULL) { if (debug) fprintf(stderr, " No replacement driver found!\n"); ret->driver_obsolete = (xmlChar *)"1"; } if (debug) fprintf(stderr, " Driver is obsolete: %s\n", ret->driver_obsolete); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "supplier"))) { if (debug) fprintf(stderr, " Driver supplier:\n"); getLocalizedText(doc, cur1, &(ret->supplier), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "manufacturersupplied"))) { ret->manufacturersupplied = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if ((ret->manufacturersupplied == NULL) || (ret->manufacturersupplied[0] == '\0')) ret->manufacturersupplied = (xmlChar *)"1"; if (debug) fprintf(stderr, " Driver supplied by manufacturer: %s\n", ret->manufacturersupplied); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "thirdpartysupplied"))) { ret->manufacturersupplied = (xmlChar *)"0"; if (debug) fprintf(stderr, " Driver supplied by a third party\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "license"))) { if (debug) fprintf(stderr, " Driver license:\n"); getLocalizedText(doc, cur1, &(ret->license), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "licensetext"))) { if (debug) fprintf(stderr, " Driver license text:\n"); getLocalizedLicenseText(doc, cur1, &(ret->licensetext), &(ret->origlicensetext), &(ret->licenselink), &(ret->origlicenselink), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "freesoftware"))) { ret->free = (xmlChar *)"1"; if (debug) fprintf(stderr, " Driver is free software\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "nonfreesoftware"))) { ret->free = (xmlChar *)"0"; if (debug) fprintf(stderr, " Driver is not free software\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "patents"))) { ret->patents = (xmlChar *)"1"; if (debug) fprintf(stderr, " There are patents applying to this driver's code\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "nopatents"))) { ret->patents = (xmlChar *)"0"; if (debug) fprintf(stderr, " There are no patents applying to this driver's code\n"); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "supportcontacts"))) { cur2 = cur1->xmlChildrenNode; if (debug) fprintf(stderr, " Driver support contacts:\n"); while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "supportcontact"))) { ret->num_supportcontacts ++; ret->supportcontacts = (xmlChar const **) realloc((xmlChar **)ret->supportcontacts, sizeof(xmlChar *) * ret->num_supportcontacts); ret->supportcontacturls = (xmlChar **) realloc((xmlChar **)ret->supportcontacturls, sizeof(xmlChar *) * ret->num_supportcontacts); ret->supportcontactlevels = (xmlChar **) realloc((xmlChar **)ret->supportcontactlevels, sizeof(xmlChar *) * ret->num_supportcontacts); level = xmlGetProp(cur2, (const xmlChar *) "level"); if (level == NULL) { level = (xmlChar *)"Unknown"; } url = xmlGetProp(cur2, (const xmlChar *) "url"); ret->supportcontactlevels[ret->num_supportcontacts - 1] = level; ret->supportcontacturls[ret->num_supportcontacts - 1] = url; getLocalizedText (doc, cur2, &(ret->supportcontacts[ret->num_supportcontacts - 1]), language, debug); if (debug) fprintf(stderr, " %s (%s):\n %s\n", ret->supportcontacts[ret->num_supportcontacts - 1], ret->supportcontactlevels[ret->num_supportcontacts - 1], ret->supportcontacturls[ret->num_supportcontacts - 1]); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "shortdescription"))) { if (debug) fprintf(stderr, " Driver short description:\n"); getLocalizedText(doc, cur1, &(ret->shortdescription), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "locales"))) { ret->locales = perlquote(xmlNodeListGetString(doc, cur1->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver list of locales: %s\n", ret->locales); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "packages"))) { cur2 = cur1->xmlChildrenNode; if (debug) fprintf(stderr, " Driver downloadable packages:\n"); while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "package"))) { ret->num_packages ++; ret->packageurls = (xmlChar **) realloc((xmlChar **)ret->packageurls, sizeof(xmlChar *) * ret->num_packages); ret->packagescopes = (xmlChar **) realloc((xmlChar **)ret->packagescopes, sizeof(xmlChar *) * ret->num_packages); scope = xmlGetProp(cur2, (const xmlChar *) "scope"); ret->packagefingerprints = (xmlChar **) realloc((xmlChar **)ret->packagefingerprints, sizeof(xmlChar *) * ret->num_packages); fingerprint = xmlGetProp(cur2, (const xmlChar *) "fingerprint"); ret->packageurls[ret->num_packages - 1] = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); ret->packagescopes[ret->num_packages - 1] = perlquote(scope); ret->packagefingerprints[ret->num_packages - 1] = perlquote(fingerprint); if (debug) fprintf(stderr, " %s (%s), key fingerprint on %s\n", ret->packageurls[ret->num_packages - 1], ret->packagescopes[ret->num_packages - 1],\ ret->packagefingerprints[ret->num_packages - 1]); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "functionality"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "maxresx"))) { ret->maxresx = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Max X resolution: %s\n", ret->maxresx); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "maxresy"))) { ret->maxresy = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Max Y resolution: %s\n", ret->maxresy); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "color"))) { ret->color = (xmlChar *)"1"; if (debug) fprintf(stderr, " Driver functionality: Color\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "monochrome"))) { ret->color = (xmlChar *)"0"; if (debug) fprintf(stderr, " Driver functionality: Monochrome\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "text"))) { ret->text = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Text support rating: %s\n", ret->text); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "lineart"))) { ret->lineart = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Line art support rating: %s\n", ret->lineart); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "graphics"))) { ret->graphics = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Graphics support rating: %s\n", ret->graphics); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "photo"))) { ret->photo = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Photo support rating: %s\n", ret->photo); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "load"))) { ret->load = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: System load rating: %s\n", ret->load); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "speed"))) { ret->speed = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver functionality: Speed rating: %s\n", ret->speed); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "execution"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "requires"))) { ret->num_requires ++; ret->requires = (xmlChar **) realloc((xmlChar **)ret->requires, sizeof(xmlChar *) * ret->num_requires); ret->requiresversion = (xmlChar **) realloc((xmlChar **)ret->requiresversion, sizeof(xmlChar *) * ret->num_requires); version = xmlGetProp(cur2, (const xmlChar *) "version"); ret->requires[ret->num_requires - 1] = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); ret->requiresversion[ret->num_requires - 1] = perlquote(version); if (debug) { if (!version) fprintf(stderr, " Driver requires driver: %s\n", ret->requires[ret->num_requires - 1]); else fprintf(stderr, " Driver requires driver: %s (%s)\n", ret->requires[ret->num_requires - 1], ret->requiresversion[ret->num_requires - 1]); } } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "cups"))) { ret->driver_type = (xmlChar *)"C"; if (debug) fprintf(stderr, " Driver type: CUPS Raster\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ijs"))) { ret->driver_type = (xmlChar *)"I"; if (debug) fprintf(stderr, " Driver type: IJS\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "opvp"))) { ret->driver_type = (xmlChar *)"V"; if (debug) fprintf(stderr, " Driver type: OpenPrinting Vector\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ghostscript"))) { ret->driver_type = (xmlChar *)"G"; if (debug) fprintf(stderr, " Driver type: Ghostscript built-in\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "filter"))) { ret->driver_type = (xmlChar *)"F"; if (debug) fprintf(stderr, " Driver type: Filter\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "uniprint"))) { ret->driver_type = (xmlChar *)"U"; if (debug) fprintf(stderr, " Driver type: Ghostscript Uniprint\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "postscript"))) { ret->driver_type = (xmlChar *)"P"; if (debug) fprintf(stderr, " Driver type: PostScript\n"); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "prototype"))) { ret->cmd = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver command line:\n\n %s\n\n", ret->cmd); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "prototype_pdf"))) { ret->cmd_pdf = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Driver PDF command line:\n\n %s\n\n", ret->cmd_pdf); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "ppdentry"))) { ret->driverppdentry = perlquote(xmlNodeListGetString(doc, cur2->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Extra lines for PPD file:\n%s\n", ret->driverppdentry); } else if ((!xmlStrcmp(cur2->name, (const xmlChar *) "margins"))) { parseMargins(doc, cur2, &(ret->drivermargins), language, debug); } cur2 = cur2->next; } } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "comments"))) { if (debug) fprintf(stderr, " Comment:\n"); getLocalizedText(doc, cur1, &(ret->comment), language, debug); } else if ((!xmlStrcmp(cur1->name, (const xmlChar *) "printers"))) { cur2 = cur1->xmlChildrenNode; while (cur2 != NULL) { if ((!xmlStrcmp(cur2->name, (const xmlChar *) "printer"))) { ret->num_printers ++; ret->printers = (drvPrnEntryPtr *)realloc((drvPrnEntryPtr *)ret->printers, sizeof(drvPrnEntryPtr) * ret->num_printers); entry = (drvPrnEntryPtr) malloc(sizeof(drvPrnEntry)); if (entry == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } ret->printers[ret->num_printers-1] = entry; memset(entry, 0, sizeof(drvPrnEntry)); entry->id = NULL; entry->comment = NULL; entry->excmaxresx = NULL; entry->excmaxresy = NULL; entry->exccolor = NULL; entry->exctext = NULL; entry->exclineart = NULL; entry->excgraphics = NULL; entry->excphoto = NULL; entry->excload = NULL; entry->excspeed = NULL; if (debug) fprintf(stderr, " Driver supports printer:\n"); cur3 = cur2->xmlChildrenNode; while (cur3 != NULL) { if ((!xmlStrcmp(cur3->name, (const xmlChar *) "id"))) { id = xmlNodeListGetString(doc, cur3->xmlChildrenNode, 1); entry->id = perlquote(id + 8); if (debug) fprintf(stderr, " ID: %s\n", entry->id); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "comments"))) { if (debug) fprintf(stderr, " Comment:\n"); getLocalizedText(doc, cur3, &(entry->comment), language, debug); } else if ((!xmlStrcmp(cur3->name, (const xmlChar *) "functionality"))) { cur4 = cur3->xmlChildrenNode; while (cur4 != NULL) { if ((!xmlStrcmp(cur4->name, (const xmlChar *) "maxresx"))) { entry->excmaxresx = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer exception: Maximum X resolution: %s\n", entry->excmaxresx); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "maxresy"))) { entry->excmaxresy = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer exception: Maximum Y resolution: %s\n", entry->excmaxresy); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "monochrome"))) { entry->exccolor = (xmlChar *)"0"; if (debug) fprintf(stderr, " Printer exception: Color: %s\n", entry->exccolor); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "color"))) { entry->exccolor = (xmlChar *)"1"; if (debug) fprintf(stderr, " Printer exception: Color: %s\n", entry->exccolor); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "text"))) { entry->exctext = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer exception: Support level for text: %s\n", entry->exctext); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "lineart"))) { entry->exclineart = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer exception: Support level for line art: %s\n", entry->exclineart); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "graphics"))) { entry->excgraphics = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer exception: Support level for graphics: %s\n", entry->excgraphics); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "photo"))) { entry->excphoto = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer exception: Support level for photos: %s\n", entry->excphoto); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "load"))) { entry->excload = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer exception: Expected relative system load: %s\n", entry->excload); } else if ((!xmlStrcmp(cur4->name, (const xmlChar *) "speed"))) { entry->excspeed = perlquote(xmlNodeListGetString(doc, cur4->xmlChildrenNode, 1)); if (debug) fprintf(stderr, " Printer exception: Expected relative driver speed: %s\n", entry->excspeed); } cur4 = cur4->next; } } cur3 = cur3->next; } } cur2 = cur2->next; } } cur1 = cur1->next; } } static xmlDocPtr /* O - Tree with data parsed from stdin */ parseXMLFromStdin() { FILE *f; xmlDocPtr doc = NULL; if (stdin != NULL) { int res, size = 1024; char chars[1024]; xmlParserCtxtPtr ctxt; res = fread(chars, 1, 4, stdin); if (res > 0) { ctxt = xmlCreatePushParserCtxt(NULL, NULL, chars, res, NULL); while ((res = fread(chars, 1, size, stdin)) > 0) { xmlParseChunk(ctxt, chars, res, 0); } xmlParseChunk(ctxt, chars, 0, 1); doc = ctxt->myDoc; xmlFreeParserCtxt(ctxt); } } return doc; } static overviewPtr /* O - C data structure of overview */ parseOverviewFile(char *filename, /* I - Input file name, NULL: stdin */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlDocPtr doc; /* Output of XML parser */ overviewPtr ret; /* C data structure of overview */ xmlNodePtr cur; /* XML node currently worked on */ driverEntryPtr driver; /* * build an XML tree from a file or stdin; */ if (filename == NULL) { doc = parseXMLFromStdin(); } else { doc = xmlParseFile(filename); } if (doc == NULL) return(NULL); /* * Check the document is of the right kind */ cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"Empty input document!\n"); xmlFreeDoc(doc); return(NULL); } if (xmlStrcmp(cur->name, (const xmlChar *) "overview")) { fprintf(stderr,"Input document is not a Foomatic overview XML file (no \"\" tag)!\n"); xmlFreeDoc(doc); return(NULL); } /* * Allocate the structure to be returned. */ ret = (overviewPtr) malloc(sizeof(overview)); if (ret == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); return(NULL); } memset(ret, 0, sizeof(overview)); ret->num_overviewPrinters = 0; ret->overviewPrinters = NULL; /* * Now, walk through the tree. */ /* On the first level we have the printer entries */ cur = cur->xmlChildrenNode; while (cur) { if (xmlIsBlankNode(cur)) { cur = cur->next; continue; } if (!xmlStrcmp(cur->name, (const xmlChar *) "driver")) { ret->num_overviewDrivers ++; ret->overviewDrivers = (driverEntryPtr *)realloc ((driverEntryPtr *)(ret->overviewDrivers), sizeof(driverEntryPtr) * ret->num_overviewDrivers); driver = (driverEntryPtr) malloc(sizeof(driverEntry)); if (driver == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); exit(1); } ret->overviewDrivers[ret->num_overviewDrivers-1] = driver; memset(driver, 0, sizeof(driverEntry)); if (debug) fprintf(stderr, "--> Parsing driver data\n"); parseDriverEntry(doc, cur, driver, language, debug); } else if (!xmlStrcmp(cur->name, (const xmlChar *) "printer")) { if (debug) fprintf(stderr, "--> Parsing printer data\n"); parseOverviewPrinter(doc, cur, ret, language, debug); } cur = cur->next; } /* We succeeded, return the result */ return(ret); } static comboDataPtr /* O - C data structure of printer/driver combo */ parseComboFile(char *filename, /* I - Input file name, NULL: stdin */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlDocPtr doc; /* Output of XML parser */ comboDataPtr ret; /* C data structure of printer/driver combo */ xmlNodePtr cur; /* XML node currently worked on */ /* * build an XML tree from a file or stdin; */ if (filename == NULL) { doc = parseXMLFromStdin(); } else { doc = xmlParseFile(filename); } if (doc == NULL) return(NULL); /* * Check the document is of the right kind */ cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"Empty input document!\n"); xmlFreeDoc(doc); return(NULL); } if (xmlStrcmp(cur->name, (const xmlChar *) "foomatic")) { fprintf(stderr,"Input document is not a Foomatic combo XML file (no \"\" tag)!\n"); xmlFreeDoc(doc); return(NULL); } /* * Allocate the structure to be returned. */ ret = (comboDataPtr) malloc(sizeof(comboData)); if (ret == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); return(NULL); } memset(ret, 0, sizeof(comboData)); ret->make = NULL; ret->driver = NULL; ret->num_args = 0; ret->args = NULL; /* * Now, walk through the tree. */ /* On the first level we have the printer, the driver, and the options */ cur = cur->xmlChildrenNode; while (cur) { if (xmlIsBlankNode(cur)) { cur = cur->next; continue; } if (!xmlStrcmp(cur->name, (const xmlChar *) "printer")) { if (debug) fprintf(stderr, "--> Parsing printer data\n"); parseComboPrinter(doc, cur, ret, language, debug); } else if (!xmlStrcmp(cur->name, (const xmlChar *) "driver")) { if (debug) fprintf(stderr, "--> Parsing driver data\n"); parseComboDriver(doc, cur, ret, language, debug); } else if (!xmlStrcmp(cur->name, (const xmlChar *) "options")) { if (debug) fprintf(stderr, "--> Parsing option data\n"); parseOptions(doc, cur, ret, language, debug); } cur = cur->next; } /* All sections present in combo XML? */ if (ret->make == NULL) { fprintf(stderr,"\"\" tag not found!\n"); exit(1); } if (ret->driver == NULL) { fprintf(stderr,"\"\" tag not found!\n"); exit(1); } /* We succeeded, return the result */ return(ret); } static printerEntryPtr /* O - C data structure of printer entry */ parsePrinterFile(char *filename, /* I - Input file name, NULL: stdin */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlDocPtr doc; /* Output of XML parser */ printerEntryPtr ret; /* C data structure of printer entry */ xmlNodePtr cur; /* XML node currently worked on */ /* * build an XML tree from a file or stdin; */ if (filename == NULL) { doc = parseXMLFromStdin(); } else { doc = xmlParseFile(filename); } if (doc == NULL) return(NULL); /* * Check the document is of the right kind */ cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"Empty input document!\n"); xmlFreeDoc(doc); return(NULL); } if (xmlStrcmp(cur->name, (const xmlChar *) "printer")) { fprintf(stderr,"Input document is not a Foomatic printer XML file (no \"\" tag)!\n"); xmlFreeDoc(doc); return(NULL); } /* * Allocate the structure to be returned. */ ret = (printerEntryPtr) malloc(sizeof(printerEntry)); if (ret == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); return(NULL); } memset(ret, 0, sizeof(printerEntry)); /* * Now, walk through the tree. */ if (debug) fprintf(stderr, "--> Parsing printer data\n"); parsePrinterEntry(doc, cur, ret, language, debug); /* We succeeded, return the result */ return(ret); } static driverEntryPtr /* O - C data structure of driver entry */ parseDriverFile(char *filename, /* I - Input file name, NULL: stdin */ xmlChar const language [], /* I - User language */ int debug) { /* I - Debug mode flag */ xmlDocPtr doc; /* Output of XML parser */ driverEntryPtr ret; /* C data structure of driver entry */ xmlNodePtr cur; /* XML node currently worked on */ /* * build an XML tree from a file or stdin; */ if (filename == NULL) { doc = parseXMLFromStdin(); } else { doc = xmlParseFile(filename); } if (doc == NULL) return(NULL); /* * Check the document is of the right kind */ cur = xmlDocGetRootElement(doc); if (cur == NULL) { fprintf(stderr,"Empty input document!\n"); xmlFreeDoc(doc); return(NULL); } if (xmlStrcmp(cur->name, (const xmlChar *) "driver")) { fprintf(stderr,"Input document is not a Foomatic driver XML file (no \"\" tag)!\n"); xmlFreeDoc(doc); return(NULL); } /* * Allocate the structure to be returned. */ ret = (driverEntryPtr) malloc(sizeof(driverEntry)); if (ret == NULL) { fprintf(stderr,"Out of memory!\n"); xmlFreeDoc(doc); return(NULL); } memset(ret, 0, sizeof(driverEntry)); /* * Now, walk through the tree. */ if (debug) fprintf(stderr, "--> Parsing driver data\n"); parseDriverEntry(doc, cur, ret, language, debug); /* We succeeded, return the result */ return(ret); } void prepareComboData(comboDataPtr combo, /* I/O - Foomatic combo data parsed from XML input */ xmlChar **defaultsettings, /* User-supplied default option settings */ int num_defaultsettings, /* number of default option settings */ int debug) { /* Debug flag */ int i, j; /* loop variables */ xmlChar *option, *value, *s;/* User option and value, temporary pointer */ /* Insert the default values (not choice IDs) for the enumerated options */ for (i = 0; i < combo->num_args; i ++) { for (j = 0; j < combo->args[i]->num_choices; j ++) { if (!xmlStrcmp(combo->args[i]->choices[j]->idx, combo->args[i]->default_value)) { combo->args[i]->default_value = combo->args[i]->choices[j]->value; if (debug) fprintf(stderr, " Setting default value for enumerated option %s: %s\n", combo->args[i]->name, combo->args[i]->default_value); } } } /* Insert the user-supplied defaults */ for (i = 0; i < num_defaultsettings; i ++) { s = xmlStrchr ((defaultsettings[i]), '=') - (defaultsettings[i]) + (defaultsettings[i]); *s = (xmlChar)'\0'; s ++; option = defaultsettings[i]; value = s; for (j = 0; j < combo->num_args; j ++) { if (!xmlStrcmp(combo->args[j]->name, option)) { combo->args[j]->default_value = value; if (debug) fprintf(stderr, " Setting user default for option %s: %s\n", combo->args[j]->name, combo->args[j]->default_value); } } } } void generateOverviewPerlData(overviewPtr overview, /* I/O - Foomatic overview data parsed from XML input */ int debug) { /* Debug flag */ int i, j, k, l; /* loop variables */ overviewPrinterPtr printer; printf("$VAR1 = [\n"); for (i = 0; i < overview->num_overviewPrinters; i ++) { printer = overview->overviewPrinters[i]; printf(" {\n"); printf(" 'id' => '%s',\n", printer->id); printf(" 'make' => '%s',\n", printer->make); printf(" 'model' => '%s',\n", printer->model); if (printer->general_ieee) { printf(" 'general_ieee' => '%s',\n", printer->general_ieee); } if (printer->general_mfg) { printf(" 'general_mfg' => '%s',\n", printer->general_mfg); } if (printer->general_mdl) { printf(" 'general_mdl' => '%s',\n", printer->general_mdl); } if (printer->general_des) { printf(" 'general_des' => '%s',\n", printer->general_des); } if (printer->general_cmd) { printf(" 'general_cmd' => '%s',\n", printer->general_cmd); } if (printer->par_ieee) { printf(" 'par_ieee' => '%s',\n", printer->par_ieee); } if (printer->par_mfg) { printf(" 'par_mfg' => '%s',\n", printer->par_mfg); } if (printer->par_mdl) { printf(" 'par_mdl' => '%s',\n", printer->par_mdl); } if (printer->par_des) { printf(" 'par_des' => '%s',\n", printer->par_des); } if (printer->par_cmd) { printf(" 'par_cmd' => '%s',\n", printer->par_cmd); } if (printer->usb_ieee) { printf(" 'usb_ieee' => '%s',\n", printer->usb_ieee); } if (printer->usb_mfg) { printf(" 'usb_mfg' => '%s',\n", printer->usb_mfg); } if (printer->usb_mdl) { printf(" 'usb_mdl' => '%s',\n", printer->usb_mdl); } if (printer->usb_des) { printf(" 'usb_des' => '%s',\n", printer->usb_des); } if (printer->usb_cmd) { printf(" 'usb_cmd' => '%s',\n", printer->usb_cmd); } if (printer->snmp_ieee) { printf(" 'snmp_ieee' => '%s',\n", printer->snmp_ieee); } if (printer->snmp_mfg) { printf(" 'snmp_mfg' => '%s',\n", printer->snmp_mfg); } if (printer->snmp_mdl) { printf(" 'snmp_mdl' => '%s',\n", printer->snmp_mdl); } if (printer->snmp_des) { printf(" 'snmp_des' => '%s',\n", printer->snmp_des); } if (printer->snmp_cmd) { printf(" 'snmp_cmd' => '%s',\n", printer->snmp_cmd); } printf(" 'functionality' => '%s',\n", printer->functionality); if (printer->unverified) { printf(" 'unverified' => 1,\n"); } else { printf(" 'unverified' => 0,\n"); } if (printer->noxmlentry) { printf(" 'noxmlentry' => 1,\n"); } else { printf(" 'noxmlentry' => 0,\n"); } if (printer->driver) { printf(" 'driver' => '%s',\n", printer->driver); } if (printer->num_drivers > 0) { printf(" 'drivers' => [\n"); for (j = 0; j < printer->num_drivers; j ++) if (printer->drivers[j]->name != NULL) printf(" '%s',\n", printer->drivers[j]->name); printf(" ],\n"); printf(" 'driverproperties' => {\n"); for (j = 0; j < printer->num_drivers; j ++) { for (k = 0; k < overview->num_overviewDrivers; k ++) { if (!xmlStrcmp(overview->overviewDrivers[k]->name, printer->drivers[j]->name)) break; } if ((k < overview->num_overviewDrivers) && (!xmlStrcmp(overview->overviewDrivers[k]->name, printer->drivers[j]->name))) { printf(" '%s' => {\n", printer->drivers[j]->name); if (overview->overviewDrivers[k]->group != NULL) { printf(" 'group' => '%s',\n", overview->overviewDrivers[k]->group); } if (overview->overviewDrivers[k]->url != NULL) { printf(" 'url' => '%s',\n", overview->overviewDrivers[k]->url); } if (overview->overviewDrivers[k]->driver_obsolete != NULL) { printf(" 'obsolete' => '%s',\n", overview->overviewDrivers[k]->driver_obsolete); } if (overview->overviewDrivers[k]->supplier != NULL) { printf(" 'supplier' => '%s',\n", overview->overviewDrivers[k]->supplier); } if (overview->overviewDrivers[k]->manufacturersupplied != NULL) { printf(" 'manufacturersupplied' => '%s',\n", overview->overviewDrivers[k]->manufacturersupplied); } if (overview->overviewDrivers[k]->license != NULL) { printf(" 'license' => '%s',\n", overview->overviewDrivers[k]->license); } if (overview->overviewDrivers[k]->licensetext != NULL) { printf(" 'licensetext' => '%s',\n", overview->overviewDrivers[k]->licensetext); } if (overview->overviewDrivers[k]->origlicensetext != NULL) { printf(" 'origlicensetext' => '%s',\n", overview->overviewDrivers[k]->origlicensetext); } if (overview->overviewDrivers[k]->licenselink != NULL) { printf(" 'licenselink' => '%s',\n", overview->overviewDrivers[k]->licenselink); } if (overview->overviewDrivers[k]->origlicenselink != NULL) { printf(" 'origlicenselink' => '%s',\n", overview->overviewDrivers[k]->origlicenselink); } if (overview->overviewDrivers[k]->free != NULL) { printf(" 'free' => '%s',\n", overview->overviewDrivers[k]->free); } if (overview->overviewDrivers[k]->patents != NULL) { printf(" 'patents' => '%s',\n", overview->overviewDrivers[k]->patents); } if (overview->overviewDrivers[k]->num_supportcontacts != 0) { printf(" 'supportcontacts' => [\n"); for (l = 0; l < overview->overviewDrivers[k]->num_supportcontacts; l ++) { if (overview->overviewDrivers[k]->supportcontacturls[l] != NULL) { printf(" {\n"); printf(" 'description' => '%s',\n", overview->overviewDrivers[k]->supportcontacts[l]); if (overview->overviewDrivers[k]->supportcontacturls[l] != NULL) printf(" 'url' => '%s',\n", overview->overviewDrivers[k]->supportcontacturls[l]); printf(" 'level' => '%s',\n", overview->overviewDrivers[k]->supportcontactlevels[l]); printf(" },\n"); } } printf(" ],\n"); } if (overview->overviewDrivers[k]->shortdescription != NULL) { printf(" 'shortdescription' => '%s',\n", overview->overviewDrivers[k]->shortdescription); } if (overview->overviewDrivers[k]->locales != NULL) { printf(" 'locales' => '%s',\n", overview->overviewDrivers[k]->locales); } if (overview->overviewDrivers[k]->num_packages != 0) { printf(" 'packages' => [\n"); for (l = 0; l < overview->overviewDrivers[k]->num_packages; l ++) { if (overview->overviewDrivers[k]->packageurls[l] != NULL) { printf(" {\n"); printf(" 'url' => '%s',\n", overview->overviewDrivers[k]->packageurls[l]); if (overview->overviewDrivers[k]->packagescopes[l] != NULL) printf(" 'scope' => '%s',\n", overview->overviewDrivers[k]->packagescopes[l]); if (overview->overviewDrivers[k]->packagefingerprints[l] != NULL) printf(" 'fingerprint' => '%s',\n", overview->overviewDrivers[k]->packagefingerprints[l]); printf(" },\n"); } } printf(" ],\n"); } if (overview->overviewDrivers[k]->num_requires != 0) { printf(" 'requires' => [\n"); for (l = 0; l < overview->overviewDrivers[k]->num_requires; l ++) { if (overview->overviewDrivers[k]->requires[l] != NULL) { printf(" {\n"); printf(" 'driver' => '%s',\n", overview->overviewDrivers[k]->requires[l]); if (overview->overviewDrivers[k]->requiresversion[l] != NULL) printf(" 'version' => '%s',\n", overview->overviewDrivers[k]->requiresversion[l]); printf(" },\n"); } } printf(" ],\n"); } if (overview->overviewDrivers[k]->driver_type != NULL) { printf(" 'type' => '%s',\n", overview->overviewDrivers[k]->driver_type); } if (printer->drivers[j]->excmaxresx != NULL) { printf(" 'drvmaxresx' => '%s',\n", printer->drivers[j]->excmaxresx); } else if (overview->overviewDrivers[k]->maxresx != NULL) { printf(" 'drvmaxresx' => '%s',\n", overview->overviewDrivers[k]->maxresx); } if (printer->drivers[j]->excmaxresy != NULL) { printf(" 'drvmaxresy' => '%s',\n", printer->drivers[j]->excmaxresy); } else if (overview->overviewDrivers[k]->maxresy != NULL) { printf(" 'drvmaxresy' => '%s',\n", overview->overviewDrivers[k]->maxresy); } if (printer->drivers[j]->exccolor != NULL) { printf(" 'drvcolor' => '%s',\n", printer->drivers[j]->exccolor); } else if (overview->overviewDrivers[k]->color != NULL) { printf(" 'drvcolor' => '%s',\n", overview->overviewDrivers[k]->color); } if (printer->drivers[j]->exctext != NULL) { printf(" 'text' => '%s',\n", printer->drivers[j]->exctext); } else if (overview->overviewDrivers[k]->text != NULL) { printf(" 'text' => '%s',\n", overview->overviewDrivers[k]->text); } if (printer->drivers[j]->exclineart != NULL) { printf(" 'lineart' => '%s',\n", printer->drivers[j]->exclineart); } else if (overview->overviewDrivers[k]->lineart != NULL) { printf(" 'lineart' => '%s',\n", overview->overviewDrivers[k]->lineart); } if (printer->drivers[j]->excgraphics != NULL) { printf(" 'graphics' => '%s',\n", printer->drivers[j]->excgraphics); } else if (overview->overviewDrivers[k]->graphics != NULL) { printf(" 'graphics' => '%s',\n", overview->overviewDrivers[k]->graphics); } if (printer->drivers[j]->excphoto != NULL) { printf(" 'photo' => '%s',\n", printer->drivers[j]->excphoto); } else if (overview->overviewDrivers[k]->photo != NULL) { printf(" 'photo' => '%s',\n", overview->overviewDrivers[k]->photo); } if (printer->drivers[j]->excload != NULL) { printf(" 'load' => '%s',\n", printer->drivers[j]->excload); } else if (overview->overviewDrivers[k]->load != NULL) { printf(" 'load' => '%s',\n", overview->overviewDrivers[k]->load); } if (printer->drivers[j]->excspeed != NULL) { printf(" 'speed' => '%s',\n", printer->drivers[j]->excspeed); } else if (overview->overviewDrivers[k]->speed != NULL) { printf(" 'speed' => '%s',\n", overview->overviewDrivers[k]->speed); } printf(" },\n"); } } printf(" },\n"); } else { printf(" 'drivers' => [],\n"); } if (printer->num_ppdfiles > 0) { printf(" 'ppds' => [\n"); for (j = 0; j < printer->num_ppdfiles; j ++) if ((printer->ppdfiles[j]->driver != NULL) && (printer->ppdfiles[j]->filename != NULL)) { printf(" {\n"); printf(" 'driver' => '%s',\n", printer->ppdfiles[j]->driver); printf(" 'ppdfile' => '%s',\n", printer->ppdfiles[j]->filename); printf(" },\n"); } printf(" ],\n"); } printf(" },\n"); } printf(" ];\n"); } void generateMarginsPerlData(marginsPtr margins, /* I/O - Foomatic margins data parsed from XML input */ int debug) { /* Debug flag */ int i; /* loop variable */ for (i = 0; i < margins->num_marginRecords; i ++) { if (margins->marginRecords[i]->pagesize) { printf(" '%s' => {\n", margins->marginRecords[i]->pagesize); } else { printf(" '_general' => {\n"); } if (margins->marginRecords[i]->unit) { printf(" 'unit' => '%s',\n", margins->marginRecords[i]->unit); } if (margins->marginRecords[i]->absolute) { printf(" 'absolute' => '%s',\n", margins->marginRecords[i]->absolute); } if (margins->marginRecords[i]->left) { printf(" 'left' => '%s',\n", margins->marginRecords[i]->left); } if (margins->marginRecords[i]->right) { printf(" 'right' => '%s',\n", margins->marginRecords[i]->right); } if (margins->marginRecords[i]->top) { printf(" 'top' => '%s',\n", margins->marginRecords[i]->top); } if (margins->marginRecords[i]->bottom) { printf(" 'bottom' => '%s',\n", margins->marginRecords[i]->bottom); } printf(" },\n"); } } xmlChar const sc_Postscript [] = "Postscript"; void generateComboPerlData(comboDataPtr combo, /* I/O - Foomatic combo data parsed from XML input */ int debug) { /* Debug flag */ int i, j; /* loop variables */ int haspsdriver = 0; /* Is the "Postscript" driver in the printer's driver list? */ printf("$VAR1 = {\n"); printf(" 'id' => '%s',\n", combo->id); printf(" 'make' => '%s',\n", combo->make); printf(" 'model' => '%s',\n", combo->model); if (combo->recdriver) { printf(" 'recdriver' => '%s',\n", combo->recdriver); } else { printf(" 'recdriver' => undef,\n"); } if ((combo->num_drivers > 0) || (combo->ppdurl)) { printf(" 'drivers' => [\n"); for (i = 0; i < combo->num_drivers; i ++) { printf(" {\n"); if (combo->drivers[i]->name) { if (xmlStrncmp(combo->drivers[i]->name, sc_Postscript, 10)) haspsdriver = 1; printf(" 'name' => '%s',\n", combo->drivers[i]->name); printf(" 'id' => '%s',\n", combo->drivers[i]->name); } if (combo->drivers[i]->ppd) { printf(" 'ppd' => '%s',\n", combo->drivers[i]->ppd); } if (combo->drivers[i]->comment) { printf(" 'comment' => '%s',\n", combo->drivers[i]->comment); } printf(" },\n"); } if ((combo->ppdurl) && !haspsdriver) { printf(" {\n"); printf(" 'name' => '%s',\n", "Postscript"); printf(" 'id' => '%s',\n", "Postscript"); printf(" 'ppd' => '%s',\n", combo->ppdurl); printf(" },\n"); } printf(" ],\n"); } if (combo->pcmodel) { printf(" 'pcmodel' => '%s',\n", combo->pcmodel); } else { printf(" 'pcmodel' => undef,\n"); } if (combo->ppdurl) { printf(" 'ppdurl' => '%s',\n", combo->ppdurl); } printf(" 'color' => %s,\n", combo->color); printf(" 'ascii' => %s,\n", combo->ascii); printf(" 'pjl' => %s,\n", combo->pjl); if (combo->printerppdentry) { printf(" 'printerppdentry' => '%s',\n", combo->printerppdentry); } else { printf(" 'printerppdentry' => undef,\n"); } if (combo->printermargins) { printf(" 'printermargins' => {\n"); generateMarginsPerlData(combo->printermargins, debug); printf(" },\n"); } if (combo->general_ieee) { printf(" 'pnp_ieee' => '%s',\n", combo->general_ieee); printf(" 'general_ieee' => '%s',\n", combo->general_ieee); } else { printf(" 'pnp_ieee' => undef,\n"); printf(" 'general_ieee' => undef,\n"); } if (combo->general_mfg) { printf(" 'pnp_mfg' => '%s',\n", combo->general_mfg); printf(" 'general_mfg' => '%s',\n", combo->general_mfg); } else { printf(" 'pnp_mfg' => undef,\n"); printf(" 'general_mfg' => undef,\n"); } if (combo->general_mdl) { printf(" 'pnp_mdl' => '%s',\n", combo->general_mdl); printf(" 'general_mdl' => '%s',\n", combo->general_mdl); } else { printf(" 'pnp_mdl' => undef,\n"); printf(" 'general_mdl' => undef,\n"); } if (combo->general_des) { printf(" 'pnp_des' => '%s',\n", combo->general_des); printf(" 'general_des' => '%s',\n", combo->general_des); } else { printf(" 'pnp_des' => undef,\n"); printf(" 'general_des' => undef,\n"); } if (combo->general_cmd) { printf(" 'pnp_cmd' => '%s',\n", combo->general_cmd); printf(" 'general_cmd' => '%s',\n", combo->general_cmd); } else { printf(" 'pnp_cmd' => undef,\n"); printf(" 'general_cmd' => undef,\n"); } if (combo->par_ieee) { printf(" 'par_ieee' => '%s',\n", combo->par_ieee); } else { printf(" 'par_ieee' => undef,\n"); } if (combo->par_mfg) { printf(" 'par_mfg' => '%s',\n", combo->par_mfg); } else { printf(" 'par_mfg' => undef,\n"); } if (combo->par_mdl) { printf(" 'par_mdl' => '%s',\n", combo->par_mdl); } else { printf(" 'par_mdl' => undef,\n"); } if (combo->par_des) { printf(" 'par_des' => '%s',\n", combo->par_des); } else { printf(" 'par_des' => undef,\n"); } if (combo->par_cmd) { printf(" 'par_cmd' => '%s',\n", combo->par_cmd); } else { printf(" 'par_cmd' => undef,\n"); } if (combo->usb_ieee) { printf(" 'usb_ieee' => '%s',\n", combo->usb_ieee); } else { printf(" 'usb_ieee' => undef,\n"); } if (combo->usb_mfg) { printf(" 'usb_mfg' => '%s',\n", combo->usb_mfg); } else { printf(" 'usb_mfg' => undef,\n"); } if (combo->usb_mdl) { printf(" 'usb_mdl' => '%s',\n", combo->usb_mdl); } else { printf(" 'usb_mdl' => undef,\n"); } if (combo->usb_des) { printf(" 'usb_des' => '%s',\n", combo->usb_des); } else { printf(" 'usb_des' => undef,\n"); } if (combo->usb_cmd) { printf(" 'usb_cmd' => '%s',\n", combo->usb_cmd); } else { printf(" 'usb_cmd' => undef,\n"); } if (combo->snmp_ieee) { printf(" 'snmp_ieee' => '%s',\n", combo->snmp_ieee); } else { printf(" 'snmp_ieee' => undef,\n"); } if (combo->snmp_mfg) { printf(" 'snmp_mfg' => '%s',\n", combo->snmp_mfg); } else { printf(" 'snmp_mfg' => undef,\n"); } if (combo->snmp_mdl) { printf(" 'snmp_mdl' => '%s',\n", combo->snmp_mdl); } else { printf(" 'snmp_mdl' => undef,\n"); } if (combo->snmp_des) { printf(" 'snmp_des' => '%s',\n", combo->snmp_des); } else { printf(" 'snmp_des' => undef,\n"); } if (combo->snmp_cmd) { printf(" 'snmp_cmd' => '%s',\n", combo->snmp_cmd); } else { printf(" 'snmp_cmd' => undef,\n"); } printf(" 'driver' => '%s',\n", combo->driver); if (combo->driver_group) { printf(" 'group' => '%s',\n", combo->driver_group); } if (combo->pcdriver) { printf(" 'pcdriver' => '%s',\n", combo->pcdriver); } else { printf(" 'pcdriver' => undef,\n"); } printf(" 'type' => '%s',\n", combo->driver_type); if (combo->driver_comment) { printf(" 'comment' => '%s',\n", combo->driver_comment); } else { printf(" 'comment' => undef,\n"); } if (combo->url) { printf(" 'url' => '%s',\n", combo->url); } else { printf(" 'url' => undef,\n"); } if (combo->driver_obsolete) { printf(" 'obsolete' => '%s',\n", combo->driver_obsolete); } if (combo->supplier != NULL) { printf(" 'supplier' => '%s',\n", combo->supplier); } if (combo->manufacturersupplied != NULL) { printf(" 'manufacturersupplied' => '%s',\n", combo->manufacturersupplied); } if (combo->license != NULL) { printf(" 'license' => '%s',\n", combo->license); } if (combo->licensetext != NULL) { printf(" 'licensetext' => '%s',\n", combo->licensetext); } if (combo->origlicensetext != NULL) { printf(" 'origlicensetext' => '%s',\n", combo->origlicensetext); } if (combo->licenselink != NULL) { printf(" 'licenselink' => '%s',\n", combo->licenselink); } if (combo->origlicenselink != NULL) { printf(" 'origlicenselink' => '%s',\n", combo->origlicenselink); } if (combo->free != NULL) { printf(" 'free' => '%s',\n", combo->free); } if (combo->patents != NULL) { printf(" 'patents' => '%s',\n", combo->patents); } if (combo->num_supportcontacts != 0) { printf(" 'supportcontacts' => [\n"); for (i = 0; i < combo->num_supportcontacts; i ++) { if (combo->supportcontacturls[i] != NULL) { printf(" {\n"); printf(" 'description' => '%s',\n", combo->supportcontacts[i]); if (combo->supportcontacturls[i] != NULL) printf(" 'url' => '%s',\n", combo->supportcontacturls[i]); printf(" 'level' => '%s',\n", combo->supportcontactlevels[i]); printf(" },\n"); } } printf(" ],\n"); } if (combo->shortdescription != NULL) { printf(" 'shortdescription' => '%s',\n", combo->shortdescription); } if (combo->locales != NULL) { printf(" 'locales' => '%s',\n", combo->locales); } if (combo->num_packages != 0) { printf(" 'packages' => [\n"); for (i = 0; i < combo->num_packages; i ++) { if (combo->packageurls[i] != NULL) { printf(" {\n"); printf(" 'url' => '%s',\n", combo->packageurls[i]); if (combo->packagescopes[i] != NULL) printf(" 'scope' => '%s',\n", combo->packagescopes[i]); if (combo->packagefingerprints[i] != NULL) printf(" 'fingerprint' => '%s',\n", combo->packagefingerprints[i]); printf(" },\n"); } } printf(" ],\n"); } if (combo->excmaxresx != NULL) { printf(" 'drvmaxresx' => '%s',\n", combo->excmaxresx); } else if (combo->drvmaxresx != NULL) { printf(" 'drvmaxresx' => '%s',\n", combo->drvmaxresx); } if (combo->excmaxresy != NULL) { printf(" 'drvmaxresy' => '%s',\n", combo->excmaxresy); } else if (combo->drvmaxresy != NULL) { printf(" 'drvmaxresy' => '%s',\n", combo->drvmaxresy); } if (combo->exccolor != NULL) { printf(" 'drvcolor' => '%s',\n", combo->exccolor); } else if (combo->drvcolor != NULL) { printf(" 'drvcolor' => '%s',\n", combo->drvcolor); } if (combo->exctext != NULL) { printf(" 'text' => '%s',\n", combo->exctext); } else if (combo->text != NULL) { printf(" 'text' => '%s',\n", combo->text); } if (combo->exclineart != NULL) { printf(" 'lineart' => '%s',\n", combo->exclineart); } else if (combo->lineart != NULL) { printf(" 'lineart' => '%s',\n", combo->lineart); } if (combo->excgraphics != NULL) { printf(" 'graphics' => '%s',\n", combo->excgraphics); } else if (combo->graphics != NULL) { printf(" 'graphics' => '%s',\n", combo->graphics); } if (combo->excphoto != NULL) { printf(" 'photo' => '%s',\n", combo->excphoto); } else if (combo->photo != NULL) { printf(" 'photo' => '%s',\n", combo->photo); } if (combo->excload != NULL) { printf(" 'load' => '%s',\n", combo->excload); } else if (combo->load != NULL) { printf(" 'load' => '%s',\n", combo->load); } if (combo->excspeed != NULL) { printf(" 'speed' => '%s',\n", combo->excspeed); } else if (combo->speed != NULL) { printf(" 'speed' => '%s',\n", combo->speed); } if (combo->num_requires != 0) { printf(" 'requires' => [\n"); for (i = 0; i < combo->num_requires; i ++) { if (combo->requires[i] != NULL) { printf(" {\n"); printf(" 'driver' => '%s',\n", combo->requires[i]); if (combo->requiresversion[i] != NULL) printf(" 'version' => '%s',\n", combo->requiresversion[i]); printf(" },\n"); } } printf(" ],\n"); } if (combo->cmd) { printf(" 'cmd' => '%s',\n", combo->cmd); } else { printf(" 'cmd' => undef,\n"); } if (combo->cmd_pdf) { printf(" 'cmd_pdf' => '%s',\n", combo->cmd_pdf); } else { printf(" 'cmd_pdf' => undef,\n"); } if (combo->nopjl) { printf(" 'drivernopjl' => %s,\n", combo->nopjl); } else { printf(" 'drivernopjl' => 0,\n"); } if (combo->nopageaccounting) { printf(" 'drivernopageaccounting' => %s,\n", combo->nopageaccounting); } else { printf(" 'drivernopageaccounting' => 0,\n"); } if (combo->driverppdentry) { printf(" 'driverppdentry' => '%s',\n", combo->driverppdentry); } else { printf(" 'driverppdentry' => undef,\n"); } if (combo->comboppdentry) { printf(" 'comboppdentry' => '%s',\n", combo->comboppdentry); } else { printf(" 'comboppdentry' => undef,\n"); } if (combo->drivermargins) { printf(" 'drivermargins' => {\n"); generateMarginsPerlData(combo->drivermargins, debug); printf(" },\n"); } if (combo->combomargins) { printf(" 'combomargins' => {\n"); generateMarginsPerlData(combo->combomargins, debug); printf(" },\n"); } if (combo->maxspot > 0) { printf(" 'maxspot' => '%s',\n", combo->maxspot); } else { printf(" 'maxspot' => 'A',\n"); } printf(" 'args_byname' => {\n"); for (i = 0; i < combo->num_args; i ++) { printf(" '%s' => {},\n", combo->args[i]->name); } printf(" },\n"); printf(" 'args' => [\n"); for (i = 0; i < combo->num_args; i ++) { printf(" {\n"); printf(" 'name' => '%s',\n", combo->args[i]->name); if (combo->args[i]->name_false) { printf(" 'name_false' => '%s',\n", combo->args[i]->name_false); } printf(" 'comment' => '%s',\n", combo->args[i]->comment); printf(" 'idx' => '%s',\n", combo->args[i]->idx); printf(" 'type' => '%s',\n", combo->args[i]->option_type); printf(" 'style' => '%s',\n", combo->args[i]->style); if (combo->args[i]->substyle) { printf(" 'substyle' => '%s',\n", combo->args[i]->substyle); } printf(" 'spot' => '%s',\n", combo->args[i]->spot); printf(" 'order' => '%s',\n", combo->args[i]->order); if (combo->args[i]->section) { printf(" 'section' => '%s',\n", combo->args[i]->section); } if (combo->args[i]->grouppath) { printf(" 'group' => '%s',\n", combo->args[i]->grouppath); } if (combo->args[i]->proto) { printf(" 'proto' => '%s',\n", combo->args[i]->proto); } if (combo->args[i]->required) { printf(" 'required' => 1,\n"); } if (combo->args[i]->min_value) { printf(" 'min' => '%s',\n", combo->args[i]->min_value); } if (combo->args[i]->max_value) { printf(" 'max' => '%s',\n", combo->args[i]->max_value); } if (combo->args[i]->max_length) { printf(" 'maxlength' => '%s',\n", combo->args[i]->max_length); } if (combo->args[i]->allowed_chars) { printf(" 'allowedchars' => '%s',\n", combo->args[i]->allowed_chars); } if (combo->args[i]->allowed_regexp) { printf(" 'allowedregexp' => '%s',\n", combo->args[i]->allowed_regexp); } if (combo->args[i]->default_value) { printf(" 'default' => '%s',\n", combo->args[i]->default_value); } else { printf(" 'default' => 'None',\n"); } if (combo->args[i]->num_choices > 0) { printf(" 'vals_byname' => {\n"); for (j = 0; j < combo->args[i]->num_choices; j ++) { if (combo->args[i]->choices[j]->value == NULL) { static xmlChar sc_None [] = "None"; combo->args[i]->choices[j]->value = sc_None; } printf(" '%s' => {\n", combo->args[i]->choices[j]->value); printf(" 'value' => '%s',\n", combo->args[i]->choices[j]->value); if (combo->args[i]->choices[j]->comment) { printf(" 'comment' => '%s',\n", combo->args[i]->choices[j]->comment); } printf(" 'idx' => '%s',\n", combo->args[i]->choices[j]->idx); if (combo->args[i]->choices[j]->driverval) { printf(" 'driverval' => '%s'\n", combo->args[i]->choices[j]->driverval); } else { printf(" 'driverval' => ''\n"); } printf(" },\n"); } printf(" },\n"); printf(" 'vals' => [\n"); for (j = 0; j < combo->args[i]->num_choices; j ++) { printf(" {},\n"); } printf(" ]\n"); } printf(" },\n"); } printf(" ]\n"); printf("};\n"); for (i = 0; i < combo->num_args; i ++) { for (j = 0; j < combo->args[i]->num_choices; j ++) { printf("$VAR1->{'args'}[%d]{'vals'}[%d] = $VAR1->{'args'}[%d]{'vals_byname'}{'%s'};\n", i, j, i, combo->args[i]->choices[j]->value); } } for (i = 0; i < combo->num_args; i ++) { printf("$VAR1->{'args_byname'}{'%s'} = $VAR1->{'args'}[%d];\n", combo->args[i]->name, i); } } void generatePrinterPerlData(printerEntryPtr printer, /* I/O - Foomatic printer data parsed from XML input */ int debug) { /* Debug flag */ int i; /* loop variable */ int haspsdriver = 0; /* Is the "Postscript" driver in the printer's driver list? */ printf("$VAR1 = {\n"); printf(" 'id' => '%s',\n", printer->id); printf(" 'make' => '%s',\n", printer->make); printf(" 'model' => '%s',\n", printer->model); if (printer->printer_type) { printf(" 'type' => '%s',\n", printer->printer_type); } if (printer->color) { printf(" 'color' => '%s',\n", printer->color); } if (printer->maxxres) { printf(" 'maxxres' => '%s',\n", printer->maxxres); } if (printer->maxyres) { printf(" 'maxyres' => '%s',\n", printer->maxyres); } if (printer->printerppdentry) { printf(" 'ppdentry' => '%s',\n", printer->printerppdentry); } else { printf(" 'ppdentry' => undef,\n"); } if (printer->printermargins) { printf(" 'margins' => {\n"); generateMarginsPerlData(printer->printermargins, debug); printf(" },\n"); } if (printer->refill) { printf(" 'refill' => '%s',\n", printer->refill); } if (printer->ascii) { printf(" 'ascii' => '%s',\n", printer->ascii); } if (printer->pjl) { printf(" 'pjl' => '%s',\n", printer->pjl); } if (printer->num_languages > 0) { printf(" 'languages' => [\n"); for (i = 0; i < printer->num_languages; i ++) { printf(" {\n"); printf(" 'name' => '%s',\n", printer->languages[i]->name); printf(" 'level' => '%s',\n", printer->languages[i]->level); printf(" },\n"); } printf(" ],\n"); } if (printer->ppdurl) { printf(" 'ppdurl' => '%s',\n", printer->ppdurl); } if (printer->general_ieee) { printf(" 'general_ieee' => '%s',\n", printer->general_ieee); } if (printer->general_mfg) { printf(" 'general_mfg' => '%s',\n", printer->general_mfg); } if (printer->general_mdl) { printf(" 'general_mdl' => '%s',\n", printer->general_mdl); } if (printer->general_des) { printf(" 'general_des' => '%s',\n", printer->general_des); } if (printer->general_cmd) { printf(" 'general_cmd' => '%s',\n", printer->general_cmd); } if (printer->par_ieee) { printf(" 'par_ieee' => '%s',\n", printer->par_ieee); } if (printer->par_mfg) { printf(" 'par_mfg' => '%s',\n", printer->par_mfg); } if (printer->par_mdl) { printf(" 'par_mdl' => '%s',\n", printer->par_mdl); } if (printer->par_des) { printf(" 'par_des' => '%s',\n", printer->par_des); } if (printer->par_cmd) { printf(" 'par_cmd' => '%s',\n", printer->par_cmd); } if (printer->usb_ieee) { printf(" 'usb_ieee' => '%s',\n", printer->usb_ieee); } if (printer->usb_mfg) { printf(" 'usb_mfg' => '%s',\n", printer->usb_mfg); } if (printer->usb_mdl) { printf(" 'usb_mdl' => '%s',\n", printer->usb_mdl); } if (printer->usb_des) { printf(" 'usb_des' => '%s',\n", printer->usb_des); } if (printer->usb_cmd) { printf(" 'usb_cmd' => '%s',\n", printer->usb_cmd); } if (printer->snmp_ieee) { printf(" 'snmp_ieee' => '%s',\n", printer->snmp_ieee); } if (printer->snmp_mfg) { printf(" 'snmp_mfg' => '%s',\n", printer->snmp_mfg); } if (printer->snmp_mdl) { printf(" 'snmp_mdl' => '%s',\n", printer->snmp_mdl); } if (printer->snmp_des) { printf(" 'snmp_des' => '%s',\n", printer->snmp_des); } if (printer->snmp_cmd) { printf(" 'snmp_cmd' => '%s',\n", printer->snmp_cmd); } if (printer->functionality) { printf(" 'functionality' => '%s',\n", printer->functionality); } if (printer->driver) { printf(" 'driver' => '%s',\n", printer->driver); } if ((printer->num_drivers > 0) || (printer->ppdurl)) { printf(" 'drivers' => [\n"); for (i = 0; i < printer->num_drivers; i ++) { printf(" {\n"); if (printer->drivers[i]->name) { if (xmlStrncmp(printer->drivers[i]->name, sc_Postscript, 10)) haspsdriver = 1; printf(" 'name' => '%s',\n", printer->drivers[i]->name); printf(" 'id' => '%s',\n", printer->drivers[i]->name); } if (printer->drivers[i]->ppd) { printf(" 'ppd' => '%s',\n", printer->drivers[i]->ppd); } if (printer->drivers[i]->comment) { printf(" 'comment' => '%s',\n", printer->drivers[i]->comment); } printf(" },\n"); } if ((printer->ppdurl) && !haspsdriver) { printf(" {\n"); printf(" 'name' => '%s',\n", "Postscript"); printf(" 'id' => '%s',\n", "Postscript"); printf(" 'ppd' => '%s',\n", printer->ppdurl); printf(" },\n"); } printf(" ],\n"); } if (printer->unverified) { printf(" 'unverified' => '%s',\n", printer->unverified); } if (printer->noxmlentry) { printf(" 'noxmlentry' => '%s',\n", printer->noxmlentry); } if (printer->url) { printf(" 'url' => '%s',\n", printer->url); } if (printer->contriburl) { printf(" 'contriburl' => '%s',\n", printer->contriburl); } if (printer->comment) { printf(" 'comment' => '%s',\n", printer->comment); } printf("};\n"); } void generateDriverPerlData(driverEntryPtr driver, /* I/O - Foomatic driver data parsed from XML input */ int debug) { /* Debug flag */ int i; /* loop variable */ xmlChar *id; xmlChar *name; xmlChar *url; xmlChar *driver_type; xmlChar *cmd; xmlChar *comment; int num_printers; xmlChar **printers; printf("$VAR1 = {\n"); printf(" 'name' => '%s',\n", driver->name); if (driver->group) { printf(" 'group' => '%s',\n", driver->group); } if (driver->url) { printf(" 'url' => '%s',\n", driver->url); } if (driver->driver_obsolete) { printf(" 'obsolete' => '%s',\n", driver->driver_obsolete); } if (driver->supplier != NULL) { printf(" 'supplier' => '%s',\n", driver->supplier); } if (driver->manufacturersupplied != NULL) { printf(" 'manufacturersupplied' => '%s',\n", driver->manufacturersupplied); } if (driver->license != NULL) { printf(" 'license' => '%s',\n", driver->license); } if (driver->licensetext != NULL) { printf(" 'licensetext' => '%s',\n", driver->licensetext); } if (driver->origlicensetext != NULL) { printf(" 'origlicensetext' => '%s',\n", driver->origlicensetext); } if (driver->licenselink != NULL) { printf(" 'licenselink' => '%s',\n", driver->licenselink); } if (driver->origlicenselink != NULL) { printf(" 'origlicenselink' => '%s',\n", driver->origlicenselink); } if (driver->free != NULL) { printf(" 'free' => '%s',\n", driver->free); } if (driver->patents != NULL) { printf(" 'patents' => '%s',\n", driver->patents); } if (driver->num_supportcontacts != 0) { printf(" 'supportcontacts' => [\n"); for (i = 0; i < driver->num_supportcontacts; i ++) { if (driver->supportcontacturls[i] != NULL) { printf(" {\n"); printf(" 'description' => '%s',\n", driver->supportcontacts[i]); if (driver->supportcontacturls[i] != NULL) printf(" 'url' => '%s',\n", driver->supportcontacturls[i]); printf(" 'level' => '%s',\n", driver->supportcontactlevels[i]); printf(" },\n"); } } printf(" ],\n"); } if (driver->shortdescription != NULL) { printf(" 'shortdescription' => '%s',\n", driver->shortdescription); } if (driver->locales != NULL) { printf(" 'locales' => '%s',\n", driver->locales); } if (driver->num_packages != 0) { printf(" 'packages' => [\n"); for (i = 0; i < driver->num_packages; i ++) { if (driver->packageurls[i] != NULL) { printf(" {\n"); printf(" 'url' => '%s',\n", driver->packageurls[i]); if (driver->packagescopes[i] != NULL) printf(" 'scope' => '%s',\n", driver->packagescopes[i]); if (driver->packagefingerprints[i] != NULL) printf(" 'fingerprint' => '%s',\n", driver->packagefingerprints[i]); printf(" },\n"); } } printf(" ],\n"); } if (driver->maxresx != NULL) { printf(" 'drvmaxresx' => '%s',\n", driver->maxresx); } if (driver->maxresy != NULL) { printf(" 'drvmaxresy' => '%s',\n", driver->maxresy); } if (driver->color != NULL) { printf(" 'drvcolor' => '%s',\n", driver->color); } if (driver->text != NULL) { printf(" 'text' => '%s',\n", driver->text); } if (driver->lineart != NULL) { printf(" 'lineart' => '%s',\n", driver->lineart); } if (driver->graphics != NULL) { printf(" 'graphics' => '%s',\n", driver->graphics); } if (driver->photo != NULL) { printf(" 'photo' => '%s',\n", driver->photo); } if (driver->load != NULL) { printf(" 'load' => '%s',\n", driver->load); } if (driver->speed != NULL) { printf(" 'speed' => '%s',\n", driver->speed); } if (driver->num_requires != 0) { printf(" 'requires' => [\n"); for (i = 0; i < driver->num_requires; i ++) { if (driver->requires[i] != NULL) { printf(" {\n"); printf(" 'driver' => '%s',\n", driver->requires[i]); if (driver->requiresversion[i] != NULL) printf(" 'version' => '%s',\n", driver->requiresversion[i]); printf(" },\n"); } } printf(" ],\n"); } if (driver->driver_type) { printf(" 'type' => '%s',\n", driver->driver_type); } if (driver->cmd) { printf(" 'cmd' => '%s',\n", driver->cmd); } if (driver->cmd_pdf) { printf(" 'cmd_cmd' => '%s',\n", driver->cmd_pdf); } if (driver->driverppdentry) { printf(" 'ppdentry' => '%s',\n", driver->driverppdentry); } else { printf(" 'ppdentry' => undef,\n"); } if (driver->drivermargins) { printf(" 'margins' => {\n"); generateMarginsPerlData(driver->drivermargins, debug); printf(" },\n"); } if (driver->comment) { printf(" 'comment' => '%s',\n", driver->comment); } if (driver->num_printers > 0) { printf(" 'printers' => [\n"); for (i = 0; i < driver->num_printers; i ++) { printf(" {\n"); printf(" 'id' => '%s',\n", driver->printers[i]->id); if (driver->printers[i]->comment) { printf(" 'comment' => '%s'\n", driver->printers[i]->comment); } if (driver->printers[i]->excmaxresx != NULL) { printf(" 'excmaxresx' => '%s',\n", driver->printers[i]->excmaxresx); } if (driver->printers[i]->excmaxresy != NULL) { printf(" 'excmaxresy' => '%s',\n", driver->printers[i]->excmaxresy); } if (driver->printers[i]->exccolor != NULL) { printf(" 'exccolor' => '%s',\n", driver->printers[i]->exccolor); } if (driver->printers[i]->exctext != NULL) { printf(" 'exctext' => '%s',\n", driver->printers[i]->exctext); } if (driver->printers[i]->exclineart != NULL) { printf(" 'exclineart' => '%s',\n", driver->printers[i]->exclineart); } if (driver->printers[i]->excgraphics != NULL) { printf(" 'excgraphics' => '%s',\n", driver->printers[i]->excgraphics); } if (driver->printers[i]->excphoto != NULL) { printf(" 'excphoto' => '%s',\n", driver->printers[i]->excphoto); } if (driver->printers[i]->excload != NULL) { printf(" 'excload' => '%s',\n", driver->printers[i]->excload); } if (driver->printers[i]->excspeed != NULL) { printf(" 'excspeed' => '%s',\n", driver->printers[i]->excspeed); } printf(" },\n"); } printf(" ]\n"); } else { printf(" 'printers' => []\n"); } printf("};\n"); } int /* O - Error state */ main(int argc, char **argv) { /* I - Command line arguments */ int i, j; /* loop variables */ int debug = 0; /* Debug output level */ xmlChar *setting; xmlChar const *language = sc_locale_C; xmlChar **defaultsettings = NULL; /* User-supplied option settings*/ int num_defaultsettings = 0; char *filename = NULL; int datatype = 1; /* Data type to parse: 0: Overview, 1: Combo 2: Printer, 3: Driver */ comboDataPtr combo; /* C data structure of printer/driver combo */ overviewPtr overview; /* C data structure of printer/driver combo */ printerEntryPtr printer; /* C data structure of printer entry */ driverEntryPtr driver; /* C data structure of driver entry*/ /* COMPAT: Do not genrate nodes for formatting spaces */ LIBXML_TEST_VERSION xmlKeepBlanksDefault(0); /* Read the command line arguments */ for (i = 1; i < argc; i ++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'O' : /* Parse overview */ datatype = 0; break; case 'C' : /* Parse combo */ datatype = 1; break; case 'P' : /* Parse printer */ datatype = 2; break; case 'D' : /* Parse driver */ datatype = 3; break; case 'o' : /* option setting */ if (argv[i][2] != '\0') setting = (xmlChar *)(argv[i] + 2); else { i ++; setting = (xmlChar *)(argv[i]); } num_defaultsettings ++; defaultsettings = (xmlChar **)realloc((xmlChar **)defaultsettings, sizeof(xmlChar *) * num_defaultsettings); defaultsettings[num_defaultsettings-1] = xmlStrdup (setting); break; case 'l' : /* language */ if (argv[i][2] != '\0') language = (xmlChar *)(argv[i] + 2); else { i ++; language = (xmlChar *)(argv[i]); } break; case 'v' : /* verbose */ debug++; j = 2; while (argv[i][j] != '\0') { if (argv[i][j] == 'v') debug++; j++; } break; case '?' : case 'h' : /* Help */ fprintf(stderr, "Usage: foomatic-perl-data [ -O ] [ -C ] [ -P ] [ -D ]\n [ -o option=setting ] [ -o ... ] [ -l language ]\n [ -v ] [ -vv ] [ filename ]\n"); fprintf(stderr, "\n"); fprintf(stderr, " -O Parse overview XML data\n"); fprintf(stderr, " -C Parse printer/driver combo XML data (default)\n"); fprintf(stderr, " -P Parse printer entry XML data\n"); fprintf(stderr, " -D Parse driver entry XML data\n"); fprintf(stderr, " -o option=setting\n"); fprintf(stderr, " Default option settings for the generated Perl data (combo\n"); fprintf(stderr, " only, no range-checking)\n"); fprintf(stderr, " -l language Language in which the texts are returned, default is \"en\"\n"); fprintf(stderr, " (English). If the text in the requested language is missing,\n"); fprintf(stderr, " english text will be returned.\n"); fprintf(stderr, " -v Verbose (debug) mode\n"); fprintf(stderr, " -vv Very verbose (debug) mode\n"); fprintf(stderr, " filename Read input from a file and not from standard input\n"); fprintf(stderr, "\n"); exit(1); break; default : fprintf(stderr, "Unknown option \'-%c\'!\n", argv[i][1]); exit(1); } } else { filename = argv[i]; } } if (debug) fprintf(stderr,"Language: %s\n", language); if (datatype == 0) { /* Parse overview data */ /* Parse the XML input */ overview = parseOverviewFile(filename, language, debug); if (overview) { /* Generate the Perl data structure on standard output */ generateOverviewPerlData(overview, debug); } else { exit(1); } } else if (datatype == 1) { /* Parse printer/driver combo data */ /* Parse the XML input */ combo = parseComboFile(filename, language, debug); if (combo) { /* Prepare the data for the output */ prepareComboData(combo, defaultsettings, num_defaultsettings, debug); /* Generate the Perl data structure on standard output */ generateComboPerlData(combo, debug); } else { exit(1); } } else if (datatype == 2) { /* Parse overview data */ /* Parse the XML input */ printer = parsePrinterFile(filename, language, debug); if (printer) { /* Generate the Perl data structure on standard output */ generatePrinterPerlData(printer, debug); } else { exit(1); } } else if (datatype == 3) { /* Parse overview data */ /* Parse the XML input */ driver = parseDriverFile(filename, language, debug); if (driver) { /* Generate the Perl data structure on standard output */ generateDriverPerlData(driver, debug); } else { exit(1); } } /* Clean up everything else before quitting. */ xmlCleanupParser(); return(0); }