# ------------------------------------------------------------------------------
# CodeHawk C Analyzer
# Author: Henny Sipma
# ------------------------------------------------------------------------------
# The MIT License (MIT)
#
# Copyright (c) 2017-2020 Kestrel Technology LLC
# Copyright (c) 2020-2022 Henny B. Sipma
# Copyright (c) 2023-2024 Aarno Labs LLC
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
# ------------------------------------------------------------------------------
"""Object representation of CIL attrparam sum type."""
from typing import List, Tuple, TYPE_CHECKING
from chc.app.CDictionaryRecord import CDictionaryRecord, cdregistry
import chc.util.fileutil as UF
import chc.util.IndexedTable as IT
from chc.util.loggingutil import chklogger
if TYPE_CHECKING:
from chc.app.CDictionary import CDictionary
from chc.app.CTyp import CTyp
from chc.app.CTypsig import CTypsig
[docs]class CAttr(CDictionaryRecord):
"""Attribute that comes with a C type."""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CDictionaryRecord.__init__(self, cd, ixval)
@property
def is_int(self) -> bool:
return False
@property
def is_str(self) -> bool:
return False
@property
def is_cons(self) -> bool:
return False
@property
def is_sizeof(self) -> bool:
return False
@property
def is_sizeofe(self) -> bool:
return False
@property
def is_sizeofs(self) -> bool:
return False
@property
def is_alignof(self) -> bool:
return False
@property
def is_alignofe(self) -> bool:
return False
@property
def is_alignofs(self) -> bool:
return False
@property
def is_unop(self) -> bool:
return False
@property
def is_binop(self) -> bool:
return False
@property
def is_dot(self) -> bool:
return False
@property
def is_star(self) -> bool:
return False
@property
def is_addrof(self) -> bool:
return False
@property
def is_index(self) -> bool:
return False
@property
def is_question(self) -> bool:
return False
def __str__(self) -> str:
return "attrparam:" + self.tags[0]
[docs]@cdregistry.register_tag("aint", CAttr)
class CAttrInt(CAttr):
"""Integer attribute.
args[0]: integer value
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def intvalue(self) -> int:
return int(self.args[0])
@property
def is_int(self) -> bool:
return True
def __str__(self) -> str:
return "aint(" + str(self.intvalue) + ")"
[docs]@cdregistry.register_tag("astr", CAttr)
class CAttrStr(CAttr):
"""String attribute.
* args[0]: index in string table of string attribute
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def stringvalue(self) -> str:
return self.cd.get_string(self.args[0])
@property
def is_str(self) -> bool:
return True
def __str__(self) -> str:
return "astr(" + str(self.stringvalue) + ")"
[docs]@cdregistry.register_tag("acons", CAttr)
class CAttrCons(CAttr):
"""Constructed attributes.
* tags[1]: name
* args[0..]: indices of attribute parameters in cdictionary.
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def name(self) -> str:
return self.tags[1]
@property
def params(self) -> List[CAttr]:
return [self.cd.get_attrparam(int(i)) for i in self.args]
@property
def is_cons(self) -> bool:
return True
def __str__(self) -> str:
return "acons(" + str(self.name) + ")"
[docs]@cdregistry.register_tag("asizeof", CAttr)
class CAttrSizeOf(CAttr):
"""Attribute that describes the size of a type.
* args[0]: index of target type in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def typ(self) -> "CTyp":
return self.cd.get_typ(int(self.args[0]))
@property
def is_sizeof(self) -> bool:
return True
def __str__(self) -> str:
return "asizeof(" + str(self.typ) + ")"
[docs]@cdregistry.register_tag("asizeofe", CAttr)
class CAttrSizeOfE(CAttr):
"""Size of an attribute parameter.
* args[0]: index of argument parameter in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def param(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[0]))
@property
def is_sizeofe(self) -> bool:
return True
def __str__(self) -> str:
return "asizeofe(" + str(self.param) + ")"
[docs]@cdregistry.register_tag("asizeofs", CAttr)
class CAttrSizeOfS(CAttr):
"""Replacement ASizeOf in type signatures.
* args[0]: index of target typsig in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def typsig(self) -> "CTypsig":
return self.cd.get_typsig(int(self.args[0]))
@property
def is_sizeofs(self) -> bool:
return True
def __str__(self) -> str:
return "asizeofs(" + str(self.typsig) + ")"
[docs]@cdregistry.register_tag("aalignof", CAttr)
class CAttrAlignOf(CAttr):
"""Alignment of a type.
* args[0]: index of target type in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def typ(self) -> "CTyp":
return self.cd.get_typ(int(self.args[0]))
@property
def is_alignof(self) -> bool:
return True
def __str__(self) -> str:
return "aalignof(" + str(self.typ) + ")"
[docs]@cdregistry.register_tag("aalignofe", CAttr)
class CAttrAlignOfE(CAttr):
"""Alignment of an attribute parameter.
* args[0]: index of attribute parameter in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def param(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[0]))
@property
def is_alignofe(self) -> bool:
return True
def __str__(self) -> str:
return "aalignofe(" + str(self.param) + ")"
[docs]@cdregistry.register_tag("aalignofs", CAttr)
class CAttrAlignOfS(CAttr):
"""Alignment of a type signature.
* args[0]: target type signature
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def typsig(self) -> "CTypsig":
return self.cd.get_typsig(int(self.args[0]))
@property
def is_alignofs(self) -> bool:
return True
def __str__(self) -> str:
return "aalignofs(" + str(self.typsig) + ")"
[docs]@cdregistry.register_tag("aunop", CAttr)
class CAttrUnOp(CAttr):
"""Unary attribute parameter operation.
* tags[1]: operator
* args[0]: index of attribute parameter in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def op(self) -> str:
return self.tags[1]
@property
def param(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[0]))
@property
def is_unop(self) -> bool:
return True
def __str__(self) -> str:
return "aunop(" + self.op + "," + str(self.param) + ")"
[docs]@cdregistry.register_tag("abinop", CAttr)
class CAttrBinOp(CAttr):
"""Binary attribute parameter operation.
* tags[1]: operator
* args[0]: index of first attribute parameter in cdictionary
* args[1]: index of second attribute parameter in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def op(self) -> str:
return self.tags[1]
@property
def param1(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[0]))
@property
def param2(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[1]))
@property
def is_binop(self) -> bool:
return True
def __str__(self) -> str:
return (
"abinop("
+ str(self.param1)
+ " "
+ self.op
+ " "
+ str(self.param2)
+ ")"
)
[docs]@cdregistry.register_tag("adot", CAttr)
class CAttrDot(CAttr):
"""Dot operator on attributes.
* tags[1]: string suffix
* args[0]: index of attribute parameter in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def suffix(self) -> str:
return self.tags[1]
@property
def param(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[0]))
@property
def is_dot(self) -> bool:
return True
def __str__(self) -> str:
return "adot(" + str(self.param) + "." + self.suffix + ")"
[docs]@cdregistry.register_tag("astr", CAttr)
class CAttrStar(CAttr):
"""Star operation on attribute.
* args[0]: index of attribute parameter in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def param(self) -> CAttr:
chklogger.logger.info("Self-referential attribute (*)")
if self.index == int(self.args[0]):
return self
else:
return self.cd.get_attrparam(int(self.args[0]))
@property
def is_star(self) -> bool:
return True
def __str__(self) -> str:
if self.index == self.args[0]:
return "astar()"
else:
return "astar(" + str(self.param) + ")"
[docs]@cdregistry.register_tag("aaddrof", CAttr)
class CAttrAddrOf(CAttr):
"""Addressof operator on attribute.
* args[0]: index of attribute parameter in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def param(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[0]))
@property
def is_addrof(self) -> bool:
return True
def __str__(self) -> str:
return "aaddrof(" + str(self.param) + ")"
[docs]@cdregistry.register_tag("aindex", CAttr)
class CAttrIndex(CAttr):
"""Index operation on attributes
* args[0]: index of first attribute parameter in cdictionary
* args[1]: index of second attribute parameter in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def param1(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[0]))
@property
def param2(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[1]))
@property
def is_index(self) -> bool:
return True
def __str__(self) -> str:
return "aindex(" + str(self.param1) + "," + str(self.param2) + ")"
[docs]@cdregistry.register_tag("aquestion", CAttr)
class CAttrQuestion(CAttr):
"""Question operator on attributes
* args[0]: index of first attribute paramter in cdictionary
* args[1]: index of second attribute parameter in cdictionary
* args[2]: index of third attribute parameter in cdictionary
"""
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CAttr.__init__(self, cd, ixval)
@property
def param1(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[0]))
@property
def param2(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[1]))
@property
def param3(self) -> CAttr:
return self.cd.get_attrparam(int(self.args[2]))
def __str__(self) -> str:
return (
"aquestion("
+ str(self.param1)
+ ","
+ str(self.param2)
+ ","
+ str(self.param3)
+ ")"
)
[docs]class CAttribute(CDictionaryRecord):
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CDictionaryRecord.__init__(self, cd, ixval)
@property
def name(self) -> str:
return self.tags[0]
@property
def params(self) -> List[CAttr]:
return [self.cd.get_attrparam(int(i)) for i in self.args]
def __str__(self) -> str:
return self.name + ": " + ",".join([str(p) for p in self.params])
[docs]class CAttributes(CDictionaryRecord):
def __init__(self, cd: "CDictionary", ixval: IT.IndexedTableValue) -> None:
CDictionaryRecord.__init__(self, cd, ixval)
@property
def attributes(self) -> List[CAttribute]:
return [self.cd.get_attribute(int(i)) for i in self.args]
@property
def length(self) -> int:
return len(self.attributes)
def __str__(self) -> str:
return ",".join([str(p) for p in self.attributes])