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

int Calculator::loadDefinitions ( const char *  file_name,
bool  is_user_defs = true 
)

Load definitions from a file.

Parameters:
file_name The path to the file to load.
is_user_defs true if the definitions are local, false if they are global.
Returns:
true if the definitions were successfully loaded.

Definition at line 5599 of file Calculator.cc.

References CompositeUnit::add(), DataProperty::addName(), addPrefix(), DataSet::addProperty(), ASSUMPTION_SIGN_NEGATIVE, ASSUMPTION_SIGN_NONNEGATIVE, ASSUMPTION_SIGN_NONPOSITIVE, ASSUMPTION_SIGN_NONZERO, ASSUMPTION_SIGN_POSITIVE, ASSUMPTION_SIGN_UNKNOWN, ASSUMPTION_TYPE_COMPLEX, ASSUMPTION_TYPE_NONMATRIX, DataProperty::countNames(), ExpressionItem::countNames(), ExpressionItem::destroy(), MathFunction::getArgumentDefinition(), getExactBinaryPrefix(), getExactDecimalPrefix(), getExactPrefix(), ExpressionItem::getName(), DataProperty::hasName(), ExpressionItem::isLocal(), Number::isZero(), ExpressionName::name, Number::set(), ExpressionItem::setActive(), Argument::setAlerts(), DataProperty::setApproximate(), ExpressionItem::setApproximate(), MathFunction::setArgumentDefinition(), DataProperty::setCaseSensitive(), ExpressionItem::setCategory(), ExpressionItem::setChanged(), NumberArgument::setComplexAllowed(), MathFunction::setCondition(), DataSet::setCopyright(), Argument::setCustomCondition(), DataSet::setDefaultDataFile(), DataSet::setDefaultProperty(), ExpressionItem::setDescription(), DataProperty::setDescription(), ExpressionItem::setHidden(), DataProperty::setHidden(), NumberArgument::setIncludeEqualsMax(), NumberArgument::setIncludeEqualsMin(), DataProperty::setKey(), ExpressionItem::setLocal(), Argument::setMatrixAllowed(), IntegerArgument::setMax(), NumberArgument::setMax(), IntegerArgument::setMin(), NumberArgument::setMin(), Argument::setName(), DataProperty::setNameIsReference(), ExpressionItem::setPrecision(), DataProperty::setPropertyType(), Unit::setSystem(), Argument::setTests(), DataProperty::setTitle(), DataProperty::setUnit(), DataProperty::setUserModified(), DataProperty::setUsesBrackets(), Argument::setZeroForbidden(), and variableNameIsValid().

Referenced by loadGlobalDefinitions(), and loadLocalDefinitions().

                                                                        {

      xmlDocPtr doc;
      xmlNodePtr cur, child, child2, child3;
      string version, stmp, name, uname, type, svalue, sexp, plural, singular, category_title, category, description, title, inverse, base, argname, usystem;
      bool best_title, next_best_title, best_category_title, next_best_category_title, best_description, next_best_description;
      bool best_plural, next_best_plural, best_singular, next_best_singular, best_argname, next_best_argname;
      bool best_proptitle, next_best_proptitle, best_propdescr, next_best_propdescr;
      string proptitle, propdescr;
      ExpressionName names[10];
      ExpressionName ref_names[10];
      string prop_names[10];
      string ref_prop_names[10];
      bool best_name[10];
      bool nextbest_name[10];
      string best_names, nextbest_names, default_names;
      string best_prop_names, nextbest_prop_names, default_prop_names;
      int name_index, prec;
      ExpressionName ename;

      string locale;
      char *clocale = setlocale(LC_MESSAGES, "");
      if(clocale) {
            locale = clocale;
            if(locale == "POSIX" || locale == "C") {
                  locale = "";
            } else {
                  size_t i = locale.find('.');
                  if(i != string::npos) locale = locale.substr(0, i);
            }
      }

      int fulfilled_translation = 0;
      string localebase;
      if(locale.length() > 2) {
            localebase = locale.substr(0, 2);
            if(locale == "en_US") {
                  fulfilled_translation = 2;
            } else if(localebase == "en") {
                  fulfilled_translation = 1;
            }
      } else {
            localebase = locale;
            if(locale == "en") {
                  fulfilled_translation = 2;
            }
      }
      while(localebase.length() < 2) {
            localebase += " ";
            fulfilled_translation = 2;
      }

      int exponent = 1, litmp = 0;
      bool active = false, hidden = false, b = false, require_translation = false;
      Number nr;
      ExpressionItem *item;
      MathFunction *f;
      Variable *v;
      Unit *u;
      AliasUnit *au;
      CompositeUnit *cu;
      Prefix *p;
      Argument *arg;
      DataSet *dc;
      DataProperty *dp;
      int itmp;
      IntegerArgument *iarg;
      NumberArgument *farg;   
      xmlChar *value, *lang, *value2;
      int in_unfinished = 0;
      bool done_something = false;
      doc = xmlParseFile(file_name);
      if(doc == NULL) {
            return false;
      }
      cur = xmlDocGetRootElement(doc);
      if(cur == NULL) {
            xmlFreeDoc(doc);
            return false;
      }
      while(cur != NULL) {
            if(!xmlStrcmp(cur->name, (const xmlChar*) "QALCULATE")) {
                  XML_GET_STRING_FROM_PROP(cur, "version", version)
                  break;
            }
            cur = cur->next;
      }
      if(cur == NULL) {
            error(true, _("File not identified as Qalculate! definitions file: %s."), file_name, NULL);
            xmlFreeDoc(doc);
            return false;
      }
      int version_numbers[] = {0, 9, 4};
      parse_qalculate_version(version, version_numbers);

      bool new_names = version_numbers[0] > 0 || version_numbers[1] > 9 || (version_numbers[1] == 9 && version_numbers[2] >= 4);
      
      ParseOptions po;

      vector<xmlNodePtr> unfinished_nodes;
      vector<string> unfinished_cats;
      queue<xmlNodePtr> sub_items;
      vector<queue<xmlNodePtr> > nodes;

      category = "";
      nodes.resize(1);

      while(true) {
            if(!in_unfinished) {
                  category_title = ""; best_category_title = false; next_best_category_title = false; 
                  child = cur->xmlChildrenNode;
                  while(child != NULL) {
                        if(!xmlStrcmp(child->name, (const xmlChar*) "title")) {
                              XML_GET_LOCALE_STRING_FROM_TEXT(child, category_title, best_category_title, next_best_category_title)
                        } else if(!xmlStrcmp(child->name, (const xmlChar*) "category")) {
                              nodes.back().push(child);
                        } else {
                              sub_items.push(child);
                        }
                        child = child->next;
                  }
                  if(!category.empty()) {
                        category += "/";
                  }
                  if(!category_title.empty() && category_title[0] == '!') {\
                        size_t i = category_title.find('!', 1);
                        if(i == string::npos) {
                              category += category_title;
                        } else if(i + 1 < category_title.length()) {
                              category += category_title.substr(i + 1, category_title.length() - (i + 1));
                        }
                  } else {
                        category += category_title;
                  }
            }
            while(!sub_items.empty() || (in_unfinished && cur)) {
                  if(!in_unfinished) {
                        cur = sub_items.front();
                        sub_items.pop();
                  }
                  if(!xmlStrcmp(cur->name, (const xmlChar*) "activate")) {
                        XML_GET_STRING_FROM_TEXT(cur, name)
                        ExpressionItem *item = getInactiveExpressionItem(name);
                        if(item && !item->isLocal()) {
                              item->setActive(true);
                              done_something = true;
                        }
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "deactivate")) {
                        XML_GET_STRING_FROM_TEXT(cur, name)
                        ExpressionItem *item = getActiveExpressionItem(name);
                        if(item && !item->isLocal()) {
                              item->setActive(false);
                              done_something = true;
                        }
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "function")) {
                        if(VERSION_BEFORE(0, 6, 3)) {
                              XML_GET_STRING_FROM_PROP(cur, "name", name)
                        } else {
                              name = "";
                        }
                        XML_GET_FALSE_FROM_PROP(cur, "active", active)
                        f = new UserFunction(category, "", "", is_user_defs, 0, "", "", 0, active);
                        item = f;
                        done_something = true;
                        child = cur->xmlChildrenNode;
                        ITEM_INIT_DTH
                        ITEM_INIT_NAME
                        while(child != NULL) {
                              if(!xmlStrcmp(child->name, (const xmlChar*) "expression")) {
                                    XML_DO_FROM_TEXT(child, ((UserFunction*) f)->setFormula);
                                    XML_GET_PREC_FROM_PROP(child, prec)
                                    f->setPrecision(prec);
                                    XML_GET_APPROX_FROM_PROP(child, b)
                                    f->setApproximate(b);
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "condition")) {
                                    XML_DO_FROM_TEXT(child, f->setCondition);
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "subfunction")) {
                                    XML_GET_FALSE_FROM_PROP(child, "precalculate", b);
                                    value = xmlNodeListGetString(doc, child->xmlChildrenNode, 1); 
                                    if(value) ((UserFunction*) f)->addSubfunction((char*) value, b); 
                                    else ((UserFunction*) f)->addSubfunction("", true); 
                                    if(value) xmlFree(value);
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "argument")) {
                                    farg = NULL; iarg = NULL;
                                    XML_GET_STRING_FROM_PROP(child, "type", type);
                                    if(type == "text") {
                                          arg = new TextArgument();
                                    } else if(type == "symbol") {
                                          arg = new SymbolicArgument();
                                    } else if(type == "date") {
                                          arg = new DateArgument();
                                    } else if(type == "integer") {
                                          iarg = new IntegerArgument();
                                          arg = iarg;
                                    } else if(type == "number") {
                                          farg = new NumberArgument();
                                          arg = farg;
                                    } else if(type == "vector") {
                                          arg = new VectorArgument();
                                    } else if(type == "matrix") {
                                          arg = new MatrixArgument();
                                    } else if(type == "boolean") {
                                          arg = new BooleanArgument();
                                    } else if(type == "function") {
                                          arg = new FunctionArgument();
                                    } else if(type == "unit") {
                                          arg = new UnitArgument();
                                    } else if(type == "variable") {
                                          arg = new VariableArgument();
                                    } else if(type == "object") {
                                          arg = new ExpressionItemArgument();
                                    } else if(type == "angle") {
                                          arg = new AngleArgument();
                                    } else if(type == "data-object") {
                                          arg = new DataObjectArgument(NULL, "");
                                    } else if(type == "data-property") {
                                          arg = new DataPropertyArgument(NULL, "");
                                    } else {
                                          arg = new Argument();
                                    }
                                    child2 = child->xmlChildrenNode;
                                    argname = ""; best_argname = false; next_best_argname = false;
                                    while(child2 != NULL) {
                                          if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) {
                                                XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname)
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "min")) {
                                                if(farg) {
                                                      XML_DO_FROM_TEXT(child2, nr.set);
                                                      farg->setMin(&nr);
                                                      XML_GET_FALSE_FROM_PROP(child, "include_equals", b)
                                                      farg->setIncludeEqualsMin(b);
                                                } else if(iarg) {
                                                      XML_GET_STRING_FROM_TEXT(child2, stmp);
                                                      Number integ(stmp);
                                                      iarg->setMin(&integ);
                                                }
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "max")) {
                                                if(farg) {
                                                      XML_DO_FROM_TEXT(child2, nr.set);
                                                      farg->setMax(&nr);
                                                      XML_GET_FALSE_FROM_PROP(child, "include_equals", b)
                                                      farg->setIncludeEqualsMax(b);
                                                } else if(iarg) {
                                                      XML_GET_STRING_FROM_TEXT(child2, stmp);
                                                      Number integ(stmp);
                                                      iarg->setMax(&integ);
                                                }
                                          } else if(farg && !xmlStrcmp(child2->name, (const xmlChar*) "complex_allowed")) {
                                                XML_GET_FALSE_FROM_TEXT(child2, b);
                                                farg->setComplexAllowed(b);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "condition")) {
                                                XML_DO_FROM_TEXT(child2, arg->setCustomCondition);    
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "matrix_allowed")) {
                                                XML_GET_TRUE_FROM_TEXT(child2, b);
                                                arg->setMatrixAllowed(b);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "zero_forbidden")) {
                                                XML_GET_TRUE_FROM_TEXT(child2, b);
                                                arg->setZeroForbidden(b);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "test")) {
                                                XML_GET_FALSE_FROM_TEXT(child2, b);
                                                arg->setTests(b);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "alert")) {
                                                XML_GET_FALSE_FROM_TEXT(child2, b);
                                                arg->setAlerts(b);
                                          }
                                          child2 = child2->next;
                                    }
                                    if(!argname.empty() && argname[0] == '!') {
                                          size_t i = argname.find('!', 1);
                                          if(i == string::npos) {
                                                arg->setName(argname);
                                          } else if(i + 1 < argname.length()) {
                                                arg->setName(argname.substr(i + 1, argname.length() - (i + 1)));
                                          }
                                    } else {
                                          arg->setName(argname);
                                    }
                                    itmp = 1;
                                    XML_GET_INT_FROM_PROP(child, "index", itmp);
                                    f->setArgumentDefinition(itmp, arg); 
                              } else ITEM_READ_NAME(functionNameIsValid)
                               else ITEM_READ_DTH
                               else {
                                    ITEM_READ_NAMES
                              }
                              child = child->next;
                        }
                        if(new_names) {
                              ITEM_SET_BEST_NAMES(functionNameIsValid)
                              ITEM_SET_REFERENCE_NAMES(functionNameIsValid)
                        } else {
                              ITEM_SET_NAME_1(functionNameIsValid)
                              ITEM_SET_NAME_2
                              ITEM_SET_NAME_3
                        }
                        ITEM_SET_DTH
                        if(f->countNames() == 0) {
                              f->destroy();
                              f = NULL;
                        } else {
                              f->setChanged(false);
                              addFunction(f, true, is_user_defs);
                        }
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "dataset") || !xmlStrcmp(cur->name, (const xmlChar*) "builtin_dataset")) {
                        bool builtin = !xmlStrcmp(cur->name, (const xmlChar*) "builtin_dataset");
                        XML_GET_FALSE_FROM_PROP(cur, "active", active)
                        if(builtin) {
                              XML_GET_STRING_FROM_PROP(cur, "name", name)
                              dc = getDataSet(name);
                              if(!dc) {
                                    goto after_load_object;
                              }
                              dc->setCategory(category);
                        } else {
                              dc = new DataSet(category, "", "", "", "", is_user_defs);
                        }
                        item = dc;
                        done_something = true;
                        child = cur->xmlChildrenNode;
                        ITEM_INIT_DTH
                        ITEM_INIT_NAME
                        while(child != NULL) {
                              if(!xmlStrcmp(child->name, (const xmlChar*) "property")) {
                                    dp = new DataProperty(dc);
                                    child2 = child->xmlChildrenNode;
                                    if(new_names) {
                                          default_prop_names = ""; best_prop_names = ""; nextbest_prop_names = "";
                                    } else {
                                          for(size_t i = 0; i < 10; i++) {
                                                best_name[i] = false;
                                                nextbest_name[i] = false;
                                          }
                                    }
                                    proptitle = ""; best_proptitle = false; next_best_proptitle = false;
                                    propdescr = ""; best_propdescr = false; next_best_propdescr = false;
                                    while(child2 != NULL) {
                                          if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) {
                                                XML_GET_LOCALE_STRING_FROM_TEXT(child2, proptitle, best_proptitle, next_best_proptitle)
                                          } else if(!new_names && !xmlStrcmp(child2->name, (const xmlChar*) "name")) {
                                                name_index = 1;
                                                XML_GET_INT_FROM_PROP(child2, "index", name_index)
                                                if(name_index > 0 && name_index <= 10) {
                                                      name_index--;
                                                      prop_names[name_index] = "";
                                                      ref_prop_names[name_index] = "";
                                                      value2 = NULL;
                                                      child3 = child2->xmlChildrenNode;
                                                      while(child3 != NULL) {
                                                            if((!best_name[name_index] || (ref_prop_names[name_index].empty() && !locale.empty())) && !xmlStrcmp(child3->name, (const xmlChar*) "name")) {
                                                                  lang = xmlNodeGetLang(child3);
                                                                  if(!lang) {
                                                                        value2 = xmlNodeListGetString(doc, child3->xmlChildrenNode, 1);
                                                                        if(locale.empty()) {
                                                                              best_name[name_index] = true;
                                                                              if(value2) prop_names[name_index] = (char*) value2;
                                                                              else prop_names[name_index] = "";
                                                                        } else {
                                                                              if(!best_name[name_index] && !nextbest_name[name_index]) {
                                                                                    if(value2) prop_names[name_index] = (char*) value2;
                                                                                    else prop_names[name_index] = "";
                                                                              }
                                                                              if(value2) ref_prop_names[name_index] = (char*) value2;
                                                                              else ref_prop_names[name_index] = "";
                                                                        }
                                                                  } else if(!best_name[name_index] && !locale.empty()) {
                                                                        if(locale == (char*) lang) {
                                                                              value2 = xmlNodeListGetString(doc, child3->xmlChildrenNode, 1);
                                                                              best_name[name_index] = true;
                                                                              if(value2) prop_names[name_index] = (char*) value2;
                                                                              else prop_names[name_index] = "";
                                                                        } else if(!nextbest_name[name_index] && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {
                                                                              value2 = xmlNodeListGetString(doc, child3->xmlChildrenNode, 1);
                                                                              nextbest_name[name_index] = true;
                                                                              if(value2) prop_names[name_index] = (char*) value2;
                                                                              else prop_names[name_index] = "";
                                                                        }
                                                                  }
                                                                  if(value2) xmlFree(value2);
                                                                  if(lang) xmlFree(lang);
                                                                  value2 = NULL; lang = NULL;
                                                            }
                                                            child3 = child3->next;
                                                      }
                                                      if(!ref_prop_names[name_index].empty() && ref_prop_names[name_index] == prop_names[name_index]) {
                                                            ref_prop_names[name_index] = "";
                                                      }
                                                }
                                          } else if(new_names && !xmlStrcmp(child2->name, (const xmlChar*) "names") && ((best_prop_names.empty() && fulfilled_translation != 2) || default_prop_names.empty())) {
                                                      value2 = xmlNodeListGetString(doc, child2->xmlChildrenNode, 1);
                                                      lang = xmlNodeGetLang(child2);
                                                      if(!lang) {
                                                            if(default_prop_names.empty()) {
                                                                  if(value2) {
                                                                        default_prop_names = (char*) value2;
                                                                        remove_blank_ends(default_prop_names);
                                                                  } else {
                                                                        default_prop_names = "";
                                                                  }
                                                            }
                                                      } else {
                                                            if(locale == (char*) lang) {
                                                                  if(value2) {
                                                                        best_prop_names = (char*) value2;
                                                                        remove_blank_ends(best_prop_names);
                                                                  } else {
                                                                        best_prop_names = " ";
                                                                  }
                                                      } else if(nextbest_prop_names.empty() && strlen((char*) lang) >= 2 && fulfilled_translation == 0 && lang[0] == localebase[0] && lang[1] == localebase[1]) {
                                                            if(value2) {
                                                                  nextbest_prop_names = (char*) value2;
                                                                  remove_blank_ends(nextbest_prop_names);
                                                            } else {
                                                                  nextbest_prop_names = " ";
                                                            }
                                                      } else if(nextbest_prop_names.empty() && default_prop_names.empty() && value2 && !require_translation) {
                                                            nextbest_prop_names = (char*) value2;
                                                            remove_blank_ends(nextbest_prop_names);
                                                      }
                                                }
                                                if(value2) xmlFree(value2);
                                                if(lang) xmlFree(lang);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "description")) {
                                                XML_GET_LOCALE_STRING_FROM_TEXT(child2, propdescr, best_propdescr, next_best_propdescr)
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "unit")) {
                                                XML_DO_FROM_TEXT(child2, dp->setUnit)
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "key")) {
                                                XML_GET_TRUE_FROM_TEXT(child2, b)
                                                dp->setKey(b);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "hidden")) {
                                                XML_GET_TRUE_FROM_TEXT(child2, b)
                                                dp->setHidden(b);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "brackets")) {
                                                XML_GET_TRUE_FROM_TEXT(child2, b)
                                                dp->setUsesBrackets(b);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "approximate")) {
                                                XML_GET_TRUE_FROM_TEXT(child2, b)
                                                dp->setApproximate(b);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "case_sensitive")) {
                                                XML_GET_TRUE_FROM_TEXT(child2, b)
                                                dp->setCaseSensitive(b);
                                          } else if(!xmlStrcmp(child2->name, (const xmlChar*) "type")) {
                                                XML_GET_STRING_FROM_TEXT(child2, stmp)
                                                if(stmp == "text") {
                                                      dp->setPropertyType(PROPERTY_STRING);
                                                } else if(stmp == "number") {
                                                      dp->setPropertyType(PROPERTY_NUMBER);
                                                } else if(stmp == "expression") {
                                                      dp->setPropertyType(PROPERTY_EXPRESSION);
                                                }
                                          }
                                          child2 = child2->next;
                                    }
                                    if(!proptitle.empty() && proptitle[0] == '!') {\
                                          size_t i = proptitle.find('!', 1);
                                          if(i == string::npos) {
                                                dp->setTitle(proptitle);
                                          } else if(i + 1 < proptitle.length()) {
                                                dp->setTitle(proptitle.substr(i + 1, proptitle.length() - (i + 1)));
                                          }
                                    } else {
                                          dp->setTitle(proptitle);
                                    }
                                    dp->setDescription(propdescr);
                                    if(new_names) {
                                          size_t names_i = 0, i2 = 0;
                                          string *str_names;
                                          bool had_ref = false;
                                          if(best_prop_names == "-") {best_prop_names = ""; nextbest_prop_names = "";}
                                          if(!best_prop_names.empty()) {str_names = &best_prop_names;}
                                          else if(!nextbest_prop_names.empty()) {str_names = &nextbest_prop_names;}
                                          else {str_names = &default_prop_names;}
                                          if(!str_names->empty() && (*str_names)[0] == '!') {
                                                names_i = str_names->find('!', 1) + 1;
                                          }
                                          while(true) {
                                                size_t i3 = names_i;
                                                names_i = str_names->find(",", i3);
                                                if(i2 == 0) {
                                                      i2 = str_names->find(":", i3);
                                                }
                                                bool b_prop_ref = false;
                                                if(i2 < names_i) {
                                                      bool b = true;
                                                      for(; i3 < i2; i3++) {
                                                            switch((*str_names)[i3]) {
                                                                  case '-': {b = false; break;}
                                                                  case 'r': {b_prop_ref = b; b = true; break;}
                                                            }
                                                      }
                                                      i3++;
                                                      i2 = 0;
                                                }
                                                if(names_i == string::npos) {stmp = str_names->substr(i3, str_names->length() - i3);}
                                                else {stmp = str_names->substr(i3, names_i - i3);}
                                                remove_blank_ends(stmp);
                                                if(!stmp.empty()) {
                                                      if(b_prop_ref) had_ref = true;
                                                      dp->addName(stmp, b_prop_ref);
                                                }
                                                if(names_i == string::npos) {break;}
                                                names_i++;
                                          }
                                          if(str_names != &default_prop_names && !default_prop_names.empty()) {
                                                if(default_prop_names[0] == '!') {
                                                      names_i = default_prop_names.find('!', 1) + 1;
                                                } else {
                                                      names_i = 0;
                                                }
                                                i2 = 0;
                                                while(true) {
                                                      size_t i3 = names_i;
                                                      names_i = default_prop_names.find(",", i3);
                                                      if(i2 == 0) {
                                                            i2 = default_prop_names.find(":", i3);
                                                      }
                                                      bool b_prop_ref = false;
                                                      if(i2 < names_i) {
                                                            bool b = true;
                                                            for(; i3 < i2; i3++) {
                                                                  switch(default_prop_names[i3]) {
                                                                        case '-': {b = false; break;}
                                                                        case 'r': {b_prop_ref = b; b = true; break;}
                                                                  }
                                                            }
                                                            i3++;
                                                            i2 = 0;
                                                      }
                                                      if(b_prop_ref || (!had_ref && names_i == string::npos)) {
                                                            had_ref = true;
                                                            if(names_i == string::npos) {stmp = default_prop_names.substr(i3, default_prop_names.length() - i3);}
                                                            else {stmp = default_prop_names.substr(i3, names_i - i3);}
                                                            remove_blank_ends(stmp);
                                                            size_t i4 = dp->hasName(stmp);
                                                            if(i4 > 0) {
                                                                  dp->setNameIsReference(i4, true);
                                                            } else if(!stmp.empty()) {
                                                                  dp->addName(stmp, true);
                                                            }
                                                      }
                                                      if(names_i == string::npos) {break;}
                                                      names_i++;
                                                }
                                          }
                                          if(!had_ref && dp->countNames() > 0) dp->setNameIsReference(1, true);
                                    } else {
                                          bool b = false;
                                          for(size_t i = 0; i < 10; i++) {
                                                if(!prop_names[i].empty()) {
                                                      if(!b && ref_prop_names[i].empty()) {
                                                            dp->addName(prop_names[i], true, i + 1);
                                                            b = true;
                                                      } else {
                                                            dp->addName(prop_names[i], false, i + 1);
                                                      }
                                                      prop_names[i] = "";
                                                }
                                          }
                                          for(size_t i = 0; i < 10; i++) {
                                                if(!ref_prop_names[i].empty()) {
                                                      if(!b) {
                                                            dp->addName(ref_prop_names[i], true);
                                                            b = true;
                                                      } else {
                                                            dp->addName(ref_prop_names[i], false);
                                                      }
                                                      ref_prop_names[i] = "";
                                                }
                                          }
                                    }
                                    dp->setUserModified(is_user_defs);
                                    dc->addProperty(dp);
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "argument")) {
                                    child2 = child->xmlChildrenNode;
                                    argname = ""; best_argname = false; next_best_argname = false;
                                    while(child2 != NULL) {
                                          if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) {
                                                XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname)
                                          }
                                          child2 = child2->next;
                                    }
                                    itmp = 1;
                                    XML_GET_INT_FROM_PROP(child, "index", itmp);
                                    if(dc->getArgumentDefinition(itmp)) {
                                          dc->getArgumentDefinition(itmp)->setName(argname);
                                    }
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "object_argument")) {
                                    child2 = child->xmlChildrenNode;
                                    argname = ""; best_argname = false; next_best_argname = false;
                                    while(child2 != NULL) {
                                          if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) {
                                                XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname)
                                          }
                                          child2 = child2->next;
                                    }
                                    itmp = 1;
                                    if(dc->getArgumentDefinition(itmp)) {
                                          if(!argname.empty() && argname[0] == '!') {
                                                size_t i = argname.find('!', 1);
                                                if(i == string::npos) {
                                                      dc->getArgumentDefinition(itmp)->setName(argname);
                                                } else if(i + 1 < argname.length()) {
                                                      dc->getArgumentDefinition(itmp)->setName(argname.substr(i + 1, argname.length() - (i + 1)));
                                                }
                                          } else {
                                                dc->getArgumentDefinition(itmp)->setName(argname);
                                          }
                                    }
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "property_argument")) {
                                    child2 = child->xmlChildrenNode;
                                    argname = ""; best_argname = false; next_best_argname = false;
                                    while(child2 != NULL) {
                                          if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) {
                                                XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname)
                                          }
                                          child2 = child2->next;
                                    }
                                    itmp = 2;
                                    if(dc->getArgumentDefinition(itmp)) {
                                          if(!argname.empty() && argname[0] == '!') {
                                                size_t i = argname.find('!', 1);
                                                if(i == string::npos) {
                                                      dc->getArgumentDefinition(itmp)->setName(argname);
                                                } else if(i + 1 < argname.length()) {
                                                      dc->getArgumentDefinition(itmp)->setName(argname.substr(i + 1, argname.length() - (i + 1)));
                                                }
                                          } else {
                                                dc->getArgumentDefinition(itmp)->setName(argname);
                                          }
                                    }
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "default_property")) {
                                    XML_DO_FROM_TEXT(child, dc->setDefaultProperty)
                              } else if(!builtin && !xmlStrcmp(child->name, (const xmlChar*) "copyright")) {
                                    XML_DO_FROM_TEXT(child, dc->setCopyright)
                              } else if(!builtin && !xmlStrcmp(child->name, (const xmlChar*) "datafile")) {
                                    XML_DO_FROM_TEXT(child, dc->setDefaultDataFile)
                              } else ITEM_READ_NAME(functionNameIsValid)
                               else ITEM_READ_DTH
                               else {
                                    ITEM_READ_NAMES
                              }
                              child = child->next;
                        }
                        if(new_names) {
                              if(builtin) {
                                    ITEM_SAVE_BUILTIN_NAMES
                              }
                              ITEM_SET_BEST_NAMES(functionNameIsValid)
                              ITEM_SET_REFERENCE_NAMES(functionNameIsValid)
                              if(builtin) {
                                    ITEM_SET_BUILTIN_NAMES
                              }
                        } else {
                              if(builtin) {
                                    BUILTIN_NAMES_1
                              }
                              ITEM_SET_NAME_2
                              ITEM_SET_NAME_3
                              if(builtin) {
                                    BUILTIN_NAMES_2
                              }
                        }
                        ITEM_SET_DTH
                        if(!builtin && dc->countNames() == 0) {
                              dc->destroy();
                              dc = NULL;
                        } else {
                              dc->setChanged(builtin && is_user_defs);
                              if(!builtin) addDataSet(dc, true, is_user_defs);
                        }
                        done_something = true;
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "builtin_function")) {
                        XML_GET_STRING_FROM_PROP(cur, "name", name)
                        f = getFunction(name);
                        if(f) {
                              XML_GET_FALSE_FROM_PROP(cur, "active", active)
                              f->setLocal(is_user_defs, active);
                              f->setCategory(category);
                              item = f;
                              child = cur->xmlChildrenNode;
                              ITEM_INIT_DTH
                              ITEM_INIT_NAME
                              while(child != NULL) {
                                    if(!xmlStrcmp(child->name, (const xmlChar*) "argument")) {
                                          child2 = child->xmlChildrenNode;
                                          argname = ""; best_argname = false; next_best_argname = false;
                                          while(child2 != NULL) {
                                                if(!xmlStrcmp(child2->name, (const xmlChar*) "title")) {
                                                      XML_GET_LOCALE_STRING_FROM_TEXT(child2, argname, best_argname, next_best_argname)
                                                }
                                                child2 = child2->next;
                                          }
                                          itmp = 1;
                                          XML_GET_INT_FROM_PROP(child, "index", itmp);
                                          if(f->getArgumentDefinition(itmp)) {
                                                if(!argname.empty() && argname[0] == '!') {
                                                      size_t i = argname.find('!', 1);
                                                      if(i == string::npos) {
                                                            f->getArgumentDefinition(itmp)->setName(argname);
                                                      } else if(i + 1 < argname.length()) {
                                                            f->getArgumentDefinition(itmp)->setName(argname.substr(i + 1, argname.length() - (i + 1)));
                                                      }
                                                } else {
                                                      f->getArgumentDefinition(itmp)->setName(argname);
                                                }
                                          } else if(itmp <= f->maxargs() || itmp <= f->minargs()) {
                                                if(!argname.empty() && argname[0] == '!') {
                                                      size_t i = argname.find('!', 1);
                                                      if(i == string::npos) {
                                                            f->setArgumentDefinition(itmp, new Argument(argname, false));
                                                      } else if(i + 1 < argname.length()) {
                                                            f->setArgumentDefinition(itmp, new Argument(argname.substr(i + 1, argname.length() - (i + 1)), false));
                                                      }
                                                } else {
                                                      f->setArgumentDefinition(itmp, new Argument(argname, false));
                                                }
                                          }
                                    } else ITEM_READ_NAME(functionNameIsValid)
                                     else ITEM_READ_DTH
                                     else {
                                          ITEM_READ_NAMES
                                    }
                                    child = child->next;
                              }
                              if(new_names) {
                                    ITEM_SAVE_BUILTIN_NAMES
                                    ITEM_SET_BEST_NAMES(functionNameIsValid)
                                    ITEM_SET_REFERENCE_NAMES(functionNameIsValid)
                                    ITEM_SET_BUILTIN_NAMES
                              } else {
                                    BUILTIN_NAMES_1
                                    ITEM_SET_NAME_2
                                    ITEM_SET_NAME_3
                                    BUILTIN_NAMES_2
                              }
                              ITEM_SET_DTH
                              f->setChanged(false);
                              done_something = true;
                        }
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "unknown")) {
                        if(VERSION_BEFORE(0, 6, 3)) {
                              XML_GET_STRING_FROM_PROP(cur, "name", name)
                        } else {
                              name = "";
                        }
                        XML_GET_FALSE_FROM_PROP(cur, "active", active)
                        svalue = "";
                        v = new UnknownVariable(category, "", "", is_user_defs, false, active);
                        item = v;
                        done_something = true;
                        child = cur->xmlChildrenNode;
                        b = true;
                        ITEM_INIT_DTH
                        ITEM_INIT_NAME
                        while(child != NULL) {
                              if(!xmlStrcmp(child->name, (const xmlChar*) "type")) {
                                    XML_GET_STRING_FROM_TEXT(child, stmp);
                                    if(!((UnknownVariable*) v)->assumptions()) ((UnknownVariable*) v)->setAssumptions(new Assumptions());
                                    if(stmp == "integer") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_INTEGER);
                                    else if(stmp == "rational") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_RATIONAL);
                                    else if(stmp == "real") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_REAL);
                                    else if(stmp == "complex") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_COMPLEX);
                                    else if(stmp == "number") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NUMBER);
                                    else if(stmp == "non-matrix") ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NONMATRIX);
                                    else if(stmp == "none") {
                                          if(VERSION_BEFORE(0, 9, 1)) {
                                                ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NONMATRIX);
                                          } else {
                                                ((UnknownVariable*) v)->assumptions()->setType(ASSUMPTION_TYPE_NONE);
                                          }
                                    }
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "sign")) {
                                    XML_GET_STRING_FROM_TEXT(child, stmp);
                                    if(!((UnknownVariable*) v)->assumptions()) ((UnknownVariable*) v)->setAssumptions(new Assumptions());
                                    if(stmp == "non-zero") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NONZERO);
                                    else if(stmp == "non-positive") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NONPOSITIVE);
                                    else if(stmp == "negative") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NEGATIVE);
                                    else if(stmp == "non-negative") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_NONNEGATIVE);
                                    else if(stmp == "positive") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_POSITIVE);
                                    else if(stmp == "unknown") ((UnknownVariable*) v)->assumptions()->setSign(ASSUMPTION_SIGN_UNKNOWN);
                              } else ITEM_READ_NAME(variableNameIsValid)
                               else ITEM_READ_DTH
                               else {
                                    ITEM_READ_NAMES
                              }
                              child = child->next;
                        }
                        if(new_names) {
                              ITEM_SET_BEST_NAMES(variableNameIsValid)
                              ITEM_SET_REFERENCE_NAMES(variableNameIsValid)
                        } else {
                              ITEM_SET_NAME_1(variableNameIsValid)
                              ITEM_SET_NAME_2
                              ITEM_SET_NAME_3
                        }
                        ITEM_SET_DTH
                        for(size_t i = 1; i <= v->countNames(); i++) {
                              if(v->getName(i).name == "x") {v_x->destroy(); v_x = (UnknownVariable*) v; break;}
                              if(v->getName(i).name == "y") {v_y->destroy(); v_y = (UnknownVariable*) v; break;}
                              if(v->getName(i).name == "z") {v_z->destroy(); v_z = (UnknownVariable*) v; break;}
                        }
                        if(v->countNames() == 0) {
                              v->destroy();
                              v = NULL;
                        } else {
                              addVariable(v, true, is_user_defs);
                              v->setChanged(false);
                        }
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "variable")) {
                        if(VERSION_BEFORE(0, 6, 3)) {
                              XML_GET_STRING_FROM_PROP(cur, "name", name)
                        } else {
                              name = "";
                        }
                        XML_GET_FALSE_FROM_PROP(cur, "active", active)
                        svalue = "";
                        v = new KnownVariable(category, "", "", "", is_user_defs, false, active);
                        item = v;
                        done_something = true;
                        child = cur->xmlChildrenNode;
                        b = true;
                        ITEM_INIT_DTH
                        ITEM_INIT_NAME
                        while(child != NULL) {
                              if(!xmlStrcmp(child->name, (const xmlChar*) "value")) {
                                    XML_DO_FROM_TEXT(child, ((KnownVariable*) v)->set);
                                    XML_GET_PREC_FROM_PROP(child, prec)
                                    v->setPrecision(prec);
                                    XML_GET_APPROX_FROM_PROP(child, b);
                                    v->setApproximate(b);
                              } else ITEM_READ_NAME(variableNameIsValid)
                               else ITEM_READ_DTH
                               else {
                                    ITEM_READ_NAMES
                              }
                              child = child->next;
                        }
                        if(new_names) {
                              ITEM_SET_BEST_NAMES(variableNameIsValid)
                              ITEM_SET_REFERENCE_NAMES(variableNameIsValid)
                        } else {
                              ITEM_SET_NAME_1(variableNameIsValid)
                              ITEM_SET_NAME_2
                              ITEM_SET_NAME_3
                        }
                        ITEM_SET_DTH
                        if(v->countNames() == 0) {
                              v->destroy();
                              v = NULL;
                        } else {
                              addVariable(v, true, is_user_defs);
                              item->setChanged(false);
                        }
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "builtin_variable")) {
                        XML_GET_STRING_FROM_PROP(cur, "name", name)
                        v = getVariable(name);
                        if(v) {     
                              XML_GET_FALSE_FROM_PROP(cur, "active", active)
                              v->setLocal(is_user_defs, active);
                              v->setCategory(category);
                              item = v;
                              child = cur->xmlChildrenNode;
                              ITEM_INIT_DTH
                              ITEM_INIT_NAME
                              while(child != NULL) {
                                    ITEM_READ_NAME(variableNameIsValid)
                                     else ITEM_READ_DTH
                                     else {
                                          ITEM_READ_NAMES
                                    }
                                    child = child->next;
                              }
                              if(new_names) {
                                    ITEM_SAVE_BUILTIN_NAMES
                                    ITEM_SET_BEST_NAMES(variableNameIsValid)
                                    ITEM_SET_REFERENCE_NAMES(variableNameIsValid)
                                    ITEM_SET_BUILTIN_NAMES
                              } else {
                                    BUILTIN_NAMES_1
                                    ITEM_SET_NAME_2
                                    ITEM_SET_NAME_3
                                    BUILTIN_NAMES_2
                              }
                              ITEM_SET_DTH
                              v->setChanged(false);
                              done_something = true;
                        }
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "unit")) {
                        XML_GET_STRING_FROM_PROP(cur, "type", type)
                        if(type == "base") {    
                              if(VERSION_BEFORE(0, 6, 3)) {
                                    XML_GET_STRING_FROM_PROP(cur, "name", name)
                              } else {
                                    name = "";
                              }
                              XML_GET_FALSE_FROM_PROP(cur, "active", active)
                              u = new Unit(category, "", "", "", "", is_user_defs, false, active);
                              item = u;
                              child = cur->xmlChildrenNode;
                              singular = ""; best_singular = false; next_best_singular = false;
                              plural = ""; best_plural = false; next_best_plural = false;
                              ITEM_INIT_DTH
                              ITEM_INIT_NAME
                              while(child != NULL) {
                                    if(!xmlStrcmp(child->name, (const xmlChar*) "system")) {    
                                          XML_DO_FROM_TEXT(child, u->setSystem)
                                    } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "singular")) {
                                          XML_GET_LOCALE_STRING_FROM_TEXT(child, singular, best_singular, next_best_singular)
                                          if(!unitNameIsValid(singular, version_numbers, is_user_defs)) {
                                                singular = "";
                                          }
                                    } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "plural") && !xmlGetProp(child, (xmlChar*) "index")) {
                                          XML_GET_LOCALE_STRING_FROM_TEXT(child, plural, best_plural, next_best_plural)
                                          if(!unitNameIsValid(plural, version_numbers, is_user_defs)) {
                                                plural = "";
                                          }
                                    } else ITEM_READ_NAME(unitNameIsValid)
                                     else ITEM_READ_DTH
                                     else {
                                          ITEM_READ_NAMES
                                    }
                                    child = child->next;
                              }
                              if(new_names) {
                                    ITEM_SET_BEST_NAMES(unitNameIsValid)
                                    ITEM_SET_REFERENCE_NAMES(unitNameIsValid)
                              } else {
                                    ITEM_SET_SHORT_NAME
                                    ITEM_SET_SINGULAR
                                    ITEM_SET_PLURAL
                                    ITEM_SET_NAME_2
                                    ITEM_SET_NAME_3
                              }
                              ITEM_SET_DTH
                              if(u->countNames() == 0) {
                                    u->destroy();
                                    u = NULL;
                              } else {
                                    addUnit(u, true, is_user_defs);
                                    u->setChanged(false);
                              }
                              done_something = true;
                        } else if(type == "alias") {  
                              if(VERSION_BEFORE(0, 6, 3)) {
                                    XML_GET_STRING_FROM_PROP(cur, "name", name)
                              } else {
                                    name = "";
                              }
                              XML_GET_FALSE_FROM_PROP(cur, "active", active)
                              u = NULL;
                              child = cur->xmlChildrenNode;
                              singular = ""; best_singular = false; next_best_singular = false;
                              plural = ""; best_plural = false; next_best_plural = false;
                              usystem = "";
                              prec = -1;
                              ITEM_INIT_DTH
                              ITEM_INIT_NAME
                              while(child != NULL) {
                                    if(!xmlStrcmp(child->name, (const xmlChar*) "base")) {
                                          child2 = child->xmlChildrenNode;
                                          exponent = 1;
                                          svalue = "";
                                          inverse = "";
                                          b = true;
                                          while(child2 != NULL) {
                                                if(!xmlStrcmp(child2->name, (const xmlChar*) "unit")) {
                                                      XML_GET_STRING_FROM_TEXT(child2, base);
                                                      u = getUnit(base);
                                                      if(!u) {
                                                            u = getCompositeUnit(base);
                                                      }
                                                } else if(!xmlStrcmp(child2->name, (const xmlChar*) "relation")) {
                                                      XML_GET_STRING_FROM_TEXT(child2, svalue);
                                                      XML_GET_APPROX_FROM_PROP(child2, b)
                                                      XML_GET_PREC_FROM_PROP(child, prec)
                                                } else if(!xmlStrcmp(child2->name, (const xmlChar*) "reverse_relation")) {
                                                      XML_GET_STRING_FROM_TEXT(child2, inverse);
                                                } else if(!xmlStrcmp(child2->name, (const xmlChar*) "inverse_relation")) {
                                                      XML_GET_STRING_FROM_TEXT(child2, inverse);
                                                } else if(!xmlStrcmp(child2->name, (const xmlChar*) "exponent")) {
                                                      XML_GET_STRING_FROM_TEXT(child2, stmp);
                                                      if(stmp.empty()) {
                                                            exponent = 1;
                                                      } else {
                                                            exponent = s2i(stmp);
                                                      }
                                                }
                                                child2 = child2->next;
                                          }
                                    } else if(!xmlStrcmp(child->name, (const xmlChar*) "system")) {
                                          XML_GET_STRING_FROM_TEXT(child, usystem);
                                    } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "singular")) {  
                                          XML_GET_LOCALE_STRING_FROM_TEXT(child, singular, best_singular, next_best_singular)
                                          if(!unitNameIsValid(singular, version_numbers, is_user_defs)) {
                                                singular = "";
                                          }
                                    } else if((VERSION_BEFORE(0, 6, 3)) && !xmlStrcmp(child->name, (const xmlChar*) "plural") && !xmlGetProp(child, (xmlChar*) "index")) {    
                                          XML_GET_LOCALE_STRING_FROM_TEXT(child, plural, best_plural, next_best_plural)
                                          if(!unitNameIsValid(plural, version_numbers, is_user_defs)) {
                                                plural = "";
                                          }
                                    } else ITEM_READ_NAME(unitNameIsValid)
                                     else ITEM_READ_DTH
                                     else {
                                          ITEM_READ_NAMES
                                    }
                                    child = child->next;
                              }
                              if(!u) {
                                    ITEM_CLEAR_NAMES
                                    if(!in_unfinished) {
                                          unfinished_nodes.push_back(cur);
                                          unfinished_cats.push_back(category);
                                    }
                              } else {
                                    au = new AliasUnit(category, name, plural, singular, title, u, svalue, exponent, inverse, is_user_defs, false, active);
                                    au->setDescription(description);
                                    au->setPrecision(prec);
                                    au->setApproximate(b);
                                    au->setHidden(hidden);
                                    au->setSystem(usystem);
                                    item = au;
                                    if(new_names) {
                                          ITEM_SET_BEST_NAMES(unitNameIsValid)
                                          ITEM_SET_REFERENCE_NAMES(unitNameIsValid)
                                    } else {
                                          ITEM_SET_NAME_2
                                          ITEM_SET_NAME_3
                                    }
                                    if(au->countNames() == 0) {
                                          au->destroy();
                                          au = NULL;
                                    } else {
                                          addUnit(au, true, is_user_defs);
                                          au->setChanged(false);
                                    }
                                    done_something = true;  
                              }
                        } else if(type == "composite") {
                              if(VERSION_BEFORE(0, 6, 3)) {
                                    XML_GET_STRING_FROM_PROP(cur, "name", name)
                              } else {
                                    name = "";
                              }
                              XML_GET_FALSE_FROM_PROP(cur, "active", active)
                              child = cur->xmlChildrenNode;
                              usystem = "";
                              cu = NULL;
                              ITEM_INIT_DTH
                              ITEM_INIT_NAME
                              b = true;
                              while(child != NULL) {
                                    u = NULL;
                                    if(!xmlStrcmp(child->name, (const xmlChar*) "part")) {
                                          child2 = child->xmlChildrenNode;
                                          p = NULL;
                                          exponent = 1;                                         
                                          while(child2 != NULL) {
                                                if(!xmlStrcmp(child2->name, (const xmlChar*) "unit")) {
                                                      XML_GET_STRING_FROM_TEXT(child2, base);                                                   
                                                      u = getUnit(base);
                                                      if(!u) {
                                                            u = getCompositeUnit(base);
                                                      }
                                                } else if(!xmlStrcmp(child2->name, (const xmlChar*) "prefix")) {
                                                      XML_GET_STRING_FROM_PROP(child2, "type", stmp)
                                                      XML_GET_STRING_FROM_TEXT(child2, svalue);
                                                      p = NULL;
                                                      if(stmp == "binary") {
                                                            litmp = s2i(svalue);
                                                            if(litmp != 0) {
                                                                  p = getExactBinaryPrefix(litmp);
                                                                  if(!p) b = false;
                                                            }
                                                      } else if(stmp == "number") {
                                                            nr.set(stmp);
                                                            if(!nr.isZero()) {
                                                                  p = getExactPrefix(stmp);
                                                                  if(!p) b = false;
                                                            }
                                                      } else {
                                                            litmp = s2i(svalue);
                                                            if(litmp != 0) {
                                                                  p = getExactDecimalPrefix(litmp);
                                                                  if(!p) b = false;
                                                            }
                                                      }
                                                      if(!b) {
                                                            if(cu) {
                                                                  delete cu;
                                                            }
                                                            cu = NULL;
                                                            break;
                                                      }                                                                       
                                                } else if(!xmlStrcmp(child2->name, (const xmlChar*) "exponent")) {
                                                      XML_GET_STRING_FROM_TEXT(child2, stmp);
                                                      if(stmp.empty()) {
                                                            exponent = 1;
                                                      } else {
                                                            exponent = s2i(stmp);
                                                      }
                                                }
                                                child2 = child2->next;
                                          }
                                          if(!b) break;
                                          if(u) {
                                                if(!cu) {
                                                      cu = new CompositeUnit("", "", "", "", is_user_defs, false, active);
                                                }
                                                cu->add(u, exponent, p);
                                          } else {
                                                if(cu) delete cu;
                                                cu = NULL;
                                                if(!in_unfinished) {
                                                      unfinished_nodes.push_back(cur);
                                                      unfinished_cats.push_back(category);
                                                }
                                                break;
                                          }
                                    } else if(!xmlStrcmp(child->name, (const xmlChar*) "system")) {
                                          XML_GET_STRING_FROM_TEXT(child, usystem);
                                    } else ITEM_READ_NAME(unitNameIsValid)
                                     else ITEM_READ_DTH
                                     else {
                                          ITEM_READ_NAMES
                                    }
                                    child = child->next;
                              }
                              if(cu) {
                                    item = cu;
                                    cu->setCategory(category);
                                    cu->setSystem(usystem);
                                    if(new_names) {
                                          ITEM_SET_BEST_NAMES(unitNameIsValid)
                                          ITEM_SET_REFERENCE_NAMES(unitNameIsValid)
                                    } else {
                                          ITEM_SET_NAME_1(unitNameIsValid)
                                          ITEM_SET_NAME_2
                                          ITEM_SET_NAME_3
                                    }
                                    ITEM_SET_DTH
                                    if(cu->countNames() == 0) {
                                          cu->destroy();
                                          cu = NULL;
                                    } else {
                                          addUnit(cu, true, is_user_defs);
                                          cu->setChanged(false);
                                    }
                                    done_something = true;
                              } else {
                                    ITEM_CLEAR_NAMES
                              }
                        }
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "builtin_unit")) {
                        XML_GET_STRING_FROM_PROP(cur, "name", name)
                        u = getUnit(name);
                        if(!u) {
                              u = getCompositeUnit(name);
                        }
                        if(u) {     
                              XML_GET_FALSE_FROM_PROP(cur, "active", active)
                              u->setLocal(is_user_defs, active);
                              u->setCategory(category);
                              item = u;
                              child = cur->xmlChildrenNode;
                              singular = ""; best_singular = false; next_best_singular = false;
                              plural = ""; best_plural = false; next_best_plural = false;
                              ITEM_INIT_DTH
                              ITEM_INIT_NAME
                              while(child != NULL) {
                                    if(!xmlStrcmp(child->name, (const xmlChar*) "singular")) {  
                                          XML_GET_LOCALE_STRING_FROM_TEXT(child, singular, best_singular, next_best_singular)
                                          if(!unitNameIsValid(singular, version_numbers, is_user_defs)) {
                                                singular = "";
                                          }
                                    } else if(!xmlStrcmp(child->name, (const xmlChar*) "plural") && !xmlGetProp(child, (xmlChar*) "index")) {   
                                          XML_GET_LOCALE_STRING_FROM_TEXT(child, plural, best_plural, next_best_plural)
                                          if(!unitNameIsValid(plural, version_numbers, is_user_defs)) {
                                                plural = "";
                                          }
                                    } else ITEM_READ_NAME(unitNameIsValid)
                                     else ITEM_READ_DTH
                                     else {
                                          ITEM_READ_NAMES
                                    }
                                    child = child->next;
                              }
                              if(new_names) {
                                    ITEM_SAVE_BUILTIN_NAMES
                                    ITEM_SET_BEST_NAMES(unitNameIsValid)
                                    ITEM_SET_REFERENCE_NAMES(unitNameIsValid)
                                    ITEM_SET_BUILTIN_NAMES
                              } else {
                                    BUILTIN_UNIT_NAMES_1
                                    ITEM_SET_SINGULAR
                                    ITEM_SET_PLURAL
                                    ITEM_SET_NAME_2
                                    ITEM_SET_NAME_3
                                    BUILTIN_NAMES_2
                              }
                              ITEM_SET_DTH
                              u->setChanged(false);
                              done_something = true;
                        }
                  } else if(!xmlStrcmp(cur->name, (const xmlChar*) "prefix")) {
                        child = cur->xmlChildrenNode;
                        XML_GET_STRING_FROM_PROP(cur, "type", type)
                        uname = ""; sexp = ""; svalue = "";
                        while(child != NULL) {
                              if(!xmlStrcmp(child->name, (const xmlChar*) "name")) {
                                    XML_GET_STRING_FROM_TEXT(child, name);
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "abbreviation")) {   
                                    XML_GET_STRING_FROM_TEXT(child, stmp);
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "unicode")) {  
                                    XML_GET_STRING_FROM_TEXT(child, uname);
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "exponent")) { 
                                    XML_GET_STRING_FROM_TEXT(child, sexp);
                              } else if(!xmlStrcmp(child->name, (const xmlChar*) "value")) {    
                                    XML_GET_STRING_FROM_TEXT(child, svalue);
                              }
                              child = child->next;
                        }
                        if(type == "decimal") {
                              addPrefix(new DecimalPrefix(s2i(sexp), name, stmp, uname));
                        } else if(type == "number") {
                              addPrefix(new NumberPrefix(svalue, name, stmp, uname));
                        } else if(type == "binary") {
                              addPrefix(new BinaryPrefix(s2i(sexp), name, stmp, uname));
                        } else {
                              if(svalue.empty()) {
                                    addPrefix(new DecimalPrefix(s2i(sexp), name, stmp, uname));
                              } else {
                                    addPrefix(new NumberPrefix(svalue, name, stmp, uname));
                              }
                        }
                        done_something = true;
                  }
                  after_load_object:
                  cur = NULL;
                  if(in_unfinished) {
                        if(done_something) {
                              in_unfinished--;
                              unfinished_nodes.erase(unfinished_nodes.begin() + in_unfinished);
                              unfinished_cats.erase(unfinished_cats.begin() + in_unfinished);
                        }
                        if((int) unfinished_nodes.size() > in_unfinished) {
                              cur = unfinished_nodes[in_unfinished];
                              category = unfinished_cats[in_unfinished];
                        } else if(done_something && unfinished_nodes.size() > 0) {
                              cur = unfinished_nodes[0];
                              category = unfinished_cats[0];
                              in_unfinished = 0;
                              done_something = false;
                        }
                        in_unfinished++;
                        done_something = false;
                  }
            }
            if(in_unfinished) {
                  break;
            }
            while(!nodes.empty() && nodes.back().empty()) {
                  size_t cat_i = category.rfind("/");
                  if(cat_i == string::npos) {
                        category = "";
                  } else {
                        category = category.substr(0, cat_i);
                  }
                  nodes.pop_back();
            }
            if(!nodes.empty()) {
                  cur = nodes.back().front();
                  nodes.back().pop();
                  nodes.resize(nodes.size() + 1);
            } else {
                  if(unfinished_nodes.size() > 0) {
                        cur = unfinished_nodes[0];
                        category = unfinished_cats[0];
                        in_unfinished = 1;
                        done_something = false;
                  } else {
                        cur = NULL;
                  }
            } 
            if(cur == NULL) {
                  break;
            } 
      }
      xmlFreeDoc(doc);
      return true;
}


Generated by  Doxygen 1.6.0   Back to index