Branch data Line data Source code
1 : : /*
2 : : * check_mdl.cpp - iterate an IC-CAP MDL file
3 : : *
4 : : * Copyright (C) 2006, 2007 Stefan Jahn <stefan@lkcc.org>
5 : : *
6 : : * This is free software; you can redistribute it and/or modify
7 : : * it under the terms of the GNU General Public License as published by
8 : : * the Free Software Foundation; either version 2, or (at your option)
9 : : * any later version.
10 : : *
11 : : * This software is distributed in the hope that it will be useful,
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : * GNU General Public License for more details.
15 : : *
16 : : * You should have received a copy of the GNU General Public License
17 : : * along with this package; see the file COPYING. If not, write to
18 : : * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19 : : * Boston, MA 02110-1301, USA.
20 : : *
21 : : * $Id$
22 : : *
23 : : */
24 : :
25 : : #if HAVE_CONFIG_H
26 : : # include <config.h>
27 : : #endif
28 : :
29 : : #include <stdio.h>
30 : : #include <stdlib.h>
31 : : #include <string.h>
32 : : #include <cmath>
33 : : #include <assert.h>
34 : : #include <float.h>
35 : : #include <ctype.h>
36 : :
37 : : #include "logging.h"
38 : : #include "strlist.h"
39 : : #include "object.h"
40 : : #include "complex.h"
41 : : #include "vector.h"
42 : : #include "dataset.h"
43 : : #include "sweep.h"
44 : : #include "valuelist.h"
45 : : #include "constants.h"
46 : : #include "check_mdl.h"
47 : : #include "tokens_mdl.h"
48 : :
49 : : using namespace qucs;
50 : :
51 : : // Global variables.
52 : : dataset * mdl_result = NULL;
53 : : struct mdl_link_t * mdl_root = NULL;
54 : : struct mdl_sync_t * mdl_sync_root = NULL;
55 : :
56 : : // Creates an independent data vector.
57 : 0 : static void mdl_create_depdataset (sweep * data, char * name) {
58 [ # # ]: 0 : vector v (name);
59 [ # # ][ # # ]: 0 : for (int i = 0; i < data->getSize (); i++) v.add (data->get (i));
[ # # ]
60 [ # # ][ # # ]: 0 : mdl_result->appendDependency (new vector (v));
[ # # ][ # # ]
61 : 0 : }
62 : :
63 : : // Creates an independent data vector with a single element.
64 : 0 : static void mdl_create_condataset (double val, char * name) {
65 [ # # ]: 0 : vector v (name);
66 [ # # ]: 0 : v.add (val);
67 [ # # ][ # # ]: 0 : mdl_result->appendDependency (new vector (v));
[ # # ][ # # ]
68 : 0 : }
69 : :
70 : : // The functions creates dependent data vector(s).
71 : 0 : static void mdl_create_vardataset (struct mdl_point_t * point,
72 : : struct mdl_datasize_t * dsize,
73 : : const char * name, const char * type,
74 : : strlist * deps) {
75 [ # # ][ # # : 0 : vector * v = new vector[dsize->x * dsize->y] ();
# # # # ]
76 : : // adjust type
77 [ # # ]: 0 : if (!strcmp (type, "MEAS"))
78 : 0 : type = ".M";
79 [ # # ]: 0 : else if (!strcmp (type, "SIMU"))
80 : 0 : type = ".S";
81 [ # # ]: 0 : else if (!strcmp (type, "COMMON"))
82 : 0 : type = "";
83 : : // create vectors
84 [ # # ]: 0 : for (struct mdl_point_t * p = point; p != NULL; p = p->next) {
85 : 0 : int n = (p->y - 1) * 2 + p->x - 1;
86 [ # # ]: 0 : v[n].add (nr_complex_t (p->r, p->i));
87 : : }
88 : : // go through indices
89 [ # # ]: 0 : for (int x = 1; x < dsize->x + 1; x++) {
90 [ # # ]: 0 : for (int y = 1; y < dsize->y + 1; y++) {
91 : : // create vector description
92 : 0 : int n = (y - 1) * 2 + x - 1;
93 : 0 : char * txt = (char *) malloc (strlen (name) + strlen (type) + 4 + 2 * 3);
94 [ # # ][ # # ]: 0 : if (dsize->x > 1 || dsize->y > 1)
95 : 0 : sprintf (txt, "%s%s[%d,%d]", name, type, x, y);
96 : : else
97 : 0 : sprintf (txt, "%s%s", name, type);
98 : 0 : v[n].setName (txt);
99 : 0 : free (txt);
100 : : // put vector into dataset
101 [ # # ]: 0 : if (v[n].getSize () > 1) {
102 [ # # ]: 0 : v[n].setDependencies (new strlist (*deps));
103 [ # # ]: 0 : mdl_result->appendVariable (new vector (v[n]));
104 : : } else {
105 [ # # ]: 0 : v[n].setDependencies (new strlist ());
106 [ # # ]: 0 : mdl_result->appendDependency (new vector (v[n]));
107 : : }
108 : : }
109 : : }
110 [ # # ][ # # ]: 0 : delete[] v;
111 : 0 : }
112 : :
113 : : // Look through hypertable elements for a name and return value.
114 : 0 : static char * mdl_find_helement (struct mdl_element_t * root,
115 : : const char * name) {
116 [ # # ]: 0 : for (; root != NULL; root = root->next) {
117 [ # # ]: 0 : if (!strcmp (root->name, name)) return root->value;
118 : : }
119 : 0 : return NULL;
120 : : }
121 : :
122 : : // Look through table elements for a name and return value.
123 : 0 : static char * mdl_find_telement (struct mdl_element_t * root,
124 : : const char * name) {
125 [ # # ]: 0 : for (; root != NULL; root = root->next) {
126 [ # # ][ # # ]: 0 : if (!strcmp (root->name, "Name") && !strcmp (root->value, name)) {
127 [ # # ][ # # ]: 0 : if (root->next && !strcmp (root->next->name, "Value")) {
128 : 0 : return root->next->value;
129 : : }
130 : : }
131 : : }
132 : 0 : return NULL;
133 : : }
134 : :
135 : : // Convert number suffix into a multiplication factor.
136 : 0 : static double mdl_convert_factor (char * end) {
137 : 0 : double f = 1.0;
138 [ # # ]: 0 : if (end) {
139 [ # # # # : 0 : switch (*end) {
# # # # #
# # ]
140 : 0 : case 'K': f = 1e+03; break;
141 : 0 : case 'M': f = 1e+06; break;
142 : 0 : case 'G': f = 1e+09; break;
143 : 0 : case 'T': f = 1e+12; break;
144 : 0 : case 'm': f = 1e-03; break;
145 : 0 : case 'u': f = 1e-06; break;
146 : 0 : case 'n': f = 1e-09; break;
147 : 0 : case 'p': f = 1e-12; break;
148 : 0 : case 'f': f = 1e-15; break;
149 : 0 : case 'a': f = 1e-18; break;
150 : : }
151 : : }
152 : 0 : return f;
153 : : }
154 : :
155 : : // Forward declaration.
156 : : static double mdl_telement_dvalue (struct mdl_link_t *, struct mdl_element_t *,
157 : : const char *);
158 : :
159 : : // The function resolves the given variable trying upscope resolving.
160 : 0 : static int mdl_resolve_variable (struct mdl_link_t * link, char * name,
161 : : double &val) {
162 : 0 : int done = 0;
163 : 0 : val = 0.0;
164 : : struct mdl_lcontent_t * root;
165 : : // try finding variable in current link
166 [ # # ][ # # ]: 0 : for (root = link->content; !done && root != NULL; root = root->next) {
[ # # ]
167 [ # # ]: 0 : if (root->type == t_TABLE) {
168 : 0 : struct mdl_element_t * eroot = root->table->data;
169 [ # # ]: 0 : if (mdl_find_telement (eroot, name)) {
170 : 0 : val = mdl_telement_dvalue (link, eroot, name);
171 : 0 : done++;
172 : : }
173 : : }
174 : : }
175 : : // resolve variable in upper scope recursively
176 [ # # ][ # # ]: 0 : if (!done && link->parent) {
177 : 0 : done = mdl_resolve_variable (link->parent, name, val);
178 : : }
179 : 0 : return done;
180 : : }
181 : :
182 : : // Converts a string into a valid value. Uses variable substitutions.
183 : 0 : static double mdl_variable_value (struct mdl_link_t * link, char * txt) {
184 : 0 : double val = 0.0;
185 : 0 : char * end = NULL;
186 [ # # ]: 0 : if (txt != NULL) {
187 : : // remove whitespaces
188 : 0 : char * t, * p = txt;
189 [ # # ]: 0 : while (*p) {
190 [ # # ][ # # ]: 0 : if (isspace (*p)) {
191 : 0 : t = p;
192 [ # # ]: 0 : while (*t) { *t = *(t + 1); t++; }
193 : 0 : p--;
194 : : }
195 : 0 : p++;
196 : : }
197 : : // extract value if possible
198 : 0 : val = strtod (txt, &end);
199 : : // not a value, a variable
200 [ # # ]: 0 : if (end == txt) {
201 : 0 : double f = 1.0;
202 [ # # ]: 0 : if (*txt == '-') { f = -1.0; txt++; }
203 [ # # ]: 0 : else if (*txt == '+') { f = +1.0; txt++; }
204 [ # # ][ # # ]: 0 : if (!mdl_resolve_variable (link, txt, val)) {
205 : : // special variables
206 [ # # ]: 0 : if (!strcmp (txt, "PI")) {
207 : 0 : val = M_PI;
208 : : }
209 : : // no resolvable (probably equation)
210 : : else {
211 : : logprint (LOG_ERROR,
212 : : "checker error, unable to resolve `%s' variable in '%s'\n",
213 [ # # ]: 0 : txt, link->name);
214 : 0 : val = 0.0;
215 : : }
216 : : }
217 : 0 : val = f * val;
218 : : }
219 : : // normal value with probably a suffix
220 : : else {
221 : 0 : val *= mdl_convert_factor (end);
222 : : }
223 : : }
224 : 0 : return val;
225 : : }
226 : :
227 : : // Returns a double variable value stored in a hypertable.
228 : 0 : static double mdl_helement_dvalue (struct mdl_link_t * link,
229 : : struct mdl_element_t * eroot,
230 : : const char * name) {
231 : 0 : char * txt = mdl_find_helement (eroot, name);
232 : 0 : return mdl_variable_value (link, txt);
233 : : }
234 : :
235 : : // Returns a double variable value stored in a table.
236 : 0 : static double mdl_telement_dvalue (struct mdl_link_t * link,
237 : : struct mdl_element_t * eroot,
238 : : const char * name) {
239 : 0 : char * txt = mdl_find_telement (eroot, name);
240 : 0 : return mdl_variable_value (link, txt);
241 : : }
242 : :
243 : : // Returns a integer variable value stored in a hypertable.
244 : 0 : static int mdl_helement_ivalue (struct mdl_link_t * link,
245 : : struct mdl_element_t * eroot,
246 : : const char * name) {
247 : 0 : return (int) mdl_helement_dvalue (link, eroot, name);
248 : : }
249 : :
250 : : // Looks for dependent data vectors and creates them.
251 : 0 : static void mdl_find_vardataset (struct mdl_dcontent_t * droot, char * name,
252 : : strlist * deps) {
253 : : struct mdl_dcontent_t * root;
254 : : // go through dataset content
255 [ # # ]: 0 : for (root = droot; root != NULL; root = root->next) {
256 [ # # ]: 0 : if (root->type == t_DATASET) {
257 : : // create possibly both - MEAS and SIMU - data vectors
258 : 0 : struct mdl_dataset_t * dset = root->data;
259 [ # # ]: 0 : if (dset->data1)
260 : : mdl_create_vardataset (dset->data1, dset->dsize, name, dset->type1,
261 : 0 : deps);
262 [ # # ]: 0 : if (dset->data2)
263 : : mdl_create_vardataset (dset->data2, dset->dsize, name, dset->type2,
264 : 0 : deps);
265 : : }
266 : : }
267 : 0 : }
268 : :
269 : : // Looks for independent data vectors and creates them.
270 : 0 : valuelist<int> * mdl_find_depdataset (struct mdl_link_t * link,
271 : : struct mdl_dcontent_t * droot,
272 : : char * name) {
273 : 0 : char * stype = NULL;
274 : : double val, start, stop, step;
275 : 0 : int nof = 0, order = 0;
276 : 0 : valuelist<int> * deps = new valuelist<int> ();
277 : : struct mdl_dcontent_t * root;
278 : :
279 : : // go through dataset content
280 [ # # ]: 0 : for (root = droot; root != NULL; root = root->next) {
281 [ # # ]: 0 : if (root->type == t_HYPTABLE) {
282 : 0 : struct mdl_hyptable_t * hyptab = root->hyptable;
283 : : // found a sweep definition?
284 [ # # ]: 0 : if (!strcmp (hyptab->name, "Edit Sweep Def")) {
285 [ # # ]: 0 : if (!strcmp (stype, "LIN")) {
286 : : // linear sweep
287 : 0 : order = mdl_helement_ivalue (link, hyptab->data, "Sweep Order");
288 : 0 : start = mdl_helement_dvalue (link, hyptab->data, "Start");
289 : 0 : stop = mdl_helement_dvalue (link, hyptab->data, "Stop");
290 : 0 : nof = mdl_helement_ivalue (link, hyptab->data, "# of Points");
291 : 0 : step = mdl_helement_dvalue (link, hyptab->data, "Step Size");
292 [ # # ]: 0 : if (nof <= 0) nof = (int) fabs ((stop - start) / step) + 1;
293 : 0 : deps->append (name, new int (order));
294 [ # # ]: 0 : linsweep * sw = new linsweep ();
295 : 0 : sw->create (start, stop, nof);
296 : 0 : mdl_create_depdataset (sw, name);
297 [ # # ]: 0 : delete sw;
298 : : }
299 [ # # ]: 0 : else if (!strcmp (stype, "CON")) {
300 : : // constant sweep
301 : 0 : val = mdl_helement_dvalue (link, hyptab->data, "Value");
302 : 0 : mdl_create_condataset (val, name);
303 : : }
304 [ # # ]: 0 : else if (!strcmp (stype, "LOG")) {
305 : : // logarithmic sweep
306 : 0 : order = mdl_helement_ivalue (link, hyptab->data, "Sweep Order");
307 : 0 : start = mdl_helement_dvalue (link, hyptab->data, "Start");
308 : 0 : stop = mdl_helement_dvalue (link, hyptab->data, "Stop");
309 : 0 : nof = mdl_helement_ivalue (link, hyptab->data, "Total Pts");
310 [ # # ]: 0 : if (nof <= 0)
311 : 0 : nof = mdl_helement_ivalue (link, hyptab->data, "# of Points");
312 [ # # ]: 0 : if (start * stop == 0.0) {
313 [ # # ]: 0 : if (start == 0.0) start = 1.0;
314 [ # # ]: 0 : if (stop == 0.0) stop = 1.0;
315 : : }
316 : 0 : deps->append (name, new int (order));
317 [ # # ]: 0 : logsweep * sw = new logsweep ();
318 : 0 : sw->create (start, stop, nof);
319 : 0 : mdl_create_depdataset (sw, name);
320 [ # # ]: 0 : delete sw;
321 : : }
322 [ # # ]: 0 : else if (!strcmp (stype, "LIST")) {
323 : : // list sweep
324 : 0 : order = mdl_helement_ivalue (link, hyptab->data, "Sweep Order");
325 : 0 : nof = mdl_helement_ivalue (link, hyptab->data, "# of Values");
326 : 0 : deps->append (name, new int (order));
327 : : }
328 [ # # ]: 0 : else if (!strcmp (stype, "SYNC")) {
329 : : // sync sweep
330 : : struct mdl_sync_t * sync = (struct mdl_sync_t *)
331 : 0 : calloc (sizeof (struct mdl_sync_t), 1);
332 : 0 : sync->ratio = mdl_helement_dvalue (link, hyptab->data, "Ratio");
333 : 0 : sync->offset = mdl_helement_dvalue (link, hyptab->data, "Offset");
334 : 0 : sync->master = mdl_find_helement (hyptab->data, "Master Sweep");
335 : 0 : sync->master = strdup (sync->master);
336 : 0 : sync->name = strdup (name);
337 : 0 : sync->next = mdl_sync_root;
338 : 0 : mdl_sync_root = sync;
339 : : }
340 : : }
341 : : // found a sweep information?
342 [ # # ]: 0 : else if (!strcmp (hyptab->name, "Edit Sweep Info")) {
343 : 0 : stype = mdl_find_helement (hyptab->data, "Sweep Type");
344 : : }
345 : : // found a list table?
346 [ # # ]: 0 : else if (!strcmp (hyptab->name, "List Table")) {
347 [ # # ][ # # ]: 0 : lstsweep * sw = new lstsweep ();
348 [ # # ]: 0 : sw->create (nof);
349 : : char txt[16];
350 [ # # ]: 0 : for (int i = 0; i < nof; i++) {
351 : 0 : sprintf (txt, "Value %d", i + 1);
352 [ # # ]: 0 : val = mdl_helement_dvalue (link, hyptab->data, txt);
353 [ # # ]: 0 : sw->set (i, val);
354 : : }
355 [ # # ]: 0 : mdl_create_depdataset (sw, name);
356 [ # # ][ # # ]: 0 : delete sw;
357 : : }
358 : : }
359 : : }
360 : 0 : return deps;
361 : : }
362 : :
363 : : // Composes a link name.
364 : 0 : static char * mdl_create_linkname (char * base, char * name) {
365 : 0 : char * txt = (char *) malloc (strlen (base) + 2 + strlen (name));
366 : 0 : sprintf (txt, "%s.%s", base, name);
367 : 0 : return txt;
368 : : }
369 : :
370 : : // Collects dependency links.
371 : 0 : static void mdl_find_deplink (struct mdl_link_t * link, char * name,
372 : : valuelist<int> * deps) {
373 : : struct mdl_lcontent_t * root;
374 : : valuelist<int> * d;
375 : : // go through link content
376 [ # # ]: 0 : for (root = link->content; root != NULL; root = root->next) {
377 : : // independent data vector
378 [ # # ]: 0 : if (root->type == t_DATA) {
379 : 0 : d = mdl_find_depdataset (link, root->data->content, name);
380 [ # # ]: 0 : if (d != NULL) {
381 : 0 : deps->append (d);
382 [ # # ]: 0 : delete d;
383 : : }
384 : : }
385 : : // link to independent data vector
386 [ # # ][ # # ]: 0 : else if (root->type == t_LINK && !strcmp (root->link->type, "SWEEP")) {
387 : 0 : char * txt = mdl_create_linkname (name, root->link->name);
388 : 0 : root->link->parent = link;
389 : 0 : mdl_find_deplink (root->link, txt, deps);
390 : 0 : free (txt);
391 : : }
392 : : }
393 : 0 : }
394 : :
395 : : // Collects variable links.
396 : 0 : static void mdl_find_varlink (struct mdl_link_t * link, char * name,
397 : : strlist * deps) {
398 : : struct mdl_lcontent_t * root;
399 : : // go through link content
400 [ # # ]: 0 : for (root = link->content; root != NULL; root = root->next) {
401 : : // dependent data vector
402 [ # # ]: 0 : if (root->type == t_DATA) {
403 : 0 : mdl_find_vardataset (root->data->content, name, deps);
404 : : }
405 : : // link to dependent data vector
406 [ # # ][ # # ]: 0 : else if (root->type == t_LINK && (!strcmp (root->link->type, "OUT") ||
[ # # ]
407 : 0 : !strcmp (root->link->type, "XFORM"))) {
408 : 0 : char * txt = mdl_create_linkname (name, root->link->name);
409 : 0 : root->link->parent = link;
410 : 0 : mdl_find_varlink (root->link, txt, deps);
411 : 0 : free (txt);
412 : : }
413 : : }
414 : 0 : }
415 : :
416 : : // Sorts a dependency list according to their sweep order.
417 : 0 : static strlist * mdl_sort_deps (valuelist<int> * d) {
418 [ # # ]: 0 : strlist * deps = new strlist ();
419 [ # # ]: 0 : for (int i = 0; i < d->length (); i++) {
420 [ # # ][ # # ]: 0 : for (valuelistiterator<int> it (*d); *it; ++it) {
[ # # ]
421 [ # # ]: 0 : if (*(it.currentVal ()) == i + 1) {
422 [ # # ][ # # ]: 0 : deps->append (it.currentKey ());
423 : : }
424 : 0 : }
425 : : }
426 : 0 : return deps;
427 : : }
428 : :
429 : : // Iterates the MDL file recursively.
430 : 0 : static void mdl_find_link (struct mdl_link_t * link, char * name) {
431 : : struct mdl_lcontent_t * root;
432 : :
433 : : // collect independent data
434 : 0 : valuelist<int> * vdeps = new valuelist<int> ();
435 : 0 : mdl_find_deplink (link, name, vdeps);
436 : 0 : strlist * deps = mdl_sort_deps (vdeps);
437 [ # # ]: 0 : delete vdeps;
438 : :
439 : : // collect dependent data
440 : 0 : mdl_find_varlink (link, name, deps);
441 [ # # ]: 0 : delete deps;
442 : :
443 : : // go through link content
444 [ # # ]: 0 : for (root = link->content; root != NULL; root = root->next) {
445 [ # # ][ # # ]: 0 : if (root->type == t_LINK &&
[ # # ][ # # ]
446 : 0 : strcmp (root->link->type, "OUT") &&
447 : 0 : strcmp (root->link->type, "SWEEP") &&
448 : 0 : strcmp (root->link->type, "XFORM")) {
449 : 0 : char * txt = mdl_create_linkname (name, root->link->name);
450 : 0 : root->link->parent = link;
451 : 0 : mdl_find_link (root->link, txt);
452 : 0 : free (txt);
453 : : }
454 : : }
455 : 0 : }
456 : :
457 : : // Creates an synchronized independent data vector.
458 : 0 : static void mdl_create_syndataset (vector * v, char * name) {
459 : 0 : v->setName (name);
460 : 0 : mdl_result->appendDependency (v);
461 : 0 : }
462 : :
463 : : // Goes through list of sync sweeps and creates them if possible.
464 : 0 : void mdl_find_syncdatasets (struct mdl_sync_t * root) {
465 : : struct mdl_sync_t * sync;
466 [ # # ]: 0 : for (sync = root; sync != NULL; sync = sync->next) {
467 : : // determine master sweep link
468 : 0 : char * link = sync->name;
469 : 0 : int i = strlen (link) - 1;
470 [ # # ][ # # ]: 0 : while (i > 0 && link[i] != '.') i--;
[ # # ]
471 [ # # ]: 0 : if (link[i] == '.') {
472 : 0 : link[i] = '\0';
473 : 0 : char * txt = (char *) malloc (i + 2 + strlen (sync->master));
474 : 0 : sprintf (txt, "%s.%s", link, sync->master);
475 : 0 : link[i] = '.';
476 : 0 : free (sync->master);
477 : 0 : sync->master = txt;
478 : : }
479 : : // create synchronize independent data vector
480 : 0 : vector * v = mdl_result->findDependency (sync->master);
481 [ # # ]: 0 : if (v != NULL) {
482 [ # # ][ # # ]: 0 : vector * s = new vector ((*v) * sync->ratio + sync->offset);
[ # # ][ # # ]
483 : 0 : mdl_create_syndataset (s, sync->name);
484 : : }
485 : : }
486 : 0 : }
487 : :
488 : : // Destroys an element structure.
489 : 0 : static void mdl_free_element (struct mdl_element_t * e) {
490 [ # # ]: 0 : if (e->name) free (e->name);
491 [ # # ]: 0 : if (e->value) free (e->value);
492 [ # # ]: 0 : if (e->attr) free (e->attr);
493 : 0 : free (e);
494 : 0 : }
495 : :
496 : : // Destroys a datasize structure.
497 : 0 : static void mdl_free_datasize (struct mdl_datasize_t * d) {
498 [ # # ]: 0 : if (d->type) free (d->type);
499 : 0 : free (d);
500 : 0 : }
501 : :
502 : : // Destroys a hypertable structure.
503 : 0 : static void mdl_free_hyptable (struct mdl_hyptable_t * h) {
504 [ # # ]: 0 : if (h->name) free (h->name);
505 : : struct mdl_element_t * e, * next;
506 [ # # ]: 0 : for (e = h->data; e != NULL; e = next) {
507 : 0 : next = e->next;
508 : 0 : mdl_free_element (e);
509 : : }
510 : 0 : free (h);
511 : 0 : }
512 : :
513 : : // Destroys a table structure.
514 : 0 : static void mdl_free_table (struct mdl_table_t * t) {
515 [ # # ]: 0 : if (t->name) free (t->name);
516 : : struct mdl_element_t * e, * next;
517 [ # # ]: 0 : for (e = t->data; e != NULL; e = next) {
518 : 0 : next = e->next;
519 : 0 : mdl_free_element (e);
520 : : }
521 : 0 : free (t);
522 : 0 : }
523 : :
524 : : // Destroys a dataset structure.
525 : 0 : static void mdl_free_dataset (struct mdl_dataset_t * d) {
526 [ # # ]: 0 : if (d->type1) free (d->type1);
527 : : struct mdl_point_t * p, * next;
528 [ # # ]: 0 : for (p = d->data1; p != NULL; p = next) {
529 : 0 : next = p->next;
530 : 0 : free (p);
531 : : }
532 [ # # ]: 0 : if (d->type2) free (d->type2);
533 [ # # ]: 0 : for (p = d->data2; p != NULL; p = next) {
534 : 0 : next = p->next;
535 : 0 : free (p);
536 : : }
537 [ # # ]: 0 : if (d->dsize) mdl_free_datasize (d->dsize);
538 : 0 : }
539 : :
540 : : // Destroys a data content structure.
541 : 0 : static void mdl_free_dcontent (struct mdl_dcontent_t * c) {
542 [ # # # ]: 0 : switch (c->type) {
543 : 0 : case t_DATASET: mdl_free_dataset (c->data); break;
544 : 0 : case t_HYPTABLE: mdl_free_hyptable (c->hyptable); break;
545 : : }
546 : 0 : }
547 : :
548 : : // Destroys a data structure.
549 : 0 : static void mdl_free_data (struct mdl_data_t * d) {
550 : : struct mdl_dcontent_t * c, * next;
551 [ # # ]: 0 : for (c = d->content; c != NULL; c = next) {
552 : 0 : next = c->next;
553 : 0 : mdl_free_dcontent (c);
554 : : }
555 : 0 : }
556 : :
557 : : // Forward declaration.
558 : : static void mdl_free_link (struct mdl_link_t *);
559 : :
560 : : // Destroys a link content structure.
561 : 0 : static void mdl_free_lcontent (struct mdl_lcontent_t * c) {
562 [ # # # # ]: 0 : switch (c->type) {
563 : 0 : case t_LINK: mdl_free_link (c->link); break;
564 : 0 : case t_DATA: mdl_free_data (c->data); break;
565 : 0 : case t_TABLE: mdl_free_table (c->table); break;
566 : : }
567 : 0 : free (c);
568 : 0 : }
569 : :
570 : : // Destroys a link structure.
571 : 0 : static void mdl_free_link (struct mdl_link_t * l) {
572 [ # # ]: 0 : if (l->name) free (l->name);
573 [ # # ]: 0 : if (l->type) free (l->type);
574 : : struct mdl_lcontent_t * c, * next;
575 [ # # ]: 0 : for (c = l->content; c != NULL; c = next) {
576 : 0 : next = c->next;
577 : 0 : mdl_free_lcontent (c);
578 : : }
579 : 0 : }
580 : :
581 : : // Destroys a sync structure.
582 : 0 : static void mdl_free_sync (struct mdl_sync_t * s) {
583 : : struct mdl_sync_t * next;
584 [ # # ]: 0 : for (; s != NULL; s = next) {
585 : 0 : next = s->next;
586 [ # # ]: 0 : if (s->name) free (s->name);
587 [ # # ]: 0 : if (s->master) free (s->master);
588 : 0 : free (s);
589 : : }
590 : 0 : }
591 : :
592 : : // Computes the dependent vector length for the given dependency list.
593 : 0 : static int mdl_get_depsize (strlist * deps) {
594 : : char * n;
595 : : vector * v;
596 : 0 : int res = 1;
597 [ # # ]: 0 : for (int i = 0; i < deps->length (); i++) {
598 [ # # ]: 0 : if ((n = deps->get (i)) != NULL)
599 [ # # ]: 0 : if ((v = mdl_result->findDependency (n)) != NULL)
600 : 0 : res *= v->getSize ();
601 : : }
602 : 0 : return res;
603 : : }
604 : :
605 : : // Checks the variable vector dependencies. Makes them independent if
606 : : // necessary.
607 : 0 : static void mdl_check_xform_deplen (void) {
608 : : vector * v, * next;
609 [ # # ]: 0 : for (v = mdl_result->getVariables (); v; v = next) {
610 : 0 : next = (vector *) v->getNext ();
611 : 0 : strlist * deps = v->getDependencies ();
612 [ # # ]: 0 : if (deps->length () <= 0) {
613 [ # # ]: 0 : vector * d = new vector (*v);
614 : 0 : mdl_result->delVariable (v);
615 : 0 : mdl_result->addDependency (d);
616 : : }
617 : : }
618 : 0 : }
619 : :
620 : : // Checks the variable vector dependencies and reduces them if necessary.
621 : 0 : static void mdl_check_xform_dep (void) {
622 : : vector * v, * d;
623 : : strlist * deps;
624 [ # # ]: 0 : for (v = mdl_result->getVariables (); v; v = (vector *) v->getNext ()) {
625 : 0 : deps = v->getDependencies ();
626 : 0 : int s = mdl_get_depsize (deps);
627 : : // dependencies differ from actual vector length
628 [ # # ]: 0 : if (v->getSize () != s) {
629 : 0 : int found = 0;
630 [ # # ]: 0 : for (int i = 0; i < deps->length (); i++) {
631 : : // find out a single dependency with the appropriate length
632 : 0 : char * n = deps->get (i);
633 [ # # ]: 0 : if (n != NULL) {
634 : 0 : d = mdl_result->findDependency (n);
635 [ # # ][ # # ]: 0 : if (d != NULL && v->getSize () == d->getSize ()) {
[ # # ]
636 [ # # ]: 0 : strlist * dep = new strlist ();
637 : 0 : dep->add (n);
638 : 0 : v->setDependencies (dep);
639 : 0 : found++;
640 : 0 : break;
641 : : }
642 : : }
643 : : }
644 : : // if not found, then no dependency vector
645 [ # # ][ # # ]: 0 : if (!found) v->setDependencies (new strlist ());
646 : : }
647 : : }
648 : 0 : }
649 : :
650 : : // Checks the XFORM's in the model file
651 : 0 : static void mdl_check_xforms (void) {
652 : 0 : mdl_check_xform_dep ();
653 : 0 : mdl_check_xform_deplen ();
654 : 0 : }
655 : :
656 : : /* This function is the overall MDL data checker. It returns zero on
657 : : success, non-zero otherwise. */
658 : 0 : int mdl_check (void) {
659 : 0 : int errors = 0;
660 [ # # ]: 0 : mdl_result = new dataset ();
661 : : struct mdl_link_t * root;
662 [ # # ]: 0 : for (root = mdl_root; root; root = root->next) {
663 : 0 : char * name = root->name;
664 : 0 : mdl_find_link (root, name);
665 : : }
666 : 0 : mdl_find_syncdatasets (mdl_sync_root);
667 : 0 : mdl_check_xforms ();
668 [ # # ]: 0 : return errors ? -1 : 0;
669 : : }
670 : :
671 : : // Destroys data used by the MDL checker.
672 : 0 : void mdl_destroy (void) {
673 [ # # ]: 0 : if (mdl_result != NULL) {
674 : : // delete associated dataset
675 [ # # ]: 0 : delete mdl_result;
676 : 0 : mdl_result = NULL;
677 : : }
678 [ # # ]: 0 : if (mdl_root != NULL) {
679 : : // release internal data structures
680 : : struct mdl_link_t * root, * next;
681 [ # # ]: 0 : for (root = mdl_root; root; root = next) {
682 : 0 : next = root->next;
683 : 0 : mdl_free_link (root);
684 : : }
685 : 0 : mdl_root = NULL;
686 : : }
687 [ # # ]: 0 : if (mdl_sync_root != NULL) {
688 : : // release internal sync structures
689 : 0 : mdl_free_sync (mdl_sync_root);
690 : 0 : mdl_sync_root = NULL;
691 : : }
692 : 0 : }
693 : :
694 : : // Initializes the MDL checker.
695 : 0 : void mdl_init (void) {
696 : 0 : mdl_root = NULL;
697 : 0 : mdl_result = NULL;
698 : 0 : mdl_sync_root = NULL;
699 : 0 : }
|