* check_citi.cpp - checker for CITIfiles
*
* Copyright (C) 2006 Stefan Jahn <stefan@lkcc.org>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this package; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* $Id$
*
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <cmath>
#include "logging.h"
#include "complex.h"
#include "object.h"
#include "vector.h"
#include "matrix.h"
#include "matvec.h"
#include "dataset.h"
#include "strlist.h"
#include "constants.h"
#include "check_citi.h"
using namespace qucs;
qucs::dataset * citi_result = NULL;
struct citi_package_t * citi_root = NULL;
static int citi_count_vectors (struct citi_package_t * p) {
int i = 0;
for (qucs::vector * v = p->data; v != NULL; v = (qucs::vector *) v->getNext ()) i++;
return i;
}
static int citi_count_variables (struct citi_package_t * p) {
int i = 0;
for (struct citi_header_t * h = p->head; h != NULL; h = h->next) {
if (h->var != NULL) i++;
}
return i;
}
static qucs::vector * citi_get_vector (struct citi_package_t * p, int n) {
qucs::vector * v = p->data;
for (int i = 0; v != NULL; v = (qucs::vector *) v->getNext (), i++) {
if (i == n) return v;
}
return NULL;
}
static int citi_count_packages (struct citi_package_t * p) {
int i = 0;
for (; p != NULL; p = p->next) i++;
return i;
}
static char * citi_get_package (struct citi_package_t * p) {
for (struct citi_header_t * h = p->head; h != NULL; h = h->next) {
if (h->package != NULL) return h->package;
}
return NULL;
}
static qucs::vector * citi_create_vector (struct citi_package_t * p, int i,
char * n, char * type) {
qucs::vector * vec;
vec = citi_get_vector (p, i);
vec = new qucs::vector (*vec);
vec->reverse ();
if (!strcmp (type, "MAGANGLE")) {
for (int i = 0; i < vec->getSize (); i++) {
nr_complex_t val = vec->get (i);
val = std::polar (real (val), deg2rad (imag (val)));
vec->set (val, i);
}
}
else if (!strcmp (type, "DBANGLE")) {
for (int i = 0; i < vec->getSize (); i++) {
nr_complex_t val = vec->get (i);
val = std::polar (std::pow (10.0, real (val) / 20.0), deg2rad (imag (val)));
vec->set (val, i);
}
}
vec->setName (n);
return vec;
}
static int citi_vector_length (strlist deps) {
int n = 1;
if (deps.length () <= 0)
return 0;
for (int i = 0; i < deps.length(); i++) {
qucs::vector * v = citi_result->findDependency (deps.get (i));
if (v != NULL) n *= v->getSize ();
}
return n;
}
static int citi_check_dep_length (qucs::vector * v, strlist deps, char * package) {
int rlength = v->getSize ();
int dlength = citi_vector_length (deps);
if (rlength != dlength) {
logprint (LOG_ERROR, "checker error, invalid vector `%s' length "
"(%d != %d) in package `%s'\n", v->getName (), rlength, dlength,
package);
return 1;
}
return 0;
}
void citi_finalize (void) {
struct citi_package_t * p, * pn;
for (p = citi_root; p != NULL; p = pn) {
struct citi_header_t * h, * hn;
for (h = p->head; h != NULL; h = hn) {
free (h->package);
free (h->var);
free (h->type);
hn = h->next;
free (h);
}
qucs::vector * v, * vn;
for (v = p->data; v != NULL; v = vn) {
vn = (qucs::vector *) v->getNext ();
delete v;
}
pn = p->next;
free (p);
}
citi_lex_destroy ();
}
returns zero on success or non-zero if it contained errors. */
int citi_check (void) {
int errors = 0;
citi_result = new dataset ();
struct citi_package_t * p = citi_root;
int packages = citi_count_packages (p);
for (p = citi_root; p != NULL; p = p->next) {
struct citi_header_t * h;
char * package = citi_get_package (p);
int n = 0;
strlist deps;
int cvec = citi_count_vectors (p);
int cvar = citi_count_variables (p);
if (cvec != cvar) {
logprint (LOG_ERROR, "checker error, no. of vectors (%d) does not equal "
"no. of variables (%d) in package `%s'\n", cvec, cvar,
package);
errors++;
break;
}
char opack[256];
if (packages < 2) {
opack[0] = '\0';
} else {
sprintf (opack, "%s.", package);
}
for (h = p->head; h != NULL; h = h->next) {
qucs::vector * v;
if (h->var != NULL) {
char txt[256];
if (h->i1 >= 0) {
if (h->i2 >= 0) {
sprintf (txt, "%s%s[%d,%d]", opack, h->var, h->i1, h->i2);
v = citi_create_vector (p, n, txt, h->type);
v->setDependencies (new strlist (deps));
errors += citi_check_dep_length (v, deps, package);
citi_result->addVariable (v);
n++;
} else {
sprintf (txt, "%s%s[%d]", opack, h->var, h->i1);
v = citi_create_vector (p, n, txt, h->type);
v->setDependencies (new strlist (deps));
errors += citi_check_dep_length (v, deps, package);
citi_result->addVariable (v);
n++;
}
} else if (h->n >= 0) {
sprintf (txt, "%s%s", opack, h->var);
v = citi_create_vector (p, n, txt, h->type);
deps.add (txt);
if (!citi_result->findDependency (txt)) {
citi_result->addDependency (v);
}
n++;
if (v->getSize () != h->n) {
logprint (LOG_ERROR, "checker error, vector `%s' length (%d) "
"does not equal defined length (%d) in package `%s'\n",
h->var, v->getSize (), h->n, package);
errors++;
}
} else {
sprintf (txt, "%s%s", opack, h->var);
v = citi_create_vector (p, n, txt, h->type);
v->setDependencies (new strlist (deps));
errors += citi_check_dep_length (v, deps, package);
citi_result->addVariable (v);
n++;
}
}
}
}
citi_finalize ();
citi_root = NULL;
return errors ? -1 : 0;
}
void citi_destroy (void) {
if (citi_result != NULL) {
delete citi_result;
citi_result = NULL;
}
if (citi_root != NULL) {
citi_finalize ();
citi_root = NULL;
}
}
void citi_init (void) {
citi_result = NULL;
citi_root = NULL;
}