Logo Search packages:      
Sourcecode: tablix2 version File versions  Download package

xmlsup.c

Go to the documentation of this file.
/* TABLIX, PGA general timetable solver                              */
/* Copyright (C) 2002 Tomaz Solc                                           */

/* 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 */

/* $Id: xmlsup.c,v 1.28.2.28 2005/09/02 19:30:42 avian Exp $ */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <libxml/parser.h>
#include <libxml/tree.h>
#include <libxml/xmlerror.h>

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "assert.h"
#include "main.h"
#include "data.h"
#include "chromo.h"
#include "xmlsup.h"
#include "modsup.h"
#include "error.h"
#include "gettext.h"
#include "xmlsup.h"

/** @file 
 * @brief XML configuration parser. */

/** @brief XML Configuration file */
00046 static xmlDocPtr config;

/* *** Error handling *** */

#if LIBXML_VERSION > 20411
  #define FAIL(msg,node) parser_fatal(_(msg), xmlGetLineNo(node))
  #define NOPROP(prop,node) parser_fatal(_("Tag <%s> without required property '%s'"), xmlGetLineNo(node), node->name, prop) 
  #define INVPROP(prop,node) parser_fatal(_("Invalid value of property '%s' in tag <%s>"), xmlGetLineNo(node), prop, node->name) 
#else
  #define FAIL(msg,node) fatal(_(msg))
  #define NOPROP(prop,node) fatal(_("Tag <%s> without required property '%s'"), node->name, prop) 
  #define INVPROP(prop,node) fatal(_("Invalid value of property '%s' in tag <%s>"), prop, node->name) 
#endif

/** @def FAIL
 * @brief Convenience macro for XML parser. Same as fatal(). It automatically 
 * appends line number of the XML \a node with error.
 *
 * @param msg Error message.
 * @param node Pointer to the XML node with error.
 */

/** @def NOPROP
 * @brief Convenience macro for XML parser. Use when a required XML node
 * property is not defined.
 *
 * @param prop Name of the property.
 * @param node Pointer to the XML node with error.
 */

/** @def INVPROP
 * @brief Convenience macro for XML parser. Use when a property has an invalid 
 * value (e.g. property is not an integer when it should be).
 *
 * @param prop Name of the property
 * @param node Pointer to the XML node with error.
 */

/** @brief Add an integer property to a XML node.
 *
 * If a property with this name already exists it is overwritten.
 *
 * @param cur Pointer to the XML node.
 * @param prop Name of the property.
 * @param value Value of the property. */
00091 static void parser_newprop_int(xmlNodePtr cur, char *prop, int value)
{
      char *temp;

      temp=xmlGetProp(cur, prop);
      if(temp!=NULL) {
            xmlUnsetProp(cur, prop);
      }

      temp=malloc(sizeof(*temp)*LINEBUFFSIZE);
      if(temp==NULL) fatal(_("Can't allocate memory"));

      snprintf(temp, LINEBUFFSIZE, "%d", value);
      xmlNewProp(cur, prop, temp);

      free(temp);
}

/** @brief Replacement for the fatal() function that adds line number to the
 * message. 
 *
 * @param fmt Format string.
 * @param no Line number. */
00114 static void parser_fatal(const char *fmt, int no, ...)
{
      va_list ap;
        char fmt2[LINEBUFFSIZE];

      va_start(ap, no);

      snprintf(fmt2, 256, _("%s (line %d)"), fmt, no);
      fmt2[LINEBUFFSIZE-1]=0;

        msg_vsend("xmlsup", MSG_FATAL, fmt2, ap);

      va_end(ap);
}


/** @brief Get an integer property from a XML node.
 *
 * Calls fatal() if property was not found or was not integer.
 *
 * @param cur Pointer to the XML node.
 * @param prop Name of the property. 
 * @return Content of the property. */
00137 static int parser_getprop_int(xmlNodePtr cur, char *prop)
{
      char *temp;
      int n, dest;

      assert(cur!=NULL);
      assert(prop!=NULL);

      temp=xmlGetProp(cur, prop);
      if(temp==NULL) NOPROP(prop, cur);
                  
      n=sscanf(temp, "%d", &dest);
      if(n!=1) INVPROP(prop, cur);

      free(temp);

      return(dest);
}

/** @brief Get a string property from a XML node.
 *
 * Calls fatal() if property was not found.
 *
 * @param cur Pointer to the XML node.
 * @param prop Name of the property. 
 * @return Content of the property (must be freed afte use). */
00163 static char *parser_getprop_str(xmlNodePtr cur, char *prop)
{
      char *dest;

      assert(cur!=NULL);
      assert(prop!=NULL);

      dest=xmlGetProp(cur, prop);
      if(dest==NULL) NOPROP(prop, cur);
                  
      return(dest);
}

/** @brief Get a resource definition for an event from the XML tree.
 *
 * @param cur Pointer to the <event> node.
 * @param restype Get a resource definition for this resource type. */
00180 static resource *parser_event_get_res(xmlNodePtr cur, resourcetype *restype)
{
      resource *res;
      char *type, *name;
      
      assert(restype!=NULL);

      res=NULL;
      
      cur=cur->children;
      while(cur!=NULL) {
            if(!strcmp(cur->name, "resource")) {
                  type=parser_getprop_str(cur, "type");

                  if(strcmp(type,restype->type)) {
                        free(type);
                        cur=cur->next;
                        continue;
                  }

                  name=parser_getprop_str(cur, "name");

                  if(res!=NULL) {
                        fatal(_("Definition of event has multiple "
                        "definitions for resource type '%s' (line %d)"),
                        restype->type, xmlGetLineNo(cur));
                  }

                  res=res_find(restype, name);
                  if(res==NULL) INVPROP("name", cur);

                  free(type);
                  free(name);
            }
            cur=cur->next;
      }
      
      return(res);
}

/** @brief Add a resource definition for an event to the XML tree.
 *
 * @param cur Pointer to the <event> node.
 * @param res Pointer to the resource to add. */
00224 static void parser_event_add_res(xmlNodePtr cur, resource *res)
{
      xmlNodePtr resnode;

        xmlNodeAddContent(cur, "\t");

        resnode=xmlNewChild(cur, NULL, "resource", NULL);

        xmlNewProp(resnode, "type", res->restype->type);
        xmlNewProp(resnode, "name", res->name);

        xmlNodeAddContent(cur, "\n\t\t");
}

/** @brief Parse miscellaneous information.
 *
 * @param cur Pointer to the <info> node. */
00241 static void parser_info(xmlNodePtr cur)
{
        while (cur!=NULL) {
                if(!strcmp(cur->name, "title")) {
                        dat_info.title=xmlNodeGetContent(cur);
                } else if (!strcmp(cur->name, "address")) {
                        dat_info.address=xmlNodeGetContent(cur);
                } else if (!strcmp(cur->name, "author")) {
                        dat_info.author=xmlNodeGetContent(cur);
                }
                cur=cur->next;
        }

      if(dat_info.title==NULL) dat_info.title=strdup("Untitled timetable");
      if(dat_info.address==NULL) dat_info.address=strdup("");
      if(dat_info.author==NULL) dat_info.author=strdup("Tablix");
}

/** @brief Parse module options.
 *
 * @param cur Pointer to the <module> node.
 * @param opt Pointer to the linked list of module options. */
00263 static moduleoption *parser_options(xmlNodePtr cur, moduleoption *opt)
{
      char *content, *name;
      moduleoption *result;

      result=opt;
      while (cur!=NULL) {
                if (!strcmp(cur->name, "option")) {
                  name=parser_getprop_str(cur, "name");

                  content=xmlNodeGetContent(cur);

                  result=option_new(result, name, content);

                  free(name);
                  free(content);
                }
                cur=cur->next;
        }

      return(result);
}

/** @brief Parse modules.
 *
 * @param cur Pointer to the <modules> node. */
00289 static void parser_modules(xmlNodePtr cur)
{
        char *name, *weight, *mandatory;
      moduleoption *opt;
      module *dest;

        while(cur!=NULL) {
                  if (!strcmp(cur->name, "module")) {
                        name=parser_getprop_str(cur, "name");
                  weight=parser_getprop_str(cur, "weight");
                  mandatory=parser_getprop_str(cur, "mandatory");

                  opt=option_new(NULL, "weight", weight);

                  if(!strcmp(mandatory, "yes")) {
                        opt=option_new(opt, "mandatory", "1");
                  } else if(!strcmp(mandatory, "no")) {
                        opt=option_new(opt, "mandatory", "0");
                  } else {
                        FAIL("Property 'mandatory' should be 'yes'"
                              "or 'no'", cur);
                  }

                  opt=parser_options(cur->children, opt);

                  dest=module_load(name,opt);
                  if(dest==NULL) {
                        fatal(_("Module %s failed to load"), name);
                  } 

                        free(name);
                  free(weight);
                  free(mandatory);

                  option_free(opt);
                } 
                cur=cur->next;
        }
}

/** @brief Parse restrictions for a single event and call proper restriction
 * handlers.
 *
 * @param cur Pointer to the <event> node.
 * @param tupleid Tuple ID for this event.
 * @param repeats Number of repeats of this event. */
00335 static void parser_event_restrictions(xmlNodePtr cur, int tupleid, int repeats)
{
      int n;
      int result;
      char *restriction;
      char *content;
        while(cur!=NULL) {
                if(!strcmp(cur->name, "restriction")) {
                  restriction=parser_getprop_str(cur, "type");
                  content=xmlNodeGetContent(cur);

                  for(n=tupleid;n<tupleid+repeats;n++) {
                        result=handler_tup_call(&dat_tuplemap[n],
                                          restriction,content);
                        if(result==1) {
                              FAIL("Restriction handler failed", cur);
                        } else if(result==2) {
                              info(_("Unknown event restriction '%s'"
                                    "(line %d)"), restriction, 
                                    xmlGetLineNo(cur));
                        }
                  }

                        free(restriction);
                  free(content);
                }
                cur=cur->next;
        }
}

/** @brief Parse all event restrictions.
 *
 * @param cur Pointer to the <events> node. */
00368 static void parser_events_restrictions(xmlNodePtr cur)
{
      int repeats;
      int tupleid;

      while(cur!=NULL) {
            if(!strcmp(cur->name, "event")) {
                  tupleid=parser_getprop_int(cur, "tupleid");
                  repeats=parser_getprop_int(cur, "repeats");
      
                  parser_event_restrictions(cur->children, 
                                          tupleid, repeats);
            }
            cur=cur->next;
      }

}

/** @brief Parse a single event.
 *
 * @param start Pointer to the <event> node.
 * @param tuple Pointer to the tuple info struct for this event. */
00390 static void parser_event(xmlNodePtr start, tupleinfo *tuple)
{
      resource *res;
      resourcetype *restype;
      char *type;
      int n;

      xmlNodePtr cur;

      assert(tuple!=NULL);

      cur=start;
      while(cur!=NULL) {
            if(!strcmp(cur->name, "resource")) {
                  type=parser_getprop_str(cur, "type");

                  restype=restype_find(type);
                  if(restype==NULL) INVPROP("type", cur);

                  free(type);
            }
            cur=cur->next;
      }
      for(n=0;n<dat_typenum;n++) {
            restype=&dat_restype[n];

            res=parser_event_get_res(start->parent,restype);
            if(res==NULL&&(!restype->var)) {
                  fatal(_("Definition of event '%s' is missing constant "
                        "resource type '%s' (line %d)"), tuple->name, 
                        restype->type, xmlGetLineNo(start));
            }

            if(res!=NULL) tuple_set(tuple, res);
      }
}

/** @brief Parse all events.
 *
 * @param cur Pointer to the <events> node. */
00430 static void parser_events(xmlNodePtr cur)
{
      char *name;
      int repeats;
      tupleinfo *dest=NULL;
      int n;

      while(cur!=NULL) {
            if(!strcmp(cur->name, "event")) {
                  name=parser_getprop_str(cur, "name");

                  repeats=parser_getprop_int(cur, "repeats");
                  if (repeats<=0) INVPROP("repeats", cur);

                  for(n=0;n<repeats;n++) {
                        dest=tuple_new(name);
                        if(dest==NULL) {
                              fatal(_("Can't allocate memory"));
                        }

                        parser_event(cur->children, dest);
                  }

                  parser_newprop_int(cur, "tupleid", 
                                    dest->tupleid-repeats+1); 

                  free(name);
            }
            cur=cur->next;
      }
}

/** @brief Parse restrictions for a single resource and call proper handlers.
 *
 * @param cur Pointer to the <resource> node.
 * @param res Pointer to the resource struct for this resource. */
00466 static void parser_resource_restrictions_one(xmlNodePtr cur, resource *res) 
{
      char *restriction, *content;
      int result;
      
      while (cur!=NULL) {
            if(!strcmp(cur->name, "restriction")) {
                  restriction=parser_getprop_str(cur, "type");
                  content=xmlNodeGetContent(cur);

                  result=handler_res_call(res, restriction, content);

                  if(result==1) FAIL("Restriction handler failed", cur);
                  if(result==2) info(_("Unknown resource restriction '%s'"
                                    "(line %d)"), restriction, 
                                    xmlGetLineNo(cur));

                  free(restriction);
                  free(content);
            }
            cur=cur->next;
      }
}

/** @brief Parse all resource restrictions for a single resource type.
 *
 * @param cur Pointer to the <resourcetype> node.
 * @param restype Pointer to the resource type struct for this resource type. */
00494 static void parser_resource_restrictions(xmlNodePtr cur, resourcetype *restype)
{
      resource *res;
      int n;
      int resid;
      int resid1, resid2;

      while(cur!=NULL) {
            if(!strcmp(cur->name, "resource")) {
                        resid=parser_getprop_int(cur, "resid");

                  res=&restype->res[resid];
                  parser_resource_restrictions_one(cur->children, res);
                } else if((!strcmp(cur->name, "linear"))||
                              (!strcmp(cur->name, "matrix"))) {
                  resid1=parser_getprop_int(cur, "resid-from");
                  resid2=parser_getprop_int(cur, "resid-to");

                  for(n=resid1;n<=resid2;n++) {
                        res=&restype->res[n];
                        parser_resource_restrictions_one(cur->children,
                                                      res);
                  }
            }
            cur=cur->next;
      }
}

/** @brief Parse all resource restrictions.
 *
 * @param cur Pointer to the <resources> node. */
00525 static void parser_resources_restrictions(xmlNodePtr cur)
{
      xmlNodePtr res;
      int typeid;
        while(cur!=NULL) {
                if ((!strcmp(cur->name, "constant"))||
                              (!strcmp(cur->name, "variable"))) {
                  res=cur->children;
                  while(res!=NULL) {
                        if(!strcmp(res->name, "resourcetype")) {
                              typeid=parser_getprop_int(
                                          res, "typeid");

                              parser_resource_restrictions(
                                          res->children, 
                                          &dat_restype[typeid]);
                        }
                        res=res->next;
                  }
            }
                cur=cur->next;
        }
}

/** @brief Parse all resources in a resource type.
 *
 * @param cur Pointer to the <resourcetype> node.
 * @param restype Pointer to the resource type struct for this resource type. */
00553 static void parser_resource(xmlNodePtr cur, resourcetype *restype)
{
      char *name, *prefix, *postfix, *fullname;
      int from, to;
      int width, height;
      int n;
      resource *dest;

      while(cur!=NULL) {
            if(!strcmp(cur->name, "resource")) {
                        name=parser_getprop_str(cur, "name");

                        dest=res_find(restype, name);
                        if(dest==NULL) {
                        dest=res_new(restype, name);
                        if(dest==NULL) {
                              fatal(_("Can't allocate memory"));
                        }
                        parser_newprop_int(cur, "resid", dest->resid);
                  } else {
                        FAIL("Resource already defined", cur);
                  }

                  free(name);
                } else if(!strcmp(cur->name, "linear")) {
                        name=parser_getprop_str(cur, "name");
                  from=parser_getprop_int(cur, "from");
                  to=parser_getprop_int(cur, "to");

                  if(from>to) FAIL("Value in 'from' property must be"
                              "smaller than the value in 'to'"
                              "property", cur);

                  postfix=name;
                  prefix=strsep(&postfix, "#");
                  if(postfix==NULL) {
                        FAIL("'name' property must contain '#'", cur);
                  }

                  fullname=malloc(sizeof(*fullname)*LINEBUFFSIZE);
                  if(fullname==NULL) fatal(_("Can't allocate memory"));

                  for(n=from;n<=to;n++) {
                        snprintf(fullname, LINEBUFFSIZE, "%s%d%s", 
                                          prefix, n, postfix);

                        dest=res_new(restype, fullname);
                        if(dest==NULL) {
                              fatal(_("Can't allocate memory"));
                        }
                        if(n==from) {
                              parser_newprop_int(cur, "resid-from", 
                                                dest->resid);
                        } else if(n==to) {
                              parser_newprop_int(cur, "resid-to", 
                                                dest->resid);
                        }
                  }


                  free(fullname);
                  free(name);
                } else if(!strcmp(cur->name, "matrix")) {
                  width=parser_getprop_int(cur, "width");
                  if(width<=0) INVPROP("width", cur);

                  height=parser_getprop_int(cur, "height");
                  if(height<=0) INVPROP("height", cur);

                  dest=res_new_matrix(restype, width, height);

                  if(dest==NULL) {
                        fatal(_("Can't allocate memory"));
                  }

                  parser_newprop_int(cur, "resid-from", 
                                    dest->resid-(height*width)+1);
                  parser_newprop_int(cur, "resid-to", dest->resid);
            }
            cur=cur->next;
      }
}

/** @brief Define a new resource type.
 *
 * @param cur pointer to the <resourcetype> node.
 * @param var Set to 1 if this node is under <variable> node. */
00640 static void parser_restype(xmlNodePtr cur, int var)
{
      char *type;
      resourcetype *dest;

      type=xmlGetProp(cur, "type");
      if(type==NULL) NOPROP("type", cur);

      dest=restype_new(var, type);
      if(dest==NULL) {
            fatal(_("Can't allocate memory"));
      }

      parser_newprop_int(cur, "typeid", dest->typeid);

      free(type);
}

/** @brief Parse all resource types.
 *
 * @param start Pointer to the <resources> node. */
00661 static void parser_resources(xmlNodePtr start)
{
      xmlNodePtr res, cur;
      int n;
      int typeid;

      cur=start;
        while(cur!=NULL) {
                if (!strcmp(cur->name, "constant")) {
                  res=cur->children;
                  while(res!=NULL) {
                        if(!strcmp(res->name, "resourcetype")) {
                              parser_restype(res, 0);
                        }
                        res=res->next;
                  }
                } else if (!strcmp(cur->name, "variable")) {
                  res=cur->children;
                  while(res!=NULL) {
                        if(!strcmp(res->name, "resourcetype")) {
                              parser_restype(res, 1);
                        }
                        res=res->next;
                  }
                }
                cur=cur->next;
        }

      cur=start;
        while(cur!=NULL) {
                if (!strcmp(cur->name, "constant")||
                              !strcmp(cur->name, "variable")) {
                  res=cur->children;
                  while(res!=NULL) {
                        if(!strcmp(res->name, "resourcetype")) {
                              typeid=parser_getprop_int(res, "typeid");
                              parser_resource(res->children, 
                                          &dat_restype[typeid]);
                        }
                        res=res->next;
                  }
                } 
                cur=cur->next;
        }

      for(n=0;n<dat_typenum;n++) {
            debug("%s %s: %d resources", 
                        dat_restype[n].var?"variable":"constant",
                        dat_restype[n].type, 
                        dat_restype[n].resnum);
      }
}

/** @brief Custom error handler for libxml. */
00715 void parser_handler(void *ctx, const char *msg, ...) {
      va_list args;
      char pmsg[LINEBUFFSIZE];
      int n;

      static char xmlerr[LINEBUFFSIZE];
      static int xmlerrp=0;

      va_start(args, msg);
      vsnprintf(pmsg, 256, msg, args);
      n=0;
      while(n<LINEBUFFSIZE&&pmsg[n]!=0) {
            if(pmsg[n]!='\n'&&xmlerrp<(LINEBUFFSIZE-1)) {
                  xmlerr[xmlerrp++]=pmsg[n];
            } else {
                  xmlerr[xmlerrp]=0;
                  error(xmlerr);
                  xmlerrp=0;
            }
            n++;
      }
      va_end(args);
}

/** @brief Parser initialization.
 *
 * @param filename Name of the XML configuration file to open. */
00742 static void parser_libxml_init(char *filename)
{
      assert(filename!=NULL);

        xmlLineNumbersDefault(1);
        xmlSetGenericErrorFunc(NULL, parser_handler);

        config=xmlParseFile(filename);
        if(config==NULL) {
            fatal("Can't parse configuration file '%s'", filename);
      }
}

/** @brief Check version of the configuration file.
 *
 * @param root Pointer to the root node of the XML tree. */
00758 static void parser_version_check(xmlNodePtr root)
{
      char *version;

        if(strcmp(root->name, "ttm")) {
            if(!strcmp(root->name, "school")) {
                  error("Configuration files from Tablix versions "
                              "prior to 0.2.1 are not supported");
            }
                FAIL("Root XML element is not 'ttm'", root);
        }

        version=xmlGetProp(root, "version");
      if(version==NULL) {
            NOPROP("version", root);
      }
      if(strcmp(version, PARSER_TTM_VERSION)) {
            FAIL("Configuration file has incompatible TTM version", root);
      }
}

/** @brief Parses an XML configuration file.
 *
 * @param filename Name of the configuration file.
 * @return 0 on success and -1 on error.
 *
 * Defines all resources and all tuples, loads miscellaneous information and
 * loads and initializes all modules. */
00786 int parser_main(char *filename)
{
        xmlNodePtr cur;
        int result;

      xmlNodePtr info=NULL;
      xmlNodePtr resources=NULL;
      xmlNodePtr events=NULL;
      xmlNodePtr modules=NULL;

      char *oldmodule;

      assert(filename!=NULL);

      oldmodule=curmodule;
      curmodule="xmlsup";

      parser_libxml_init(filename);

        cur=xmlDocGetRootElement(config);

        parser_version_check(cur);
      
      cur=cur->children;

        while (cur!=NULL) {
                if(!strcmp(cur->name, "info")) {
                        info=cur->children;
                } else if(!strcmp(cur->name, "resources")) {
                        resources=cur->children;
                } else if(!strcmp(cur->name, "events")) {
                        events=cur->children;
                } else if(!strcmp(cur->name, "modules")) {
                        modules=cur->children;
                }

                cur=cur->next;
        }

        if (resources==NULL) {
                fatal("no <resources>");
        }
      if (events==NULL) {
            fatal("no <events>");
      }
      if (modules==NULL) {
            fatal("no <modules>");
      }

      parser_resources(resources);
      parser_events(events);
      parser_info(info);

        parser_modules(modules);

      parser_resources_restrictions(resources);
      parser_events_restrictions(events);

      result=precalc_call();
      if(result) fatal("One or more modules failed to precalculate");

        /* done parsing */

      curmodule=oldmodule;

      return(0);
}

/** @brief Removes definitions of variable resources for an event in the 
 * XML tree.
 *
 * @param cur Pointer to the <event> node in the XML tree. */
00858 static void parser_clean(xmlNodePtr cur)
{
      char *type;
      resourcetype *restype;
      xmlNodePtr next;
      
      assert(cur!=NULL);

      cur=cur->children;
      while(cur!=NULL) {
            next=cur->next;
                if (!strcmp(cur->name, "resource")) {
                  type=parser_getprop_str(cur, "type");
                  restype=restype_find(type);

                  assert(restype!=NULL);

                  if(restype->var) {
                        xmlUnlinkNode(cur);
                        xmlFreeNode(cur);
                  }
            }
            cur=next;
      }
}

/** @brief Replaces event tags with repeats > 1 with multiple tags with
 * repeats = 1.
 *
 * @param cur Pointer to the <events> node in the XML tree. */
00888 static void parser_remove_repeats(xmlNodePtr cur)
{
      int repeats, tupleid;
      int n;
      xmlNodePtr copy;

      while(cur!=NULL) {
                if (!strcmp(cur->name, "event")) {
                  repeats=parser_getprop_int(cur, "repeats");
                  tupleid=parser_getprop_int(cur, "tupleid");
                  if(repeats>1) {
                        xmlSetProp(cur, "repeats", "1");
                        for(n=repeats-1;n>0;n--) {
                              copy=xmlCopyNode(cur, 1);
                              parser_newprop_int(copy, "tupleid", 
                                                tupleid+n);
                              xmlAddNextSibling(cur, copy);
                        }
                  }
            }
            cur=cur->next;
      }
}

/** @brief Loads definitions of variable resources for all events in the 
 * XML tree to a table struct.
 *
 * @brief tab Pointer to the table struct. */
00916 void parser_gettable(table *tab)
{
        xmlNodePtr cur, root;
      xmlNodePtr events=NULL;
      int tupleid, repeats;

      int fitness;
      int n;

      char *temp;

      resourcetype *restype;
      resource *res;

      assert(tab!=NULL);

        root=xmlDocGetRootElement(config);

      temp=xmlGetProp(root, "fitness");
      if(temp==NULL) error(_("This file does not seem to contain a solution"));
      free(temp);
      
      fitness=parser_getprop_int(root, "fitness");

        cur=root->children;
        while (cur!=NULL) {
                if (!strcmp(cur->name, "events")) events=cur;
                cur=cur->next;
        }

      assert(events!=NULL);

        cur=events->children;
        while (cur!=NULL) {
                if (!strcmp(cur->name, "event")) {
                  tupleid=parser_getprop_int(cur, "tupleid");
                  repeats=parser_getprop_int(cur, "repeats");

                  if(repeats!=1) {
                        fatal(_("Configuration file does not contain"
                              "a complete solution"));
                  }

                  for(n=0;n<dat_typenum;n++) {
                        restype=&dat_restype[n];

                        if(!restype->var) continue;

                        res=parser_event_get_res(cur, restype);

                        if(res==NULL) {   
                              fatal(_("Configuration file does not"
                                    "contain a complete solution"));
                        }

                        tab->chr[n].gen[tupleid]=res->resid;
                  }
                }
                cur=cur->next;
        }

      tab->fitness=fitness;
}

/** @brief Saves definitions of variable resources for all events in the 
 * table struct to the XML tree.
 *
 * Any previous definitions of variable resources are replaced.
 *
 * @brief tab Pointer to the table struct. */
00986 void parser_addtable(table *tab)
{
        xmlNodePtr cur, root;
      xmlNodePtr events=NULL;
      int n;

      resourcetype *restype;
      resource *res;
      int resid;
      int tupleid;

      assert(tab!=NULL);

        root=xmlDocGetRootElement(config);

      parser_newprop_int(root, "fitness", tab->fitness);

        cur=root->children;
        while(cur!=NULL) {
                if (!strcmp(cur->name, "events")) events=cur;
                cur=cur->next;
        }

      assert(events!=NULL);

      parser_remove_repeats(events->children);

      cur=events->children;
      while(cur!=NULL) {
                if (!strcmp(cur->name, "event")) {
                  parser_clean(cur);
                  tupleid=parser_getprop_int(cur, "tupleid");
                  assert(parser_getprop_int(cur, "repeats")==1);

                  for(n=0;n<dat_typenum;n++) {
                        restype=&dat_restype[n];

                        if(!restype->var) continue;

                        resid=tab->chr[n].gen[tupleid];
                        res=&restype->res[resid];

                        parser_event_add_res(cur, res);
                  }
                }
            cur=cur->next;
      }

}

/** @brief Dumps XML tree into a file.
 *
 * @param f File to dump the XML tree to. */
01039 void parser_dump(FILE *f)
{
        xmlDocDump(f, config);
}

/** @brief Free all memory allocated by the parser. */
01045 void parser_exit()
{
        xmlFreeDoc(config);
}

Generated by  Doxygen 1.6.0   Back to index