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
This commit is contained in:
rlar 2017-04-08 19:43:23 +02:00
parent cf9dbff890
commit 1e6b809af8
4 changed files with 106 additions and 1 deletions

View File

@ -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])

View File

@ -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

View File

@ -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,

View File

@ -1514,3 +1514,101 @@ com_alter_mod(wordlist *wl)
tfree(arglist[0]);
tfree(arglist[3]);
}
#ifdef HAVE_TSEARCH
#include <search.h>
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