/*
** 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
*/
/*
** cprim.c
*/
# include "splintMacros.nf"
# include "basic.h"
static bool cprim_isReal (cprim c)
{
return (cprim_isAnyReal (c));
}
static bool cprim_isNumeric (cprim c)
{
return (cprim_isReal (c) || cprim_isInt (c));
}
cprim
cprim_fromInt (int i)
{
if (i < CTX_UNKNOWN || i > CTX_LAST)
{
llcontbug (message ("cprim_fromInt: out of range: %d", i));
return CTX_UNKNOWN;
}
return (cprim) i;
}
/*
** not symmetric: c1 := c2 or c2 is passed as c1
** (if RELAXQUALS, c1 must be "bigger" than c2)
*/
static bool cprim_closeEnoughAux (cprim p_c1, cprim p_c2, bool p_deep);
bool
cprim_closeEnoughDeep (cprim c1, cprim c2)
{
/*
** If * c2 is passed as * c1
** Comparison is slightly different since it is safe to pass int as long,
** but not to pass int * as long *!
**
** For deep comparisons, +relaxquals does not permit the long/int break.
*/
return cprim_closeEnoughAux (c1, c2, TRUE);
}
bool
cprim_closeEnough (cprim c1, cprim c2)
{
return cprim_closeEnoughAux (c1, c2, FALSE);
}
static bool
cprim_closeEnoughAux (cprim c1, cprim c2, bool deep)
{
if (c1 == c2) return TRUE;
DPRINTF (("cprim close: %s / %s", cprim_unparse (c1), cprim_unparse (c2)));
if (c1 == CTX_ANYINTEGRAL)
{
if (context_getFlag (FLG_MATCHANYINTEGRAL)
|| context_getFlag (FLG_IGNOREQUALS))
{
return (cprim_isAnyInt (c2)
|| (cprim_isAnyChar (c2) && context_msgCharInt ()));
}
else if (context_getFlag (FLG_LONGINTEGRAL))
{
return (cprim_closeEnough (CTX_LINT, c2));
}
else if (context_getFlag (FLG_LONGUNSIGNEDINTEGRAL))
{
return (cprim_closeEnough (CTX_ULINT, c2));
}
else
{
return FALSE;
}
}
if (c1 == CTX_UNSIGNEDINTEGRAL)
{
/* We allow signed ints to match any integral if matchanyintegral is set */
if (context_getFlag (FLG_MATCHANYINTEGRAL)) {
return (cprim_isAnyInt (c2)
|| (cprim_isAnyChar (c2) && context_msgCharInt ()));
}
if (context_getFlag (FLG_IGNOREQUALS))
{
if (context_getFlag (FLG_IGNORESIGNS))
{
return (cprim_isAnyUnsignedInt (c2)
|| (cprim_isUnsignedChar (c2) && context_msgCharInt ()));
}
else
{
return (cprim_isAnyInt (c2)
|| (cprim_isAnyChar (c2) && context_msgCharInt ()));
}
}
else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
{
return (cprim_closeEnough (CTX_ULINT, c2));
}
else
{
return FALSE;
}
}
if (c1 == CTX_SIGNEDINTEGRAL)
{
/* We allow signed ints to match any integral if matchanyintegral is set */
if (context_getFlag (FLG_MATCHANYINTEGRAL)) {
return (cprim_isAnyInt (c2)
|| (cprim_isAnyChar (c2) && context_msgCharInt ()));
}
if (context_getFlag (FLG_IGNOREQUALS))
{
return (cprim_isAnyInt (c2)
|| (cprim_isAnyChar (c2) && context_msgCharInt ()));
}
else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
{
return (cprim_closeEnough (CTX_LINT, c2));
}
else
{
return FALSE;
}
}
if (c2 == CTX_ANYINTEGRAL)
{
if (context_getFlag (FLG_MATCHANYINTEGRAL))
{
return (cprim_isAnyInt (c1)
|| (cprim_isAnyChar (c1) && context_msgCharInt ()));
}
else if (context_getFlag (FLG_LONGINTEGRAL))
{
return (cprim_closeEnough (c1, CTX_LINT));
}
else if (context_getFlag (FLG_LONGUNSIGNEDINTEGRAL))
{
return (cprim_closeEnough (c1, CTX_ULINT));
}
else
{
return FALSE;
}
}
if (c2 == CTX_UNSIGNEDINTEGRAL)
{
if (context_getFlag (FLG_MATCHANYINTEGRAL))
{
return (cprim_isAnyInt (c1)
|| (cprim_isAnyChar (c1) && context_msgCharInt ()));
}
else if (context_getFlag (FLG_LONGUNSIGNEDUNSIGNEDINTEGRAL))
{
return (cprim_closeEnough (c1, CTX_ULINT));
}
else
{
return FALSE;
}
}
if (c2 == CTX_SIGNEDINTEGRAL)
{
if (context_getFlag (FLG_MATCHANYINTEGRAL))
{
return (cprim_isAnyInt (c2)
|| (cprim_isAnyChar (c2) && context_msgCharInt ()));
}
else if (context_getFlag (FLG_LONGSIGNEDINTEGRAL))
{
return (cprim_closeEnough (c1, CTX_LINT));
}
else
{
return FALSE;
}
}
DPRINTF (("cprim close: %s / %s", cprim_unparse (c1), cprim_unparse (c2)));
if (context_getFlag (FLG_RELAXTYPES))
{
if (cprim_isNumeric (c1) && cprim_isNumeric (c2)) return TRUE;
}
if (context_getFlag (FLG_IGNOREQUALS))
{
switch (c1)
{
case CTX_CHAR:
case CTX_UCHAR:
if (cprim_isAnyChar (c2)
|| (cprim_isAnyInt (c2) && (context_msgCharInt ()))) {
return TRUE;
}
break;
case CTX_DOUBLE:
case CTX_FLOAT:
case CTX_LDOUBLE:
if (c2 == CTX_DOUBLE || c2 == CTX_FLOAT || c2 == CTX_LDOUBLE) {
return TRUE;
}
break;
case CTX_INT:
case CTX_LINT:
case CTX_LLINT:
case CTX_ULLINT:
case CTX_SINT:
case CTX_UINT:
case CTX_ULINT:
case CTX_USINT:
if (cprim_isAnyInt (c2)
|| (cprim_isAnyChar (c2) && context_msgCharInt ())) {
return TRUE;
}
/*@fallthrough@*/
default:
;
}
}
if (context_getFlag (FLG_IGNORESIGNS))
{
if (c1 == CTX_UCHAR)
{
c1 = CTX_CHAR;
}
else if (c1 == CTX_UINT)
{
c1 = CTX_INT;
}
else if (c1 == CTX_ULINT)
{
c1 = CTX_LINT;
}
/* 2001-06-10: This fix provided by Jim Zelenka: */
else if (c1 == CTX_ULLINT)
{
c1 = CTX_LLINT;
}
/* End fix */
else if (c1 == CTX_USINT)
{
c1 = CTX_SINT;
}
else
{
;
}
if (c2 == CTX_UCHAR)
{
c2 = CTX_CHAR;
}
else if (c2 == CTX_UINT)
{
c2 = CTX_INT;
}
else if (c2 == CTX_ULINT)
{
c2 = CTX_LINT;
}
/* 2001-06-10: This fix provided by Jim Zelenka: */
else if (c2 == CTX_ULLINT)
{
c2 = CTX_LLINT;
}
/* End fix */
else if (c2 == CTX_USINT)
{
c2 = CTX_SINT;
}
else
{
;
}
}
if (c1 == c2) return TRUE;
if (context_getFlag (FLG_FLOATDOUBLE))
{
if (c1 == CTX_FLOAT && c2 == CTX_DOUBLE)
{
return TRUE;
}
if (c2 == CTX_FLOAT && c1 == CTX_DOUBLE)
{
return TRUE;
}
}
DPRINTF (("cprim close: %s / %s", cprim_unparse (c1), cprim_unparse (c2)));
if (!deep && context_getFlag (FLG_RELAXQUALS))
{
switch (c1)
{
case CTX_DOUBLE:
return (c2 == CTX_FLOAT);
case CTX_LDOUBLE:
return (c2 == CTX_DOUBLE || c2 == CTX_FLOAT);
case CTX_SINT:
return ((c2 == CTX_CHAR && context_msgCharInt ())
|| (c2 == CTX_INT && context_msgShortInt ())
|| (c2 == CTX_LINT && context_msgShortInt () && context_msgLongInt ()));
case CTX_INT:
return ((c2 == CTX_SINT
|| (cprim_isAnyChar (c2) && context_msgCharInt ())
|| (c2 == CTX_LINT && context_msgLongInt ())));
case CTX_LLINT:
return (c2 == CTX_SINT
|| c2 == CTX_INT
|| c2 == CTX_LINT
|| (cprim_isAnyChar (c2) && context_msgCharInt ()));
case CTX_ULLINT:
return (c2 == CTX_USINT
|| c2 == CTX_UINT
|| c2 == CTX_ULINT
/* 2001-06-10: This fix provided by Jim Zelenka: */
|| (cprim_isAnyChar (c2) && context_msgCharInt ()));
case CTX_LINT:
return (c2 == CTX_SINT
|| c2 == CTX_INT
|| (cprim_isAnyChar (c2) && context_msgCharInt ()));
case CTX_UINT:
return (c2 == CTX_USINT
|| (c2 == CTX_UCHAR && context_msgCharInt ()));
case CTX_USINT:
return (c2 == CTX_UCHAR && context_msgCharInt ());
case CTX_ULINT:
/* 2001-06-10: This fix provided by Jim Zelenka: */
return (c2 == CTX_UINT || c2 == CTX_USINT
|| (c2 == CTX_UCHAR && context_msgCharInt()));
case CTX_UCHAR:
return (c2 == CTX_UINT && context_msgCharInt ());
case CTX_CHAR:
return ((c2 == CTX_INT || c2 == CTX_SINT)
&& context_msgCharInt ());
default:
return FALSE;
}
}
else
{
switch (c1)
{
case CTX_DOUBLE:
case CTX_LDOUBLE:
return FALSE;
case CTX_SINT:
if (c2 == CTX_INT && context_msgShortInt ()) {
return TRUE;
}
/*@fallthrough@*/
case CTX_INT:
if (c2 == CTX_INT && context_msgLongInt ()) {
return TRUE;
}
if (c2 == CTX_SINT && context_msgShortInt ()) {
return TRUE;
}
/*@fallthrough@*/
case CTX_LINT:
if (c2 == CTX_INT && context_msgLongInt ()) {
return TRUE;
}
/*@fallthrough@*/
case CTX_LLINT:
return (c2 == CTX_CHAR && context_msgCharInt ());
case CTX_UINT:
case CTX_USINT:
case CTX_ULINT:
case CTX_ULLINT:
return (c2 == CTX_UCHAR && context_msgCharInt ());
case CTX_UCHAR:
return (c2 == CTX_UINT && context_msgCharInt ());
case CTX_CHAR:
return ((c2 == CTX_INT || c2 == CTX_SINT)
&& context_msgCharInt ());
default:
return FALSE;
}
}
}
/*@only@*/ cstring
cprim_unparse (cprim c)
{
switch (c)
{
case CTX_UNKNOWN:
return cstring_makeLiteral ("-");
case CTX_VOID:
return cstring_makeLiteral ("void");
case CTX_CHAR:
return cstring_makeLiteral ("char");
case CTX_UCHAR:
return cstring_makeLiteral ("unsigned char");
case CTX_DOUBLE:
return cstring_makeLiteral ("double");
case CTX_LDOUBLE:
return cstring_makeLiteral ("long double");
case CTX_FLOAT:
return cstring_makeLiteral ("float");
case CTX_INT:
return cstring_makeLiteral ("int");
case CTX_LINT:
return cstring_makeLiteral ("long int");
case CTX_LLINT:
return cstring_makeLiteral ("long long");
case CTX_ULLINT:
return cstring_makeLiteral ("unsigned long long");
case CTX_SINT:
return cstring_makeLiteral ("short int");
case CTX_UINT:
return cstring_makeLiteral ("unsigned int");
case CTX_ULINT:
return cstring_makeLiteral ("unsigned long int");
case CTX_USINT:
return cstring_makeLiteral ("unsigned short int");
case CTX_UNSIGNEDINTEGRAL:
return cstring_makeLiteral ("arbitrary unsigned integral type");
case CTX_SIGNEDINTEGRAL:
return cstring_makeLiteral ("arbitrary signed integral type");
case CTX_ANYINTEGRAL:
return cstring_makeLiteral ("arbitrary integral type");
default:
return cstring_makeLiteral ("unknown prim");
}
}
bool cprim_isInt (cprim c)
{
return (cprim_isAnyInt (c)
|| (cprim_isAnyChar (c) && context_msgCharInt ()));
}
int cprim_getExpectedBits (cprim c)
{
/* Any basis to these numbers? Just guesses for now..., check ISO spec */
switch (c)
{
case CTX_UNKNOWN:
return 0;
case CTX_VOID:
return 0;
case CTX_CHAR:
return 8;
case CTX_UCHAR:
return 8;
case CTX_DOUBLE:
return 64;
case CTX_LDOUBLE:
return 128;
case CTX_FLOAT:
return 32;
case CTX_INT:
return 32;
case CTX_LINT:
return 64;
case CTX_LLINT:
return 128;
case CTX_ULLINT:
return 128;
case CTX_SINT:
return 8;
case CTX_UINT:
return 32;
case CTX_ULINT:
return 64;
case CTX_USINT:
return 8;
case CTX_UNSIGNEDINTEGRAL:
return 64;
case CTX_SIGNEDINTEGRAL:
return 64;
case CTX_ANYINTEGRAL:
return 64;
default:
return 0;
}
}
syntax highlighted by Code2HTML, v. 0.9.1