LCOV - code coverage report
Current view: top level - src - check_mdl.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 0 383 0.0 %
Date: 2015-01-05 16:01:02 Functions: 0 37 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 364 0.0 %

           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 : }

Generated by: LCOV version 1.11