Qucs-core  0.0.19
input.cpp
Go to the documentation of this file.
00001 /*
00002  * input.cpp - input netlist class implementation
00003  *
00004  * Copyright (C) 2003-2008 Stefan Jahn <stefan@lkcc.org>
00005  *
00006  * This is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2, or (at your option)
00009  * any later version.
00010  *
00011  * This software is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this package; see the file COPYING.  If not, write to
00018  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020  *
00021  * $Id$
00022  *
00023  */
00024 
00025 #if HAVE_CONFIG_H
00026 # include <config.h>
00027 #endif
00028 
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <errno.h>
00033 #include <assert.h>
00034 
00035 #include "logging.h"
00036 #include "component.h"
00037 #include "components.h"
00038 #include "net.h"
00039 #include "variable.h"
00040 #include "property.h"
00041 #include "environment.h"
00042 #include "nodeset.h"
00043 #include "input.h"
00044 #include "check_netlist.h"
00045 #include "equation.h"
00046 #include "module.h"
00047 
00048 namespace qucs {
00049 
00050 // Global variables.
00051 int netlist_check = 0;
00052 
00053 // Constructor creates an unnamed instance of the input class.
00054 input::input () : object () {
00055   fd = stdin;
00056   subnet = NULL;
00057   env = NULL;
00058 }
00059 
00060 // Constructor creates an named instance of the input class.
00061 input::input (char * file) : object (file) {
00062   if ((fd = fopen (file, "r")) == NULL) {
00063     logprint (LOG_ERROR, "cannot open file `%s': %s, using stdin instead\n",
00064               file, strerror (errno));
00065     fd = stdin;
00066   }
00067   subnet = NULL;
00068   env = NULL;
00069 }
00070 
00071 // Destructor deletes an input object.
00072 input::~input () {
00073   if (fd != stdin) fclose (fd);
00074 }
00075 
00076 /* This function scans, parses and checks a netlist from the input
00077    file (specified by the constructor call) or stdin if there is no
00078    such file.  Afterwards the function builds the netlist
00079    representation and stores it into the given netlist object.  The
00080    function returns zero on success and non-zero otherwise. */
00081 int input::netlist (net * netlist) {
00082 
00083   // tell the scanner to use the specified file
00084   netlist_in = getFile ();
00085 
00086   // save the netlist object
00087   subnet = netlist;
00088 
00089   logprint (LOG_STATUS, "parsing netlist...\n");
00090 
00091   if (netlist_parse () != 0)
00092     return -1;
00093 
00094   logprint (LOG_STATUS, "checking netlist...\n");
00095   if (netlist_checker (env) != 0)
00096     return -1;
00097 
00098   if (netlist_checker_variables (env) != 0)
00099     return -1;
00100 
00101 #if DEBUG
00102   netlist_list ();
00103 #endif /* DEBUG */
00104   netlist_status ();
00105 
00106   logprint (LOG_STATUS, "creating netlist...\n");
00107   factory ();
00108 
00109   netlist_destroy ();
00110   return 0;
00111 }
00112 
00113 /* The little helper function creates a vector given by the list of
00114    values. */
00115 qucs::vector * input::createVector (struct value_t * values) {
00116   qucs::vector * v = new qucs::vector ();
00117   for (; values != NULL; values = values->next) v->add (values->value);
00118   return v;
00119 }
00120 
00121 /* This function builds up the netlist representation from the checked
00122    netlist input.  It creates circuit components as necessary. */
00123 void input::factory (void) {
00124 
00125   struct definition_t * def, * next;
00126   struct node_t * nodes;
00127   struct pair_t * pairs;
00128   circuit * c;
00129   object * o;
00130   analysis * a;
00131   substrate * s;
00132   nodeset * n;
00133   int i;
00134 
00135   // go through the list of input definitions
00136   for (def = definition_root; def != NULL; def = next) {
00137     next = def->next;
00138     // handle actions
00139     if (def->action) {
00140       if ((a = createAnalysis (def->type)) != NULL) {
00141         a->setName (def->instance);
00142 
00143         // add the properties to analysis
00144         for (pairs = def->pairs; pairs != NULL; pairs = pairs->next)
00145           if (pairs->value->ident) {
00146             if (pairs->value->var && strcmp (pairs->key, "Param")) {
00147               variable * v;
00148               if ((v = def->env->getVariable (pairs->value->ident)) != NULL) {
00149                 // equation variable reference in analysis property
00150                 a->addProperty (pairs->key, v);
00151               }
00152               else {
00153                 // should not be reached!
00154                 a->addProperty (pairs->key, pairs->value->ident);
00155               }
00156             }
00157             else {
00158               // ususal string property
00159               a->addProperty (pairs->key, pairs->value->ident);
00160             }
00161           } else {
00162             if (pairs->value->var) {
00163               // add list sweeps and constants to the properties
00164               variable * v = new variable (pairs->key);
00165               eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
00166               c->v = createVector (pairs->value);
00167               v->setConstant (c);
00168               a->addProperty (pairs->key, v);
00169             }
00170             else {
00171               a->addProperty (pairs->key, pairs->value->value);
00172             }
00173           }
00174         // additionally add missing optional properties
00175         assignDefaultProperties (a, def->define);
00176         a->setEnv (def->env);
00177         subnet->insertAnalysis (a);
00178       }
00179       // remove this definition from the list
00180       definition_root = netlist_unchain_definition (definition_root, def);
00181     }
00182   }
00183 
00184   // go through the list of input definitions
00185   for (def = definition_root; def != NULL; def = next) {
00186     next = def->next;
00187     // handle substrate definitions
00188     if (!def->action && def->substrate) {
00189       if ((s = createSubstrate (def->type)) != NULL) {
00190         s->setName (def->instance);
00191 
00192         // add the properties to substrate
00193         for (pairs = def->pairs; pairs != NULL; pairs = pairs->next)
00194           if (pairs->value->ident) {
00195             // a variable
00196             if (pairs->value->var) {
00197               // at this stage it should be ensured that the variable is
00198               // already in the root environment
00199               variable * v = def->env->getVariable (pairs->value->ident);
00200               s->addProperty (pairs->key, v);
00201             }
00202             // a usual string property
00203             else {
00204               s->addProperty (pairs->key, pairs->value->ident);
00205             }
00206           } else {
00207             s->addProperty (pairs->key, pairs->value->value);
00208           }
00209         // additionally add missing optional properties
00210         assignDefaultProperties (s, def->define);
00211 
00212         // put new substrate definition into environment
00213         char * n = strrchr (def->instance, '.');
00214         variable * v = new variable (n ? n + 1 : def->instance);
00215         v->setSubstrate (s);
00216         def->env->addVariable (v);
00217       }
00218       // remove this definition from the list
00219       definition_root = netlist_unchain_definition (definition_root, def);
00220     }
00221     // handle nodeset definitions
00222     else if (!def->action && def->nodeset) {
00223       n = new nodeset ();
00224       n->setName (def->nodes->node);
00225       n->setValue (def->pairs->value->value);
00226       subnet->addNodeset (n);
00227       // remove this definition from the list
00228       definition_root = netlist_unchain_definition (definition_root, def);
00229     }
00230   }
00231 
00232   // go through the list of input definitions
00233   for (def = definition_root; def != NULL; def = next) {
00234     next = def->next;
00235     // handle component definitions
00236     if (!def->action && !def->substrate && !def->nodeset) {
00237       c = createCircuit (def->type);
00238       assert (c != NULL);
00239       o = (object *) c;
00240       c->setName (def->instance);
00241       c->setNonLinear (def->nonlinear != 0);
00242       c->setSubcircuit (def->subcircuit == nullptr ? "" : def->subcircuit);
00243 
00244       // change size (number of ports) of variable sized components
00245       if (c->isVariableSized ()) {
00246         c->setSize (def->ncount);
00247       }
00248       // add appropriate nodes to circuit
00249       for (i = 0, nodes = def->nodes; nodes; nodes = nodes->next, i++)
00250         if (i < c->getSize ())
00251           c->setNode (i, nodes->node);
00252 
00253       // add the properties to circuit
00254       for (pairs = def->pairs; pairs != NULL; pairs = pairs->next) {
00255         if (pairs->value == NULL) {
00256           // zero-length value lists
00257           variable * v = new variable (pairs->key);
00258           eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
00259           c->v = new qucs::vector ();
00260           v->setConstant (c);
00261           o->addProperty (pairs->key, v);
00262         }
00263         else if (pairs->value->ident) {
00264           if (pairs->value->var) {
00265             // at this stage it should be ensured that the variable is
00266             // already in the root environment
00267             variable * v = def->env->getVariable (pairs->value->ident);
00268             o->addProperty (pairs->key, v);
00269           } else {
00270             if (pairs->value->subst) {
00271               variable * v = def->env->getVariable (pairs->value->ident);
00272               c->setSubstrate (v->getSubstrate ());
00273             }
00274             o->addProperty (pairs->key, pairs->value->ident);
00275           }
00276         } else {
00277           if (pairs->value->var) {
00278             // add value lists to the properties
00279             variable * v = new variable (pairs->key);
00280             eqn::constant * c = new eqn::constant (eqn::TAG_VECTOR);
00281             c->v = createVector (pairs->value);
00282             v->setConstant (c);
00283             o->addProperty (pairs->key, v);
00284           } else {
00285             o->addProperty (pairs->key, pairs->value->value);
00286           }
00287         }
00288       }
00289       // set local circuit environment
00290       c->setEnv (def->env);
00291 
00292       // additionally add missing optional properties
00293       assignDefaultProperties (c, def->define);
00294 
00295       // insert the circuit into the netlist object
00296       subnet->insertCircuit (c);
00297 
00298       // remove this definition from the list
00299       definition_root = netlist_unchain_definition (definition_root, def);
00300     }
00301   }
00302 }
00303 
00304 /* This static function applies the optional missing properties's
00305    default values to the given object. */
00306 void input::assignDefaultProperties (object * obj, struct define_t * def) {
00307   // go through optional properties
00308   for (int i = 0; PROP_IS_PROP (def->optional[i]); i++) {
00309     // is the property already assigned ?
00310     if (!obj->hasProperty (def->optional[i].key)) {
00311       if (PROP_IS_VAL (def->optional[i])) {
00312         // add double property
00313         obj->addProperty (def->optional[i].key,
00314                           def->optional[i].defaultval.d,true);
00315       }
00316       else {
00317         // add string property
00318         obj->addProperty (def->optional[i].key,
00319                           def->optional[i].defaultval.s,true);
00320       }
00321     }
00322   }
00323 }
00324 
00325 // The function creates components specified by the type of component.
00326 circuit * input::createCircuit (char * type) {
00327   module * m;
00328   if ((m = module::modules.get (type)) != NULL)
00329     return m->circreate ();
00330 
00331   logprint (LOG_ERROR, "no such circuit type `%s'\n", type);
00332   return NULL;
00333 }
00334 
00335 // The function creates an analysis specified by the type of analysis.
00336 analysis * input::createAnalysis (char * type) {
00337   module * m;
00338   if ((m = module::modules.get (type)) != NULL)
00339     return m->anacreate ();
00340 
00341   logprint (LOG_ERROR, "no such analysis type `%s'\n", type);
00342   return NULL;
00343 }
00344 
00345 // The function creates a substrate specified by the type of substrate.
00346 substrate * input::createSubstrate (char * type) {
00347   if (!strcmp (type, "SUBST"))
00348     return new substrate ();
00349 
00350   logprint (LOG_ERROR, "no such substrate type `%s'\n", type);
00351   return NULL;
00352 }
00353 
00354 } // namespace qucs