libgimpprint API Reference: src/main/xml.c Source File

Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

# src/main/xml.c

Go to the documentation of this file.

    00001 /*
    00002  * "$Id: xml_8c-source.html,v 1.1.1.2 2004/12/22 23:49:22 jlovell Exp $"
    00003  *
    00004  *   XML parser - process gimp-print XML data with mxml.
    00005  *
    00006  *   Copyright 2002-2003 Roger Leigh (rleigh@debian.org)
    00007  *
    00008  *   This program is free software; you can redistribute it and/or modify it
    00009  *   under the terms of the GNU General Public License as published by the Free
    00010  *   Software Foundation; either version 2 of the License, or (at your option)
    00011  *   any later version.
    00012  *
    00013  *   This program is distributed in the hope that it will be useful, but
    00014  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    00015  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    00016  *   for more details.
    00017  *
    00018  *   You should have received a copy of the GNU General Public License
    00019  *   along with this program; if not, write to the Free Software
    00020  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    00021  */
    00022
    00023
    00024 #ifdef HAVE_CONFIG_H
    00025 #include <config.h>
    00026 #endif
    00027 #include <gimp-print/gimp-print.h>
    00028 #include "gimp-print-internal.h"
    00029 #include <gimp-print/gimp-print-intl-internal.h>
    00030 #include <assert.h>
    00031 #include <ctype.h>
    00032 #include <stdio.h>
    00033 #include <stdlib.h>
    00034 #include <string.h>
    00035 #include <math.h>
    00036 #include <errno.h>
    00037 #ifdef HAVE_LIMITS_H
    00038 #include <limits.h>
    00039 #endif
    00040 #if defined(HAVE_VARARGS_H) && !defined(HAVE_STDARG_H)
    00041 #include <varargs.h>
    00042 #else
    00043 #include <stdarg.h>
    00044 #endif
    00045
    00046 typedef struct
    00047 {
    00048   char *name;
    00049   stp_xml_parse_func parse_func;
    00050 } stpi_xml_parse_registry;
    00051
    00052 static stp_list_t *stpi_xml_registry;
    00053
    00054 static stp_list_t *stpi_xml_preloads;
    00055
    00056 static const char *
    00057 xml_registry_namefunc(const void *item)
    00058 {
    00059   const stpi_xml_parse_registry *xmlp = (const stpi_xml_parse_registry *) item;
    00060   return xmlp->name;
    00061 }
    00062
    00063 static void
    00064 xml_registry_freefunc(void *item)
    00065 {
    00066   stpi_xml_parse_registry *xmlp = (stpi_xml_parse_registry *) item;
    00067   stp_free(xmlp->name);
    00068   stp_free(xmlp);
    00069 }
    00070
    00071 static const char *
    00072 xml_preload_namefunc(const void *item)
    00073 {
    00074   return (const char *) item;
    00075 }
    00076
    00077 static void
    00078 xml_preload_freefunc(void *item)
    00079 {
    00080   stp_free(item);
    00081 }
    00082
    00083 void
    00084 stp_register_xml_parser(const char *name, stp_xml_parse_func parse_func)
    00085 {
    00086   stpi_xml_parse_registry *xmlp;
    00087   stp_list_item_t *item = stp_list_get_item_by_name(stpi_xml_registry, name);
    00088   if (item)
    00089     xmlp = (stpi_xml_parse_registry *) stp_list_item_get_data(item);
    00090   else
    00091     {
    00092       xmlp = stp_malloc(sizeof(stpi_xml_parse_registry));
    00093       xmlp->name = stp_strdup(name);
    00094       stp_list_item_create(stpi_xml_registry, NULL, xmlp);
    00095     }
    00096   xmlp->parse_func = parse_func;
    00097 }
    00098
    00099 void
    00100 stp_unregister_xml_parser(const char *name)
    00101 {
    00102   stp_list_item_t *item = stp_list_get_item_by_name(stpi_xml_registry, name);
    00103   if (item)
    00104     stp_list_item_destroy(stpi_xml_registry, item);
    00105 }
    00106
    00107 void
    00108 stp_register_xml_preload(const char *filename)
    00109 {
    00110   stp_list_item_t *item = stp_list_get_item_by_name(stpi_xml_preloads, filename);
    00111   if (!item)
    00112     {
    00113       char *the_filename = stp_strdup(filename);
    00114       stp_list_item_create(stpi_xml_preloads, NULL, the_filename);
    00115     }
    00116 }
    00117
    00118 void
    00119 stp_unregister_xml_preload(const char *name)
    00120 {
    00121   stp_list_item_t *item = stp_list_get_item_by_name(stpi_xml_preloads, name);
    00122   if (item)
    00123     stp_list_item_destroy(stpi_xml_preloads, item);
    00124 }
    00125
    00126
    00127 static void stpi_xml_process_gimpprint(stp_mxml_node_t *gimpprint, const char *file);
    00128
    00129 static char *saved_lc_collate;                 /* Saved LC_COLLATE */
    00130 static char *saved_lc_ctype;                   /* Saved LC_CTYPE */
    00131 static char *saved_lc_numeric;                 /* Saved LC_NUMERIC */
    00132 static int xml_is_initialised;                 /* Flag for init */
    00133
    00134 void
    00135 stp_xml_preinit(void)
    00136 {
    00137   static int xml_is_preinitialized = 0;
    00138   if (!xml_is_preinitialized)
    00139     {
    00140       stpi_xml_registry = stp_list_create();
    00141       stp_list_set_freefunc(stpi_xml_registry, xml_registry_freefunc);
    00142       stp_list_set_namefunc(stpi_xml_registry, xml_registry_namefunc);
    00143       stpi_xml_preloads = stp_list_create();
    00144       stp_list_set_freefunc(stpi_xml_preloads, xml_preload_freefunc);
    00145       stp_list_set_namefunc(stpi_xml_preloads, xml_preload_namefunc);
    00146     }
    00147 }
    00148
    00149 /*
    00150  * Call before using any of the static functions in this file.  All
    00151  * public functions should call this before using any mxml
    00152  * functions.
    00153  */
    00154 void
    00155 stp_xml_init(void)
    00156 {
    00157   if (xml_is_initialised >= 1)
    00158     {
    00159       xml_is_initialised++;
    00160       return;
    00161     }
    00162
    00163   /* Set some locale facets to "C" */
    00164   saved_lc_collate = setlocale(LC_COLLATE, "C");
    00165   saved_lc_ctype = setlocale(LC_CTYPE, "C");
    00166   saved_lc_numeric = setlocale(LC_NUMERIC, "C");
    00167
    00168   xml_is_initialised = 1;
    00169 }
    00170
    00171 /*
    00172  * Call after using any of the static functions in this file.  All
    00173  * public functions should call this after using any mxml functions.
    00174  */
    00175 void
    00176 stp_xml_exit(void)
    00177 {
    00178   if (xml_is_initialised > 1) /* don't restore original state */
    00179     {
    00180       xml_is_initialised--;
    00181       return;
    00182     }
    00183   else if (xml_is_initialised < 1)
    00184     return;
    00185
    00186   /* Restore locale */
    00187   setlocale(LC_COLLATE, saved_lc_collate);
    00188   setlocale(LC_CTYPE, saved_lc_ctype);
    00189   setlocale(LC_NUMERIC, saved_lc_numeric);
    00190   xml_is_initialised = 0;
    00191 }
    00192
    00193 void
    00194 stp_xml_parse_file_named(const char *name)
    00195 {
    00196   stp_list_t *dir_list;                  /* List of directories to scan */
    00197   stp_list_t *file_list;                 /* List of XML files */
    00198   stp_list_item_t *item;                 /* Pointer to current list item */
    00199   if (!(dir_list = stp_list_create()))
    00200     return;
    00201   stp_list_set_freefunc(dir_list, stp_list_node_free_data);
    00202   if (getenv("STP_DATA_PATH"))
    00203     stp_path_split(dir_list, getenv("STP_DATA_PATH"));
    00204   else
    00205     stp_path_split(dir_list, PKGXMLDATADIR);
    00206   file_list = stp_path_search(dir_list, name);
    00207   stp_list_destroy(dir_list);
    00208   item = stp_list_get_start(file_list);
    00209   while (item)
    00210     {
    00211       stp_deprintf(STP_DBG_XML,
    00212                    "stp_xml_parse_file_named: source file: %s\n",
    00213                    (const char *) stp_list_item_get_data(item));
    00214       stp_xml_parse_file((const char *) stp_list_item_get_data(item));
    00215       item = stp_list_item_next(item);
    00216     }
    00217   stp_list_destroy(file_list);
    00218 }
    00219
    00220
    00221 /*
    00222  * Read all available XML files.
    00223  */
    00224 int
    00225 stp_xml_init_defaults(void)
    00226 {
    00227   stp_list_item_t *item;                 /* Pointer to current list item */
    00228
    00229   stp_xml_init();
    00230
    00231   /* Parse each XML file */
    00232   item = stp_list_get_start(stpi_xml_preloads);
    00233   while (item)
    00234     {
    00235       stp_deprintf(STP_DBG_XML, "stp_xml_init_defaults: source file: %s\n",
    00236                    (const char *) stp_list_item_get_data(item));
    00237       stp_xml_parse_file_named((const char *) stp_list_item_get_data(item));
    00238       item = stp_list_item_next(item);
    00239     }
    00240   stp_list_destroy(stpi_xml_preloads);
    00241
    00242   stp_xml_exit();
    00243
    00244   return 0;
    00245 }
    00246
    00247
    00248 /*
    00249  * Parse a single XML file.
    00250  */
    00251 int
    00252 stp_xml_parse_file(const char *file) /* File to parse */
    00253 {
    00254   stp_mxml_node_t *doc;
    00255   stp_mxml_node_t *cur;
    00256   FILE *fp;
    00257
    00258   stp_deprintf(STP_DBG_XML, "stp_xml_parse_file: reading  `%s'...\n", file);
    00259
    00260   fp = fopen(file, "r");
    00261   if (!fp)
    00262     {
    00263       stp_erprintf("stp_xml_parse_file: unable to open %s: %s\n", file,
    00264                    strerror(errno));
    00265       return 1;
    00266     }
    00267
    00268   stp_xml_init();
    00269
    00270   doc = stp_mxmlLoadFile(NULL, fp, STP_MXML_NO_CALLBACK);
    00271   fclose(fp);
    00272
    00273   cur = doc->child;
    00274   while (cur &&
    00275          (cur->type != STP_MXML_ELEMENT ||
    00276           strcmp(cur->value.element.name, "gimp-print") != 0))
    00277     cur = cur->next;
    00278
    00279   if (cur == NULL || cur->type != STP_MXML_ELEMENT)
    00280     {
    00281       stp_erprintf("stp_xml_parse_file: %s: parse error\n", file);
    00282       stp_mxmlDelete(doc);
    00283       return 1;
    00284     }
    00285
    00286   if (strcmp(cur->value.element.name, "gimp-print") != 0)
    00287     {
    00288       stp_erprintf
    00289         ("XML file of the wrong type, root node is %s != gimp-print",
    00290          cur->value.element.name);
    00291       stp_mxmlDelete(doc);
    00292       return 1;
    00293     }
    00294
    00295   /* The XML file was read and is the right format */
    00296
    00297   stpi_xml_process_gimpprint(cur, file);
    00298   stp_mxmlDelete(doc);
    00299
    00300   stp_xml_exit();
    00301
    00302   return 0;
    00303 }
    00304
    00305 /*
    00306  * Convert a text string into an integer.
    00307  */
    00308 long
    00309 stp_xmlstrtol(const char *textval)
    00310 {
    00311   long val; /* The value to return */
    00312   val = strtol(textval, (char **)NULL, 10);
    00313
    00314   return val;
    00315 }
    00316
    00317 /*
    00318  * Convert a text string into an unsigned int.
    00319  */
    00320 unsigned long
    00321 stp_xmlstrtoul(const char *textval)
    00322 {
    00323   unsigned long val; /* The value to return */
    00324   val = strtoul(textval, (char **)NULL, 10);
    00325
    00326   return val;
    00327 }
    00328
    00329 /*
    00330  * Convert a text string into a double.
    00331  */
    00332 double
    00333 stp_xmlstrtod(const char *textval)
    00334 {
    00335   double val; /* The value to return */
    00336   val = strtod(textval, (char **)NULL);
    00337
    00338   return val;
    00339 }
    00340
    00341
    00342 /*
    00343  * Find a node in an XML tree.  This function takes an xmlNodePtr,
    00344  * followed by a NULL-terminated list of nodes which are required.
    00345  * For example stp_xml_get_node(myroot, "gimp-print", "dither") will
    00346  * return the first dither node in the tree.  Additional dither nodes
    00347  * cannot be accessed with this function.
    00348  */
    00349 stp_mxml_node_t *
    00350 stp_xml_get_node(stp_mxml_node_t *xmlroot, ...)
    00351 {
    00352   stp_mxml_node_t *child;
    00353   va_list ap;
    00354   const char *target = NULL;
    00355
    00356   va_start(ap, xmlroot);
    00357
    00358   child = xmlroot;
    00359   target = va_arg(ap, const char *);
    00360
    00361   while (target && child)
    00362     {
    00363       child = stp_mxmlFindElement(child, child, target, NULL, NULL, STP_MXML_DESCEND);
    00364       target = va_arg(ap, const char *);
    00365     }
    00366   va_end(ap);
    00367   return child;
    00368 }
    00369
    00370 static void
    00371 stpi_xml_process_node(stp_mxml_node_t *node, const char *file)
    00372 {
    00373   stp_list_item_t *item =
    00374     stp_list_get_item_by_name(stpi_xml_registry, node->value.element.name);
    00375   if (item)
    00376     {
    00377       stpi_xml_parse_registry *xmlp =
    00378         (stpi_xml_parse_registry *) stp_list_item_get_data(item);
    00379       (xmlp->parse_func)(node, file);
    00380     }
    00381 }
    00382
    00383 /*
    00384  * Parse the <gimp-print> root node.
    00385  */
    00386 static void
    00387 stpi_xml_process_gimpprint(stp_mxml_node_t *cur, const char *file) /* The node to parse */
    00388 {
    00389   stp_mxml_node_t *child;                       /* Child node pointer */
    00390
    00391   child = cur->child;
    00392   while (child)
    00393     {
    00394       /* process nodes with corresponding parser */
    00395       if (child->type == STP_MXML_ELEMENT)
    00396         stpi_xml_process_node(child, file);
    00397       child = child->next;
    00398     }
    00399 }
    00400
    00401 /*
    00402  * Create a basic gimp-print XML document tree root
    00403  */
    00404 stp_mxml_node_t *
    00405 stp_xmldoc_create_generic(void)
    00406 {
    00407   stp_mxml_node_t *doc;
    00408   stp_mxml_node_t *rootnode;
    00409
    00410   /* Create the XML tree */
    00411   doc = stp_mxmlNewElement(NULL, "?xml");
    00412   stp_mxmlElementSetAttr(doc, "version", "1.0");
    00413
    00414   rootnode = stp_mxmlNewElement(doc, "gimp-print");
    00415   stp_mxmlElementSetAttr
    00416     (rootnode, "xmlns", "http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0");
    00417   stp_mxmlElementSetAttr
    00418     (rootnode, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
    00419   stp_mxmlElementSetAttr
    00420     (rootnode, "xsi:schemaLocation",
    00421      "http://gimp-print.sourceforge.net/xsd/gp.xsd-1.0 gimpprint.xsd");
    00422
    00423   return doc;
    00424 }
    00425
    00426
    00427