# ------------------------------------------------------------------------------
# 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.
# ------------------------------------------------------------------------------
"""Local variable declarations at the function level."""
import xml.etree.ElementTree as ET
from typing import Dict, List, TYPE_CHECKING
import chc.util.fileutil as UF
from chc.util.IndexedTable import IndexedTable, IndexedTableValue
from chc.app.CVarInfo import CVarInfo
if TYPE_CHECKING:
from chc.app.CFile import CFile
from chc.app.CFileDeclarations import CFileDeclarations
from chc.app.CFunction import CFunction
from chc.app.CLocation import CLocation
[docs]class CFunDeclarations:
"""Function parameter and local variable declarations.
This information is generated by cchcil/cHCilFunDeclarations and stored on
disk in <fname>_cfun.xml, in the <declarations> element.
"""
def __init__(self, cfun: "CFunction", xnode: ET.Element) -> None:
self._cfun = cfun
self.xnode = xnode
self._varinfos: Dict[int, CVarInfo] = {} # indexed by vid
self.local_varinfo_table = IndexedTable("local-varinfo-table")
self.initialize(xnode)
@property
def cfun(self) -> "CFunction":
return self._cfun
@property
def cfile(self) -> "CFile":
return self.cfun.cfile
@property
def fdecls(self) -> "CFileDeclarations":
return self.cfile.declarations
@property
def varinfos(self) -> Dict[int, CVarInfo]:
if len(self._varinfos) == 0:
for itv in self.local_varinfo_table.values():
vinfo = CVarInfo(self.cfile.declarations, itv)
self._varinfos[vinfo.vid] = vinfo
return self._varinfos
@property
def formals(self) -> List[CVarInfo]:
return [x for x in self.varinfos.values() if x.vparam > 0]
@property
def locals(self) -> List[CVarInfo]:
return [x for x in self.varinfos.values() if x.vparam == 0]
[docs] def get_varinfo(self, vid: int) -> CVarInfo:
if vid in self.varinfos:
return self.varinfos[vid]
return self.cfun.cfile.get_global_varinfo(vid)
[docs] def get_local_varinfo(self, ix: int) -> CVarInfo:
return CVarInfo(
self.cfile.declarations, self.local_varinfo_table.retrieve(ix))
[docs] def get_local_varinfo_map(self) -> Dict[int, IndexedTableValue]:
return self.local_varinfo_table.objectmap(self.get_local_varinfo)
[docs] def get_global_varinfo_by_name(self, name: str) -> CVarInfo:
return self.cfile.get_global_varinfo_by_name(name)
[docs] def get_location(self, ix: int) -> "CLocation":
return self.fdecls.get_location(ix)
# --------------------------- printing -------------------------------------
[docs] def objectmap_to_string(self, name: str) -> str:
if name == "local-varinfo":
objmap = self.get_local_varinfo_map()
lines: List[str] = []
for (ix, obj) in objmap.items():
lines.append(str(ix).rjust(3) + " " + str(obj))
return "\n".join(lines)
else:
raise UF.CHCError(
"Name: " + name + " does not correspond to a table")
def __str__(self) -> str:
lines: List[str] = []
lines.append("\nVarinfos:")
lines.append("-" * 40)
for vid in sorted(self.varinfos):
lines.append(str(vid).rjust(5) + " " + self.varinfos[vid].vname)
return "\n".join(lines)
[docs] def initialize(self, xnode: ET.Element) -> None:
xtable = xnode.find(self.local_varinfo_table.name)
if xtable is not None:
self.local_varinfo_table.reset()
self.local_varinfo_table.read_xml(xtable, "n")
else:
raise UF.CHCError(
"Local-varinfo-table not found in cfun for " + self.cfun.name)