From c739b978a440bcc612566b627e73d1425340e7fb Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Wed, 20 Dec 2023 21:57:03 +0000 Subject: [PATCH] Avoid illegal characters in design unit file names. Fixes #816 --- src/lib.c | 42 ++++++++++++++++++++++------ test/regress/gold/issue816.txt | 1 + test/regress/issue816.vhd | 51 ++++++++++++++++++++++++++++++++++ test/regress/testlist.txt | 1 + 4 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 test/regress/gold/issue816.txt create mode 100644 test/regress/issue816.vhd diff --git a/src/lib.c b/src/lib.c index d4c3d5ae..cc48e964 100644 --- a/src/lib.c +++ b/src/lib.c @@ -736,15 +736,37 @@ void lib_put_error(lib_t lib, tree_t unit) lib_put_aux(lib, obj, true, true, get_real_time(), NULL); } -static lib_unit_t *lib_read_unit(lib_t lib, const char *fname) +static void lib_encode_file_name(ident_t id, text_buf_t *tb) { - fbuf_t *f = lib_fbuf_open(lib, fname, FBUF_IN, FBUF_CS_ADLER32); + // Encode extended identifiers in file names using the hexadecimal + // value of the ISO-8859-1 code points to avoid illegal characters + // and case sensitivity issues on Windows and macOS + + bool esc = false; + for (const char *p = istr(id); *p; p++) { + if (*p == '\\') { + esc = !esc; + tb_append(tb, '+'); + } + else if (esc) + tb_printf(tb, "%02x", *p); + else + tb_append(tb, *p); + } +} + +static lib_unit_t *lib_read_unit(lib_t lib, ident_t id) +{ + LOCAL_TEXT_BUF tb = tb_new(); + lib_encode_file_name(id, tb); + + fbuf_t *f = lib_fbuf_open(lib, tb_get(tb), FBUF_IN, FBUF_CS_ADLER32); if (f == NULL) return NULL; file_info_t info; if (!get_handle_info(fbuf_file_handle(f), &info)) - fatal_errno("%s", fname); + fatal_errno("%s", tb_get(tb)); ident_rd_ctx_t ident_ctx = ident_read_begin(f); loc_rd_ctx_t *loc_ctx = loc_read_begin(f); @@ -762,7 +784,7 @@ static lib_unit_t *lib_read_unit(lib_t lib, const char *fname) // Ignore it (remove after 1.12 release) break; default: - fatal_trace("unhandled tag %c in %s", tag, fname); + fatal_trace("unhandled tag %c in %s", tag, tb_get(tb)); } } @@ -773,7 +795,7 @@ static lib_unit_t *lib_read_unit(lib_t lib, const char *fname) fbuf_close(f, &checksum); if (obj == NULL) - fatal_trace("%s did not HDL design unit", fname); + fatal_trace("%s did not contain a HDL design unit", tb_get(tb)); arena_set_checksum(object_arena(obj), checksum); @@ -802,7 +824,7 @@ static lib_unit_t *lib_get_aux(lib_t lib, ident_t ident) file_read_lock(lib->lock_fd); // Otherwise search in the filesystem if not in the cache - lu = lib_read_unit(lib, istr(ident)); + lu = lib_read_unit(lib, ident); file_unlock(lib->lock_fd); @@ -940,10 +962,12 @@ ident_t lib_name(lib_t lib) static void lib_save_unit(lib_t lib, lib_unit_t *unit) { - fbuf_t *f = lib_fbuf_open(lib, istr(unit->name), FBUF_OUT, FBUF_CS_ADLER32); + LOCAL_TEXT_BUF tb = tb_new(); + lib_encode_file_name(unit->name, tb); + + fbuf_t *f = lib_fbuf_open(lib, tb_get(tb), FBUF_OUT, FBUF_CS_ADLER32); if (f == NULL) - fatal("failed to create %s in library %s", istr(unit->name), - istr(lib->name)); + fatal("failed to create %s in library %s", tb_get(tb), istr(lib->name)); write_u8('T', f); diff --git a/test/regress/gold/issue816.txt b/test/regress/gold/issue816.txt new file mode 100644 index 00000000..3398f2a9 --- /dev/null +++ b/test/regress/gold/issue816.txt @@ -0,0 +1 @@ +2ns+0: Report Failure: passed diff --git a/test/regress/issue816.vhd b/test/regress/issue816.vhd new file mode 100644 index 00000000..c3a55b9a --- /dev/null +++ b/test/regress/issue816.vhd @@ -0,0 +1,51 @@ +entity \foo\ is + port ( x : out integer ); +end entity; + +architecture \test\ of \foo\ is +begin + x <= 1; +end architecture; + +------------------------------------------------------------------------------- + +entity \Foo\ is + port ( x : out integer ); +end entity; + +architecture \test\ of \Foo\ is +begin + x <= 2; +end architecture; + +------------------------------------------------------------------------------- + +entity issue816 is +end entity; + +architecture test of issue816 is + signal a, b : integer; +begin + + u1: entity work.\foo\ port map ( a ); + + u2: entity work.\Foo\ port map ( b ); + + check: process is + begin + wait for 1 ns; + + assert a = 1 severity failure; + assert b = 2 severity failure; + + wait for 1 ns; + + -- Make this test fail so that run_regr does analysis/elaboration and + -- execution in two separate processes, causing the library units to be + -- re-read from disk + report "passed" severity failure; + + wait; + end process; + +end architecture; diff --git a/test/regress/testlist.txt b/test/regress/testlist.txt index ad87b260..2466eba4 100644 --- a/test/regress/testlist.txt +++ b/test/regress/testlist.txt @@ -913,3 +913,4 @@ cmdline9 shell,slow genpack16 normal,2008 issue815 normal,2019 issue817 fail,gold,2008 +issue816 fail,gold -- 2.39.2