/* * Foomatic Combo XML * ------------------ * * Compute a Foomatic printer/driver combo by a pure C program doing * a simplified sequential-reading XML-parsing. Perl libraries which * make Perl data structures out of the XML files are very slow and * memory-consuming. * * 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 * */ /* * Include necessary headers (standard libraries) */ #include #include #include #include #include /* * Data structures for the printer/driver combo by printer list for the * overview ("-O" option) */ typedef struct { /* structure for a driver entry (linear list) */ char name[128]; /* Name of driver */ struct driverlist_t *next; /* pointer to next driver */ } driverlist_t; typedef struct { /* structure for a printer entry (linear list) */ char id[128]; /* ID of printer */ driverlist_t *drivers; /* pointer to the list of the drivers with which this printer works */ struct printerlist_t *next; /* pointer to next printer */ } printerlist_t; typedef struct { /* structure for a ready-made PPD entry (linear list) */ char driver[128]; /* ID of driver */ char ppd[1024]; /* ID of PPD URL */ struct ppdlist_t *next; /* pointer to next PPD */ } ppdlist_t; typedef struct { /* structure for printer ID translations (linear list) */ char *oldid, /* old ID of printer */ *newid; /* current ID of printer */ struct idlist_t *next; /* pointer to next entry */ } idlist_t; /* * function to load a file into the memory */ char /* O - pointer to the file in memory */ *loadfile(const char *filename) { /* I - file name */ const int blocksize = 1024 * 1024; FILE *inputfile; /* file to be read currently */ char buffer[blocksize + 1];/* data block currently read */ char *data = NULL; /* the read data */ int size = 1; /* size of the data in memory */ int bytesread; /* bytes actually read */ /* Open the file */ inputfile = fopen(filename, "r"); if (inputfile == NULL) { fprintf(stderr, "Cannot read file %s!\n", filename); return NULL; } /* Read the whole file into the memory */ data = (char *)malloc(size); data[0] = '\0'; while((bytesread = fread(buffer,1,blocksize,inputfile))) { data = (char *)realloc(data, size + bytesread); buffer[bytesread] = '\0'; strcat(data, buffer); size += bytesread; } fclose(inputfile); /* Make space for additional data */ data = (char *)realloc(data, size + 4096); if (strcmp(data, "")) return(data); else { free((void *)data); return(NULL); } } /* * function to load the printer ID translation table */ idlist_t /* O - pointer to the printer ID translation table */ *loadidlist(const char *filename) { /* I - file name */ char *idlistbuffer = NULL; /* ID list in memory */ char *scan; /* pointer for scanning through the list */ char *oldid = NULL, *newid = NULL; /* pointers to IDs in the current line */ int inoldid = 0, /* Are we reading and old or a new ID */ innewid = 0; /* currently */ idlist_t *idlist = NULL, /* Pointer to ID list */ *currentitem = NULL, /* Pointer to current ID list item */ *newitem; /* Pointer to newly created ID list item */ idlistbuffer = loadfile(filename); if (!idlistbuffer) return NULL; for (scan = idlistbuffer; *scan != '\0'; scan++) { switch(*scan) { case '\r': case '\n': /* line break */ /* line end */ if (inoldid) { /* Line with only one word, ignore it */ inoldid = 0; oldid = NULL; break; } case '\t': /* tab */ case ' ': /* space */ /* white space */ if (inoldid) { /* old ID completed */ inoldid = 0; *scan = '\0'; } if (innewid) { /* new ID completed */ innewid = 0; *scan = '\0'; if (oldid && newid && (*oldid != '#')) { /* found a pair of old ID and new ID, add it to the translation list */ newitem = (idlist_t *)malloc(sizeof(idlist_t)); newitem->oldid = oldid; newitem->newid = newid; newitem->next = NULL; if (currentitem) { currentitem->next = (struct idlist_t *)newitem; } else { idlist = newitem; } currentitem = newitem; } oldid = NULL; newid = NULL; } break; default: /* all other characters, so no whitespace now */ if (!(inoldid || innewid)) { /* last character was whitespace */ if (oldid) { /* Beginning of second word in the line */ innewid = 1; newid = scan; } else { /* Beginning of first word in the line */ inoldid = 1; oldid = scan; } } } } return idlist; } /* * function to translate an old printer ID into a new one */ char /* O - new ID */ *translateid(const char *oldid, /* I - Old ID */ idlist_t *idlist) { /* I - ID translation table */ idlist_t *currentitem = idlist; /* Pointer to current ID list item */ while(currentitem) { if (strcmp(oldid, currentitem->oldid) == 0) { return currentitem->newid; } currentitem = (idlist_t *)(currentitem->next); } return (char *)oldid; } /* * function to parse an XML file and do a task on it */ int /* O - Is the requested printer driver combo already confirmed by the section in the printer XML file (operation = 0 only) */ parse(char **data, /* I/O - Data to process */ const char *pid, /* I - Foomatic printer ID */ const char *driver,/* I - driver name */ const char *filename, /* I - file name for error messages */ printerlist_t **printerlist, /* I/O printer list for overview */ int operation, /* I - Operation type: 0: printer, 1: driver, 2: option 3: overview driver 4: overview printer */ const char **defaultsettings, /* I - Default option settings given on the command line */ int num_defaultsettings, /* I - Number of default option settings */ int *nopjl, /* I/O - 0: driver allows PJL options, 1: driver does not allow PJL options (has "" flag in "" section) */ idlist_t *idlist, /* I - ID translation table */ int debug) { /* I - Debug flag: If set, debugging output is produced */ char *trpid = NULL; /* current printer ID translated according to translation table */ int datalength = 0; /* length of the XML file */ int linecount = 1; /* Count the lines for error messages */ int nestinglevel = 0;/* How many XML environments are nested at the point where we are */ int intag = 0; int incomment = 0; int tagnamefound = 0; int intagword = 0; int inquotes = 0; int insinglequotes = 0; int indoublequotes = 0; int tagtype = 0; /*1: opening, -1: closing, 0: opening & closing*/ int inprinter = 0; int inmake = 0; int inmodel = 0; int inautodetect = 0; int indriver = 0; int indrivers = 0; int inexecution = 0; int inprototype = 0; int innopjl = 0; int inprinters = 0; int inid = 0; int inppd = 0; int inlang = 0; int inpostscript = 0; int inoption = 0; int inargshortname = 0; int inargexecution = 0; int inargpjl = 0; int inevshortname = 0; int inen = 0; int inargmax = 0; int inargmin = 0; int inenumval = 0; int inconstraints = 0; int inconstraint = 0; int inargdefault = 0; int infunctionality = 0; int inunverified = 0; int printertobesaved = 0; int printerentryfound = 0; int constrainttoberemoved = 0; int enumvaltoberemoved = 0; int optionqualified = 0; int enumvalqualified = 1; int numenumvals = 1; /* Number of enumeration values, disqualifies option when 0 at the end of the file. It is set to zero in the beginning of an enum option, for boolean or numerical options it stays 1 to not disqualify the option */ int optiontype = 0; /* 0: enum, 1: bool, 2: int, 3: float */ int printerscore = 0; int driverscore = 0; int printerhiscore = 0; int driverhiscore = 0; int defaultlinelength = 0; char currtagname[256]; char currtagparam[256]; char currtagbody[65536]; char optiondefault[256]; int userdefault = 0; int userdefaultfound = 0; char userdefaultvalue[256]; char userdefaultid[256]; char currevid[256]; double maxnumvalue = 0; double minnumvalue = 0; int csense = 0; char cprinter[256]; char cmake[256]; char cmodel[256]; char cdriver[256]; char cid[256]; char cppd[1024]; char cfunctionality[256]; int cunverified = 0; char cautodetectentry[4096]; char cargdefault[256]; char argdefault[256]; char defaultline[256]; char printerentry[1024*1024]; const char *scan; /* pointer for scanning through the file*/ const char *lasttag = NULL; /* Start of last XML tag */ const char *lasttagend = NULL; /* End of last XML tag */ const char *tagwordstart = NULL;/* Beginning of tagname */ char *lastprinters = NULL; /* Start of last tag */ char *lastprinter = NULL; /* Start of last tag */ char *lastenumval = NULL; /* Start of last tag */ char *lastconstraints = NULL; /* Start of last tag */ char *lastoption = NULL; /* Start of last