Qucs-core
0.0.19
|
00001 /* 00002 * check_citi.cpp - checker for CITIfiles 00003 * 00004 * Copyright (C) 2006 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 <ctype.h> 00033 #include <cmath> 00034 00035 #include "logging.h" 00036 #include "complex.h" 00037 #include "object.h" 00038 #include "vector.h" 00039 #include "matrix.h" 00040 #include "matvec.h" 00041 #include "dataset.h" 00042 #include "strlist.h" 00043 #include "constants.h" 00044 #include "check_citi.h" 00045 00046 using namespace qucs; 00047 00048 qucs::dataset * citi_result = NULL; 00049 struct citi_package_t * citi_root = NULL; 00050 00051 /* Returns the number of vectors in a package. */ 00052 static int citi_count_vectors (struct citi_package_t * p) { 00053 int i = 0; 00054 for (qucs::vector * v = p->data; v != NULL; v = (qucs::vector *) v->getNext ()) i++; 00055 return i; 00056 } 00057 00058 /* Returns the number of variables in a package. */ 00059 static int citi_count_variables (struct citi_package_t * p) { 00060 int i = 0; 00061 for (struct citi_header_t * h = p->head; h != NULL; h = h->next) { 00062 if (h->var != NULL) i++; 00063 } 00064 return i; 00065 } 00066 00067 /* Returns the n-th vector in the package. */ 00068 static qucs::vector * citi_get_vector (struct citi_package_t * p, int n) { 00069 qucs::vector * v = p->data; 00070 for (int i = 0; v != NULL; v = (qucs::vector *) v->getNext (), i++) { 00071 if (i == n) return v; 00072 } 00073 return NULL; 00074 } 00075 00076 /* Returns the number of packages. */ 00077 static int citi_count_packages (struct citi_package_t * p) { 00078 int i = 0; 00079 for (; p != NULL; p = p->next) i++; 00080 return i; 00081 } 00082 00083 /* Find name of the package in its headers. */ 00084 static char * citi_get_package (struct citi_package_t * p) { 00085 for (struct citi_header_t * h = p->head; h != NULL; h = h->next) { 00086 if (h->package != NULL) return h->package; 00087 } 00088 return NULL; 00089 } 00090 00091 /* Create a valid vector for the dataset. */ 00092 static qucs::vector * citi_create_vector (struct citi_package_t * p, int i, 00093 char * n, char * type) { 00094 qucs::vector * vec; 00095 vec = citi_get_vector (p, i); // fetch vector 00096 vec = new qucs::vector (*vec); // copy vector 00097 vec->reverse (); // reverse vector 00098 00099 // convert data if necessary 00100 if (!strcmp (type, "MAGANGLE")) { 00101 for (int i = 0; i < vec->getSize (); i++) { 00102 nr_complex_t val = vec->get (i); 00103 val = std::polar (real (val), deg2rad (imag (val))); 00104 vec->set (val, i); 00105 } 00106 } 00107 else if (!strcmp (type, "DBANGLE")) { 00108 for (int i = 0; i < vec->getSize (); i++) { 00109 nr_complex_t val = vec->get (i); 00110 val = std::polar (std::pow (10.0, real (val) / 20.0), deg2rad (imag (val))); 00111 vec->set (val, i); 00112 } 00113 } 00114 00115 // return named vector 00116 vec->setName (n); 00117 return vec; 00118 } 00119 00120 /* Returns dependent variable length for the given dependencies. */ 00121 static int citi_vector_length (strlist deps) { 00122 int n = 1; 00123 // no dependencies 00124 if (deps.length () <= 0) 00125 return 0; 00126 // calculate length of resulting dependent variable 00127 for (int i = 0; i < deps.length(); i++) { 00128 qucs::vector * v = citi_result->findDependency (deps.get (i)); 00129 if (v != NULL) n *= v->getSize (); 00130 } 00131 return n; 00132 } 00133 00134 /* Checks length of variable vectors. */ 00135 static int citi_check_dep_length (qucs::vector * v, strlist deps, char * package) { 00136 int rlength = v->getSize (); 00137 int dlength = citi_vector_length (deps); 00138 if (rlength != dlength) { 00139 logprint (LOG_ERROR, "checker error, invalid vector `%s' length " 00140 "(%d != %d) in package `%s'\n", v->getName (), rlength, dlength, 00141 package); 00142 return 1; 00143 } 00144 return 0; 00145 } 00146 00147 // Destroys data used by the CITIfile parser. 00148 void citi_finalize (void) { 00149 struct citi_package_t * p, * pn; 00150 /* go through all packages */ 00151 for (p = citi_root; p != NULL; p = pn) { 00152 struct citi_header_t * h, * hn; 00153 /* go through each header */ 00154 for (h = p->head; h != NULL; h = hn) { 00155 free (h->package); 00156 free (h->var); 00157 free (h->type); 00158 hn = h->next; 00159 free (h); 00160 } 00161 qucs::vector * v, * vn; 00162 /* go through each vector */ 00163 for (v = p->data; v != NULL; v = vn) { 00164 vn = (qucs::vector *) v->getNext (); 00165 delete v; 00166 } 00167 pn = p->next; 00168 free (p); 00169 } 00170 citi_lex_destroy (); 00171 } 00172 00173 /* This function is the checker routine for a parsed CITIfile. It 00174 returns zero on success or non-zero if it contained errors. */ 00175 int citi_check (void) { 00176 00177 int errors = 0; 00178 00179 /* create dataset */ 00180 citi_result = new dataset (); 00181 /* get root package */ 00182 struct citi_package_t * p = citi_root; 00183 /* count packages */ 00184 int packages = citi_count_packages (p); 00185 00186 /* go through all packages */ 00187 for (p = citi_root; p != NULL; p = p->next) { 00188 struct citi_header_t * h; 00189 char * package = citi_get_package (p); 00190 int n = 0; 00191 strlist deps; 00192 00193 /* check number of defined variables and vectors */ 00194 int cvec = citi_count_vectors (p); 00195 int cvar = citi_count_variables (p); 00196 if (cvec != cvar) { 00197 logprint (LOG_ERROR, "checker error, no. of vectors (%d) does not equal " 00198 "no. of variables (%d) in package `%s'\n", cvec, cvar, 00199 package); 00200 errors++; 00201 break; 00202 } 00203 00204 /* no package info if there is just one */ 00205 char opack[256]; 00206 if (packages < 2) { 00207 opack[0] = '\0'; 00208 } else { 00209 sprintf (opack, "%s.", package); 00210 } 00211 00212 /* go through each header */ 00213 for (h = p->head; h != NULL; h = h->next) { 00214 qucs::vector * v; 00215 if (h->var != NULL) { 00216 char txt[256]; 00217 if (h->i1 >= 0) { 00218 /* dependent variables */ 00219 if (h->i2 >= 0) { 00220 sprintf (txt, "%s%s[%d,%d]", opack, h->var, h->i1, h->i2); 00221 v = citi_create_vector (p, n, txt, h->type); 00222 v->setDependencies (new strlist (deps)); 00223 errors += citi_check_dep_length (v, deps, package); 00224 citi_result->addVariable (v); 00225 n++; 00226 } else { 00227 sprintf (txt, "%s%s[%d]", opack, h->var, h->i1); 00228 v = citi_create_vector (p, n, txt, h->type); 00229 v->setDependencies (new strlist (deps)); 00230 errors += citi_check_dep_length (v, deps, package); 00231 citi_result->addVariable (v); 00232 n++; 00233 } 00234 } else if (h->n >= 0) { 00235 /* independent variable */ 00236 sprintf (txt, "%s%s", opack, h->var); 00237 v = citi_create_vector (p, n, txt, h->type); 00238 deps.add (txt); 00239 if (!citi_result->findDependency (txt)) { 00240 /* add independent vectors only once */ 00241 citi_result->addDependency (v); 00242 } 00243 n++; 00244 // check length of independent vector 00245 if (v->getSize () != h->n) { 00246 logprint (LOG_ERROR, "checker error, vector `%s' length (%d) " 00247 "does not equal defined length (%d) in package `%s'\n", 00248 h->var, v->getSize (), h->n, package); 00249 errors++; 00250 } 00251 } else { 00252 /* dependent variables, no indices */ 00253 sprintf (txt, "%s%s", opack, h->var); 00254 v = citi_create_vector (p, n, txt, h->type); 00255 v->setDependencies (new strlist (deps)); 00256 errors += citi_check_dep_length (v, deps, package); 00257 citi_result->addVariable (v); 00258 n++; 00259 } 00260 } 00261 } 00262 } 00263 00264 citi_finalize (); 00265 citi_root = NULL; 00266 return errors ? -1 : 0; 00267 } 00268 00269 // Destroys data used by the CITIfile parser and checker. 00270 void citi_destroy (void) { 00271 if (citi_result != NULL) { 00272 // delete associated dataset 00273 delete citi_result; 00274 citi_result = NULL; 00275 } 00276 if (citi_root != NULL) { 00277 citi_finalize (); 00278 citi_root = NULL; 00279 } 00280 } 00281 00282 // Initializes the CITIfile checker. 00283 void citi_init (void) { 00284 citi_result = NULL; 00285 citi_root = NULL; 00286 } 00287