LCOV - code coverage report
Current view: top level - src - check_netlist.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 773 965 80.1 %
Date: 2015-01-05 16:01:02 Functions: 69 69 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 553 793 69.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * check_netlist.cpp - checker for the Qucs netlist
       3                 :            :  *
       4                 :            :  * Copyright (C) 2003-2009 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                 :            : 
      36                 :            : #include "logging.h"
      37                 :            : #include "strlist.h"
      38                 :            : #include "netdefs.h"
      39                 :            : #include "equation.h"
      40                 :            : #include "check_netlist.h"
      41                 :            : #include "constants.h"
      42                 :            : #include "environment.h"
      43                 :            : #include "variable.h"
      44                 :            : #include "module.h"
      45                 :            : 
      46                 :            : using namespace qucs;
      47                 :            : using namespace qucs::eqn;
      48                 :            : 
      49                 :            : /* Global definitions for parser and checker. */
      50                 :            : struct definition_t * definition_root = NULL;
      51                 :            : struct definition_t * subcircuit_root = NULL;
      52                 :            : environment * env_root = NULL;
      53                 :            : 
      54                 :            : /* The function counts the nodes in a definition line. */
      55                 :       1157 : static int checker_count_nodes (struct definition_t * def)
      56                 :            : {
      57                 :       1157 :     int count = 0;
      58         [ +  + ]:       3472 :     for (struct node_t * node = def->nodes; node != NULL; node = node->next)
      59                 :       2315 :         count++;
      60                 :       1157 :     return count;
      61                 :            : }
      62                 :            : 
      63                 :            : /* The function returns an available definition line for the given
      64                 :            :    type.  If there is no such definition type the function returns
      65                 :            :    NULL. */
      66                 :       1098 : static struct define_t * checker_find_definition (char * type, int action)
      67                 :            : {
      68                 :       1098 :     struct define_t * def = module::getModule (type);
      69 [ +  - ][ +  - ]:       1098 :     if (def != NULL && action == def->action) return def;
      70                 :       1098 :     return NULL;
      71                 :            : }
      72                 :            : 
      73                 :            : /* The function returns the number of properties in a definition line
      74                 :            :    specified by the given key. */
      75                 :      10960 : static int checker_find_property (const char * key, struct pair_t * pp)
      76                 :            : {
      77                 :      10960 :     int count = 0;
      78         [ +  + ]:     840530 :     while (pp != NULL)
      79                 :            :     {
      80         [ +  + ]:     829570 :         if (!strcmp (pp->key, key))
      81                 :      10433 :             count++;
      82                 :     829570 :         pp = pp->next;
      83                 :            :     }
      84                 :      10960 :     return count;
      85                 :            : }
      86                 :            : 
      87                 :            : /* Checks if the given property key is either optional or required for
      88                 :            :    the given definition type and returns the type of the property. */
      89                 :      12004 : static int checker_is_property (struct define_t * available,
      90                 :            :                                 const char * key)
      91                 :            : {
      92                 :            :     int i;
      93         [ +  + ]:     393027 :     for (i = 0; PROP_IS_PROP (available->required[i]); i++)
      94                 :            :     {
      95         [ +  + ]:     386514 :         if (!strcmp (available->required[i].key, key))
      96                 :       5491 :             return available->required[i].type;
      97                 :            :     }
      98         [ +  + ]:      52526 :     for (i = 0; PROP_IS_PROP (available->optional[i]); i++)
      99                 :            :     {
     100         [ +  + ]:      50788 :         if (!strcmp (available->optional[i].key, key))
     101                 :       4775 :             return available->optional[i].type;
     102                 :            :     }
     103                 :      12004 :     return PROP_NONE;
     104                 :            : }
     105                 :            : 
     106                 :            : /* Counts the number of definitions given by the specified type and
     107                 :            :    instance name in the definition list. */
     108                 :       1122 : static int checker_count_definition (struct definition_t * root,
     109                 :            :                                      const char * type, char * instance)
     110                 :            : {
     111                 :       1122 :     int count = 0;
     112         [ +  + ]:      14292 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     113                 :            :     {
     114 [ +  + ][ +  + ]:      13170 :         if (!strcmp (def->type, type) && !strcmp (def->instance, instance))
     115                 :            :         {
     116         [ -  + ]:       1122 :             if (++count > 1)
     117                 :          0 :                 def->duplicate = 1;
     118                 :            :         }
     119                 :            :     }
     120                 :       1122 :     return count;
     121                 :            : }
     122                 :            : 
     123                 :            : /* Returns the value for a given definition type, key and variable
     124                 :            :    identifier if it is in the list of definitions.  Otherwise the
     125                 :            :    function returns NULL. */
     126                 :       5640 : static struct value_t * checker_find_variable (struct definition_t * root,
     127                 :            :         const char * type,
     128                 :            :         const char * key,
     129                 :            :         char * ident)
     130                 :            : {
     131                 :            :     struct pair_t * pair;
     132         [ +  + ]:      68500 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     133                 :            :     {
     134         [ +  + ]:      63078 :         if (!strcmp (def->type, type))
     135                 :            :         {
     136         [ +  + ]:       8711 :             for (pair = def->pairs; pair != NULL; pair = pair->next)
     137                 :            :             {
     138         [ +  + ]:       7405 :                 if (!strcmp (pair->key, key))
     139 [ +  - ][ +  - ]:       1524 :                     if (pair->value->ident != NULL && ident != NULL &&
                 [ +  + ]
     140                 :       1524 :                             strcmp (pair->value->ident, ident) == 0)
     141                 :        218 :                         return pair->value;
     142                 :            :             }
     143                 :            :         }
     144                 :            :     }
     145                 :       5640 :     return NULL;
     146                 :            : }
     147                 :            : 
     148                 :            : /* The function returns the appropriate value for a given key within
     149                 :            :    the given netlist definition if the value is a reference (a
     150                 :            :    string).  If there is no such key value pair the function returns
     151                 :            :    NULL. */
     152                 :        471 : static struct value_t * checker_find_reference (struct definition_t * def,
     153                 :            :         const char * key)
     154                 :            : {
     155                 :            :     struct pair_t * pair;
     156         [ +  - ]:        648 :     for (pair = def->pairs; pair != NULL; pair = pair->next)
     157                 :            :     {
     158         [ +  + ]:        648 :         if (!strcmp (pair->key, key))
     159         [ +  - ]:        471 :             if (pair->value->ident != NULL)
     160                 :        471 :                 return pair->value;
     161                 :            :     }
     162                 :        471 :     return NULL;
     163                 :            : }
     164                 :            : 
     165                 :            : /* The function looks for the given property key within the properties
     166                 :            :    of the given definition line and returns its value if the property
     167                 :            :    is not an identifier.  Otherwise the function returns NULL. */
     168                 :         98 : static struct value_t * checker_find_prop_value (struct definition_t * def,
     169                 :            :         const char * key)
     170                 :            : {
     171                 :            :     struct pair_t * pair;
     172         [ +  - ]:        110 :     for (pair = def->pairs; pair != NULL; pair = pair->next)
     173                 :            :     {
     174         [ +  + ]:        110 :         if (!strcmp (pair->key, key))
     175         [ +  - ]:         98 :             if (pair->value->ident == NULL)
     176                 :         98 :                 return pair->value;
     177                 :            :     }
     178                 :         98 :     return NULL;
     179                 :            : }
     180                 :            : 
     181                 :            : /* The function returns the number of properties in a definition line
     182                 :            :    specified by the given key. */
     183                 :        376 : static int checker_find_property (struct definition_t * def,
     184                 :            :                                   const char * key)
     185                 :            : {
     186                 :        376 :     return checker_find_property (key, def->pairs);
     187                 :            : }
     188                 :            : 
     189                 :            : /* This function looks for the specified property 'key' in the given
     190                 :            :    definition and return its value (a string reference) if it is a
     191                 :            :    reference.  Otherwise the function returns NULL and emits an
     192                 :            :    appropriate error message. */
     193                 :        102 : static struct value_t * checker_validate_reference (struct definition_t * def,
     194                 :            :         const char * key)
     195                 :            : {
     196                 :            :     struct value_t * val;
     197         [ -  + ]:        102 :     if ((val = checker_find_reference (def, key)) == NULL)
     198                 :            :     {
     199                 :            :         logprint (LOG_ERROR, "line %d: checker error, not a valid `%s' property "
     200                 :          0 :                   "found in `%s:%s'\n", def->line, key, def->type, def->instance);
     201                 :            :     }
     202                 :        102 :     return val;
     203                 :            : }
     204                 :            : 
     205                 :            : /* This function checks whether the given definition is a known
     206                 :            :    microstrip component with a substrate definition.  If the given
     207                 :            :    identifier equals this substrate definition then the function
     208                 :            :    returns the appropriate value.  Otherwise it returns NULL. */
     209                 :        940 : static struct value_t * checker_find_substrate (struct definition_t * def,
     210                 :            :         char * ident)
     211                 :            : {
     212                 :            :     struct value_t * val;
     213         [ +  + ]:        940 :     if (checker_is_property (def->define, "Subst") == PROP_STR)
     214                 :            :     {
     215         [ +  - ]:         82 :         if ((val = checker_find_reference (def, "Subst")) != NULL)
     216                 :            :         {
     217 [ +  - ][ +  + ]:         82 :             if (ident != NULL && !strcmp (val->ident, ident))
     218                 :         24 :                 return val;
     219                 :            :         }
     220                 :            :     }
     221                 :        940 :     return NULL;
     222                 :            : }
     223                 :            : 
     224                 :            : /* Puts the given double value variable into an environment. */
     225                 :         81 : static variable * checker_add_variable (environment * env,
     226                 :            :                                         char * var, int type, bool pass)
     227                 :            : {
     228         [ +  - ]:         81 :     variable * v = new variable (var);
     229         [ +  - ]:         81 :     eqn::constant * c = new eqn::constant (type);
     230      [ +  -  - ]:         81 :     switch (type)
     231                 :            :     {
     232                 :            :     case TAG_DOUBLE:
     233                 :         81 :         c->d = 0.0; // initialize the variable
     234                 :         81 :         break;
     235                 :            :     case TAG_VECTOR:
     236         [ #  # ]:          0 :           c->v = new qucs::vector ();
     237                 :          0 :         break;
     238                 :            :     }
     239                 :         81 :     v->setConstant (c);
     240                 :         81 :     env->addVariable (v, pass);
     241                 :         81 :     return v;
     242                 :            : }
     243                 :            : 
     244                 :            : /* Resolves the variable of a property value.  Returns non-zero on
     245                 :            :    success, otherwise zero. */
     246                 :      10160 : static int checker_resolve_variable (struct definition_t * root,
     247                 :            :                                      struct definition_t * def,
     248                 :            :                                      struct pair_t * pair, int type)
     249                 :            : {
     250                 :            :     struct value_t * val;
     251                 :      10160 :     struct value_t * value = pair->value;
     252         [ +  + ]:      10160 :     if (value->ident != NULL)
     253                 :            :     {
     254                 :        940 :         int found = 0;
     255                 :            :         /* 1. find variable in parameter sweeps */
     256         [ +  + ]:        940 :         if ((val = checker_find_variable (root, "SW", "Param", value->ident)))
     257                 :            :         {
     258                 :            :             /* add parameter sweep variable to environment */
     259 [ +  + ][ +  - ]:        140 :             if (!strcmp (def->type, "SW") && !strcmp (pair->key, "Param"))
     260                 :            :             {
     261                 :         59 :                 checker_add_variable (root->env, value->ident, TAG_DOUBLE, true);
     262                 :            :             }
     263                 :            :             /* mark both the variable identifier and the parameter sweep
     264                 :            :             variable to be actually variables */
     265                 :        140 :             val->var = TAG_DOUBLE;
     266                 :        140 :             value->var = TAG_DOUBLE;
     267                 :        140 :             found++;
     268                 :            :         }
     269                 :            :         /* 2. find analysis in parameter sweeps */
     270         [ +  + ]:        940 :         if ((val = checker_find_variable (root, "SW", "Sim", value->ident)))
     271                 :            :         {
     272                 :         59 :             found++;
     273                 :            :         }
     274                 :            :         /* 3. find substrate in microstrip components */
     275         [ +  + ]:        940 :         if ((val = checker_find_substrate (def, value->ident)))
     276                 :            :         {
     277                 :         24 :             value->subst = 1;
     278                 :         24 :             found++;
     279                 :            :         }
     280                 :            :         /* 4. find subcircuit definition in subcircuit components */
     281         [ +  + ]:        940 :         if ((val = checker_find_variable (root, "Sub", "Type", value->ident)))
     282                 :            :         {
     283                 :         19 :             found++;
     284                 :            :         }
     285                 :            :         /* 5. find special identifiers in certain properties */
     286         [ +  + ]:        940 :         if (value->range)
     287                 :            :         {
     288                 :        672 :             found++;
     289                 :            :         }
     290                 :            :         /* 6. find file reference in S-parameter file components */
     291         [ -  + ]:        940 :         if ((val = checker_find_variable (root, "SPfile", "File", value->ident)))
     292                 :            :         {
     293                 :          0 :             found++;
     294                 :            :         }
     295                 :            :         /* 7. find variable in equation */
     296         [ +  - ]:        940 :         if (root->env)
     297                 :            :         {
     298         [ +  + ]:        940 :             if (root->env->getChecker()->containsVariable (value->ident))
     299                 :            :             {
     300                 :            :                 variable * v;
     301         [ -  + ]:         26 :                 value->var = (type == PROP_LIST) ? TAG_VECTOR : TAG_DOUBLE;
     302         [ +  + ]:         26 :                 if ((v = root->env->getVariable (value->ident)) == NULL)
     303                 :            :                 {
     304                 :            :                     // put variable into the environment
     305                 :         22 :                     checker_add_variable (root->env, value->ident, value->var, false);
     306                 :            :                 }
     307                 :         26 :                 found++;
     308                 :            :             }
     309                 :            :         }
     310                 :            :         /* 8. find file reference in file based sources */
     311         [ -  + ]:        940 :         if ((val = checker_find_variable (root, "Vfile", "File", value->ident)))
     312                 :            :         {
     313                 :          0 :             found++;
     314                 :            :         }
     315         [ -  + ]:        940 :         if ((val = checker_find_variable (root, "Ifile", "File", value->ident)))
     316                 :            :         {
     317                 :          0 :             found++;
     318                 :            :         }
     319                 :            :         /* 9. find property reference in the instance */
     320   [ -  +  #  # ]:        940 :         if (!found &&
                 [ -  + ]
     321                 :          0 :                 checker_is_property (def->define, value->ident) != PROP_NONE)
     322                 :            :         {
     323         [ #  # ]:          0 :             if (root->env)
     324                 :            :             {
     325                 :            : 
     326                 :            :                 // create reference variable names
     327                 :            :                 char * txt = (char *)
     328                 :          0 :                              malloc (strlen (def->instance) + 1 + strlen (value->ident) + 1);
     329                 :          0 :                 sprintf (txt, "%s.%s", def->instance, value->ident);
     330                 :            :                 char * ref = (char *)
     331                 :          0 :                              malloc (strlen (def->instance) + 5 + strlen (value->ident) + 1);
     332                 :          0 :                 sprintf (ref, "%s.%s.ref", def->instance, value->ident);
     333                 :            : 
     334                 :            :                 // replace property string
     335                 :          0 :                 free (value->ident);
     336                 :          0 :                 value->ident = strdup (ref);
     337                 :          0 :                 value->var = TAG_DOUBLE;
     338                 :            : 
     339                 :            :                 // already done previously?
     340                 :            :                 variable * v;
     341         [ #  # ]:          0 :                 if ((v = root->env->getVariable (ref)) == NULL)
     342                 :            :                 {
     343                 :            :                     // put variable into the environment
     344                 :          0 :                     checker_add_variable (root->env, ref, TAG_DOUBLE, false);
     345                 :            :                     // also add reference equation into environment
     346                 :          0 :                     root->env->getChecker()->addReference ("#propref", ref, txt);
     347                 :            :                 }
     348                 :            : 
     349                 :            :                 // done
     350                 :          0 :                 free (txt);
     351                 :          0 :                 free (ref);
     352                 :          0 :                 found++;
     353                 :            :             }
     354                 :            :         }
     355                 :            :         /* not found */
     356         [ -  + ]:        940 :         if (!found)
     357                 :            :         {
     358                 :            :             logprint (LOG_ERROR, "line %d: checker error, no such variable `%s' "
     359                 :            :                       "used in a `%s:%s' property\n", def->line, value->ident,
     360                 :          0 :                       def->type, def->instance);
     361                 :          0 :             return 0;
     362                 :            :         }
     363                 :            :     }
     364                 :      10160 :     return 1;
     365                 :            : }
     366                 :            : 
     367                 :            : /* Evaluates the unit scale in a property value.  It adjusts the
     368                 :            :    actual value and omits the scale.  The function returns non-zero
     369                 :            :    on success and zero otherwise. */
     370                 :      10194 : static int checker_evaluate_scale (struct value_t * value)
     371                 :            : {
     372                 :      10194 :     double val = value->value, factor = 1.0;
     373                 :            :     char * scale;
     374         [ +  + ]:      10194 :     if (value->scale != NULL)
     375                 :            :     {
     376                 :       1660 :         scale = value->scale;
     377   [ -  -  -  +  :       1660 :         switch (*scale)
          +  +  +  +  +  
          +  +  -  +  -  
                   -  + ]
     378                 :            :         {
     379                 :            :         case 'E':
     380                 :          0 :             scale++;
     381                 :          0 :             factor = 1e18;
     382                 :          0 :             break;
     383                 :            :         case 'P':
     384                 :          0 :             scale++;
     385                 :          0 :             factor = 1e15;
     386                 :          0 :             break;
     387                 :            :         case 'T':
     388                 :          0 :             scale++;
     389                 :          0 :             factor = 1e12;
     390                 :          0 :             break;
     391                 :            :         case 'G':
     392                 :         82 :             scale++;
     393                 :         82 :             factor = 1e9;
     394                 :         82 :             break;
     395                 :            :         case 'M':
     396                 :         40 :             scale++;
     397                 :         40 :             factor = 1e6;
     398                 :         40 :             break;
     399                 :            :         case 'k':
     400                 :        118 :             scale++;
     401                 :        118 :             factor = 1e3;
     402                 :        118 :             break;
     403                 :            :         case 'm':
     404                 :        144 :             scale++;
     405         [ -  + ]:        144 :             if (*scale == 'i')
     406                 :            :             {
     407                 :          0 :                 scale++;
     408         [ #  # ]:          0 :                 if (*scale == 'l')
     409                 :            :                 {
     410                 :          0 :                     scale++;
     411                 :          0 :                     factor = 2.54e-5;
     412                 :            :                 }
     413                 :            :             }
     414                 :            :             else
     415                 :        144 :                 factor = 1e-3;
     416                 :        144 :             break;
     417                 :            :         case 'u':
     418                 :        219 :             scale++;
     419                 :        219 :             factor = 1e-6;
     420                 :        219 :             break;
     421                 :            :         case 'n':
     422                 :        143 :             scale++;
     423                 :        143 :             factor = 1e-9;
     424                 :        143 :             break;
     425                 :            :         case 'p':
     426                 :        231 :             scale++;
     427                 :        231 :             factor = 1e-12;
     428                 :        231 :             break;
     429                 :            :         case 'f':
     430                 :         93 :             scale++;
     431         [ -  + ]:         93 :             if (*scale == 't')
     432                 :            :             {
     433                 :          0 :                 scale++;
     434                 :          0 :                 factor = 0.3048;
     435                 :            :             }
     436                 :            :             else
     437                 :         93 :                 factor = 1e-15;
     438                 :         93 :             break;
     439                 :            :         case 'a':
     440                 :          0 :             scale++;
     441                 :          0 :             factor = 1e-18;
     442                 :          0 :             break;
     443                 :            :         case 'd':
     444                 :         41 :             scale++;
     445         [ +  - ]:         41 :             if (*scale == 'B')
     446                 :            :             {
     447                 :         41 :                 scale++;
     448                 :         41 :                 val = std::pow (10.0, val / 10.0);
     449         [ +  + ]:         41 :                 if (*scale == 'm')
     450                 :            :                 {
     451                 :         38 :                     scale++;
     452                 :         38 :                     factor = 1e-3;
     453                 :            :                 }
     454         [ -  + ]:          3 :                 else if (*scale == 'u')
     455                 :            :                 {
     456                 :          0 :                     scale++;
     457                 :          0 :                     factor = 1e-6;
     458                 :            :                 }
     459                 :            :             }
     460                 :         41 :             break;
     461                 :            :         case 'i':
     462                 :          0 :             scale++;
     463         [ #  # ]:          0 :             if (*scale == 'n')
     464                 :            :             {
     465                 :          0 :                 scale++;
     466                 :          0 :                 factor = 2.54e-2;
     467                 :            :             }
     468                 :          0 :             break;
     469                 :            :         case 'y':
     470                 :          0 :             scale++;
     471         [ #  # ]:          0 :             if (*scale == 'd')
     472                 :            :             {
     473                 :          0 :                 scale++;
     474                 :          0 :                 factor = 0.9144;
     475                 :            :             }
     476                 :          0 :             break;
     477                 :            :         }
     478         [ +  + ]:       1660 :         if (*scale != '\0')
     479                 :            :         {
     480                 :       1353 :             value->unit = strdup (scale);
     481                 :            :         }
     482                 :       1660 :         free (value->scale);
     483                 :       1660 :         value->scale = NULL;
     484                 :            :     }
     485                 :      10194 :     value->value = val * factor;
     486                 :      10194 :     return 1;
     487                 :            : }
     488                 :            : 
     489                 :            : /* The function returns the number of instances of the given type within
     490                 :            :    the list of definitions. */
     491                 :        430 : static int checker_count_definitions (struct definition_t * root,
     492                 :            :                                       const char * type, int action)
     493                 :            : {
     494                 :        430 :     int count = 0;
     495         [ +  + ]:       4636 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     496                 :            :     {
     497         [ +  + ]:       4206 :         if (def->action == action)
     498                 :            :         {
     499         [ +  + ]:        910 :             if (type == NULL)
     500                 :        181 :                 count++;
     501         [ +  + ]:        729 :             else if (!strcmp (def->type, type))
     502                 :        123 :                 count++;
     503                 :            :         }
     504                 :            :     }
     505                 :        430 :     return count;
     506                 :            : }
     507                 :            : 
     508                 :            : /* This function looks for the specified subcircuit type in the list
     509                 :            :    of available subcircuits and returns its definition.  If there is
     510                 :            :    no such subcircuit the function returns NULL: */
     511                 :         73 : static struct definition_t * checker_find_subcircuit (char * n)
     512                 :            : {
     513                 :            :     struct definition_t * def;
     514         [ +  - ]:        101 :     for (def = subcircuit_root; def != NULL; def = def->next)
     515 [ +  - ][ +  + ]:        101 :         if (n != NULL && !strcmp (def->instance, n)) return def;
     516                 :         73 :     return NULL;
     517                 :            : }
     518                 :            : 
     519                 :            : /* The function returns the subcircuit definition for the given
     520                 :            :    subcircuit instance. */
     521                 :            : static struct definition_t *
     522                 :         46 : checker_get_subcircuit (struct definition_t * def)
     523                 :            : {
     524                 :            :     struct value_t * val;
     525                 :         46 :     struct definition_t * sub = NULL;
     526         [ +  - ]:         46 :     if ((val = checker_find_reference (def, "Type")) != NULL)
     527                 :         46 :         sub = checker_find_subcircuit (val->ident);
     528                 :         46 :     return sub;
     529                 :            : }
     530                 :            : 
     531                 :            : // Global variable indicating cycles in subcircuit definitions.
     532                 :            : static int checker_sub_cycles = 0;
     533                 :            : 
     534                 :            : /* The following function returns the number of circuit instances
     535                 :            :    requiring a DC analysis (being nonlinear) in the list of definitions. */
     536                 :        126 : static int checker_count_nonlinearities (struct definition_t * root)
     537                 :            : {
     538                 :        126 :     int count = 0;
     539                 :            :     struct definition_t * sub;
     540         [ +  + ]:       1268 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     541                 :            :     {
     542         [ +  + ]:       1142 :         if (def->nonlinear != 0) count++;
     543                 :            :         // also recurse into subcircuits if possible
     544         [ +  - ]:       1142 :         if (checker_sub_cycles <= 0)
     545                 :            :         {
     546         [ +  + ]:       1142 :             if (!strcmp (def->type, "Sub"))
     547                 :            :             {
     548         [ +  - ]:         23 :                 if ((sub = checker_get_subcircuit (def)) != NULL)
     549                 :            :                 {
     550                 :         23 :                     count += checker_count_nonlinearities (sub->sub);
     551                 :            :                 }
     552                 :            :             }
     553                 :            :         }
     554                 :            :     }
     555                 :        126 :     return count;
     556                 :            : }
     557                 :            : 
     558                 :            : /* This function returns the number of action definitions with the
     559                 :            :    given instance name. */
     560                 :         59 : static int checker_count_action (struct definition_t * root, char * instance)
     561                 :            : {
     562                 :         59 :     int count = 0;
     563         [ +  + ]:        620 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     564                 :            :     {
     565 [ +  + ][ +  + ]:        561 :         if (def->action == 1 && !strcmp (def->instance, instance))
     566                 :         59 :             count++;
     567                 :            :     }
     568                 :         59 :     return count;
     569                 :            : }
     570                 :            : 
     571                 :            : /* This (recursive) function detects any kind of cyclic definitions of
     572                 :            :    parameter sweeps for the given instance name.  The string list
     573                 :            :    argument is used to pass the dependencies.  The function returns
     574                 :            :    zero if the parameter sweep in non-cyclic. */
     575                 :         79 : static int checker_validate_para_cycles (struct definition_t * root,
     576                 :            :         char * instance, strlist * deps)
     577                 :            : {
     578                 :         79 :     int errors = 0;
     579                 :            :     struct value_t * val;
     580         [ +  + ]:        768 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     581                 :            :     {
     582                 :            :         /* find the appropriate definition for the given instance */
     583 [ +  + ][ +  + ]:        709 :         if (def->action == 1 && !strcmp (def->instance, instance))
     584                 :            :         {
     585                 :            :             /* emit error message if the instance is already in the dependencies */
     586         [ -  + ]:         79 :             if (deps->contains (instance))
     587                 :            :             {
     588                 :            :                 logprint (LOG_ERROR, "checker error, cyclic definition of `%s' "
     589                 :          0 :                           "detected, involves: %s\n", instance, deps->toString ());
     590                 :          0 :                 return ++errors;
     591                 :            :             }
     592                 :         79 :             deps->append (instance);
     593                 :            :             /* recurse into parameter sweeps */
     594         [ +  + ]:         79 :             if (!strcmp (def->type, "SW"))
     595                 :            :             {
     596         [ +  - ]:         20 :                 if ((val = checker_find_reference (def, "Sim")) != NULL)
     597                 :            :                 {
     598                 :         20 :                     return checker_validate_para_cycles (root, val->ident, deps);
     599                 :            :                 }
     600                 :            :             }
     601                 :            :         }
     602                 :            :     }
     603                 :         79 :     return errors;
     604                 :            : }
     605                 :            : 
     606                 :            : /* This function validates each parameter sweep within the list of
     607                 :            :    definitions and return non-zero on errors.  Emits appropriate error
     608                 :            :    messages. */
     609                 :        103 : static int checker_validate_para (struct definition_t * root)
     610                 :            : {
     611                 :        103 :     int errors = 0;
     612                 :            :     struct value_t * val;
     613         [ +  + ]:       1102 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     614                 :            :     {
     615                 :            :         /* find parameter sweep */
     616 [ +  + ][ +  + ]:        999 :         if (def->action == 1 && !strcmp (def->type, "SW"))
     617                 :            :         {
     618                 :            :             /* the 'Sim' property must be an identifier */
     619         [ -  + ]:         59 :             if ((val = checker_validate_reference (def, "Sim")) == NULL)
     620                 :            :             {
     621                 :          0 :                 errors++;
     622                 :            :             }
     623                 :            :             else
     624                 :            :             {
     625                 :            :                 /* check for self-referring sweeps */
     626         [ -  + ]:         59 :                 if (!strcmp (def->instance, val->ident))
     627                 :            :                 {
     628                 :            :                     logprint (LOG_ERROR, "line %d: checker error, definition `%s:%s' "
     629                 :          0 :                               "refers to itself\n", def->line, def->type, def->instance);
     630                 :          0 :                     errors++;
     631                 :            :                 }
     632                 :            :                 /* look for the referred analysis action definition */
     633         [ -  + ]:         59 :                 if (checker_count_action (root, val->ident) != 1)
     634                 :            :                 {
     635                 :            :                     logprint (LOG_ERROR, "line %d: checker error, no such action `%s' "
     636                 :            :                               "found as referred in `%s:%s'\n", def->line, val->ident,
     637                 :          0 :                               def->type, def->instance);
     638                 :          0 :                     errors++;
     639                 :            :                 }
     640                 :            :                 /* finally detect cyclic definitions */
     641         [ +  - ]:         59 :                 strlist * deps = new strlist ();
     642                 :         59 :                 errors += checker_validate_para_cycles (root, val->ident, deps);
     643         [ +  - ]:         59 :                 delete deps;
     644                 :            :             }
     645                 :            :         }
     646                 :            :     }
     647                 :        103 :     return errors;
     648                 :            : }
     649                 :            : 
     650                 :            : /* This function returns the next port definition in the given list of
     651                 :            :    definitions or NULL if there is no such definition. */
     652                 :        277 : static struct definition_t * checker_find_port (struct definition_t * root)
     653                 :            : {
     654         [ +  + ]:       1594 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     655                 :            :     {
     656 [ +  + ][ +  + ]:       1451 :         if (def->action == PROP_COMPONENT && !strcmp (def->type, "Pac"))
     657                 :            :         {
     658                 :        134 :             return def;
     659                 :            :         }
     660                 :            :     }
     661                 :        277 :     return NULL;
     662                 :            : }
     663                 :            : 
     664                 :            : /* This function checks whether the port numbers for the S-parameter
     665                 :            :    analysis are unique or not.  It returns zero on success and
     666                 :            :    non-zero if it detected duplicate entries. */
     667                 :        103 : static int checker_validate_ports (struct definition_t * root)
     668                 :            : {
     669                 :        103 :     int p, errors = 0;
     670                 :            :     struct value_t * val;
     671                 :        103 :     struct definition_t * port, * def = root;
     672                 :        103 :     const char * prop = "Num";
     673         [ +  + ]:        143 :     while ((def = checker_find_port (def)) != NULL)
     674                 :            :     {
     675         [ +  - ]:         40 :         if ((val = checker_find_prop_value (def, prop)) != NULL)
     676                 :            :         {
     677                 :         40 :             p = (int) val->value;
     678                 :         40 :             port = root;
     679         [ +  + ]:        134 :             while ((port = checker_find_port (port)) != NULL)
     680                 :            :             {
     681         [ +  + ]:         94 :                 if (port != def)
     682                 :            :                 {
     683         [ +  - ]:         54 :                     if ((val = checker_find_prop_value (port, prop)) != NULL)
     684                 :            :                     {
     685         [ -  + ]:         54 :                         if (p == (int) val->value)
     686                 :            :                         {
     687                 :            :                             logprint (LOG_ERROR, "line %d: checker error, `%s' definitions "
     688                 :            :                                       "with duplicate `%s=%d' property found: `%s:%s' and "
     689                 :            :                                       "`%s:%s'\n", def->line, def->type, prop, p, def->type,
     690                 :          0 :                                       def->instance, port->type, port->instance);
     691                 :          0 :                             errors++;
     692                 :            :                         }
     693                 :            :                     }
     694                 :            :                 }
     695                 :         94 :                 port = port->next;
     696                 :            :             }
     697                 :            :         }
     698                 :         40 :         def = def->next;
     699                 :            :     }
     700                 :        103 :     return errors;
     701                 :            : }
     702                 :            : 
     703                 :            : /* The following function checks whether the parametric sweeps in the
     704                 :            :    netlist are valid or not.  It returns zero on success and non-zero
     705                 :            :    otherwise. */
     706                 :        103 : static int checker_validate_lists (struct definition_t * root)
     707                 :            : {
     708                 :        103 :     int errors = 0;
     709                 :            :     // go through each definition
     710         [ +  + ]:       1102 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     711                 :            :     {
     712                 :            :         /* sweeps possible in parameter sweep, ac-analysis and
     713                 :            :            s-parameter analysis */
     714 [ +  + ][ +  + ]:        999 :         if (def->action == 1 && (!strcmp (def->type, "SW") ||
         [ +  + ][ +  + ]
     715                 :        122 :                                  !strcmp (def->type, "AC") ||
     716                 :        104 :                                  !strcmp (def->type, "SP")))
     717                 :            :         {
     718                 :         95 :             struct value_t * val = checker_find_reference (def, "Type");
     719                 :         95 :             char * type = val->ident;
     720                 :            :             // list of constant values and constant values
     721 [ +  - ][ +  - ]:         95 :             if (type && (!strcmp (type, "const") || !strcmp (type, "list")))
                 [ +  + ]
     722                 :            :             {
     723                 :            :                 // property 'Values' is required
     724         [ -  + ]:          4 :                 if ((val = checker_find_prop_value (def, "Values")) == NULL)
     725                 :            :                 {
     726         [ #  # ]:          0 :                     if (!strcmp (type, "const"))
     727                 :            :                     {
     728         [ #  # ]:          0 :                         if ((val = checker_validate_reference (def, "Values")) == NULL)
     729                 :            :                         {
     730                 :          0 :                             errors++;
     731                 :            :                         }
     732                 :            :                     }
     733                 :            :                     else
     734                 :            :                     {
     735                 :            :                         logprint (LOG_ERROR, "line %d: checker error, required property "
     736                 :            :                                   "`%s' not found in `%s:%s'\n", def->line, "Values",
     737                 :          0 :                                   def->type, def->instance);
     738                 :          0 :                         errors++;
     739                 :            :                     }
     740                 :            :                 }
     741                 :            :                 else
     742                 :            :                 {
     743         [ -  + ]:          4 :                     if (!strcmp (type, "const"))
     744                 :            :                     {
     745                 :            :                         // in constant sweeps only one value allowed
     746         [ #  # ]:          0 :                         if (val->next != NULL)
     747                 :            :                         {
     748                 :            :                             logprint (LOG_ERROR, "line %d: checker error, value of `%s' "
     749                 :            :                                       "needs to be a single constant value in `%s:%s', no "
     750                 :            :                                       "lists possible\n", def->line, "Values",
     751                 :          0 :                                       def->type, def->instance);
     752                 :          0 :                             errors++;
     753                 :            :                         }
     754                 :          0 :                         val->var = TAG_UNKNOWN;
     755                 :            :                     }
     756         [ +  - ]:          4 :                     if (!strcmp (type, "list"))
     757                 :            :                     {
     758                 :          4 :                         val->var = TAG_VECTOR;
     759                 :            :                     }
     760                 :            :                     // check and evaluate the unit scale in a value list
     761         [ +  + ]:         20 :                     for (; val != NULL; val = val->next)
     762                 :            :                     {
     763         [ -  + ]:         16 :                         if (!checker_evaluate_scale (val))
     764                 :          0 :                             errors++;
     765                 :            :                     }
     766                 :            :                 }
     767                 :            :                 // property 'Start' is invalid
     768         [ -  + ]:          4 :                 if (checker_find_property (def, "Start") > 0)
     769                 :            :                 {
     770                 :            :                     logprint (LOG_ERROR, "line %d: checker error, extraneous property "
     771                 :            :                               "`%s' is invalid in `%s:%s'\n", def->line, "Start",
     772                 :          0 :                               def->type, def->instance);
     773                 :          0 :                     errors++;
     774                 :            :                 }
     775                 :            :                 // property 'Stop' is invalid
     776         [ -  + ]:          4 :                 if (checker_find_property (def, "Stop") > 0)
     777                 :            :                 {
     778                 :            :                     logprint (LOG_ERROR, "line %d: checker error, extraneous property "
     779                 :            :                               "`%s' is invalid in `%s:%s'\n", def->line, "Stop",
     780                 :          0 :                               def->type, def->instance);
     781                 :          0 :                     errors++;
     782                 :            :                 }
     783                 :            :                 // property 'Points' is also invalid
     784         [ -  + ]:          4 :                 if (checker_find_property (def, "Points") > 0)
     785                 :            :                 {
     786                 :            :                     logprint (LOG_ERROR, "line %d: checker error, extraneous property "
     787                 :            :                               "`%s' is invalid in `%s:%s'\n", def->line, "Points",
     788                 :          0 :                               def->type, def->instance);
     789                 :          0 :                     errors++;
     790                 :            :                 }
     791                 :            :             }
     792                 :            :             // linearly and logarithmically stepped sweeps
     793 [ +  - ][ +  + ]:         91 :             else if (type && (!strcmp (type, "lin") || !strcmp (type, "log")))
                 [ +  - ]
     794                 :            :             {
     795                 :            :                 // property 'Start' required
     796         [ -  + ]:         91 :                 if (checker_find_property (def, "Start") <= 0)
     797                 :            :                 {
     798                 :            :                     logprint (LOG_ERROR, "line %d: checker error, required property "
     799                 :            :                               "`%s' not found in `%s:%s'\n", def->line, "Start",
     800                 :          0 :                               def->type, def->instance);
     801                 :          0 :                     errors++;
     802                 :            :                 }
     803                 :            :                 // property 'Stop' required
     804         [ -  + ]:         91 :                 if (checker_find_property (def, "Stop") <= 0)
     805                 :            :                 {
     806                 :            :                     logprint (LOG_ERROR, "line %d: checker error, required property "
     807                 :            :                               "`%s' not found in `%s:%s'\n", def->line, "Stop",
     808                 :          0 :                               def->type, def->instance);
     809                 :          0 :                     errors++;
     810                 :            :                 }
     811                 :            :                 // property 'Points' is also required
     812         [ -  + ]:         91 :                 if (checker_find_property (def, "Points") <= 0)
     813                 :            :                 {
     814                 :            :                     logprint (LOG_ERROR, "line %d: checker error, required property "
     815                 :            :                               "`%s' not found in `%s:%s'\n", def->line, "Points",
     816                 :          0 :                               def->type, def->instance);
     817                 :          0 :                     errors++;
     818                 :            :                 }
     819                 :            :                 // property 'Values' is invalid
     820         [ -  + ]:         91 :                 if (checker_find_property (def, "Values") > 0)
     821                 :            :                 {
     822                 :            :                     logprint (LOG_ERROR, "line %d: checker error, extraneous property "
     823                 :            :                               "`%s' is invalid in `%s:%s'\n", def->line, "Values",
     824                 :          0 :                               def->type, def->instance);
     825                 :          0 :                     errors++;
     826                 :            :                 }
     827                 :            :             }
     828                 :            :         }
     829                 :            :     }
     830                 :        103 :     return errors;
     831                 :            : }
     832                 :            : 
     833                 :            : /* This function checks the actions to be taken in the netlist.  It
     834                 :            :    returns zero on success, non-zero otherwise. */
     835                 :        103 : static int checker_validate_actions (struct definition_t * root)
     836                 :            : {
     837                 :        103 :     int a, c, n, errors = 0;
     838         [ -  + ]:        103 :     if ((n = checker_count_definitions (root, NULL, 1)) < 1)
     839                 :            :     {
     840                 :          0 :         logprint (LOG_ERROR, "checker error, no actions defined: nothing to do\n");
     841                 :          0 :         errors++;
     842                 :            :     }
     843                 :            :     else
     844                 :            :     {
     845                 :            :         // check requirements for s-parameter analysis
     846         [ +  + ]:        103 :         if ((a = checker_count_definitions (root, "SP", 1)) >= 1)
     847                 :            :         {
     848         [ -  + ]:         18 :             if ((n = checker_count_definitions (root, "Pac", 0)) < 1)
     849                 :            :             {
     850                 :            :                 logprint (LOG_ERROR, "checker error, %d `Pac' definitions found, at "
     851                 :          0 :                           "least 1 required\n", n);
     852                 :          0 :                 errors++;
     853                 :            :             }
     854                 :            :         }
     855                 :            :         // count analyses requiring a DC solution
     856                 :        103 :         a += checker_count_definitions (root, "AC", 1);
     857                 :            :         // check dc-analysis requirements
     858                 :        103 :         c = checker_count_nonlinearities (root);
     859                 :        103 :         n = checker_count_definitions (root, "DC", 1);
     860         [ -  + ]:        103 :         if (n > 1)
     861                 :            :         {
     862                 :            :             logprint (LOG_ERROR, "checker error, the .DC action is defined %dx, "
     863                 :          0 :                       "single or none required\n", n);
     864                 :          0 :             errors++;
     865                 :            :         }
     866 [ +  + ][ +  + ]:        103 :         if (a >= 1 && c >= 1 && n < 1)
                 [ -  + ]
     867                 :            :         {
     868                 :            :             logprint (LOG_ERROR, "checker error, a .DC action is required for this "
     869                 :          0 :                       "circuit definition (accounted %d non-linearities)\n", c);
     870                 :          0 :             errors++;
     871                 :            :         }
     872                 :            :     }
     873                 :        103 :     errors += checker_validate_para (root);
     874                 :        103 :     errors += checker_validate_ports (root);
     875                 :        103 :     errors += checker_validate_lists (root);
     876                 :        103 :     return errors;
     877                 :            : }
     878                 :            : 
     879                 :            : /* This function checks the validity of each microstrip component and
     880                 :            :    its substrate and model references.  It returns zero on success,
     881                 :            :    emit error messages if necessary and returns non-zero on errors. */
     882                 :        219 : static int checker_validate_strips (struct definition_t * root)
     883                 :            : {
     884                 :        219 :     int errors = 0;
     885                 :            :     struct value_t * val;
     886         [ +  + ]:       1317 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     887                 :            :     {
     888         [ +  + ]:       1098 :         if (!def->action)
     889                 :            :         {
     890                 :            :             /* find components with substrate property */
     891         [ +  + ]:        904 :             if (checker_is_property (def->define, "Subst") == PROP_STR)
     892                 :            :             {
     893                 :            :                 /* check validity of 'Subst' property */
     894         [ -  + ]:         24 :                 if ((val = checker_validate_reference (def, "Subst")) == NULL)
     895                 :            :                 {
     896                 :          0 :                     errors++;
     897                 :            :                 }
     898                 :            :                 else
     899                 :            :                 {
     900         [ -  + ]:         24 :                     if (checker_count_definition (root, "SUBST", val->ident) != 1)
     901                 :            :                     {
     902                 :            :                         logprint (LOG_ERROR, "line %d: checker error, no such substrate "
     903                 :            :                                   "`%s' found as specified in `%s:%s'\n", def->line,
     904                 :          0 :                                   val->ident, def->type, def->instance);
     905                 :          0 :                         errors++;
     906                 :            :                     }
     907                 :            :                 }
     908                 :            :                 /* check validity of 'Model' property */
     909                 :            : #if DISABLE_FOR_NOW /* ThinkME!!! */
     910                 :            :                 if ((val = checker_validate_reference (def, "Model")) == NULL)
     911                 :            :                 {
     912                 :            :                     errors++;
     913                 :            :                 }
     914                 :            : #endif
     915                 :            :             }
     916                 :            :         }
     917                 :            :     }
     918                 :        219 :     return errors;
     919                 :            : }
     920                 :            : 
     921                 :            : /* This function counts the number of occurrences of the given node
     922                 :            :    name in the given netlist definition root. */
     923                 :          2 : static int checker_count_nodes (struct definition_t * root, char * n)
     924                 :            : {
     925                 :          2 :     int count = 0;
     926                 :            :     struct node_t * node;
     927         [ +  + ]:         34 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     928                 :            :     {
     929 [ +  + ][ +  + ]:         32 :         if (!def->action && !def->nodeset)
     930                 :            :         {
     931         [ +  + ]:         84 :             for (node = def->nodes; node != NULL; node = node->next)
     932         [ +  + ]:         58 :                 if (!strcmp (node->node, n)) count++;
     933                 :            :         }
     934                 :            :     }
     935                 :          2 :     return count;
     936                 :            : }
     937                 :            : 
     938                 :            : /* The function identifies duplicate nodesets for the same node which
     939                 :            :    is not allowed.  It returns the number of duplications. */
     940                 :          2 : static int checker_count_nodesets (struct definition_t * root, char * n)
     941                 :            : {
     942                 :          2 :     int count = 0;
     943         [ +  + ]:         34 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     944                 :            :     {
     945 [ +  + ][ +  - ]:         32 :         if (def->nodeset && !def->duplicate)
     946                 :            :         {
     947                 :          4 :             char * node = def->nodes->node;
     948         [ +  + ]:          4 :             if (!strcmp (node, n))
     949                 :            :             {
     950         [ -  + ]:          2 :                 if (++count > 1) def->duplicate = 1;
     951                 :            :             }
     952                 :            :         }
     953                 :            :     }
     954                 :          2 :     return count;
     955                 :            : }
     956                 :            : 
     957                 :            : /* The following function checks whether the nodes specified by the
     958                 :            :    nodeset functionality is valid in its current scope.  It does not
     959                 :            :    check across subcircuit boundaries. */
     960                 :        219 : static int checker_validate_nodesets (struct definition_t * root)
     961                 :            : {
     962                 :        219 :     int errors = 0;
     963         [ +  + ]:       1317 :     for (struct definition_t * def = root; def != NULL; def = def->next)
     964                 :            :     {
     965 [ +  + ][ +  - ]:       1098 :         if (def->nodeset && checker_count_nodes (def) == 1)
                 [ +  + ]
     966                 :            :         {
     967                 :          2 :             char * node = def->nodes->node;
     968         [ -  + ]:          2 :             if (checker_count_nodes (root, node) <= 0)
     969                 :            :             {
     970                 :            :                 logprint (LOG_ERROR, "line %d: checker error, no such node `%s' found "
     971                 :            :                           "as referenced by `%s:%s'\n", def->line, node, def->type,
     972                 :          0 :                           def->instance);
     973                 :          0 :                 errors++;
     974                 :            :             }
     975         [ -  + ]:          2 :             if (checker_count_nodesets (root, node) > 1)
     976                 :            :             {
     977                 :            :                 logprint (LOG_ERROR, "line %d: checker error, the node `%s' is not "
     978                 :            :                           "uniquely defined by `%s:%s'\n", def->line, node, def->type,
     979                 :          0 :                           def->instance);
     980                 :          0 :                 errors++;
     981                 :            :             }
     982                 :            :         }
     983                 :            :     }
     984                 :        219 :     return errors;
     985                 :            : }
     986                 :            : 
     987                 :            : /* This function should be called after the netlist and the equation
     988                 :            :    list have been checked.  It verifies that parameter sweep
     989                 :            :    definitions and equation variable identifiers are unique.  The
     990                 :            :    function returns zero on success and non-zero otherwise. */
     991                 :        103 : static int netlist_checker_variables_intern (struct definition_t * root,
     992                 :            :         environment * env)
     993                 :            : {
     994                 :        103 :     int errors = 0, pos;
     995                 :            :     struct value_t * para, * ref;
     996                 :        103 :     strlist * eqnvars = env->getChecker()->variables ();
     997         [ +  - ]:        103 :     strlist * instances = new strlist ();
     998         [ +  - ]:        103 :     strlist * vars = new strlist ();
     999         [ +  - ]:        103 :     strlist * refs = new strlist ();
    1000                 :            :     // go through list of netlist definitions
    1001         [ +  + ]:       1222 :     for (struct definition_t * def = root; def != NULL; def = def->next)
    1002                 :            :     {
    1003                 :            :         // find parameters sweeps
    1004 [ +  + ][ +  + ]:       1119 :         if (def->action == 1 && !strcmp (def->type, "SW"))
    1005                 :            :         {
    1006                 :         59 :             para = checker_find_reference (def, "Param");
    1007                 :         59 :             ref = checker_find_reference (def, "Sim");
    1008 [ +  - ][ +  - ]:         59 :             if (para != NULL && ref != NULL)
    1009                 :            :             {
    1010                 :            :                 // check whether sweep variable collides with equations
    1011 [ +  - ][ -  + ]:         59 :                 if (eqnvars && eqnvars->contains (para->ident))
                 [ -  + ]
    1012                 :            :                 {
    1013                 :            :                     logprint (LOG_ERROR, "checker error, equation variable `%s' "
    1014                 :            :                               "already defined by `%s:%s'\n", para->ident,
    1015                 :          0 :                               def->type, def->instance);
    1016                 :          0 :                     errors++;
    1017                 :            :                 }
    1018                 :            :                 // check for duplicate parameter names in parameter sweeps, but
    1019                 :            :                 // allow them in same order sweeps
    1020         [ -  + ]:         59 :                 if ((pos = vars->index (para->ident)) != -1)
    1021                 :            :                 {
    1022         [ #  # ]:          0 :                     if (strcmp (ref->ident, refs->get (pos)))
    1023                 :            :                     {
    1024                 :            :                         logprint (LOG_ERROR, "checker error, variable `%s' in `%s:%s' "
    1025                 :            :                                   "already defined by `%s:%s'\n", para->ident, def->type,
    1026                 :          0 :                                   def->instance, def->type, instances->get (pos));
    1027                 :          0 :                         errors++;
    1028                 :            :                     }
    1029                 :            :                 }
    1030                 :            :                 // check for duplicate simulations in parameter sweeps (same order
    1031                 :            :                 // sweep) and allow same parameter name only
    1032         [ -  + ]:         59 :                 if ((pos = refs->index (ref->ident)) != -1)
    1033                 :            :                 {
    1034         [ #  # ]:          0 :                     if (strcmp (para->ident, vars->get (pos)))
    1035                 :            :                     {
    1036                 :            :                         logprint (LOG_ERROR, "checker error, conflicting variables `%s' "
    1037                 :            :                                   "in `%s:%s' and `%s' in `%s:%s' for `%s'\n",
    1038                 :            :                                   para->ident, def->type, def->instance,
    1039                 :            :                                   vars->get (pos), def->type, instances->get (pos),
    1040                 :          0 :                                   ref->ident);
    1041                 :          0 :                         errors++;
    1042                 :            :                     }
    1043                 :            :                 }
    1044                 :            :                 // collect parameter sweep variables for the above two checks
    1045                 :         59 :                 instances->add (def->instance);
    1046                 :         59 :                 vars->add (para->ident);
    1047                 :         59 :                 refs->add (ref->ident);
    1048                 :            :             }
    1049                 :            :         }
    1050                 :            :     }
    1051         [ +  - ]:        103 :     delete eqnvars;
    1052         [ +  - ]:        103 :     delete refs;
    1053         [ +  - ]:        103 :     delete vars;
    1054         [ +  - ]:        103 :     delete instances;
    1055                 :        103 :     return errors;
    1056                 :            : }
    1057                 :            : 
    1058                 :            : /* This is the overall variable checker for the parsed netlist.  See
    1059                 :            :    the above function for details. */
    1060                 :        103 : int netlist_checker_variables (environment * env)
    1061                 :            : {
    1062                 :        103 :     return netlist_checker_variables_intern (definition_root, env);
    1063                 :            : }
    1064                 :            : 
    1065                 :            : /* The function checks whether the given key-value combination is
    1066                 :            :    inside the allowed range defined by the given property definition
    1067                 :            :    and returns the number of error or zero otherwise. */
    1068                 :      10160 : static int checker_value_in_prop_range (char * instance, struct define_t * def,
    1069                 :            :                                         struct pair_t * pp,
    1070                 :            :                                         struct property_t * prop)
    1071                 :            : {
    1072                 :      10160 :     int errors = 0;
    1073                 :            :     // check values
    1074         [ +  + ]:      10160 :     if (PROP_IS_VAL (*prop))
    1075                 :            :     {
    1076         [ +  + ]:       9327 :         if (!PROP_IS_LST (*prop))
    1077                 :            :         {
    1078                 :            :             // lists of values possible?
    1079         [ -  + ]:       9321 :             if (pp->value->next != NULL)
    1080                 :            :             {
    1081                 :            :                 logprint (LOG_ERROR,
    1082                 :            :                           "checker error, value of `%s' needs to be "
    1083                 :            :                           "a single value in `%s:%s', no lists possible\n",
    1084                 :          0 :                           pp->key, def->type, instance);
    1085                 :          0 :                 errors++;
    1086                 :            :             }
    1087                 :            :         }
    1088                 :            :         else
    1089                 :            :         {
    1090                 :            :             // a value list
    1091                 :          6 :             struct value_t * val = pp->value;
    1092                 :          6 :             val->var = TAG_VECTOR;
    1093                 :            :             // check and evaluate the unit scale in a value list
    1094         [ +  + ]:         24 :             for (; val != NULL; val = val->next)
    1095                 :            :             {
    1096         [ -  + ]:         18 :                 if (!checker_evaluate_scale (val))
    1097                 :          0 :                     errors++;
    1098                 :            :             }
    1099                 :            :         }
    1100                 :            :         // check range of all values
    1101 [ +  + ][ +  + ]:       9327 :         if (PROP_HAS_RANGE (*prop))
         [ +  + ][ +  + ]
    1102                 :            :         {
    1103                 :       5617 :             struct value_t * val = pp->value;
    1104         [ +  + ]:       5617 :             if (val->ident)
    1105                 :            :             {
    1106                 :            :                 /* no range checking on variable identifier */
    1107                 :            :                 logprint (LOG_STATUS,
    1108                 :            :                           "checker notice, value of `%s' (variable `%s') could be "
    1109                 :            :                           "out of range `%c%g,%g%c' in `%s:%s'\n",
    1110                 :            :                           pp->key, val->ident, prop->range.il, prop->range.l,
    1111                 :         22 :                           prop->range.h, prop->range.ih, def->type, instance);
    1112                 :         22 :                 val = NULL;
    1113                 :            :             }
    1114         [ +  + ]:      11212 :             for (; val != NULL; val = val->next)
    1115                 :            :             {
    1116                 :       5595 :                 int rerror = 0;
    1117 [ +  + ][ -  + ]:       5595 :                 if (prop->range.il == '[' &&  (val->value < prop->range.l))
    1118                 :          0 :                     rerror++;
    1119 [ +  + ][ -  + ]:       5595 :                 if (prop->range.il == ']' && !(val->value > prop->range.l))
    1120                 :          0 :                     rerror++;
    1121 [ +  + ][ -  + ]:       5595 :                 if (prop->range.ih == '[' && !(val->value < prop->range.h))
    1122                 :          0 :                     rerror++;
    1123 [ +  + ][ -  + ]:       5595 :                 if (prop->range.ih == ']' &&  (val->value > prop->range.h))
    1124                 :          0 :                     rerror++;
    1125         [ -  + ]:       5595 :                 if (rerror)
    1126                 :            :                 {
    1127                 :            :                     logprint (LOG_ERROR,
    1128                 :            :                               "checker error, value of `%s' (%g) is out of "
    1129                 :            :                               "range `%c%g,%g%c' in `%s:%s'\n",
    1130                 :            :                               pp->key, val->value, prop->range.il, prop->range.l,
    1131                 :          0 :                               prop->range.h, prop->range.ih, def->type, instance);
    1132                 :          0 :                     errors++;
    1133                 :            :                 }
    1134                 :            :             }
    1135                 :            :         }
    1136                 :            :         // check fraction of integers
    1137         [ +  + ]:       9327 :         if (PROP_IS_INT (*prop))
    1138                 :            :         {
    1139                 :            :             double integral;
    1140         [ -  + ]:        349 :             if (modf (pp->value->value, &integral) != 0)
    1141                 :            :             {
    1142                 :            :                 logprint (LOG_ERROR,
    1143                 :            :                           "checker error, value of `%s' (%g) needs to be "
    1144                 :            :                           "an integer in `%s:%s'\n",
    1145         [ #  # ]:          0 :                           pp->key, pp->value->value, def->type, instance);
    1146                 :        349 :                 errors++;
    1147                 :            :             }
    1148                 :            :         }
    1149                 :            :     }
    1150                 :            :     // check identifiers
    1151                 :            :     else
    1152                 :            :     {
    1153                 :            :         // no identifier given
    1154         [ -  + ]:        833 :         if (pp->value->ident == NULL)
    1155                 :            :         {
    1156                 :            :             logprint (LOG_ERROR,
    1157                 :            :                       "checker error, value of `%s' (%g) needs to be "
    1158                 :            :                       "an identifier in `%s:%s'\n",
    1159                 :          0 :                       pp->key, pp->value->value, def->type, instance);
    1160                 :          0 :             errors++;
    1161                 :            :         }
    1162                 :            :         // check identifier range
    1163                 :            :         else
    1164                 :            :         {
    1165         [ +  + ]:        833 :             if (PROP_HAS_STR (*prop))
    1166                 :            :             {
    1167                 :        672 :                 int i, found = 0;
    1168                 :            :                 char range[256];
    1169                 :        672 :                 sprintf (range, "[");
    1170         [ +  + ]:       2843 :                 for (i = 0; prop->range.str[i]; i++)
    1171                 :            :                 {
    1172                 :       2171 :                     strcat (range, prop->range.str[i]);
    1173                 :       2171 :                     strcat (range, ",");
    1174         [ +  + ]:       2171 :                     if (!strcmp (prop->range.str[i], pp->value->ident)) found++;
    1175                 :            :                 }
    1176         [ -  + ]:        672 :                 if (!found)
    1177                 :            :                 {
    1178                 :          0 :                     range[strlen (range) - 1] = ']';
    1179                 :            :                     logprint (LOG_ERROR,
    1180                 :            :                               "checker error, value of `%s' (%s) needs to be "
    1181                 :            :                               "in %s in `%s:%s'\n",
    1182         [ #  # ]:          0 :                               pp->key, pp->value->ident, range, def->type, instance);
    1183                 :          0 :                     errors++;
    1184                 :            :                 }
    1185                 :        672 :                 else pp->value->range = 1;
    1186                 :            :             }
    1187                 :            :         }
    1188                 :            :     }
    1189                 :      10160 :     return errors;
    1190                 :            : }
    1191                 :            : 
    1192                 :            : /* The function checks whether the given key-value combination being
    1193                 :            :    part of the available definition is inside the allowed range and
    1194                 :            :    returns zero if not.  Otherwise the function returns non-zero. */
    1195                 :      10160 : static int checker_value_in_range (char * instance, struct define_t * def,
    1196                 :            :                                    struct pair_t * pp)
    1197                 :            : {
    1198                 :      10160 :     int i, errors = 0;
    1199                 :            :     // go through required properties
    1200         [ +  + ]:     724777 :     for (i = 0; PROP_IS_PROP (def->required[i]); i++)
    1201                 :            :     {
    1202         [ +  + ]:     714617 :         if (!strcmp (def->required[i].key, pp->key))
    1203                 :            :         {
    1204                 :            :             errors += checker_value_in_prop_range (instance, def, pp,
    1205                 :       5385 :                                                    &def->required[i]);
    1206                 :            :         }
    1207                 :            :     }
    1208                 :            :     // go through optional properties
    1209         [ +  + ]:     122737 :     for (i = 0; PROP_IS_PROP (def->optional[i]); i++)
    1210                 :            :     {
    1211         [ +  + ]:     112577 :         if (!strcmp (def->optional[i].key, pp->key))
    1212                 :            :         {
    1213                 :            :             errors += checker_value_in_prop_range (instance, def, pp,
    1214                 :       4775 :                                                    &def->optional[i]);
    1215                 :            :         }
    1216                 :            :     }
    1217                 :      10160 :     return errors ? 0 : 1;
    1218                 :            : }
    1219                 :            : 
    1220                 :            : /* The function determines the subcircuit definitions defined in the
    1221                 :            :    original netlist and builds an appropriate subcircuit definition
    1222                 :            :    list.  It returns the given definition list with the subcircuits
    1223                 :            :    removed. */
    1224                 :            : static struct definition_t *
    1225                 :        116 : checker_build_subcircuits (struct definition_t * root)
    1226                 :            : {
    1227                 :            :     struct definition_t * def, * next, * prev;
    1228         [ +  + ]:       1282 :     for (prev = NULL, def = root; def != NULL; def = next)
    1229                 :            :     {
    1230                 :       1166 :         next = def->next;
    1231         [ +  + ]:       1166 :         if (!strcmp (def->type, "Def"))
    1232                 :            :         {
    1233         [ -  + ]:         13 :             if (prev)
    1234                 :            :             {
    1235                 :          0 :                 prev->next = next;
    1236                 :            :             }
    1237                 :            :             else
    1238                 :            :             {
    1239                 :         13 :                 root = next;
    1240                 :            :             }
    1241                 :         13 :             def->sub = checker_build_subcircuits (def->sub);
    1242                 :         13 :             def->next = subcircuit_root;
    1243                 :         13 :             subcircuit_root = def;
    1244                 :            :         }
    1245                 :       1153 :         else prev = def;
    1246                 :            :     }
    1247                 :        116 :     return root;
    1248                 :            : }
    1249                 :            : 
    1250                 :            : /* The function produces a copy of the given circuit definition and
    1251                 :            :    marks it as a copy.  The node definition are not included within
    1252                 :            :    the copy. */
    1253                 :            : static struct definition_t *
    1254                 :        135 : checker_copy_subcircuit (struct definition_t * sub)
    1255                 :            : {
    1256                 :            :     struct definition_t * copy;
    1257                 :        135 :     copy = (struct definition_t *) calloc (sizeof (struct definition_t), 1);
    1258                 :        135 :     copy->action = sub->action;
    1259                 :        135 :     copy->nonlinear = sub->nonlinear;
    1260                 :        135 :     copy->substrate = sub->substrate;
    1261                 :        135 :     copy->nodeset = sub->nodeset;
    1262                 :        135 :     copy->define = sub->define;
    1263                 :        135 :     copy->pairs = sub->pairs;
    1264                 :        135 :     copy->ncount = sub->ncount;
    1265                 :        135 :     copy->type = strdup (sub->type);
    1266                 :        135 :     copy->copy = 1;
    1267                 :        135 :     return copy;
    1268                 :            : }
    1269                 :            : 
    1270                 :            : /* This function translates the node definitions of the given
    1271                 :            :    subcircuit element 'sub'.  The translation is based upon the node
    1272                 :            :    definitions of the subcircuit 'type' and the instance 'inst' of
    1273                 :            :    such a subcircuit.  The translated nodes are saved in an extra
    1274                 :            :    'xlate' field of each node of the subcircuit element 'sub'. */
    1275                 :        143 : static void checker_xlat_subcircuit_nodes (struct definition_t * type,
    1276                 :            :         struct definition_t * inst,
    1277                 :            :         struct definition_t * sub)
    1278                 :            : {
    1279                 :            :     struct node_t * n, * ninst, * ntype;
    1280                 :            :     int i;
    1281                 :            :     // go through nodes of the subcircuit 'type' and 'inst'
    1282         [ +  + ]:        691 :     for (i = 1, ntype = type->nodes, ninst = inst->nodes; ntype != NULL;
    1283                 :            :             ntype = ntype->next, ninst = ninst->next, i++)
    1284                 :            :     {
    1285         [ +  + ]:       1906 :         for (n = sub->nodes; n != NULL; n = n->next)
    1286                 :            :         {
    1287                 :            :             /* check whether a node in the subcircuit element 'sub' corresponds
    1288                 :            :             with the 'type', then assign the 'inst's node name */
    1289         [ +  + ]:       1358 :             if (!strcmp (n->node, ntype->node))
    1290                 :            :             {
    1291                 :        149 :                 n->xlate = strdup (ninst->node);
    1292                 :        149 :                 n->xlatenr = i;
    1293                 :            :             }
    1294                 :            :         }
    1295                 :            :     }
    1296                 :        143 : }
    1297                 :            : 
    1298                 :            : /* The function creates a subcircuit node name consisting of the given
    1299                 :            :    arguments.  If the given 'instances' is NULL it is left out.  The
    1300                 :            :    caller is responsible to free() the returned string. */
    1301                 :        219 : static char * checker_subcircuit_node (char * type, char * instances,
    1302                 :            :                                        char * instance, char * node)
    1303                 :            : {
    1304                 :            :     char * txt = (char *)
    1305                 :        438 :                  calloc (1, strlen (type) + strlen (instance) + strlen (node) +
    1306         [ +  + ]:        219 :                          (instances ? strlen (instances) : 0) + 4);
    1307         [ +  + ]:        219 :     if (instances)
    1308                 :        128 :         sprintf (txt, "%s.%s.%s.%s", type, instances, instance, node);
    1309                 :            :     else
    1310                 :         91 :         sprintf (txt, "%s.%s.%s", type, instance, node);
    1311                 :        219 :     return txt;
    1312                 :            : }
    1313                 :            : 
    1314                 :            : /* The function reverses the order of the given node list and returns
    1315                 :            :    the reversed list. */
    1316                 :        135 : struct node_t * netlist_reverse_nodes (struct node_t * nodes)
    1317                 :            : {
    1318                 :            :     struct node_t * root, * next;
    1319         [ +  + ]:        455 :     for (root = NULL; nodes != NULL; nodes = next)
    1320                 :            :     {
    1321                 :        320 :         next = nodes->next;
    1322                 :        320 :         nodes->next = root;
    1323                 :        320 :         root = nodes;
    1324                 :            :     }
    1325                 :        135 :     return root;
    1326                 :            : }
    1327                 :            : 
    1328                 :            : /* This function assigns new node names to the subcircuit element
    1329                 :            :    'copy' based upon the previous node translation between the
    1330                 :            :    subcircuit 'type' and the instance 'inst' of this type.  The global
    1331                 :            :    'gnd' node is not touched. */
    1332                 :            : static void
    1333                 :        135 : checker_copy_subcircuit_nodes (struct definition_t * type,
    1334                 :            :                                struct definition_t * inst,
    1335                 :            :                                struct definition_t * sub,
    1336                 :            :                                struct definition_t * copy,
    1337                 :            :                                char * instances)
    1338                 :            : {
    1339                 :        135 :     struct node_t * n, * ncopy, * root = NULL;
    1340                 :            : 
    1341                 :            :     // go through the list of the subcircuit element's 'sub' nodes
    1342         [ +  + ]:        455 :     for (n = sub->nodes; n != NULL; n = n->next)
    1343                 :            :     {
    1344                 :            : 
    1345                 :            :         // create new node based upon the node translation
    1346                 :        320 :         ncopy = (struct node_t *) calloc (sizeof (struct node_t), 1);
    1347                 :        320 :         ncopy->xlatenr = n->xlatenr;
    1348         [ +  + ]:        320 :         if (n->xlate)   // translated node
    1349                 :            :         {
    1350         [ +  + ]:        125 :             if (instances == NULL)
    1351                 :         45 :                 ncopy->node = strdup (n->xlate);
    1352                 :            :             else
    1353                 :         80 :                 ncopy->node = NULL; // leave it blank yet, indicates translation
    1354                 :            :         }
    1355         [ +  + ]:        195 :         else if (!strcmp (n->node, "gnd"))   // ground node
    1356                 :            :         {
    1357                 :          8 :             ncopy->node = strdup (n->node);
    1358                 :            :         }
    1359         [ -  + ]:        187 :         else if (n->node[strlen (n->node) - 1] == '!')   // global node
    1360                 :            :         {
    1361                 :          0 :             ncopy->node = strdup (n->node);
    1362                 :            :         }
    1363                 :            :         else   // internal subcircuit element node
    1364                 :            :         {
    1365                 :            :             ncopy->node = checker_subcircuit_node (type->instance, instances,
    1366                 :        187 :                                                    inst->instance, n->node);
    1367                 :            :         }
    1368                 :            :         // chain the new node list
    1369                 :        320 :         ncopy->next = root;
    1370                 :        320 :         root = ncopy;
    1371                 :            :     }
    1372                 :            : 
    1373                 :            :     /* and finally reverse the created node list and assign it to the
    1374                 :            :        subcircuit element's 'copy' */
    1375                 :        135 :     copy->nodes = netlist_reverse_nodes (root);
    1376                 :        135 : }
    1377                 :            : 
    1378                 :            : // Returns the node at the given position.
    1379                 :         80 : static struct node_t * checker_get_circuit_node (struct node_t * root, int n)
    1380                 :            : {
    1381         [ +  + ]:        224 :     for (int i = 1; i < n; i++)
    1382                 :            :     {
    1383                 :        144 :         root = root->next;
    1384         [ -  + ]:        144 :         assert (root != NULL);
    1385                 :            :     }
    1386                 :         80 :     return root;
    1387                 :            : }
    1388                 :            : 
    1389                 :            : // The function cleans the translated nodes of a subcircuit template.
    1390                 :        143 : static void checker_cleanup_xlat_nodes (struct definition_t * sub)
    1391                 :            : {
    1392         [ +  + ]:        495 :     for (struct node_t * n = sub->nodes; n != NULL; n = n->next)
    1393                 :            :     {
    1394         [ +  + ]:        352 :         if (n->xlate) free (n->xlate);
    1395                 :        352 :         n->xlate = NULL;
    1396                 :        352 :         n->xlatenr = 0;
    1397                 :            :     }
    1398                 :        143 : }
    1399                 :            : 
    1400                 :            : /* The function is used to assign the nodes of the 'copy' subcircuit
    1401                 :            :    element which were left blank intentionally by the element copy in
    1402                 :            :    order to indicate that it is an external node.  Again, if the
    1403                 :            :    current node translation indicates an external node it is blanked
    1404                 :            :    again, otherwise the node gets a unique internal name.  If the
    1405                 :            :    'instances' list is NULL, then this indicates the root circuit list
    1406                 :            :    and node translations are done though they are 'external'. */
    1407                 :            : static void
    1408                 :         96 : checker_copy_circuit_nodes (struct definition_t * type,
    1409                 :            :                             struct definition_t * inst,
    1410                 :            :                             struct definition_t * sub,
    1411                 :            :                             struct definition_t * copy,
    1412                 :            :                             char * instances)
    1413                 :            : {
    1414                 :            :     struct node_t * n, * ncopy;
    1415                 :            : 
    1416                 :            :     // go through the list of the subcircuit element's 'copy' nodes
    1417         [ +  + ]:        304 :     for (ncopy = copy->nodes; ncopy != NULL; ncopy = ncopy->next)
    1418                 :            :     {
    1419                 :            :         // these NULL nodes have intentionally been blanked
    1420         [ +  + ]:        208 :         if (ncopy->node == NULL)
    1421                 :            :         {
    1422         [ -  + ]:         80 :             assert (ncopy->xlatenr != 0);
    1423                 :            :             // get translated node
    1424                 :         80 :             n = checker_get_circuit_node (sub->nodes, ncopy->xlatenr);
    1425                 :         80 :             ncopy->xlatenr = n->xlatenr;
    1426         [ +  + ]:         80 :             if (n->xlate)   // translated node
    1427                 :            :             {
    1428         [ +  - ]:         48 :                 if (instances == NULL)
    1429                 :            :                     // external node indicated by no instances given
    1430                 :         48 :                     ncopy->node = strdup (n->xlate);
    1431                 :            :                 else
    1432                 :          0 :                     ncopy->node = NULL; // keep blank
    1433                 :            :             }
    1434         [ -  + ]:         32 :             else if (!strcmp (n->node, "gnd"))   // global ground node
    1435                 :            :             {
    1436                 :          0 :                 ncopy->node = strdup (n->node);
    1437                 :            :             }
    1438         [ -  + ]:         32 :             else if (n->node[strlen (n->node) - 1] == '!')   // other global node
    1439                 :            :             {
    1440                 :          0 :                 ncopy->node = strdup (n->node);
    1441                 :            :             }
    1442                 :            :             else   // internal subcircuit element node
    1443                 :            :             {
    1444                 :            :                 ncopy->node = checker_subcircuit_node (type->instance, instances,
    1445                 :         32 :                                                        inst->instance, n->node);
    1446                 :            :             }
    1447                 :            :         }
    1448                 :            :     }
    1449                 :         96 : }
    1450                 :            : 
    1451                 :            : /* This function returns the last entry of the given list of
    1452                 :            :    definitions or NULL if there is no such element. */
    1453                 :            : static struct definition_t *
    1454                 :         23 : checker_find_last_definition (struct definition_t * root)
    1455                 :            : {
    1456         [ +  - ]:        231 :     for (struct definition_t * def = root; def != NULL; def = def->next)
    1457         [ +  + ]:        231 :         if (def->next == NULL) return def;
    1458                 :         23 :     return NULL;
    1459                 :            : }
    1460                 :            : 
    1461                 :            : /* Based upon the the given subcircuit instance identifier list the
    1462                 :            :    function returns a "." - concatenated string or NULL. */
    1463                 :        143 : static char * checker_subcircuit_instance_list (strlist * instances)
    1464                 :            : {
    1465 [ +  + ][ +  + ]:        143 :     if (instances && instances->length () > 0)
                 [ +  + ]
    1466                 :         96 :         return instances->toString (".");
    1467                 :        143 :     return NULL;
    1468                 :            : }
    1469                 :            : 
    1470                 :            : /* The function creates a subcircuit instance name consisting of the
    1471                 :            :    given arguments.  If the given 'instances' is NULL it is left out.
    1472                 :            :    The caller is responsible to free() the returned string. */
    1473                 :        135 : static char * checker_subcircuit_instance (char * type, char * instances,
    1474                 :            :         char * instance, char * base)
    1475                 :            : {
    1476                 :            :     char * txt = (char *)
    1477                 :        270 :                  calloc (1, strlen (type) + strlen (instance) + strlen (base) +
    1478         [ +  + ]:        135 :                          (instances ? strlen (instances) : 0) + 4);
    1479         [ +  + ]:        135 :     if (instances)
    1480                 :         96 :         sprintf (txt, "%s.%s.%s.%s", type, instances, instance, base);
    1481                 :            :     else
    1482                 :         39 :         sprintf (txt, "%s.%s.%s", type, instance, base);
    1483                 :        135 :     return txt;
    1484                 :            : }
    1485                 :            : 
    1486                 :            : /* This function produces a copy of the given subcircuit 'type'
    1487                 :            :    containing the subcircuit elements.  Based upon the instance 'inst'
    1488                 :            :    definitions (node names and instance name) it assign new element
    1489                 :            :    instances and node names.  The function returns a NULL terminated
    1490                 :            :    circuit element list in reverse order. */
    1491                 :            : static struct definition_t *
    1492                 :         23 : checker_copy_subcircuits (struct definition_t * type,
    1493                 :            :                           struct definition_t * inst, strlist * * instances,
    1494                 :            :                           environment * parent)
    1495                 :            : {
    1496                 :            :     struct definition_t * def, * copy;
    1497                 :         23 :     struct definition_t * root = NULL;
    1498                 :            :     strlist * instcopy;
    1499                 :            :     char * list;
    1500                 :            : 
    1501                 :            :     // create environment for subcircuit instance
    1502         [ +  - ]:         23 :     environment * child = new environment (*(type->env));
    1503                 :         23 :     parent->push_front_Child (child);
    1504                 :            : 
    1505                 :            :     // put instance properties into subcircuit environment
    1506         [ +  + ]:         46 :     for (struct pair_t * pair = inst->pairs; pair != NULL; pair = pair->next)
    1507                 :            :     {
    1508                 :            :         // anything else than the 'Type'
    1509         [ -  + ]:         23 :         if (strcmp (pair->key, "Type"))
    1510                 :            :         {
    1511         [ #  # ]:          0 :             if (pair->value->ident == NULL)
    1512                 :            :             {
    1513                 :            :                 // simple value
    1514                 :          0 :                 child->setDoubleConstant (pair->key, pair->value->value);
    1515                 :          0 :                 child->setDouble (pair->key, pair->value->value);
    1516                 :            :             }
    1517                 :            :             else
    1518                 :            :             {
    1519                 :            :                 // reference to variable in upper environment
    1520                 :          0 :                 child->setDoubleReference (pair->key, pair->value->ident);
    1521                 :            :             }
    1522                 :            :         }
    1523                 :            :     }
    1524                 :            : 
    1525                 :            :     // go through element list of subcircuit
    1526         [ +  + ]:        166 :     for (def = type->sub; def != NULL; def = def->next)
    1527                 :            :     {
    1528                 :            : 
    1529                 :            :         // translate the node list
    1530                 :        143 :         checker_xlat_subcircuit_nodes (type, inst, def);
    1531                 :            : 
    1532                 :            :         // allow recursive subcircuits
    1533         [ +  + ]:        143 :         if (!strcmp (def->type, "Sub"))
    1534                 :            :         {
    1535                 :            :             // get subcircuit template definition
    1536                 :          8 :             struct definition_t * sub = checker_get_subcircuit (def);
    1537                 :            :             // create a copy of the current subcircuit instance list
    1538 [ +  - ][ +  - ]:          8 :             if ((*instances) == NULL) (*instances) = new strlist ();
    1539         [ +  - ]:          8 :             instcopy = new strlist (*(*instances));
    1540                 :            :             // append instance name to recursive instance list
    1541                 :          8 :             (*instances)->append (inst->instance);
    1542                 :          8 :             copy = checker_copy_subcircuits (sub, def, instances, child);
    1543                 :            :             // put the expanded definitions into the sublist
    1544         [ +  - ]:          8 :             if (copy)
    1545                 :            :             {
    1546                 :          8 :                 list = checker_subcircuit_instance_list (instcopy);
    1547                 :            :                 // assign blanked node names to each subcircuit
    1548         [ +  + ]:        104 :                 for (struct definition_t * c = copy; c != NULL; c = c->next)
    1549                 :            :                 {
    1550                 :         96 :                     checker_copy_circuit_nodes (type, inst, def, c, list);
    1551                 :            :                 }
    1552                 :            :                 // append the copies to the subcircuit list
    1553                 :          8 :                 struct definition_t * last = checker_find_last_definition (copy);
    1554                 :          8 :                 last->next = root;
    1555                 :          8 :                 root = copy;
    1556                 :            :             }
    1557                 :            :             // restore original instance list
    1558         [ +  - ]:          8 :             delete *instances;
    1559                 :          8 :             *instances = instcopy;
    1560                 :            :         }
    1561                 :            :         else
    1562                 :            :         {
    1563                 :            :             // element copy
    1564                 :        135 :             copy = checker_copy_subcircuit (def);
    1565                 :            :             // assign new instance name to the element
    1566                 :        135 :             list = checker_subcircuit_instance_list (*instances);
    1567                 :            :             copy->instance =
    1568                 :            :                 checker_subcircuit_instance (type->instance, list,
    1569                 :        135 :                                              inst->instance, def->instance);
    1570                 :        135 :             copy->subcircuit = strdup (type->instance);
    1571                 :            :             // assign node list
    1572                 :        135 :             checker_copy_subcircuit_nodes (type, inst, def, copy, list);
    1573                 :            :             // apply environment
    1574                 :        135 :             copy->env = child;
    1575                 :            :             // chain definition (circuit) list
    1576                 :        135 :             copy->next = root;
    1577                 :        135 :             root = copy;
    1578                 :            :         }
    1579                 :            : 
    1580                 :            :         // cleanup translated nodes
    1581                 :        143 :         checker_cleanup_xlat_nodes (def);
    1582                 :            :     }
    1583                 :            : 
    1584                 :            :     // try giving child environment a unique name
    1585         [ +  - ]:         23 :     strlist * icopy = new strlist ();
    1586                 :         23 :     icopy->append (type->instance);
    1587                 :         23 :     icopy->append (*(instances));
    1588                 :         23 :     icopy->append (inst->instance);
    1589 [ +  - ][ +  - ]:         23 :     child->setName (std::string(icopy->toString (".")));
                 [ +  - ]
    1590         [ +  - ]:         23 :     delete icopy;
    1591                 :            : 
    1592                 :         23 :     return root;
    1593                 :            : }
    1594                 :            : 
    1595                 :            : /* The function checks whether the subcircuit 'instance' with the
    1596                 :            :    subcircuit 'type' is defined in cycles.  It recursively goes
    1597                 :            :    through the definitions and emits an appropriate error message if
    1598                 :            :    necessary.  The function returns zero if there are no cycles
    1599                 :            :    detected and non-zero with cycles found. */
    1600                 :         27 : static int checker_validate_sub_cycles (struct definition_t * root,
    1601                 :            :                                         char * type, char * instance,
    1602                 :            :                                         strlist * * deps)
    1603                 :            : {
    1604                 :         27 :     int errors = 0, error;
    1605                 :            :     struct value_t * val;
    1606                 :            : 
    1607                 :            :     /* emit an appropriate error message if the subcircuit type is already
    1608                 :            :        in the dependencies */
    1609         [ -  + ]:         27 :     if ((*deps)->contains (type))
    1610                 :            :     {
    1611                 :            :         logprint (LOG_ERROR, "checker error, cyclic definition of `%s:%s' "
    1612                 :            :                   "detected, involves: %s\n",
    1613                 :          0 :                   type, instance, (*deps)->toString ());
    1614                 :          0 :         return ++errors;
    1615                 :            :     }
    1616                 :         27 :     (*deps)->append (type);
    1617                 :            : 
    1618                 :            :     // create temporary list of subcircuit types already tested
    1619         [ +  - ]:         27 :     strlist * checked = new strlist ();
    1620                 :            :     // go through the list of circuit elements of the subcircuit
    1621         [ +  + ]:        218 :     for (struct definition_t * def = root->sub; def != NULL; def = def->next)
    1622                 :            :     {
    1623                 :            :         // find the appropriate definitions
    1624         [ +  + ]:        191 :         if (!strcmp (def->type, "Sub"))
    1625                 :            :         {
    1626                 :            :             // recurse into subcircuit instances
    1627         [ +  - ]:          8 :             if ((val = checker_find_reference (def, "Type")) != NULL)
    1628                 :            :             {
    1629         [ +  - ]:          8 :                 if (!checked->contains (val->ident))   // only if not already checked
    1630                 :            :                 {
    1631                 :            :                     struct definition_t * sub;
    1632                 :          8 :                     checked->append (val->ident);
    1633                 :            :                     // copy current dependencies
    1634         [ +  - ]:          8 :                     strlist * copy = new strlist (*(*deps));
    1635                 :            :                     // validate subcircuit
    1636                 :          8 :                     sub = checker_find_subcircuit (val->ident);
    1637         [ +  - ]:          8 :                     if (sub != NULL) // if possible
    1638                 :            :                         error = checker_validate_sub_cycles (sub, sub->instance,
    1639                 :          8 :                                                              instance, deps);
    1640                 :            :                     else
    1641                 :          0 :                         error = 1;
    1642                 :            :                     // on errors: go on
    1643         [ -  + ]:          8 :                     if (error)
    1644                 :            :                     {
    1645                 :          0 :                         errors += error;
    1646         [ #  # ]:          0 :                         delete copy;
    1647                 :            :                     }
    1648                 :            :                     // no errors: restore original dependencies
    1649                 :            :                     else
    1650                 :            :                     {
    1651         [ +  - ]:          8 :                         delete *deps;
    1652                 :          8 :                         *deps = copy;
    1653                 :            :                     }
    1654                 :            :                 }
    1655                 :            :             }
    1656                 :            :         }
    1657                 :            :     }
    1658         [ +  - ]:         27 :     delete checked;
    1659                 :         27 :     return errors;
    1660                 :            : }
    1661                 :            : 
    1662                 :            : /* This function dynamically creates a circuit definition based on a
    1663                 :            :    given subcircuit definition including type, number of nodes and the
    1664                 :            :    properties. */
    1665                 :         19 : static struct define_t * netlist_create_define (struct definition_t * def)
    1666                 :            : {
    1667                 :            :     int o, r;
    1668                 :            :     struct pair_t * p;
    1669                 :            :     struct define_t * d =
    1670                 :         19 :         (struct define_t *) calloc (sizeof (struct define_t), 1);
    1671                 :         19 :     d->type = strdup (def->instance);
    1672                 :         19 :     d->nodes = checker_count_nodes (def);
    1673                 :         19 :     d->action = PROP_COMPONENT;
    1674                 :            : 
    1675                 :            :     // determine number of required and optional parameters
    1676         [ -  + ]:         19 :     for (o = r = 0, p = def->pairs; p != NULL; p = p->next)
    1677                 :            :     {
    1678         [ #  # ]:          0 :         if (p->value == NULL)
    1679                 :          0 :             r++;
    1680                 :            :         else
    1681                 :          0 :             o++;
    1682                 :            :     }
    1683                 :            :     d->required =
    1684                 :         19 :         (struct property_t *) calloc (sizeof (struct property_t), r + 2);
    1685                 :            :     d->optional =
    1686                 :         19 :         (struct property_t *) calloc (sizeof (struct property_t), o + 1);
    1687                 :            : 
    1688                 :            :     // fill in parameters
    1689         [ -  + ]:         19 :     for (o = r = 0, p = def->pairs; p != NULL; p = p->next)
    1690                 :            :     {
    1691         [ #  # ]:          0 :         if (p->value == NULL)
    1692                 :            :         {
    1693                 :            :             // required
    1694                 :          0 :             d->required[r].key = strdup (p->key);
    1695                 :          0 :             d->required[r].type = PROP_REAL;
    1696                 :          0 :             d->required[r].defaultval.d = PROP_NO_VAL;
    1697                 :          0 :             d->required[r].defaultval.s = PROP_NO_STR;
    1698                 :          0 :             d->required[r].range.il = '.';
    1699                 :          0 :             d->required[r].range.l = 0;
    1700                 :          0 :             d->required[r].range.h = 0;
    1701                 :          0 :             d->required[r].range.ih = '.';
    1702                 :          0 :             r++;
    1703                 :            :         }
    1704                 :            :         else
    1705                 :            :         {
    1706                 :            :             // optional
    1707                 :          0 :             d->optional[o].key = strdup (p->key);
    1708                 :          0 :             d->optional[o].type = PROP_REAL;
    1709                 :          0 :             d->optional[o].defaultval.d = p->value->value;
    1710                 :          0 :             d->optional[o].defaultval.s = PROP_NO_STR;
    1711                 :          0 :             d->optional[o].range.il = '.';
    1712                 :          0 :             d->optional[o].range.l = 0;
    1713                 :          0 :             d->optional[o].range.h = 0;
    1714                 :          0 :             d->optional[o].range.ih = '.';
    1715                 :          0 :             o++;
    1716                 :            :         }
    1717                 :            :     }
    1718                 :            : 
    1719                 :            :     // extra required
    1720                 :         19 :     d->required[r].key = strdup ("Type");
    1721                 :         19 :     d->required[r].type = PROP_STR;
    1722                 :         19 :     d->required[r].defaultval.d = PROP_NO_VAL;
    1723                 :         19 :     d->required[r].defaultval.s = PROP_NO_STR;
    1724                 :         19 :     d->required[r].range.il = '.';
    1725                 :         19 :     d->required[r].range.l = 0;
    1726                 :         19 :     d->required[r].range.h = 0;
    1727                 :         19 :     d->required[r].range.ih = '.';
    1728                 :         19 :     return d;
    1729                 :            : }
    1730                 :            : 
    1731                 :            : /* The function destroys the given circuit definition which must have
    1732                 :            :    been dynamically created before. */
    1733                 :         19 : static void netlist_free_define (struct define_t * d)
    1734                 :            : {
    1735                 :            :     int i;
    1736                 :            :     struct property_t * p;
    1737                 :         19 :     free ((char *) d->type);
    1738                 :            :     // free required properties
    1739         [ +  + ]:         38 :     for (i = 0, p = d->required; p[i].key != NULL; i++)
    1740                 :            :     {
    1741                 :         19 :         free ((char *) p[i].key);
    1742                 :            :     }
    1743                 :         19 :     free (d->required);
    1744                 :            :     // free optional properties
    1745         [ -  + ]:         19 :     for (i = 0, p = d->optional; p[i].key != NULL; i++)
    1746                 :            :     {
    1747                 :          0 :         free ((char *) p[i].key);
    1748                 :            :     }
    1749                 :         19 :     free (d->optional);
    1750                 :         19 :     free (d);
    1751                 :         19 : }
    1752                 :            : 
    1753                 :            : /* The function checks the presence of required and optional
    1754                 :            :    properties as well as their content in the given definition.  It
    1755                 :            :    returns zero on success and non-zero otherwise. */
    1756                 :       1098 : static int checker_validate_properties (struct definition_t * root,
    1757                 :            :                                         struct definition_t * def,
    1758                 :            :                                         struct define_t * available)
    1759                 :            : {
    1760                 :            :     struct pair_t * pair;
    1761                 :       1098 :     int i, n, errors = 0;
    1762                 :            : 
    1763                 :            :     /* check whether the required properties are given */
    1764         [ +  + ]:       6483 :     for (i = 0; PROP_IS_PROP (available->required[i]); i++)
    1765                 :            :     {
    1766                 :       5385 :         n = checker_find_property (available->required[i].key, def->pairs);
    1767         [ -  + ]:       5385 :         if (n != 1)
    1768                 :            :         {
    1769                 :            :             logprint (LOG_ERROR, "line %d: checker error, required property "
    1770                 :            :                       "`%s' occurred %dx in `%s:%s'\n", def->line,
    1771                 :          0 :                       available->required[i].key, n, def->type, def->instance);
    1772                 :          0 :             errors++;
    1773                 :            :         }
    1774                 :            :     }
    1775                 :            :     /* check whether the optional properties are given zero/once */
    1776         [ +  + ]:       6297 :     for (i = 0; PROP_IS_PROP (available->optional[i]); i++)
    1777                 :            :     {
    1778                 :       5199 :         n = checker_find_property (available->optional[i].key, def->pairs);
    1779         [ -  + ]:       5199 :         if (n >= 2)
    1780                 :            :         {
    1781                 :            :             logprint (LOG_ERROR, "line %d: checker error, optional property "
    1782                 :            :                       "`%s' occurred %dx in `%s:%s'\n", def->line,
    1783                 :          0 :                       available->optional[i].key, n, def->type, def->instance);
    1784                 :          0 :             errors++;
    1785                 :            :         }
    1786                 :            :     }
    1787                 :            : 
    1788                 :            :     /* check the property content */
    1789         [ +  + ]:      11258 :     for (pair = def->pairs; pair != NULL; pair = pair->next)
    1790                 :            :     {
    1791                 :            :         /* check whether properties are either required or optional */
    1792                 :      10160 :         int type = checker_is_property (available, pair->key);
    1793         [ -  + ]:      10160 :         if (type == PROP_NONE)
    1794                 :            :         {
    1795         [ #  # ]:          0 :             if (strcmp (def->type, "Def"))
    1796                 :            :             {
    1797                 :            :                 logprint (LOG_ERROR,
    1798                 :            :                           "line %d: checker error, extraneous property `%s' is "
    1799                 :            :                           "invalid in `%s:%s'\n", def->line,
    1800                 :          0 :                           pair->key, def->type, def->instance);
    1801                 :          0 :                 errors++;
    1802                 :            :             }
    1803                 :            :         }
    1804                 :            :         // do not check zero-length lists
    1805         [ +  - ]:      10160 :         if (pair->value != NULL)
    1806                 :            :         {
    1807                 :            :             /* check and evaluate the unit scale in a property */
    1808         [ -  + ]:      10160 :             if (!checker_evaluate_scale (pair->value))
    1809                 :          0 :                 errors++;
    1810                 :            :             /* check whether properties are in range */
    1811         [ -  + ]:      10160 :             if (!checker_value_in_range (def->instance, available, pair))
    1812                 :            :             {
    1813                 :          0 :                 errors++;
    1814                 :            :             }
    1815                 :            :             /* check variables in properties */
    1816         [ -  + ]:      10160 :             if (!checker_resolve_variable (root, def, pair, type))
    1817                 :          0 :                 errors++;
    1818                 :            :         }
    1819                 :            :     }
    1820                 :       1098 :     return errors;
    1821                 :            : }
    1822                 :            : 
    1823                 :            : /* This function is used by the netlist checker to validate the
    1824                 :            :    subcircuits.  It returns zero with no errors and non-zero on
    1825                 :            :    errors. */
    1826                 :        219 : static int checker_validate_subcircuits (struct definition_t * root)
    1827                 :            : {
    1828                 :        219 :     int errors = 0;
    1829                 :            :     // go through list of definitions
    1830         [ +  + ]:       1317 :     for (struct definition_t * def = root; def != NULL; def = def->next)
    1831                 :            :     {
    1832                 :            :         // check subcircuit instances
    1833         [ +  + ]:       1098 :         if (!strcmp (def->type, "Sub"))
    1834                 :            :         {
    1835                 :            :             struct value_t * val;
    1836                 :            :             // validate the 'Type' reference
    1837         [ -  + ]:         19 :             if ((val = checker_validate_reference (def, "Type")) == NULL)
    1838                 :            :             {
    1839                 :          0 :                 errors++;
    1840                 :            :             }
    1841                 :            :             else
    1842                 :            :             {
    1843                 :            :                 // find an appropriate subcircuit type
    1844                 :         19 :                 struct definition_t * sub = checker_find_subcircuit (val->ident);
    1845         [ -  + ]:         19 :                 if (sub == NULL)
    1846                 :            :                 {
    1847                 :            :                     logprint (LOG_ERROR, "line %d: checker error, no such subcircuit "
    1848                 :            :                               "`%s' found as referred in `%s:%s'\n", def->line,
    1849                 :          0 :                               val->ident, def->type, def->instance);
    1850                 :          0 :                     errors++;
    1851                 :            :                 }
    1852                 :            :                 else
    1853                 :            :                 {
    1854                 :            :                     // check the number of nodes of the instance and the type
    1855                 :         19 :                     int n1 = checker_count_nodes (def);
    1856                 :         19 :                     int n2 = checker_count_nodes (sub);
    1857         [ -  + ]:         19 :                     if (n1 != n2)
    1858                 :            :                     {
    1859                 :            :                         logprint (LOG_ERROR, "line %d: checker error, subcircuit type "
    1860                 :            :                                   "`%s' requires %d nodes in `%s:%s', found %d\n",
    1861                 :            :                                   def->line, sub->instance, n2,
    1862         [ #  # ]:          0 :                                   def->type, def->instance, n1);
    1863                 :          0 :                         errors++;
    1864                 :            :                     }
    1865                 :            :                     // check the subcircuit instance properties
    1866         [ +  - ]:         19 :                     struct define_t * available = netlist_create_define (sub);
    1867         [ +  - ]:         19 :                     errors += checker_validate_properties (root, def, available);
    1868                 :         19 :                     netlist_free_define (available);
    1869                 :            :                     // and finally check for cyclic definitions
    1870 [ +  - ][ +  - ]:         19 :                     strlist * deps = new strlist ();
    1871                 :            :                     int err = checker_validate_sub_cycles (sub, sub->instance,
    1872         [ +  - ]:         19 :                                                            def->instance, &deps);
    1873                 :         19 :                     errors += err;
    1874                 :         19 :                     checker_sub_cycles = err;
    1875 [ +  - ][ +  - ]:         19 :                     delete deps;
    1876                 :            :                 }
    1877                 :            :             }
    1878                 :            :         }
    1879                 :            :     }
    1880                 :        219 :     return errors;
    1881                 :            : }
    1882                 :            : 
    1883                 :            : /* Deletes node list of a definition. */
    1884                 :       1301 : static void netlist_free_nodes (struct node_t * node)
    1885                 :            : {
    1886                 :            :     struct node_t * n;
    1887         [ +  + ]:       3736 :     for (; node != NULL; node = n)
    1888                 :            :     {
    1889                 :       2435 :         n = node->next;
    1890                 :       2435 :         free (node->node);
    1891                 :       2435 :         free (node);
    1892                 :            :     }
    1893                 :       1301 : }
    1894                 :            : 
    1895                 :            : /* The following function free()'s the given value. */
    1896                 :      10172 : static void netlist_free_value (struct value_t * value)
    1897                 :            : {
    1898         [ +  + ]:      10172 :     if (value->ident) free (value->ident);
    1899         [ +  + ]:      10172 :     if (value->unit)  free (value->unit);
    1900         [ -  + ]:      10172 :     if (value->scale) free (value->scale);
    1901                 :      10172 :     free (value);
    1902                 :      10172 : }
    1903                 :            : 
    1904                 :            : /* Deletes pair list of a definition. */
    1905                 :       1166 : static void netlist_free_pairs (struct pair_t * pp)
    1906                 :            : {
    1907                 :            :     struct pair_t * np;
    1908         [ +  + ]:      11326 :     for (; pp != NULL; pp = np)
    1909                 :            :     {
    1910                 :      10160 :         np = pp->next;
    1911                 :            :         struct value_t * nv, * value;
    1912         [ +  + ]:      20332 :         for (value = pp->value; value != NULL; value = nv)
    1913                 :            :         {
    1914                 :      10172 :             nv = value->next;
    1915                 :      10172 :             netlist_free_value (value);
    1916                 :            :         }
    1917                 :      10160 :         free (pp->key);
    1918                 :      10160 :         free (pp);
    1919                 :            :     }
    1920                 :       1166 : }
    1921                 :            : 
    1922                 :            : /* Deletes the given definition. */
    1923                 :       1301 : static void netlist_free_definition (struct definition_t * def)
    1924                 :            : {
    1925                 :       1301 :     netlist_free_nodes (def->nodes);
    1926         [ +  + ]:       1301 :     if (!def->copy) netlist_free_pairs (def->pairs);
    1927         [ +  + ]:       1301 :     if (def->subcircuit) free (def->subcircuit);
    1928                 :       1301 :     free (def->type);
    1929                 :       1301 :     free (def->instance);
    1930                 :       1301 :     free (def);
    1931                 :       1301 : }
    1932                 :            : 
    1933                 :            : /* The function removes the given definition 'cand' from the
    1934                 :            :    definition root.  It returns the new definition root. */
    1935                 :            : struct definition_t *
    1936                 :       1119 : netlist_unchain_definition (struct definition_t * root,
    1937                 :            :                             struct definition_t * cand)
    1938                 :            : {
    1939                 :            :     struct definition_t * prev;
    1940         [ +  + ]:       1119 :     if (cand == root)
    1941                 :            :     {
    1942                 :        937 :         root = cand->next;
    1943                 :        937 :         netlist_free_definition (cand);
    1944                 :            :     }
    1945                 :            :     else
    1946                 :            :     {
    1947                 :            :         // find previous to the candidate to be deleted
    1948 [ +  - ][ +  + ]:       1512 :         for (prev = root; prev != NULL && prev->next != cand; prev = prev->next) ;
                 [ +  + ]
    1949         [ +  - ]:        182 :         if (prev != NULL)
    1950                 :            :         {
    1951                 :        182 :             prev->next = cand->next;
    1952                 :        182 :             netlist_free_definition (cand);
    1953                 :            :         }
    1954                 :            :     }
    1955                 :       1119 :     return root;
    1956                 :            : }
    1957                 :            : 
    1958                 :            : /* The function expands the subcircuits within the given definition
    1959                 :            :    list and returns the expanded list with the subcircuit definitions
    1960                 :            :    removed. */
    1961                 :            : static struct definition_t *
    1962                 :        103 : checker_expand_subcircuits (struct definition_t * root, environment * parent)
    1963                 :            : {
    1964                 :            :     struct definition_t * def, * sub, * copy, * next, * prev;
    1965                 :        103 :     strlist * instances = NULL;
    1966                 :            : 
    1967                 :            :     // go through the list of definitions
    1968         [ +  + ]:       1102 :     for (prev = NULL, def = root; def != NULL; def = next)
    1969                 :            :     {
    1970                 :        999 :         next = def->next;
    1971                 :            :         // is this a subcircuit instance definition ?
    1972         [ +  + ]:        999 :         if (!strcmp (def->type, "Sub"))
    1973                 :            :         {
    1974                 :            :             // get the subcircuit type definition
    1975                 :         15 :             sub = checker_get_subcircuit (def);
    1976                 :            :             // and make a copy of it
    1977         [ +  - ]:         15 :             copy = checker_copy_subcircuits (sub, def, &instances, parent);
    1978         [ +  + ]:         15 :             if (instances)
    1979                 :            :             {
    1980 [ +  - ][ +  - ]:          8 :                 delete instances;
    1981                 :          8 :                 instances = NULL;
    1982                 :            :             }
    1983                 :            :             // remove the subcircuit instance from the original list
    1984         [ +  + ]:         15 :             if (prev)
    1985                 :            :             {
    1986                 :         12 :                 prev->next = next;
    1987                 :            :             }
    1988                 :            :             else
    1989                 :            :             {
    1990                 :          3 :                 root = next;
    1991                 :            :             }
    1992                 :         15 :             netlist_free_definition (def);
    1993                 :            :             // put the expanded definitions into the netlist
    1994         [ +  - ]:         15 :             if (copy)
    1995                 :            :             {
    1996                 :         15 :                 struct definition_t * last = checker_find_last_definition (copy);
    1997                 :         15 :                 last->next = root;
    1998         [ +  + ]:         15 :                 if (!prev) prev = last;
    1999                 :         15 :                 root = copy;
    2000                 :            :             }
    2001                 :            :         }
    2002                 :            :         // component in the root environment
    2003                 :            :         else
    2004                 :            :         {
    2005                 :        984 :             prev = def;
    2006                 :        984 :             def->env = parent;
    2007                 :            :         }
    2008                 :            :     }
    2009                 :        103 :     return root;
    2010                 :            : }
    2011                 :            : 
    2012                 :            : /* This function is the checker routine for a parsed netlist.  It
    2013                 :            :    returns zero on success or non-zero if the parsed netlist contained
    2014                 :            :    errors. */
    2015                 :        219 : static int netlist_checker_intern (struct definition_t * root)
    2016                 :            : {
    2017                 :            :     struct definition_t * def;
    2018                 :            :     struct define_t * available;
    2019                 :        219 :     int n, errors = 0;
    2020                 :            : 
    2021                 :            :     /* go through all definitions */
    2022         [ +  + ]:       1317 :     for (def = root; def != NULL; def = def->next)
    2023                 :            :     {
    2024                 :            : 
    2025                 :            :         /* check whether the definition type is known */
    2026                 :       1098 :         available = checker_find_definition (def->type, def->action);
    2027         [ -  + ]:       1098 :         if (available == NULL)
    2028                 :            :         {
    2029                 :            :             logprint (LOG_ERROR, "line %d: checker error, invalid definition type "
    2030                 :          0 :                       "`%s'\n", def->line, def->type);
    2031                 :          0 :             errors++;
    2032                 :            :         }
    2033                 :            :         else
    2034                 :            :         {
    2035                 :            :             /* mark nodeset definitions */
    2036         [ +  + ]:       1098 :             def->nodeset = !strcmp (def->type, "NodeSet") ? 1 : 0;
    2037                 :            :             /* mark nonlinear circuit definitions */
    2038                 :       1098 :             def->nonlinear = available->nonlinear;
    2039                 :            :             /* mark substrate definitions */
    2040                 :       1098 :             def->substrate = available->substrate;
    2041                 :            :             /* save available definition */
    2042                 :       1098 :             def->define = available;
    2043                 :            :             /* check whether the number of nodes is correct and save the
    2044                 :            :                number of given nodes */
    2045                 :       1098 :             n = def->ncount = checker_count_nodes (def);
    2046         [ +  + ]:       1098 :             if (available->nodes == PROP_NODES)
    2047                 :            :             {
    2048         [ -  + ]:         32 :                 if (n < 1)
    2049                 :            :                 {
    2050                 :            :                     logprint (LOG_ERROR,
    2051                 :            :                               "line %d: checker error, at least 1 node required in "
    2052                 :            :                               "`%s:%s', found %d\n", def->line, def->type,
    2053                 :          0 :                               def->instance, n);
    2054                 :          0 :                     errors++;
    2055                 :            :                 }
    2056                 :            :             }
    2057         [ -  + ]:       1066 :             else if (available->nodes != n)
    2058                 :            :             {
    2059                 :            :                 logprint (LOG_ERROR,
    2060                 :            :                           "line %d: checker error, %d node(s) required in `%s:%s', "
    2061                 :            :                           "found %d\n", def->line,
    2062                 :          0 :                           available->nodes, def->type, def->instance, n);
    2063                 :          0 :                 errors++;
    2064                 :            :             }
    2065                 :            :             /* check the properties except for subcircuits */
    2066         [ +  + ]:       1098 :             if (strcmp (def->type, "Sub"))
    2067                 :            :             {
    2068                 :       1079 :                 errors += checker_validate_properties (root, def, available);
    2069                 :            :             }
    2070                 :            :         }
    2071                 :            :         /* check the number of definitions */
    2072                 :       1098 :         n = checker_count_definition (root, def->type, def->instance);
    2073 [ -  + ][ #  # ]:       1098 :         if (n != 1 && def->duplicate == 0)
    2074                 :            :         {
    2075                 :            :             logprint (LOG_ERROR, "checker error, found %d definitions of `%s:%s'\n",
    2076                 :          0 :                       n, def->type, def->instance);
    2077                 :          0 :             errors++;
    2078                 :            :         }
    2079                 :            :     }
    2080                 :            :     /* check microstrip definitions */
    2081                 :        219 :     errors += checker_validate_strips (root);
    2082                 :            :     /* check subcircuit definitions */
    2083                 :        219 :     errors += checker_validate_subcircuits (root);
    2084                 :            :     /* check nodeset definitions */
    2085                 :        219 :     errors += checker_validate_nodesets (root);
    2086                 :        219 :     return errors;
    2087                 :            : }
    2088                 :            : 
    2089                 :            : #if DEBUG
    2090                 :            : /* Debug function: Prints value representation. */
    2091                 :      10974 : static void netlist_list_value (struct value_t * value)
    2092                 :            : {
    2093         [ -  + ]:      10974 :     if (value == NULL)
    2094                 :          0 :         logprint (LOG_STATUS, "[]");
    2095         [ +  + ]:      10974 :     else if (value->ident)
    2096                 :        941 :         logprint (LOG_STATUS, "%s", value->ident);
    2097         [ +  + ]:      10033 :     else if (value->next)
    2098                 :            :     {
    2099                 :          4 :         logprint (LOG_STATUS, "[");
    2100         [ +  + ]:         20 :         for (; value != NULL; value = value->next)
    2101         [ +  + ]:         16 :             logprint (LOG_STATUS, "%g%s", value->value, value->next ? ";" : "");
    2102                 :          4 :         logprint (LOG_STATUS, "]");
    2103                 :            :     }
    2104                 :            :     else
    2105                 :            :     {
    2106                 :      10029 :         logprint (LOG_STATUS, "%g", value->value);
    2107         [ -  + ]:      10029 :         if (value->scale)
    2108                 :          0 :             logprint (LOG_STATUS, "%s", value->scale);
    2109         [ +  + ]:      10029 :         if (value->unit)
    2110                 :       1475 :             logprint (LOG_STATUS, "%s", value->unit);
    2111                 :            :     }
    2112                 :      10974 : }
    2113                 :            : 
    2114                 :            : /* Debug function: Prints definition list representation. */
    2115                 :        116 : static void netlist_lister (struct definition_t * root, const char * prefix)
    2116                 :            : {
    2117                 :            :     struct definition_t * def;
    2118                 :            :     struct node_t * node;
    2119                 :            :     struct pair_t * pair;
    2120         [ +  + ]:       1321 :     for (def = root; def != NULL; def = def->next)
    2121                 :            :     {
    2122                 :       1205 :         logprint (LOG_STATUS, "%s%s:%s", prefix, def->type, def->instance);
    2123         [ +  + ]:       3544 :         for (node = def->nodes; node != NULL; node = node->next)
    2124                 :            :         {
    2125                 :       2339 :             logprint (LOG_STATUS, " %s", node->node);
    2126                 :            :         }
    2127         [ +  + ]:      12179 :         for (pair = def->pairs; pair != NULL; pair = pair->next)
    2128                 :            :         {
    2129                 :      10974 :             logprint (LOG_STATUS, " %s=\"", pair->key);
    2130                 :      10974 :             netlist_list_value (pair->value);
    2131                 :      10974 :             logprint (LOG_STATUS, "\"");
    2132                 :            :         }
    2133                 :       1205 :         logprint (LOG_STATUS, "\n");
    2134                 :            :     }
    2135                 :        116 : }
    2136                 :            : 
    2137                 :            : /* Debug function: Prints the overall netlist representation. */
    2138                 :        103 : void netlist_list (void)
    2139                 :            : {
    2140                 :            :     struct definition_t * def;
    2141                 :        103 :     logprint (LOG_STATUS, "subcircuit %s\n", "root");
    2142                 :        103 :     netlist_lister (definition_root, "  ");
    2143         [ +  + ]:        116 :     for (def = subcircuit_root; def != NULL; def = def->next)
    2144                 :            :     {
    2145                 :         13 :         logprint (LOG_STATUS, "subcircuit %s\n", def->instance);
    2146                 :         13 :         netlist_lister (def->sub, "  ");
    2147                 :            :     }
    2148                 :        103 : }
    2149                 :            : #endif /* DEBUG */
    2150                 :            : 
    2151                 :            : /* The function logs the content of the current netlist by telling how
    2152                 :            :    many instances of which kind of components are used in the netlist. */
    2153                 :        103 : void netlist_status (void)
    2154                 :            : {
    2155                 :            :     struct define_t * def;
    2156                 :            :     struct definition_t * cir;
    2157                 :            :     int count;
    2158         [ +  - ]:        103 :     logprint (LOG_STATUS, "netlist content\n");
    2159                 :        103 :     hashiterator<module> it;
    2160 [ +  - ][ +  - ]:      16274 :     for (it = hashiterator<module> (module::modules); *it; ++it)
                 [ +  + ]
    2161                 :            :     {
    2162                 :      16171 :         def = it.currentVal()->definition;
    2163         [ +  + ]:     191854 :         for (count = 0, cir = definition_root; cir != NULL; cir = cir->next)
    2164                 :            :         {
    2165         [ +  + ]:     175683 :             if (!strcmp (def->type, cir->type)) count++;
    2166                 :            :         }
    2167         [ +  + ]:      16171 :         if (count > 0)
    2168                 :            :         {
    2169         [ +  - ]:        605 :             logprint (LOG_STATUS, "  %5d %s instances\n", count, def->type);
    2170                 :            :         }
    2171                 :        103 :     }
    2172                 :        103 : }
    2173                 :            : 
    2174                 :            : /* The function builds the equation list for a given list of
    2175                 :            :    definition and removes the definition containing the equations from
    2176                 :            :    the list. */
    2177                 :            : static struct definition_t *
    2178                 :        116 : checker_build_equations (struct definition_t * root, eqn::node ** eroot)
    2179                 :            : {
    2180                 :            :     struct definition_t * def, * next, * prev;
    2181                 :            :     eqn::node * eqns, * last;
    2182                 :        116 :     *eroot = NULL;
    2183                 :            :     // go through list of definitions
    2184         [ +  + ]:       1269 :     for (prev = NULL, def = root; def != NULL; def = next)
    2185                 :            :     {
    2186                 :       1153 :         next = def->next;
    2187         [ +  + ]:       1153 :         if (!strcmp (def->type, "Eqn"))
    2188                 :            :         {
    2189                 :            :             // rechain definition list
    2190         [ +  - ]:         68 :             if (prev)
    2191                 :            :             {
    2192                 :         68 :                 prev->next = next;
    2193                 :            :             }
    2194                 :            :             else
    2195                 :            :             {
    2196                 :          0 :                 root = next;
    2197                 :            :             }
    2198                 :            :             // append equations
    2199                 :         68 :             eqns = (eqn::node *) def->eqns;
    2200                 :         68 :             last = eqn::checker::lastEquation (eqns);
    2201                 :         68 :             last->setNext (*eroot);
    2202                 :         68 :             *eroot = eqns;
    2203                 :            :             // free this definition
    2204                 :         68 :             netlist_free_definition (def);
    2205                 :            :         }
    2206                 :       1085 :         else prev = def;
    2207                 :            :     }
    2208                 :        116 :     return root;
    2209                 :            : }
    2210                 :            : 
    2211                 :            : /* The function creates an environment for the given definition root
    2212                 :            :    including equation checker and solver. */
    2213                 :        116 : static void checker_setup_env (struct definition_t * root,
    2214                 :            :                                environment * env, eqn::node * eqns)
    2215                 :            : {
    2216                 :            :     // create equation checker
    2217         [ +  - ]:        116 :     eqn::checker * checkee = new eqn::checker ();
    2218                 :            :     // pass equations to the checker
    2219                 :        116 :     checkee->setEquations (eqns);
    2220                 :            :     // add constants to the list of equations
    2221                 :        116 :     checkee->constants ();
    2222                 :            :     // pass checker
    2223                 :        116 :     env->setChecker (checkee);
    2224                 :            :     // create equation solver
    2225         [ +  - ]:        116 :     eqn::solver * solvee = new eqn::solver (checkee);
    2226                 :            :     // pass solver
    2227                 :        116 :     env->setSolver (solvee);
    2228                 :            :     // apply environment to the netlist root
    2229         [ +  - ]:        116 :     if (root) root->env = env;
    2230                 :        116 : }
    2231                 :            : 
    2232                 :            : /* Adds the arguments of a subcircuit into the equation checker of the
    2233                 :            :    given environment. */
    2234                 :         13 : static void checker_subcircuit_args (struct definition_t * def,
    2235                 :            :                                      environment * env)
    2236                 :            : {
    2237         [ -  + ]:         13 :     for (struct pair_t * pair = def->pairs; pair != NULL; pair = pair->next)
    2238                 :            :     {
    2239                 :            :         // anything else than the 'Type'
    2240         [ #  # ]:          0 :         if (strcmp (pair->key, "Type"))
    2241                 :            :         {
    2242                 :            :             // put it into the equation checker
    2243                 :            :             env->getChecker()->addDouble ("#subcircuit",
    2244                 :          0 :                                           pair->key, pair->value->value);
    2245                 :            :             // also put it into the environment
    2246                 :          0 :             variable * v = checker_add_variable (env, pair->key, TAG_DOUBLE, true);
    2247                 :          0 :             v->getConstant()->d = pair->value->value;
    2248                 :            :         }
    2249                 :            :     }
    2250                 :         13 : }
    2251                 :            : 
    2252                 :            : /* This is the global netlist checker.  It returns zero on success and
    2253                 :            :    non-zero on errors. */
    2254                 :        103 : int netlist_checker (environment * env)
    2255                 :            : {
    2256                 :        103 :     int errors = 0;
    2257                 :            :     eqn::node * eqns;
    2258                 :            :     struct definition_t * def;
    2259                 :            : 
    2260                 :            :     // create top-level environment
    2261 [ +  - ][ +  - ]:        103 :     env_root = new environment (env->getName ());
    2262                 :            :     // create the subcircuit list
    2263         [ +  - ]:        103 :     definition_root = checker_build_subcircuits (definition_root);
    2264                 :            :     // get equation list
    2265         [ +  - ]:        103 :     definition_root = checker_build_equations (definition_root, &eqns);
    2266                 :            :     // setup the root environment
    2267         [ +  - ]:        103 :     checker_setup_env (definition_root, env_root, eqns);
    2268                 :            :     // check list of subcircuits
    2269         [ +  - ]:        103 :     errors += netlist_checker_intern (subcircuit_root);
    2270                 :            :     // check global netlist
    2271         [ +  - ]:        103 :     errors += netlist_checker_intern (definition_root);
    2272                 :            :     // check equations in root
    2273                 :        103 :     env_root->setDefinitions (definition_root);
    2274         [ +  - ]:        103 :     errors += env_root->equationChecker (0);
    2275                 :        103 :     env_root->setDefinitions (NULL);
    2276                 :            : 
    2277                 :            :     // then check each subcircuit list
    2278         [ +  + ]:        116 :     for (def = subcircuit_root; def != NULL; def = def->next)
    2279                 :            :     {
    2280                 :            :         // get equation list
    2281         [ +  - ]:         13 :         def->sub = checker_build_equations (def->sub, &eqns);
    2282                 :            :         // setup the subcircuit environment
    2283 [ +  - ][ +  - ]:         13 :         environment * subenv = new environment (def->instance);
                 [ +  - ]
    2284         [ +  - ]:         13 :         env_root->push_front_Child (subenv);
    2285         [ +  - ]:         13 :         checker_setup_env (def, subenv, eqns);
    2286         [ +  - ]:         13 :         if (def->sub) def->sub->env = subenv;
    2287                 :            :         // add subcircuit parameters to equations
    2288         [ +  - ]:         13 :         checker_subcircuit_args (def, subenv);
    2289                 :            :         // check subcircuit netlist
    2290         [ +  - ]:         13 :         errors += netlist_checker_intern (def->sub);
    2291                 :            :         // check equations in subcircuit
    2292                 :         13 :         subenv->setDefinitions (def->sub);
    2293         [ +  - ]:         13 :         errors += subenv->equationChecker (0);
    2294                 :         13 :         subenv->setDefinitions (NULL);
    2295                 :            :     }
    2296                 :            : 
    2297                 :            :     // check actions
    2298         [ +  - ]:        103 :     errors += checker_validate_actions (definition_root);
    2299                 :            : 
    2300         [ +  - ]:        103 :     if (!errors)
    2301                 :            :     {
    2302                 :            :         // create actual root environment
    2303         [ +  - ]:        103 :         env->copy (*env_root);
    2304                 :            :         // and finally expand the subcircuits into the global netlist
    2305         [ +  - ]:        103 :         definition_root = checker_expand_subcircuits (definition_root, env);
    2306                 :            :     }
    2307                 :            : 
    2308         [ -  + ]:        103 :     return errors ? -1 : 0;
    2309                 :            : }
    2310                 :            : 
    2311                 :            : /* The function deletes the given definition list. */
    2312                 :        219 : static void netlist_destroy_intern (struct definition_t * root)
    2313                 :            : {
    2314                 :            :     struct definition_t * def, * next;
    2315         [ +  + ]:        318 :     for (def = root; def != NULL; def = next)
    2316                 :            :     {
    2317                 :         99 :         next = def->next;
    2318                 :         99 :         netlist_free_definition (def);
    2319                 :            :     }
    2320                 :        219 : }
    2321                 :            : 
    2322                 :            : /* Deletes all available definition lists. */
    2323                 :        103 : void netlist_destroy (void)
    2324                 :            : {
    2325                 :        103 :     netlist_destroy_intern (definition_root);
    2326         [ +  + ]:        116 :     for (struct definition_t * def = subcircuit_root; def; def = def->next)
    2327                 :            :     {
    2328                 :         13 :         netlist_destroy_intern (def->sub);
    2329                 :            :     }
    2330                 :        103 :     netlist_destroy_intern (subcircuit_root);
    2331                 :        103 :     definition_root = subcircuit_root = NULL;
    2332                 :        103 :     netlist_lex_destroy ();
    2333                 :        103 : }
    2334                 :            : 
    2335                 :            : /* Delete root environment(s) if necessary. */
    2336                 :        103 : void netlist_destroy_env (void)
    2337                 :            : {
    2338         [ +  - ]:        103 :     if (env_root != NULL)
    2339                 :            :     {
    2340         [ +  - ]:        103 :         delete env_root;
    2341                 :        103 :         env_root = NULL;
    2342                 :            :     }
    2343                 :        103 : }
    2344                 :            : 

Generated by: LCOV version 1.11