From d48237b8c89673f41ebe49d1bf4a55e4f6182380 Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 24 Jun 2023 09:34:56 +0100 Subject: [PATCH] Partial implementation of vhpiCaseNameP for declarations --- src/util.c | 8 +++++ src/util.h | 1 + src/vhpi/vhpi-model.c | 60 ++++++++++++++++++++++++++++++++++--- test/regress/gold/vhpi1.txt | 3 ++ test/regress/vhpi1.vhd | 1 + test/vhpi/vhpi1.c | 8 +++++ 6 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/util.c b/src/util.c index 7b97d64ed..5e69c97de 100644 --- a/src/util.c +++ b/src/util.c @@ -244,6 +244,14 @@ char *xstrdup(const char *str) return copy; } +char *xstrndup(const char *str, size_t n) +{ + char *copy = strndup(str, n); + if (copy == NULL) + fatal("memory exhausted (strndup)"); + return copy; +} + char *xvasprintf(const char *fmt, va_list ap) { char *strp = NULL; diff --git a/src/util.h b/src/util.h index 28a89bba1..a3a640a18 100644 --- a/src/util.h +++ b/src/util.h @@ -187,6 +187,7 @@ void *xrealloc_array(void *ptr, size_t nelems, size_t size) RETURNS_NONNULL; void *xrealloc_flex(void *ptr, size_t fixed, size_t nelems, size_t size) RETURNS_NONNULL; char *xstrdup(const char *str) RETURNS_NONNULL; +char *xstrndup(const char *str, size_t n) RETURNS_NONNULL; char *xvasprintf(const char *fmt, va_list ap) RETURNS_NONNULL; char *xasprintf(const char *fmt, ...) diff --git a/src/vhpi/vhpi-model.c b/src/vhpi/vhpi-model.c index 9440dd1cc..a47fb2c24 100644 --- a/src/vhpi/vhpi-model.c +++ b/src/vhpi/vhpi-model.c @@ -603,6 +603,14 @@ static vhpiCharT *new_string(const char *s) return p; } +static vhpiCharT *new_string_n(const char *s, size_t n) +{ + vhpiCharT *p = shash_get(strtab, s); + if (p == NULL) + shash_put(strtab, s, (p = (vhpiCharT *)xstrndup(s, n))); + return p; +} + static void init_abstractRegion(c_abstractRegion *r, tree_t t) { const loc_t *loc = tree_loc(t); @@ -633,10 +641,10 @@ static void init_abstractDecl(c_abstractDecl *d, tree_t t, c_abstractRegion *r) d->LineNo = loc->first_line; d->LineOffset = loc->line_delta; - d->Name = d->CaseName = new_string(istr(tree_ident(t))); + d->Name = new_string(istr(tree_ident(t))); if (r) { char *full LOCAL = xasprintf("%s:%s", r->FullName, d->Name); - d->FullName = d->FullCaseName = new_string(full); + d->FullName = new_string(full); } d->ImmRegion = r; @@ -1867,6 +1875,50 @@ vhpiIntT vhpi_get(vhpiIntPropertyT property, vhpiHandleT handle) } } +static vhpiCharT *cached_caseName(c_abstractDecl *decl) +{ + if (decl->CaseName != NULL) + return decl->CaseName; + + // We do not save the orignal case of identifiers as it does not seem + // to be required except for this property. Instead try to recover + // the original identifier text using the source location. + + const loc_t *loc = tree_loc(decl->tree); + if (loc->line_delta != 0) + goto failed; + + const char *src = loc_get_source(loc); + if (src == NULL) + goto failed; + + // Do some basic sanity checks to make sure we found the right + // identifier + + const char *start = src + loc->first_column; + if (decl->Name[0] != toupper_iso88591(*start)) + goto failed; + + return (decl->CaseName = new_string_n(start, loc->column_delta + 1)); + + failed: + return (decl->CaseName = decl->Name); +} + +static vhpiCharT *cached_fullCaseName(c_abstractDecl *decl) +{ + if (decl->FullCaseName != NULL) + return decl->FullCaseName; + + vhpiCharT *cn = cached_caseName(decl); + + if (decl->ImmRegion == NULL) + return (decl->FullCaseName = cn); + + char *full LOCAL = xasprintf("%s:%s", decl->ImmRegion->FullCaseName, cn); + return (decl->FullCaseName = new_string(full)); +} + DLLEXPORT const vhpiCharT *vhpi_get_str(vhpiStrPropertyT property, vhpiHandleT handle) { @@ -1906,10 +1958,10 @@ const vhpiCharT *vhpi_get_str(vhpiStrPropertyT property, vhpiHandleT handle) if (d != NULL) { switch (property) { case vhpiNameP: return d->Name; - case vhpiCaseNameP: return d->CaseName; + case vhpiCaseNameP: return cached_caseName(d); case vhpiFileNameP: return (vhpiCharT *)loc_file_str(&(d->object.loc)); case vhpiFullNameP: return d->FullName; - case vhpiFullCaseNameP: return d->FullCaseName; + case vhpiFullCaseNameP: return cached_fullCaseName(d); default: goto unsupported; } } diff --git a/test/regress/gold/vhpi1.txt b/test/regress/gold/vhpi1.txt index dbbc3d856..739c8cc4d 100644 --- a/test/regress/gold/vhpi1.txt +++ b/test/regress/gold/vhpi1.txt @@ -48,6 +48,9 @@ VHPI printf v indexed name is V(3) VHPI printf v indexed name is V(2) VHPI printf v indexed name is V(1) VHPI printf v indexed name is V(0) +VHPI printf name is A_NAME_WITH_MIXED_CASE +VHPI printf case name is A_name_with_MIXED_case +VHPI printf full case name is :VHPI1:A_name_with_MIXED_case VHPI printf start of sim callback! user data is 'some user data' 0ms+0: Report Note: x=5 VHPI printf after_5ns callback! diff --git a/test/regress/vhpi1.vhd b/test/regress/vhpi1.vhd index 76d698c80..f3900703b 100644 --- a/test/regress/vhpi1.vhd +++ b/test/regress/vhpi1.vhd @@ -8,6 +8,7 @@ architecture test of vhpi1 is signal v : bit_vector(3 downto 0) := "0011"; signal b : bit; signal r : real; + signal A_name_with_MIXED_case : bit; begin p1: process (x) is diff --git a/test/vhpi/vhpi1.c b/test/vhpi/vhpi1.c index 3f083426a..e294083b7 100644 --- a/test/vhpi/vhpi1.c +++ b/test/vhpi/vhpi1.c @@ -483,5 +483,13 @@ void vhpi1_startup(void) for (vhpiHandleT name = vhpi_scan(v_names); name != NULL; name = vhpi_scan(v_names)) vhpi_printf("v indexed name is %s", vhpi_get_str(vhpiNameP, name)); + vhpiHandleT handle_case = vhpi_handle_by_name("a_name_with_mixed_case", root); + check_error(); + fail_if(handle_case == NULL); + vhpi_printf("handle %p", handle_case); + vhpi_printf("name is %s", vhpi_get_str(vhpiNameP, handle_case)); + vhpi_printf("case name is %s", vhpi_get_str(vhpiCaseNameP, handle_case)); + vhpi_printf("full case name is %s", vhpi_get_str(vhpiFullCaseNameP, handle_case)); + vhpi_release_handle(root); }