/*
** Splint - annotation-assisted static program checker
** Copyright (C) 1994-2003 University of Virginia,
** Massachusetts Institute of Technology
**
** This program 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 of the License, or (at your
** option) any later version.
**
** This program 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.
**
** The GNU General Public License is available from http://www.gnu.org/ or
** the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
** MA 02111-1307, USA.
**
** For information on splint: info@splint.org
** To report a bug: splint-bug@splint.org
** For more information: http://www.splint.org
*/
/*
** uentryList.c (from slist_template.c)
*/
# include "splintMacros.nf"
# include "basic.h"
/*@only@*/ /*@notnull@*/ uentryList
uentryList_new ()
{
uentryList s = (uentryList) dmalloc (sizeof (*s));
s->nelements = 0;
s->nspace = uentryListBASESIZE;
s->elements = (uentry *)
dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
s->current = 0;
return (s);
}
/*@only@*/ uentryList
uentryList_single (/*@keep@*/ uentry el)
{
uentryList s = (uentryList) dmalloc (sizeof (*s));
s->nelements = 1;
s->nspace = uentryListBASESIZE - 1;
s->elements = (uentry *) dmalloc (sizeof (*s->elements) * uentryListBASESIZE);
s->elements[0] = el;
s->current = 0;
return (s);
}
static void
uentryList_grow (uentryList s)
{
int i;
uentry *newelements;
llassert (!uentryList_isUndefined (s));
s->nspace += uentryListBASESIZE;
newelements = (uentry *) dmalloc (sizeof (*newelements)
* (s->nelements + s->nspace));
for (i = 0; i < s->nelements; i++)
{
newelements[i] = s->elements[i];
}
sfree (s->elements);
s->elements = newelements;
}
void uentryList_clear (uentryList s)
{
if (uentryList_isUndefined (s))
{
;
}
else
{
s->nspace += s->nelements;
s->nelements = 0;
}
}
uentryList uentryList_add (uentryList s, /*@keep@*/ uentry el)
{
if (uentryList_isUndefined (s))
{
s = uentryList_new ();
}
if (s->nspace <= 0)
uentryList_grow (s);
s->nspace--;
s->elements[s->nelements] = el;
s->nelements++;
return s;
}
/*@only@*/ cstring
uentryList_unparse (uentryList s)
{
cstring st = cstring_undefined;
int i;
if (uentryList_isDefined (s))
{
for (i = 0; i < uentryList_size (s); i++)
{
if (i == 0)
{
st = message ("%q;", uentry_unparse (s->elements[i]));
}
else
st = message ("%q %q;", st, uentry_unparse (s->elements[i]));
}
}
return (st);
}
/*@unused@*/ /*@only@*/ cstring
uentryList_unparseFull (uentryList s)
{
cstring st = cstring_undefined;
int i;
if (uentryList_isDefined (s))
{
for (i = 0; i < uentryList_size (s); i++)
{
if (i == 0)
{
st = message ("%q;", uentry_unparseFull (s->elements[i]));
}
else
{
st = message ("%q %q;", st, uentry_unparseFull (s->elements[i]));
}
}
}
return (st);
}
cstring uentryList_unparseParams (uentryList s)
{
int i;
cstring st = cstring_undefined;
if (uentryList_isUndefined (s))
{
return st;
}
else if (uentryList_isVoid (s))
{
return (cstring_makeLiteral ("void"));
}
else
{
for (i = 0; i < uentryList_size (s); i++)
{
if (i == 0)
{
st = message ("%s", ctype_unparse (uentry_getType (s->elements[i])));
}
else
{
st = message ("%q, %s", st, ctype_unparse (uentry_getType (s->elements[i])));
}
}
return st;
}
}
bool uentryList_matchParams (uentryList p1, uentryList p2, bool force, bool arg)
{
int sz1 = uentryList_size (p1);
int sz2 = uentryList_size (p2);
int i;
if (p1 == p2) return TRUE;
if (uentryList_isMissingParams (p1) || uentryList_isMissingParams (p2))
{
return TRUE;
}
if (sz1 != sz2)
return FALSE;
for (i = 0; i < sz1; i++)
{
if (!ctype_genMatch (uentry_getType (p1->elements[i]),
uentry_getType (p2->elements[i]),
force, arg, FALSE, FALSE))
{
return FALSE;
}
}
return TRUE;
}
/*@only@*/ cstring
uentryList_unparseAbbrev (uentryList p)
{
bool first = TRUE;
cstring s = cstring_undefined;
int i = 0;
if (uentryList_isUndefined (p))
return s;
if (uentryList_size (p) == 0)
return cstring_makeLiteral ("void");
for (i = 0; i < p->nelements && i < uentryList_abbrevBreadth; i++)
{
if (first)
{
s = message ("%q;", uentry_unparseAbbrev (p->elements[i]));
first = FALSE;
}
else
{
s = message ("%q %q;", s, uentry_unparseAbbrev (p->elements[i]));
}
}
if (i != uentryList_size (p))
s = message ("%q, ...", s);
return (s);
}
static int
uentryList_lookupDirectName (uentryList s, cstring name)
{
if (uentryList_isDefined (s))
{
int i;
for (i = 0; i < uentryList_size (s); i++)
{
if (cstring_equal (name, uentry_rawName (s->elements[i])))
{
return i;
}
}
}
return -1;
}
int
uentryList_lookupRealName (uentryList s, cstring name)
{
if (uentryList_isDefined (s))
{
int i;
for (i = 0; i < uentryList_size (s); i++)
{
cstring uname = uentry_getName (s->elements[i]);
if (cstring_equal (name, uname))
{
cstring_free (uname);
return i;
}
cstring_free (uname);
}
}
return -1;
}
uentryList uentryList_copy (uentryList s)
{
if (uentryList_isDefined (s))
{
uentryList t = (uentryList) dmalloc (sizeof (*t));
int i;
t->nelements = s->nelements;
t->nspace = 0;
t->current = s->current;
if (s->nelements > 0)
{
t->elements = (uentry *) dmalloc (sizeof (*t->elements) * t->nelements);
for (i = 0; i < s->nelements; i++)
{
t->elements[i] = uentry_copy (s->elements[i]);
}
}
else
{
t->elements = NULL;
}
return t;
}
else
{
return uentryList_undefined;
}
}
void
uentryList_free (uentryList s)
{
if (!uentryList_isUndefined (s))
{
int i;
for (i = 0; i < s->nelements; i++)
{
uentry_free (s->elements[i]);
}
sfree (s->elements);
sfree (s);
}
}
void
uentryList_freeShallow (uentryList s)
{
if (!uentryList_isUndefined (s))
{
/*@-mustfree@*/ /* free shallow does not free the element */
sfree (s->elements);
/*@=mustfree@*/
sfree (s);
}
}
bool
uentryList_isVoid (uentryList cl)
{
if (cl != NULL && cl->nelements == 1)
{
return (ctype_isVoid (ctype_realType (uentry_getType (cl->elements[0]))));
}
return FALSE;
}
/*@exposed@*/ uentry
uentryList_getN (uentryList p, int n)
{
llassert (uentryList_isDefined (p));
if (n < 0 || (n >= uentryList_size (p)))
{
llcontbug (message ("uentryList_getN: out of range: %d (size %d)",
n, uentryList_size (p)));
return uentry_undefined;
}
return (p->elements[n]);
}
void uentryList_fixMissingNames (uentryList cl)
{
uentryList_elements (cl, ce)
{
if (!uentry_hasRealName (ce))
{
ctype ct = uentry_getType (ce);
if (ctype_isUA (ct))
{
uentry_setName (ce, usymtab_getTypeEntryName (ctype_typeId (ct)));
}
else
{
llbug (message ("uentryList_fixMissingNames: not UA: %s",
ctype_unparse (ct)));
}
uentry_setType (ce, ctype_int);
}
} end_uentryList_elements;
}
void uentryList_fixImpParams (uentryList cl)
{
if (context_getFlag (FLG_PARAMIMPTEMP))
{
uentryList_elements (cl, ce)
{
sRef s = uentry_getSref (ce);
alkind ak = sRef_getAliasKind (s);
if (alkind_isUnknown (ak) || alkind_isImplicit (ak))
{
exkind ek = sRef_getExKind (s);
if (exkind_isKnown (ek))
{
sRef_setAliasKind (s, AK_IMPDEPENDENT, fileloc_undefined);
}
else
{
sRef_setAliasKind (s, AK_IMPTEMP, fileloc_undefined);
}
}
else
{
}
} end_uentryList_elements;
}
}
int
uentryList_compareParams (uentryList s, uentryList t)
{
int i, sz;
if (s == t) return 0;
if (uentryList_isUndefined (s)) return 1;
if (uentryList_isUndefined (t)) return -1;
sz = uentryList_size (s);
INTCOMPARERETURN (uentryList_size (t), sz);
for (i = 0; i < sz; i++)
{
COMPARERETURN (uentry_compare (s->elements[i], t->elements[i]));
}
return 0;
}
int
uentryList_compareStrict (uentryList s, uentryList t)
{
int i, sz;
if (s == t)
{
return 0;
}
if (uentryList_isMissingParams (s))
{
if (uentryList_isMissingParams (t))
{
return 0;
}
else
{
return 1;
}
}
else
{
if (uentryList_isMissingParams (t))
{
return -1;
}
else
{
sz = uentryList_size (s);
INTCOMPARERETURN (uentryList_size (t), sz);
for (i = 0; i < sz; i++)
{
COMPARERETURN (uentry_compareStrict (s->elements[i], t->elements[i]));
}
return 0;
}
}
}
int
uentryList_compareFields (uentryList s, uentryList t)
{
int i, sz;
if (s == t) return 0;
if (uentryList_isUndefined (s))
return 1;
if (uentryList_isUndefined (t))
return -1;
sz = uentryList_size (s);
if (uentryList_size (t) != sz)
{
return (int_compare (sz, uentryList_size (t)));
}
for (i = 0; i < sz; i++)
{
uentry se = s->elements[i];
uentry te = t->elements[i];
int namecmp = cstring_compare (uentry_rawName (se), uentry_rawName (te));
if (namecmp == 0)
{
int uc = uentry_compare (s->elements[i], t->elements[i]);
if (uc != 0)
{
DPRINTF (("Bad compare: %s / %s",
uentry_unparseFull (s->elements [i]),
uentry_unparseFull (t->elements [i])));
return uc;
}
}
else
{
return (namecmp);
}
}
return 0;
}
/*@exposed@*/ uentry
uentryList_current (uentryList s)
{
llassert (uentryList_isDefined (s));
llassert (!(s->current < 0 || (s->current >= s->nelements)));
return (s->elements[s->current]);
}
cstring
uentryList_dumpParams (uentryList s)
{
cstring st = cstring_undefined;
if (uentryList_isUndefined (s)) return st;
uentryList_elements (s, current)
{
DPRINTF (("Dump param: %s", uentry_unparse (current)));
st = message ("%q%q,", st, uentry_dumpParam (current));
} end_uentryList_elements;
return st;
}
/*@only@*/ cstring
uentryList_dumpFields (uentryList s)
{
cstring st = cstring_undefined;
if (uentryList_isUndefined (s)) return st;
uentryList_elements (s, current)
{
if (!uentry_isVariable (current))
{
llassert (uentry_isFunction (current));
DPRINTF (("Dump field: %s", uentry_unparse (current)));
st = message ("%q!%q,", st, uentry_dump (current));
}
else
{
DPRINTF (("Dump field: %s", uentry_unparse (current)));
st = message ("%q%q,", st, uentry_dump (current));
}
} end_uentryList_elements;
return st;
}
/*@only@*/ uentryList
uentryList_undumpFields (char **s, fileloc loc)
{
uentryList ul = uentryList_new ();
while (**s != '\0' && **s != '}')
{
if (**s == '!')
{
reader_checkChar (s, '!');
ul = uentryList_add (ul, uentry_undump (ekind_function, loc, s));
}
else
{
ul = uentryList_add (ul, uentry_undump (ekind_variable, loc, s));
}
reader_checkChar (s, ',');
}
reader_checkChar (s, '}');
return ul;
}
/*@only@*/ uentryList
uentryList_undump (char **s)
{
char c;
uentryList pn = uentryList_new ();
int paramno = 0;
c = **s;
while (c != '#' && c != '@' && c != ')')
{
uentry ue = uentry_undump (ekind_variable, g_currentloc, s);
if (!uentry_isUndefined (ue))
{
pn = uentryList_add (pn, ue);
}
else
{
uentry_free (ue);
}
reader_checkChar (s, ',');
c = **s;
paramno++;
}
reader_checkChar (s, ')');
return pn;
}
void
uentryList_reset (uentryList s)
{
if (uentryList_isUndefined (s)) return;
s->current = 0;
}
bool
uentryList_isFinished (uentryList s)
{
if (uentryList_isUndefined (s)) return TRUE;
return (s->current > s->nelements - 1);
}
void
uentryList_advanceSafe (uentryList s)
{
if (uentryList_isUndefined (s)) return;
s->current++;
if (s->current > s->nelements)
{
s->current = s->nelements;
}
}
int
uentryList_size (uentryList s)
{
if (uentryList_isUndefined (s)) return 0;
if (uentryList_isVoid (s))
return 0;
return s->nelements;
}
bool
uentryList_isMissingParams (uentryList s)
{
return (uentryList_isUndefined (s) || s->nelements == 0);
}
bool uentryList_hasReturned (uentryList ul)
{
uentryList_elements (ul, current)
{
if (uentry_isReturned (current)) return TRUE;
} end_uentryList_elements;
return FALSE;
}
/*@exposed@*/ uentry
uentryList_lookupField (uentryList f, cstring name)
{
int i = uentryList_lookupDirectName (f, name);
if (i >= 0)
{
return (uentryList_getN (f, i));
}
else
{
uentryList_elements (f, el)
{
if (uentry_isUnnamedVariable (el))
{
ctype ct = uentry_getType (el);
if (ctype_isStruct (ct) || ctype_isUnion (ct))
{
uentryList fields = ctype_getFields (ct);
uentry ue = uentryList_lookupField (fields, name);
if (uentry_isValid (ue))
{
return ue;
}
}
}
}
end_uentryList_elements ;
return uentry_undefined;
}
}
/*@only@*/ uentryList
uentryList_mergeFields (/*@only@*/ uentryList f1, /*@only@*/ uentryList f2)
{
DPRINTF (("Merge: %s + %s", uentryList_unparse (f1), uentryList_unparse (f2)));
if (uentryList_isUndefined (f1))
{
return (f2);
}
if (uentryList_isDefined (f2))
{
uentryList_elements (f2, current)
{
uentry old = uentryList_lookupField (f1, uentry_rawName (current));
if (uentry_isValid (old))
{
voptgenerror
(FLG_SYNTAX,
message ("Field name reused: %s", uentry_rawName (current)),
uentry_whereDefined (current));
llgenmsg (message ("Previous use of %s", uentry_rawName (current)),
uentry_whereDefined (old));
}
/* okay to use exposed current since f2 is killed */
/*@-exposetrans@*/ /*@-dependenttrans@*/
f1 = uentryList_add (f1, current);
/*@=exposetrans@*/ /*@=dependenttrans@*/
} end_uentryList_elements;
sfree (f2->elements);
sfree (f2);
}
return (f1);
}
void
uentryList_showFieldDifference (uentryList p1, uentryList p2)
{
uentry cp1, cp2;
int index;
llassert (NOALIAS (p1, p2));
llassert (uentryList_isDefined (p1));
llassert (uentryList_isDefined (p2));
for (index = 0; index < p1->nelements; index++)
{
cp1 = p1->elements[index];
if (index == p2->nelements)
{
llgenindentmsg
(message ("Field present in %s, missing in %rdeclaration: %q",
uentry_specDeclName (cp1),
uentry_isDeclared (cp1),
uentry_unparse (cp1)),
uentry_whereEither (cp1));
return;
}
cp2 = p2->elements[index];
if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))))
{
llgenindentmsg
(message ("Field %s in %s corresponds to %s in %rdeclaration",
uentry_rawName (cp1),
uentry_specOrDefName (cp1),
uentry_rawName (cp2),
uentry_isCodeDefined (cp1)),
uentry_whereDefined (cp2));
uentry_showWhereLastPlain (cp1);
return;
}
else
{
/* evs 2000-07-25 was ctype_match, should match uentryList_matchFields */
if (!ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))
{
llgenindentmsg
(message ("Field %s %rdeclared as %s, %s as %s",
uentry_rawName (cp2),
uentry_isCodeDefined (cp1),
ctype_unparse (uentry_getType (cp1)),
uentry_specOrDefName (cp2),
ctype_unparse (uentry_getType (cp2))),
uentry_whereDefined (cp2));
uentry_showWhereLastPlain (cp1);
return;
}
}
}
if (index != p2->nelements)
{
cp2 = p2->elements[index];
llgenindentmsg
(message ("Extra field in new declaration: %q",
uentry_unparse (cp2)),
uentry_whereEither (cp2));
return;
}
llbug (message ("uentryList_showFieldDifference: match: %q / %q",
uentryList_unparse (p1), uentryList_unparse (p2)));
}
bool
uentryList_equivFields (uentryList p1, uentryList p2)
{
return (uentryList_compareFields (p1, p2) == 0);
}
bool
uentryList_matchFields (uentryList p1, uentryList p2)
{
int index;
uentry cp1, cp2;
if (p1 == p2)
{
return (TRUE);
}
if (uentryList_isEmpty (p1) || uentryList_isEmpty (p2))
{
return (TRUE);
}
if (uentryList_size (p1) != uentryList_size (p2))
{
return FALSE;
}
for (index = 0; index < p1->nelements; index++)
{
cp1 = p1->elements[index];
cp2 = p2->elements[index];
/*
** Should compare uentry's --- need to fix report errors too.
*/
if (!(cstring_equal (uentry_rawName (cp1), uentry_rawName (cp2))
&& (ctype_almostEqual (uentry_getType (cp1), uentry_getType (cp2)))))
{
return FALSE;
}
}
return TRUE;
}
syntax highlighted by Code2HTML, v. 0.9.1