LCOV - code coverage report
Current view: top level - src - input.cpp (source / functions) Hit Total Coverage
Test: qucs-core-0.0.19 Code Coverage Lines: 125 152 82.2 %
Date: 2015-01-05 16:01:02 Functions: 10 14 71.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 77 142 54.2 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * input.cpp - input netlist class implementation
       3                 :            :  *
       4                 :            :  * Copyright (C) 2003-2008 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 <errno.h>
      33                 :            : #include <assert.h>
      34                 :            : 
      35                 :            : #include "logging.h"
      36                 :            : #include "component.h"
      37                 :            : #include "components.h"
      38                 :            : #include "net.h"
      39                 :            : #include "variable.h"
      40                 :            : #include "property.h"
      41                 :            : #include "environment.h"
      42                 :            : #include "nodeset.h"
      43                 :            : #include "input.h"
      44                 :            : #include "check_netlist.h"
      45                 :            : #include "equation.h"
      46                 :            : #include "module.h"
      47                 :            : 
      48                 :            : namespace qucs {
      49                 :            : 
      50                 :            : // Global variables.
      51                 :            : int netlist_check = 0;
      52                 :            : 
      53                 :            : // Constructor creates an unnamed instance of the input class.
      54                 :          0 : input::input () : object () {
      55                 :          0 :   fd = stdin;
      56                 :          0 :   subnet = NULL;
      57                 :          0 :   env = NULL;
      58                 :          0 : }
      59                 :            : 
      60                 :            : // Constructor creates an named instance of the input class.
      61                 :        103 : input::input (char * file) : object (file) {
      62         [ +  - ]:        103 :   if ((fd = fopen (file, "r")) == NULL) {
           [ -  +  #  # ]
                 [ #  # ]
      63                 :            :     logprint (LOG_ERROR, "cannot open file `%s': %s, using stdin instead\n",
      64 [ #  # ][ #  # ]:          0 :               file, strerror (errno));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
      65                 :          0 :     fd = stdin;
      66                 :            :   }
      67                 :        103 :   subnet = NULL;
      68                 :        103 :   env = NULL;
      69                 :        103 : }
      70                 :            : 
      71                 :            : // Destructor deletes an input object.
      72                 :        103 : input::~input () {
      73 [ +  - ][ +  - ]:        103 :   if (fd != stdin) fclose (fd);
         [ #  # ][ #  # ]
      74 [ -  + ][ #  # ]:        206 : }
      75                 :            : 
      76                 :            : /* This function scans, parses and checks a netlist from the input
      77                 :            :    file (specified by the constructor call) or stdin if there is no
      78                 :            :    such file.  Afterwards the function builds the netlist
      79                 :            :    representation and stores it into the given netlist object.  The
      80                 :            :    function returns zero on success and non-zero otherwise. */
      81                 :        103 : int input::netlist (net * netlist) {
      82                 :            : 
      83                 :            :   // tell the scanner to use the specified file
      84                 :        103 :   netlist_in = getFile ();
      85                 :            : 
      86                 :            :   // save the netlist object
      87                 :        103 :   subnet = netlist;
      88                 :            : 
      89                 :        103 :   logprint (LOG_STATUS, "parsing netlist...\n");
      90                 :            : 
      91         [ -  + ]:        103 :   if (netlist_parse () != 0)
      92                 :          0 :     return -1;
      93                 :            : 
      94                 :        103 :   logprint (LOG_STATUS, "checking netlist...\n");
      95         [ -  + ]:        103 :   if (netlist_checker (env) != 0)
      96                 :          0 :     return -1;
      97                 :            : 
      98         [ -  + ]:        103 :   if (netlist_checker_variables (env) != 0)
      99                 :          0 :     return -1;
     100                 :            : 
     101                 :            : #if DEBUG
     102                 :        103 :   netlist_list ();
     103                 :            : #endif /* DEBUG */
     104                 :        103 :   netlist_status ();
     105                 :            : 
     106                 :        103 :   logprint (LOG_STATUS, "creating netlist...\n");
     107                 :        103 :   factory ();
     108                 :            : 
     109                 :        103 :   netlist_destroy ();
     110                 :        103 :   return 0;
     111                 :            : }
     112                 :            : 
     113                 :            : /* The little helper function creates a vector given by the list of
     114                 :            :    values. */
     115                 :          6 : qucs::vector * input::createVector (struct value_t * values) {
     116         [ +  - ]:          6 :   qucs::vector * v = new qucs::vector ();
     117 [ +  - ][ +  + ]:         24 :   for (; values != NULL; values = values->next) v->add (values->value);
     118                 :          6 :   return v;
     119                 :            : }
     120                 :            : 
     121                 :            : /* This function builds up the netlist representation from the checked
     122                 :            :    netlist input.  It creates circuit components as necessary. */
     123                 :        103 : void input::factory (void) {
     124                 :            : 
     125                 :            :   struct definition_t * def, * next;
     126                 :            :   struct node_t * nodes;
     127                 :            :   struct pair_t * pairs;
     128                 :            :   circuit * c;
     129                 :            :   object * o;
     130                 :            :   analysis * a;
     131                 :            :   substrate * s;
     132                 :            :   nodeset * n;
     133                 :            :   int i;
     134                 :            : 
     135                 :            :   // go through the list of input definitions
     136         [ +  + ]:       1222 :   for (def = definition_root; def != NULL; def = next) {
     137                 :       1119 :     next = def->next;
     138                 :            :     // handle actions
     139         [ +  + ]:       1119 :     if (def->action) {
     140         [ +  - ]:        181 :       if ((a = createAnalysis (def->type)) != NULL) {
     141                 :        181 :         a->setName (def->instance);
     142                 :            : 
     143                 :            :         // add the properties to analysis
     144         [ +  + ]:       1968 :         for (pairs = def->pairs; pairs != NULL; pairs = pairs->next)
     145         [ +  + ]:       1787 :           if (pairs->value->ident) {
     146 [ +  + ][ +  + ]:        674 :             if (pairs->value->var && strcmp (pairs->key, "Param")) {
     147                 :            :               variable * v;
     148         [ +  - ]:         11 :               if ((v = def->env->getVariable (pairs->value->ident)) != NULL) {
     149                 :            :                 // equation variable reference in analysis property
     150                 :         11 :                 a->addProperty (pairs->key, v);
     151                 :            :               }
     152                 :            :               else {
     153                 :            :                 // should not be reached!
     154                 :          0 :                 a->addProperty (pairs->key, pairs->value->ident);
     155                 :         11 :               }
     156                 :            :             }
     157                 :            :             else {
     158                 :            :               // ususal string property
     159                 :        674 :               a->addProperty (pairs->key, pairs->value->ident);
     160                 :            :             }
     161                 :            :           } else {
     162         [ +  + ]:       1113 :             if (pairs->value->var) {
     163                 :            :               // add list sweeps and constants to the properties
     164         [ +  - ]:          4 :               variable * v = new variable (pairs->key);
     165         [ +  - ]:          4 :               eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
     166                 :          4 :               c->v = createVector (pairs->value);
     167                 :          4 :               v->setConstant (c);
     168                 :          4 :               a->addProperty (pairs->key, v);
     169                 :            :             }
     170                 :            :             else {
     171                 :       1109 :               a->addProperty (pairs->key, pairs->value->value);
     172                 :            :             }
     173                 :            :           }
     174                 :            :         // additionally add missing optional properties
     175                 :        181 :         assignDefaultProperties (a, def->define);
     176                 :        181 :         a->setEnv (def->env);
     177                 :        181 :         subnet->insertAnalysis (a);
     178                 :            :       }
     179                 :            :       // remove this definition from the list
     180                 :        181 :       definition_root = netlist_unchain_definition (definition_root, def);
     181                 :            :     }
     182                 :            :   }
     183                 :            : 
     184                 :            :   // go through the list of input definitions
     185         [ +  + ]:       1041 :   for (def = definition_root; def != NULL; def = next) {
     186                 :        938 :     next = def->next;
     187                 :            :     // handle substrate definitions
     188 [ +  - ][ +  + ]:        938 :     if (!def->action && def->substrate) {
     189         [ +  - ]:          3 :       if ((s = createSubstrate (def->type)) != NULL) {
     190                 :          3 :         s->setName (def->instance);
     191                 :            : 
     192                 :            :         // add the properties to substrate
     193         [ +  + ]:         21 :         for (pairs = def->pairs; pairs != NULL; pairs = pairs->next)
     194         [ -  + ]:         18 :           if (pairs->value->ident) {
     195                 :            :             // a variable
     196         [ #  # ]:          0 :             if (pairs->value->var) {
     197                 :            :               // at this stage it should be ensured that the variable is
     198                 :            :               // already in the root environment
     199                 :          0 :               variable * v = def->env->getVariable (pairs->value->ident);
     200                 :          0 :               s->addProperty (pairs->key, v);
     201                 :            :             }
     202                 :            :             // a usual string property
     203                 :            :             else {
     204                 :          0 :               s->addProperty (pairs->key, pairs->value->ident);
     205                 :            :             }
     206                 :            :           } else {
     207                 :         18 :             s->addProperty (pairs->key, pairs->value->value);
     208                 :            :           }
     209                 :            :         // additionally add missing optional properties
     210                 :          3 :         assignDefaultProperties (s, def->define);
     211                 :            : 
     212                 :            :         // put new substrate definition into environment
     213                 :          3 :         char * n = strrchr (def->instance, '.');
     214 [ -  + ][ +  - ]:          3 :         variable * v = new variable (n ? n + 1 : def->instance);
     215                 :          3 :         v->setSubstrate (s);
     216                 :          3 :         def->env->addVariable (v);
     217                 :            :       }
     218                 :            :       // remove this definition from the list
     219                 :          3 :       definition_root = netlist_unchain_definition (definition_root, def);
     220                 :            :     }
     221                 :            :     // handle nodeset definitions
     222 [ +  - ][ +  + ]:        935 :     else if (!def->action && def->nodeset) {
     223         [ +  - ]:          2 :       n = new nodeset ();
     224                 :          2 :       n->setName (def->nodes->node);
     225                 :          2 :       n->setValue (def->pairs->value->value);
     226                 :          2 :       subnet->addNodeset (n);
     227                 :            :       // remove this definition from the list
     228                 :          2 :       definition_root = netlist_unchain_definition (definition_root, def);
     229                 :            :     }
     230                 :            :   }
     231                 :            : 
     232                 :            :   // go through the list of input definitions
     233         [ +  + ]:       1036 :   for (def = definition_root; def != NULL; def = next) {
     234                 :        933 :     next = def->next;
     235                 :            :     // handle component definitions
     236 [ +  - ][ +  - ]:        933 :     if (!def->action && !def->substrate && !def->nodeset) {
                 [ +  - ]
     237                 :        933 :       c = createCircuit (def->type);
     238         [ -  + ]:        933 :       assert (c != NULL);
     239                 :        933 :       o = (object *) c;
     240                 :        933 :       c->setName (def->instance);
     241                 :        933 :       c->setNonLinear (def->nonlinear != 0);
     242                 :        933 :       c->setSubcircuit (def->subcircuit);
     243                 :            : 
     244                 :            :       // change size (number of ports) of variable sized components
     245         [ -  + ]:        933 :       if (c->isVariableSized ()) {
     246                 :          0 :         c->setSize (def->ncount);
     247                 :            :       }
     248                 :            :       // add appropriate nodes to circuit
     249         [ +  + ]:       3056 :       for (i = 0, nodes = def->nodes; nodes; nodes = nodes->next, i++)
     250         [ +  - ]:       2123 :         if (i < c->getSize ())
     251                 :       2123 :           c->setNode (i, nodes->node);
     252                 :            : 
     253                 :            :       // add the properties to circuit
     254         [ +  + ]:       9475 :       for (pairs = def->pairs; pairs != NULL; pairs = pairs->next) {
     255         [ -  + ]:       8542 :         if (pairs->value == NULL) {
     256                 :            :           // zero-length value lists
     257         [ #  # ]:          0 :           variable * v = new variable (pairs->key);
     258         [ #  # ]:          0 :           eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
     259         [ #  # ]:          0 :           c->v = new qucs::vector ();
     260                 :          0 :           v->setConstant (c);
     261                 :          0 :           o->addProperty (pairs->key, v);
     262                 :            :         }
     263         [ +  + ]:       8542 :         else if (pairs->value->ident) {
     264         [ +  + ]:        251 :           if (pairs->value->var) {
     265                 :            :             // at this stage it should be ensured that the variable is
     266                 :            :             // already in the root environment
     267                 :         96 :             variable * v = def->env->getVariable (pairs->value->ident);
     268                 :         96 :             o->addProperty (pairs->key, v);
     269                 :            :           } else {
     270         [ +  + ]:        155 :             if (pairs->value->subst) {
     271                 :         24 :               variable * v = def->env->getVariable (pairs->value->ident);
     272                 :         24 :               c->setSubstrate (v->getSubstrate ());
     273                 :            :             }
     274                 :        155 :             o->addProperty (pairs->key, pairs->value->ident);
     275                 :            :           }
     276                 :            :         } else {
     277         [ +  + ]:       8291 :           if (pairs->value->var) {
     278                 :            :             // add value lists to the properties
     279         [ +  - ]:          2 :             variable * v = new variable (pairs->key);
     280         [ +  - ]:          2 :             eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
     281                 :          2 :             c->v = createVector (pairs->value);
     282                 :          2 :             v->setConstant (c);
     283                 :          2 :             o->addProperty (pairs->key, v);
     284                 :            :           } else {
     285                 :       8289 :             o->addProperty (pairs->key, pairs->value->value);
     286                 :            :           }
     287                 :            :         }
     288                 :            :       }
     289                 :            :       // set local circuit environment
     290                 :        933 :       c->setEnv (def->env);
     291                 :            : 
     292                 :            :       // additionally add missing optional properties
     293                 :        933 :       assignDefaultProperties (c, def->define);
     294                 :            : 
     295                 :            :       // insert the circuit into the netlist object
     296                 :        933 :       subnet->insertCircuit (c);
     297                 :            : 
     298                 :            :       // remove this definition from the list
     299                 :        933 :       definition_root = netlist_unchain_definition (definition_root, def);
     300                 :            :     }
     301                 :            :   }
     302                 :        103 : }
     303                 :            : 
     304                 :            : /* This static function applies the optional missing properties's
     305                 :            :    default values to the given object. */
     306                 :       1117 : void input::assignDefaultProperties (object * obj, struct define_t * def) {
     307                 :            :   // go through optional properties
     308         [ +  + ]:       6471 :   for (int i = 0; PROP_IS_PROP (def->optional[i]); i++) {
     309                 :            :     // is the property already assigned ?
     310         [ +  + ]:       5354 :     if (!obj->hasProperty (def->optional[i].key)) {
     311                 :            :       property * p;
     312         [ +  - ]:        545 :       if (PROP_IS_VAL (def->optional[i])) {
     313                 :            :         // add double property
     314                 :        545 :         p = obj->addProperty (def->optional[i].key,
     315                 :        545 :                               def->optional[i].defaultval.d);
     316                 :        545 :         p->setDefault (true);
     317                 :            :       }
     318                 :            :       else {
     319                 :            :         // add string property
     320                 :          0 :         p = obj->addProperty (def->optional[i].key,
     321                 :          0 :                               def->optional[i].defaultval.s);
     322                 :          0 :         p->setDefault (true);
     323                 :            :       }
     324                 :            :     }
     325                 :            :   }
     326                 :       1117 : }
     327                 :            : 
     328                 :            : // The function creates components specified by the type of component.
     329                 :        933 : circuit * input::createCircuit (char * type) {
     330                 :            :   module * m;
     331         [ +  - ]:        933 :   if ((m = module::modules.get (type)) != NULL)
     332                 :        933 :     return m->circreate ();
     333                 :            : 
     334                 :          0 :   logprint (LOG_ERROR, "no such circuit type `%s'\n", type);
     335                 :        933 :   return NULL;
     336                 :            : }
     337                 :            : 
     338                 :            : // The function creates an analysis specified by the type of analysis.
     339                 :        181 : analysis * input::createAnalysis (char * type) {
     340                 :            :   module * m;
     341         [ +  - ]:        181 :   if ((m = module::modules.get (type)) != NULL)
     342                 :        181 :     return m->anacreate ();
     343                 :            : 
     344                 :          0 :   logprint (LOG_ERROR, "no such analysis type `%s'\n", type);
     345                 :        181 :   return NULL;
     346                 :            : }
     347                 :            : 
     348                 :            : // The function creates a substrate specified by the type of substrate.
     349                 :          3 : substrate * input::createSubstrate (char * type) {
     350         [ +  - ]:          3 :   if (!strcmp (type, "SUBST"))
     351         [ +  - ]:          3 :     return new substrate ();
     352                 :            : 
     353                 :          0 :   logprint (LOG_ERROR, "no such substrate type `%s'\n", type);
     354                 :          3 :   return NULL;
     355                 :            : }
     356                 :            : 
     357                 :            : } // namespace qucs

Generated by: LCOV version 1.11