From 1e6b809af8afe5bce1e3827c4577ca12d4fd771a Mon Sep 17 00:00:00 2001 From: rlar Date: Sat, 8 Apr 2017 19:43:23 +0200 Subject: [PATCH] introduce command "check_ifparm" to check consistency of the device IFparm sets For developing purpose only, and bound to HAVE_TSEARCH, HAVE_TDESTROY IFparm descriptors must obey certain contracts, 1) aliases must be grouped together with their associated main descriptor, and all must have flag IF_REDUNDANT set 2) there shall be no duplicated .id fields except for aliases. 3) aliased entries shall have consistent .dataType fields check_ifparm will traverse all IFparm sets and report violations --- configure.ac | 2 +- src/frontend/com_commands.h | 1 + src/frontend/commands.c | 6 +++ src/frontend/device.c | 98 +++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 2141b038e..20a5cbe4c 100644 --- a/configure.ac +++ b/configure.ac @@ -712,7 +712,7 @@ AC_CHECK_FUNCS([isatty tcgetattr tcsetattr]) # Check for a few functions: AC_FUNC_FORK([]) -AC_CHECK_FUNCS([access qsort dup2 popen]) +AC_CHECK_FUNCS([access qsort dup2 popen tsearch tdestroy]) AC_CHECK_FUNCS([strchr index], [break]) AC_CHECK_FUNCS([strrchr rindex], [break]) AC_CHECK_FUNCS([getcwd getwd], [break]) diff --git a/src/frontend/com_commands.h b/src/frontend/com_commands.h index 089e4537e..38d959075 100644 --- a/src/frontend/com_commands.h +++ b/src/frontend/com_commands.h @@ -7,5 +7,6 @@ void com_alter(wordlist *wl); void com_altermod(wordlist *wl); void com_meas(wordlist *wl); void com_sysinfo(wordlist *wl); +void com_check_ifparm(wordlist *wl); #endif diff --git a/src/frontend/commands.c b/src/frontend/commands.c index 548c5459c..1480c0139 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -586,6 +586,12 @@ struct comm spcp_coms[] = { { 0, 0, 0, 0 }, E_DEFHMASK, 0, 0, NULL, ": Print circuit inventory" }, +#ifdef HAVE_TSEARCH + { "check_ifparm", com_check_ifparm, TRUE, FALSE, + { 0, 0, 0, 0 }, E_DEFHMASK, 0, 0, + NULL, + ": Check model ifparm descriptors (for developpers)" }, +#endif { NULL, NULL, FALSE, FALSE, { 0, 0, 0, 0 }, E_DEFHMASK, 0, LOTS, NULL, diff --git a/src/frontend/device.c b/src/frontend/device.c index 376528278..cbb7b0cc8 100644 --- a/src/frontend/device.c +++ b/src/frontend/device.c @@ -1514,3 +1514,101 @@ com_alter_mod(wordlist *wl) tfree(arglist[0]); tfree(arglist[3]); } + + +#ifdef HAVE_TSEARCH + +#include + +static int +check_ifparm_compare(const void *a, const void *b) +{ + IFparm *pa = (IFparm *) a; + IFparm *pb = (IFparm *) b; + return pa->id - pb->id; +} + + +static void +check_ifparm_freenode(void *node) +{ + NG_IGNORE(node); +} + + +static void +check_ifparm(IFdevice *device, int instance_flag) +{ + int i, xcount; + IFparm *plist; + + if (instance_flag) { + plist = device->instanceParms; + if (!plist) + return; + fprintf(stderr," checking %s instanceParams\n", device->name); + xcount = *device->numInstanceParms; + } else { + plist = device->modelParms; + if (!plist) + return; + fprintf(stderr," checking %s modelParams\n", device->name); + xcount = *device->numModelParms; + } + + void *root = NULL; + + for (i = 0; i < xcount; i++) { + + IFparm *psearch = *(IFparm **) tsearch(plist + i, &root, + check_ifparm_compare); + + int type_err = (psearch->dataType ^ plist[i].dataType) & ~IF_REDUNDANT; + if (type_err) + fprintf(stderr, + " ERROR, dataType mismatch \"%s\" \"%s\" %08x\n", + psearch->keyword, plist[i].keyword, type_err); + + if ((plist[i].dataType & IF_REDUNDANT) && + (i == 0 || plist[i-1].id != plist[i].id)) { + fprintf(stderr, + "ERROR, alias \"%s\" has non matching predecessor \"%s\"\n", + plist[i].keyword, plist[i-1].keyword); + } + + if (i == 0) + continue; + + if (plist[i-1].id != plist[i].id) { + if (psearch != plist + i) + fprintf(stderr, + "ERROR: non neighbored duplicate id: \"%s\" \"%s\"\n", + psearch->keyword, plist[i].keyword); + } else if (!(plist[i].dataType & IF_REDUNDANT)) { + fprintf(stderr, + "ERROR: non R duplicate id: \"%s\" \"%s\"\n", + plist[i-1].keyword, plist[i].keyword); + } + } + +#ifdef HAVE_TDESTROY + tdestroy (root, check_ifparm_freenode); +#endif +} + + +void +com_check_ifparm(wordlist *wl) +{ + NG_IGNORE(wl); + + int k; + + for (k = 0; k < ft_sim->numDevices; k++) + if (ft_sim->devices[k]) { + check_ifparm(ft_sim->devices[k], 0); + check_ifparm(ft_sim->devices[k], 1); + } +} + +#endif