Qucs-core
0.0.19
|
00001 /* 00002 * check_mdl.cpp - iterate an IC-CAP MDL file 00003 * 00004 * Copyright (C) 2006, 2007 Stefan Jahn <stefan@lkcc.org> 00005 * 00006 * This is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU General Public License as published by 00008 * the Free Software Foundation; either version 2, or (at your option) 00009 * any later version. 00010 * 00011 * This software is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this package; see the file COPYING. If not, write to 00018 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 * $Id$ 00022 * 00023 */ 00024 00025 #if HAVE_CONFIG_H 00026 # include <config.h> 00027 #endif 00028 00029 #include <stdio.h> 00030 #include <stdlib.h> 00031 #include <string.h> 00032 #include <cmath> 00033 #include <assert.h> 00034 #include <float.h> 00035 #include <ctype.h> 00036 00037 #include "logging.h" 00038 #include "strlist.h" 00039 #include "object.h" 00040 #include "complex.h" 00041 #include "vector.h" 00042 #include "dataset.h" 00043 #include "sweep.h" 00044 #include "valuelist.h" 00045 #include "constants.h" 00046 #include "check_mdl.h" 00047 #include "tokens_mdl.h" 00048 00049 using namespace qucs; 00050 00051 // Global variables. 00052 dataset * mdl_result = NULL; 00053 struct mdl_link_t * mdl_root = NULL; 00054 struct mdl_sync_t * mdl_sync_root = NULL; 00055 00056 // Creates an independent data vector. 00057 static void mdl_create_depdataset (sweep * data, char * name) { 00058 vector v (name); 00059 for (int i = 0; i < data->getSize (); i++) v.add (data->get (i)); 00060 mdl_result->appendDependency (new vector (v)); 00061 } 00062 00063 // Creates an independent data vector with a single element. 00064 static void mdl_create_condataset (double val, char * name) { 00065 vector v (name); 00066 v.add (val); 00067 mdl_result->appendDependency (new vector (v)); 00068 } 00069 00070 // The functions creates dependent data vector(s). 00071 static void mdl_create_vardataset (struct mdl_point_t * point, 00072 struct mdl_datasize_t * dsize, 00073 const char * name, const char * type, 00074 strlist * deps) { 00075 vector * v = new vector[dsize->x * dsize->y] (); 00076 // adjust type 00077 if (!strcmp (type, "MEAS")) 00078 type = ".M"; 00079 else if (!strcmp (type, "SIMU")) 00080 type = ".S"; 00081 else if (!strcmp (type, "COMMON")) 00082 type = ""; 00083 // create vectors 00084 for (struct mdl_point_t * p = point; p != NULL; p = p->next) { 00085 int n = (p->y - 1) * 2 + p->x - 1; 00086 v[n].add (nr_complex_t (p->r, p->i)); 00087 } 00088 // go through indices 00089 for (int x = 1; x < dsize->x + 1; x++) { 00090 for (int y = 1; y < dsize->y + 1; y++) { 00091 // create vector description 00092 int n = (y - 1) * 2 + x - 1; 00093 char * txt = (char *) malloc (strlen (name) + strlen (type) + 4 + 2 * 3); 00094 if (dsize->x > 1 || dsize->y > 1) 00095 sprintf (txt, "%s%s[%d,%d]", name, type, x, y); 00096 else 00097 sprintf (txt, "%s%s", name, type); 00098 v[n].setName (txt); 00099 free (txt); 00100 // put vector into dataset 00101 if (v[n].getSize () > 1) { 00102 v[n].setDependencies (new strlist (*deps)); 00103 mdl_result->appendVariable (new vector (v[n])); 00104 } else { 00105 v[n].setDependencies (new strlist ()); 00106 mdl_result->appendDependency (new vector (v[n])); 00107 } 00108 } 00109 } 00110 delete[] v; 00111 } 00112 00113 // Look through hypertable elements for a name and return value. 00114 static char * mdl_find_helement (struct mdl_element_t * root, 00115 const char * name) { 00116 for (; root != NULL; root = root->next) { 00117 if (!strcmp (root->name, name)) return root->value; 00118 } 00119 return NULL; 00120 } 00121 00122 // Look through table elements for a name and return value. 00123 static char * mdl_find_telement (struct mdl_element_t * root, 00124 const char * name) { 00125 for (; root != NULL; root = root->next) { 00126 if (!strcmp (root->name, "Name") && !strcmp (root->value, name)) { 00127 if (root->next && !strcmp (root->next->name, "Value")) { 00128 return root->next->value; 00129 } 00130 } 00131 } 00132 return NULL; 00133 } 00134 00135 // Convert number suffix into a multiplication factor. 00136 static double mdl_convert_factor (char * end) { 00137 double f = 1.0; 00138 if (end) { 00139 switch (*end) { 00140 case 'K': f = 1e+03; break; 00141 case 'M': f = 1e+06; break; 00142 case 'G': f = 1e+09; break; 00143 case 'T': f = 1e+12; break; 00144 case 'm': f = 1e-03; break; 00145 case 'u': f = 1e-06; break; 00146 case 'n': f = 1e-09; break; 00147 case 'p': f = 1e-12; break; 00148 case 'f': f = 1e-15; break; 00149 case 'a': f = 1e-18; break; 00150 } 00151 } 00152 return f; 00153 } 00154 00155 // Forward declaration. 00156 static double mdl_telement_dvalue (struct mdl_link_t *, struct mdl_element_t *, 00157 const char *); 00158 00159 // The function resolves the given variable trying upscope resolving. 00160 static int mdl_resolve_variable (struct mdl_link_t * link, char * name, 00161 double &val) { 00162 int done = 0; 00163 val = 0.0; 00164 struct mdl_lcontent_t * root; 00165 // try finding variable in current link 00166 for (root = link->content; !done && root != NULL; root = root->next) { 00167 if (root->type == t_TABLE) { 00168 struct mdl_element_t * eroot = root->table->data; 00169 if (mdl_find_telement (eroot, name)) { 00170 val = mdl_telement_dvalue (link, eroot, name); 00171 done++; 00172 } 00173 } 00174 } 00175 // resolve variable in upper scope recursively 00176 if (!done && link->parent) { 00177 done = mdl_resolve_variable (link->parent, name, val); 00178 } 00179 return done; 00180 } 00181 00182 // Converts a string into a valid value. Uses variable substitutions. 00183 static double mdl_variable_value (struct mdl_link_t * link, char * txt) { 00184 double val = 0.0; 00185 char * end = NULL; 00186 if (txt != NULL) { 00187 // remove whitespaces 00188 char * t, * p = txt; 00189 while (*p) { 00190 if (isspace (*p)) { 00191 t = p; 00192 while (*t) { *t = *(t + 1); t++; } 00193 p--; 00194 } 00195 p++; 00196 } 00197 // extract value if possible 00198 val = strtod (txt, &end); 00199 // not a value, a variable 00200 if (end == txt) { 00201 double f = 1.0; 00202 if (*txt == '-') { f = -1.0; txt++; } 00203 else if (*txt == '+') { f = +1.0; txt++; } 00204 if (!mdl_resolve_variable (link, txt, val)) { 00205 // special variables 00206 if (!strcmp (txt, "PI")) { 00207 val = pi; 00208 } 00209 // no resolvable (probably equation) 00210 else { 00211 logprint (LOG_ERROR, 00212 "checker error, unable to resolve `%s' variable in '%s'\n", 00213 txt, link->name); 00214 val = 0.0; 00215 } 00216 } 00217 val = f * val; 00218 } 00219 // normal value with probably a suffix 00220 else { 00221 val *= mdl_convert_factor (end); 00222 } 00223 } 00224 return val; 00225 } 00226 00227 // Returns a double variable value stored in a hypertable. 00228 static double mdl_helement_dvalue (struct mdl_link_t * link, 00229 struct mdl_element_t * eroot, 00230 const char * name) { 00231 char * txt = mdl_find_helement (eroot, name); 00232 return mdl_variable_value (link, txt); 00233 } 00234 00235 // Returns a double variable value stored in a table. 00236 static double mdl_telement_dvalue (struct mdl_link_t * link, 00237 struct mdl_element_t * eroot, 00238 const char * name) { 00239 char * txt = mdl_find_telement (eroot, name); 00240 return mdl_variable_value (link, txt); 00241 } 00242 00243 // Returns a integer variable value stored in a hypertable. 00244 static int mdl_helement_ivalue (struct mdl_link_t * link, 00245 struct mdl_element_t * eroot, 00246 const char * name) { 00247 return (int) mdl_helement_dvalue (link, eroot, name); 00248 } 00249 00250 // Looks for dependent data vectors and creates them. 00251 static void mdl_find_vardataset (struct mdl_dcontent_t * droot, char * name, 00252 strlist * deps) { 00253 struct mdl_dcontent_t * root; 00254 // go through dataset content 00255 for (root = droot; root != NULL; root = root->next) { 00256 if (root->type == t_DATASET) { 00257 // create possibly both - MEAS and SIMU - data vectors 00258 struct mdl_dataset_t * dset = root->data; 00259 if (dset->data1) 00260 mdl_create_vardataset (dset->data1, dset->dsize, name, dset->type1, 00261 deps); 00262 if (dset->data2) 00263 mdl_create_vardataset (dset->data2, dset->dsize, name, dset->type2, 00264 deps); 00265 } 00266 } 00267 } 00268 00269 // Looks for independent data vectors and creates them. 00270 valuelist<int> * mdl_find_depdataset (struct mdl_link_t * link, 00271 struct mdl_dcontent_t * droot, 00272 char * name) { 00273 char * stype = NULL; 00274 double val, start, stop, step; 00275 int nof = 0, order = 0; 00276 valuelist<int> * deps = new valuelist<int> (); 00277 struct mdl_dcontent_t * root; 00278 00279 // go through dataset content 00280 for (root = droot; root != NULL; root = root->next) { 00281 if (root->type == t_HYPTABLE) { 00282 struct mdl_hyptable_t * hyptab = root->hyptable; 00283 // found a sweep definition? 00284 if (!strcmp (hyptab->name, "Edit Sweep Def")) { 00285 if (!strcmp (stype, "LIN")) { 00286 // linear sweep 00287 order = mdl_helement_ivalue (link, hyptab->data, "Sweep Order"); 00288 start = mdl_helement_dvalue (link, hyptab->data, "Start"); 00289 stop = mdl_helement_dvalue (link, hyptab->data, "Stop"); 00290 nof = mdl_helement_ivalue (link, hyptab->data, "# of Points"); 00291 step = mdl_helement_dvalue (link, hyptab->data, "Step Size"); 00292 if (nof <= 0) nof = (int) fabs ((stop - start) / step) + 1; 00293 deps->insert({{name,order}}); 00294 linsweep * sw = new linsweep (); 00295 sw->create (start, stop, nof); 00296 mdl_create_depdataset (sw, name); 00297 delete sw; 00298 } 00299 else if (!strcmp (stype, "CON")) { 00300 // constant sweep 00301 val = mdl_helement_dvalue (link, hyptab->data, "Value"); 00302 mdl_create_condataset (val, name); 00303 } 00304 else if (!strcmp (stype, "LOG")) { 00305 // logarithmic sweep 00306 order = mdl_helement_ivalue (link, hyptab->data, "Sweep Order"); 00307 start = mdl_helement_dvalue (link, hyptab->data, "Start"); 00308 stop = mdl_helement_dvalue (link, hyptab->data, "Stop"); 00309 nof = mdl_helement_ivalue (link, hyptab->data, "Total Pts"); 00310 if (nof <= 0) 00311 nof = mdl_helement_ivalue (link, hyptab->data, "# of Points"); 00312 if (start * stop == 0.0) { 00313 if (start == 0.0) start = 1.0; 00314 if (stop == 0.0) stop = 1.0; 00315 } 00316 deps->insert({{name,order}}); 00317 logsweep * sw = new logsweep (); 00318 sw->create (start, stop, nof); 00319 mdl_create_depdataset (sw, name); 00320 delete sw; 00321 } 00322 else if (!strcmp (stype, "LIST")) { 00323 // list sweep 00324 order = mdl_helement_ivalue (link, hyptab->data, "Sweep Order"); 00325 nof = mdl_helement_ivalue (link, hyptab->data, "# of Values"); 00326 deps->insert({{name,order}}); 00327 } 00328 else if (!strcmp (stype, "SYNC")) { 00329 // sync sweep 00330 struct mdl_sync_t * sync = (struct mdl_sync_t *) 00331 calloc (sizeof (struct mdl_sync_t), 1); 00332 sync->ratio = mdl_helement_dvalue (link, hyptab->data, "Ratio"); 00333 sync->offset = mdl_helement_dvalue (link, hyptab->data, "Offset"); 00334 sync->master = mdl_find_helement (hyptab->data, "Master Sweep"); 00335 sync->master = strdup (sync->master); 00336 sync->name = strdup (name); 00337 sync->next = mdl_sync_root; 00338 mdl_sync_root = sync; 00339 } 00340 } 00341 // found a sweep information? 00342 else if (!strcmp (hyptab->name, "Edit Sweep Info")) { 00343 stype = mdl_find_helement (hyptab->data, "Sweep Type"); 00344 } 00345 // found a list table? 00346 else if (!strcmp (hyptab->name, "List Table")) { 00347 lstsweep * sw = new lstsweep (); 00348 sw->create (nof); 00349 char txt[16]; 00350 for (int i = 0; i < nof; i++) { 00351 sprintf (txt, "Value %d", i + 1); 00352 val = mdl_helement_dvalue (link, hyptab->data, txt); 00353 sw->set (i, val); 00354 } 00355 mdl_create_depdataset (sw, name); 00356 delete sw; 00357 } 00358 } 00359 } 00360 return deps; 00361 } 00362 00363 // Composes a link name. 00364 static char * mdl_create_linkname (char * base, char * name) { 00365 char * txt = (char *) malloc (strlen (base) + 2 + strlen (name)); 00366 sprintf (txt, "%s.%s", base, name); 00367 return txt; 00368 } 00369 00370 // Collects dependency links. 00371 static void mdl_find_deplink (struct mdl_link_t * link, char * name, 00372 valuelist<int> * deps) { 00373 struct mdl_lcontent_t * root; 00374 const valuelist<int> * d; 00375 // go through link content 00376 for (root = link->content; root != NULL; root = root->next) { 00377 // independent data vector 00378 if (root->type == t_DATA) { 00379 d = mdl_find_depdataset (link, root->data->content, name); 00380 if (d != NULL) { 00381 valuelist<int> copy = *d; 00382 delete d; 00383 copy.insert(deps->begin(),deps->end()); 00384 *deps=copy; 00385 } 00386 } 00387 // link to independent data vector 00388 else if (root->type == t_LINK && !strcmp (root->link->type, "SWEEP")) { 00389 char * txt = mdl_create_linkname (name, root->link->name); 00390 root->link->parent = link; 00391 mdl_find_deplink (root->link, txt, deps); 00392 free (txt); 00393 } 00394 } 00395 } 00396 00397 // Collects variable links. 00398 static void mdl_find_varlink (struct mdl_link_t * link, char * name, 00399 strlist * deps) { 00400 struct mdl_lcontent_t * root; 00401 // go through link content 00402 for (root = link->content; root != NULL; root = root->next) { 00403 // dependent data vector 00404 if (root->type == t_DATA) { 00405 mdl_find_vardataset (root->data->content, name, deps); 00406 } 00407 // link to dependent data vector 00408 else if (root->type == t_LINK && (!strcmp (root->link->type, "OUT") || 00409 !strcmp (root->link->type, "XFORM"))) { 00410 char * txt = mdl_create_linkname (name, root->link->name); 00411 root->link->parent = link; 00412 mdl_find_varlink (root->link, txt, deps); 00413 free (txt); 00414 } 00415 } 00416 } 00417 00418 // Sorts a dependency list according to their sweep order. 00419 static strlist * mdl_sort_deps (valuelist<int> * d) { 00420 strlist * deps = new strlist (); 00421 for (int i = 0; i < d->size(); i++) { 00422 for (auto &val: *d) { 00423 if (val.second == i + 1) { 00424 deps->append (val.first.c_str()); 00425 } 00426 } 00427 } 00428 return deps; 00429 } 00430 00431 // Iterates the MDL file recursively. 00432 static void mdl_find_link (struct mdl_link_t * link, char * name) { 00433 struct mdl_lcontent_t * root; 00434 00435 // collect independent data 00436 valuelist<int> * vdeps = new valuelist<int> (); 00437 mdl_find_deplink (link, name, vdeps); 00438 strlist * deps = mdl_sort_deps (vdeps); 00439 delete vdeps; 00440 00441 // collect dependent data 00442 mdl_find_varlink (link, name, deps); 00443 delete deps; 00444 00445 // go through link content 00446 for (root = link->content; root != NULL; root = root->next) { 00447 if (root->type == t_LINK && 00448 strcmp (root->link->type, "OUT") && 00449 strcmp (root->link->type, "SWEEP") && 00450 strcmp (root->link->type, "XFORM")) { 00451 char * txt = mdl_create_linkname (name, root->link->name); 00452 root->link->parent = link; 00453 mdl_find_link (root->link, txt); 00454 free (txt); 00455 } 00456 } 00457 } 00458 00459 // Creates an synchronized independent data vector. 00460 static void mdl_create_syndataset (vector * v, char * name) { 00461 v->setName (name); 00462 mdl_result->appendDependency (v); 00463 } 00464 00465 // Goes through list of sync sweeps and creates them if possible. 00466 void mdl_find_syncdatasets (struct mdl_sync_t * root) { 00467 struct mdl_sync_t * sync; 00468 for (sync = root; sync != NULL; sync = sync->next) { 00469 // determine master sweep link 00470 char * link = sync->name; 00471 int i = strlen (link) - 1; 00472 while (i > 0 && link[i] != '.') i--; 00473 if (link[i] == '.') { 00474 link[i] = '\0'; 00475 char * txt = (char *) malloc (i + 2 + strlen (sync->master)); 00476 sprintf (txt, "%s.%s", link, sync->master); 00477 link[i] = '.'; 00478 free (sync->master); 00479 sync->master = txt; 00480 } 00481 // create synchronize independent data vector 00482 vector * v = mdl_result->findDependency (sync->master); 00483 if (v != NULL) { 00484 vector * s = new vector ((*v) * sync->ratio + sync->offset); 00485 mdl_create_syndataset (s, sync->name); 00486 } 00487 } 00488 } 00489 00490 // Destroys an element structure. 00491 static void mdl_free_element (struct mdl_element_t * e) { 00492 free (e->name); 00493 free (e->value); 00494 free (e->attr); 00495 free (e); 00496 } 00497 00498 // Destroys a datasize structure. 00499 static void mdl_free_datasize (struct mdl_datasize_t * d) { 00500 free (d->type); 00501 free (d); 00502 } 00503 00504 // Destroys a hypertable structure. 00505 static void mdl_free_hyptable (struct mdl_hyptable_t * h) { 00506 free (h->name); 00507 struct mdl_element_t * e, * next; 00508 for (e = h->data; e != NULL; e = next) { 00509 next = e->next; 00510 mdl_free_element (e); 00511 } 00512 free (h); 00513 } 00514 00515 // Destroys a table structure. 00516 static void mdl_free_table (struct mdl_table_t * t) { 00517 free (t->name); 00518 struct mdl_element_t * e, * next; 00519 for (e = t->data; e != NULL; e = next) { 00520 next = e->next; 00521 mdl_free_element (e); 00522 } 00523 free (t); 00524 } 00525 00526 // Destroys a dataset structure. 00527 static void mdl_free_dataset (struct mdl_dataset_t * d) { 00528 free (d->type1); 00529 struct mdl_point_t * p, * next; 00530 for (p = d->data1; p != NULL; p = next) { 00531 next = p->next; 00532 free (p); 00533 } 00534 free (d->type2); 00535 for (p = d->data2; p != NULL; p = next) { 00536 next = p->next; 00537 free (p); 00538 } 00539 if (d->dsize) mdl_free_datasize (d->dsize); 00540 } 00541 00542 // Destroys a data content structure. 00543 static void mdl_free_dcontent (struct mdl_dcontent_t * c) { 00544 switch (c->type) { 00545 case t_DATASET: mdl_free_dataset (c->data); break; 00546 case t_HYPTABLE: mdl_free_hyptable (c->hyptable); break; 00547 } 00548 } 00549 00550 // Destroys a data structure. 00551 static void mdl_free_data (struct mdl_data_t * d) { 00552 struct mdl_dcontent_t * c, * next; 00553 for (c = d->content; c != NULL; c = next) { 00554 next = c->next; 00555 mdl_free_dcontent (c); 00556 } 00557 } 00558 00559 // Forward declaration. 00560 static void mdl_free_link (struct mdl_link_t *); 00561 00562 // Destroys a link content structure. 00563 static void mdl_free_lcontent (struct mdl_lcontent_t * c) { 00564 switch (c->type) { 00565 case t_LINK: mdl_free_link (c->link); break; 00566 case t_DATA: mdl_free_data (c->data); break; 00567 case t_TABLE: mdl_free_table (c->table); break; 00568 } 00569 free (c); 00570 } 00571 00572 // Destroys a link structure. 00573 static void mdl_free_link (struct mdl_link_t * l) { 00574 free (l->name); 00575 free (l->type); 00576 struct mdl_lcontent_t * c, * next; 00577 for (c = l->content; c != NULL; c = next) { 00578 next = c->next; 00579 mdl_free_lcontent (c); 00580 } 00581 } 00582 00583 // Destroys a sync structure. 00584 static void mdl_free_sync (struct mdl_sync_t * s) { 00585 struct mdl_sync_t * next; 00586 for (; s != NULL; s = next) { 00587 next = s->next; 00588 free (s->name); 00589 free (s->master); 00590 free (s); 00591 } 00592 } 00593 00594 // Computes the dependent vector length for the given dependency list. 00595 static int mdl_get_depsize (strlist * deps) { 00596 char * n; 00597 vector * v; 00598 int res = 1; 00599 for (int i = 0; i < deps->length (); i++) { 00600 if ((n = deps->get (i)) != NULL) 00601 if ((v = mdl_result->findDependency (n)) != NULL) 00602 res *= v->getSize (); 00603 } 00604 return res; 00605 } 00606 00607 // Checks the variable vector dependencies. Makes them independent if 00608 // necessary. 00609 static void mdl_check_xform_deplen (void) { 00610 vector * v, * next; 00611 for (v = mdl_result->getVariables (); v; v = next) { 00612 next = (vector *) v->getNext (); 00613 strlist * deps = v->getDependencies (); 00614 if (deps->length () <= 0) { 00615 vector * d = new vector (*v); 00616 mdl_result->delVariable (v); 00617 mdl_result->addDependency (d); 00618 } 00619 } 00620 } 00621 00622 // Checks the variable vector dependencies and reduces them if necessary. 00623 static void mdl_check_xform_dep (void) { 00624 vector * v, * d; 00625 strlist * deps; 00626 for (v = mdl_result->getVariables (); v; v = (vector *) v->getNext ()) { 00627 deps = v->getDependencies (); 00628 int s = mdl_get_depsize (deps); 00629 // dependencies differ from actual vector length 00630 if (v->getSize () != s) { 00631 int found = 0; 00632 for (int i = 0; i < deps->length (); i++) { 00633 // find out a single dependency with the appropriate length 00634 char * n = deps->get (i); 00635 if (n != NULL) { 00636 d = mdl_result->findDependency (n); 00637 if (d != NULL && v->getSize () == d->getSize ()) { 00638 strlist * dep = new strlist (); 00639 dep->add (n); 00640 v->setDependencies (dep); 00641 found++; 00642 break; 00643 } 00644 } 00645 } 00646 // if not found, then no dependency vector 00647 if (!found) v->setDependencies (new strlist ()); 00648 } 00649 } 00650 } 00651 00652 // Checks the XFORM's in the model file 00653 static void mdl_check_xforms (void) { 00654 mdl_check_xform_dep (); 00655 mdl_check_xform_deplen (); 00656 } 00657 00658 /* This function is the overall MDL data checker. It returns zero on 00659 success, non-zero otherwise. */ 00660 int mdl_check (void) { 00661 int errors = 0; 00662 mdl_result = new dataset (); 00663 struct mdl_link_t * root; 00664 for (root = mdl_root; root; root = root->next) { 00665 char * name = root->name; 00666 mdl_find_link (root, name); 00667 } 00668 mdl_find_syncdatasets (mdl_sync_root); 00669 mdl_check_xforms (); 00670 return errors ? -1 : 0; 00671 } 00672 00673 // Destroys data used by the MDL checker. 00674 void mdl_destroy (void) { 00675 if (mdl_result != NULL) { 00676 // delete associated dataset 00677 delete mdl_result; 00678 mdl_result = NULL; 00679 } 00680 if (mdl_root != NULL) { 00681 // release internal data structures 00682 struct mdl_link_t * root, * next; 00683 for (root = mdl_root; root; root = next) { 00684 next = root->next; 00685 mdl_free_link (root); 00686 } 00687 mdl_root = NULL; 00688 } 00689 if (mdl_sync_root != NULL) { 00690 // release internal sync structures 00691 mdl_free_sync (mdl_sync_root); 00692 mdl_sync_root = NULL; 00693 } 00694 } 00695 00696 // Initializes the MDL checker. 00697 void mdl_init (void) { 00698 mdl_root = NULL; 00699 mdl_result = NULL; 00700 mdl_sync_root = NULL; 00701 }