Version in base suite: 3.3.104-2 Base version: gtkwave_3.3.104-2 Target version: gtkwave_3.3.104+really3.3.118-0+deb11u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/g/gtkwave/gtkwave_3.3.104-2.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/g/gtkwave/gtkwave_3.3.104+really3.3.118-0+deb11u1.dsc /srv/release.debian.org/tmp/MWBuIGaNam/gtkwave-3.3.104+really3.3.118/doc/gtkwave.odt |binary gtkwave-3.3.104+really3.3.118/AUTHORS | 20 gtkwave-3.3.104+really3.3.118/ChangeLog | 365 - gtkwave-3.3.104+really3.3.118/LICENSE.TXT | 18 gtkwave-3.3.104+really3.3.118/configure | 20 gtkwave-3.3.104+really3.3.118/configure.ac | 2 gtkwave-3.3.104+really3.3.118/contrib/bundle_for_osx/Info-gtkwave.plist | 8 gtkwave-3.3.104+really3.3.118/contrib/bundle_for_osx/gtkwave.bundle | 14 gtkwave-3.3.104+really3.3.118/contrib/rtlbrowse/stem_recurse.c | 31 gtkwave-3.3.104+really3.3.118/contrib/wlf2vcd/wlf2vcd.c | 2 gtkwave-3.3.104+really3.3.118/contrib/xml2stems/xml2stems.cc | 304 - gtkwave-3.3.104+really3.3.118/debian/changelog | 31 gtkwave-3.3.104+really3.3.118/debian/patches/readd-ghwdump.patch | 2911 ++++++++++ gtkwave-3.3.104+really3.3.118/debian/patches/series | 1 gtkwave-3.3.104+really3.3.118/man/Makefile.am | 2 gtkwave-3.3.104+really3.3.118/man/Makefile.in | 2 gtkwave-3.3.104+really3.3.118/man/fstminer.1 | 2 gtkwave-3.3.104+really3.3.118/man/ghwdump.1 | 39 gtkwave-3.3.104+really3.3.118/man/gtkwaverc.5 | 3 gtkwave-3.3.104+really3.3.118/man/vcd2fst.1 | 2 gtkwave-3.3.104+really3.3.118/share/appdata/Makefile.am | 2 gtkwave-3.3.104+really3.3.118/share/appdata/Makefile.in | 2 gtkwave-3.3.104+really3.3.118/share/appdata/gtkwave.appdata.xml | 20 gtkwave-3.3.104+really3.3.118/share/appdata/io.github.gtkwave.GTKWave.metainfo.xml | 136 gtkwave-3.3.104+really3.3.118/src/Makefile.am | 2 gtkwave-3.3.104+really3.3.118/src/Makefile.in | 6 gtkwave-3.3.104+really3.3.118/src/analyzer.c | 16 gtkwave-3.3.104+really3.3.118/src/analyzer.h | 8 gtkwave-3.3.104+really3.3.118/src/baseconvert.c | 396 - gtkwave-3.3.104+really3.3.118/src/currenttime.c | 33 gtkwave-3.3.104+really3.3.118/src/debug.c | 37 gtkwave-3.3.104+really3.3.118/src/debug.h | 2 gtkwave-3.3.104+really3.3.118/src/extload.c | 6 gtkwave-3.3.104+really3.3.118/src/fst.c | 18 gtkwave-3.3.104+really3.3.118/src/ghw.c | 81 gtkwave-3.3.104+really3.3.118/src/ghwlib.c | 2183 ------- gtkwave-3.3.104+really3.3.118/src/ghwlib.h | 445 - gtkwave-3.3.104+really3.3.118/src/globals.c | 6 gtkwave-3.3.104+really3.3.118/src/globals.h | 4 gtkwave-3.3.104+really3.3.118/src/helpers/Makefile.am | 4 gtkwave-3.3.104+really3.3.118/src/helpers/Makefile.in | 42 gtkwave-3.3.104+really3.3.118/src/helpers/evcd2vcd.c | 14 gtkwave-3.3.104+really3.3.118/src/helpers/fst/CMakeLists.txt | 23 gtkwave-3.3.104+really3.3.118/src/helpers/fst/Makefile.am | 4 gtkwave-3.3.104+really3.3.118/src/helpers/fst/Makefile.in | 4 gtkwave-3.3.104+really3.3.118/src/helpers/fst/fastlz.c | 2 gtkwave-3.3.104+really3.3.118/src/helpers/fst/fastlz.h | 2 gtkwave-3.3.104+really3.3.118/src/helpers/fst/fst_win_unistd.h | 52 gtkwave-3.3.104+really3.3.118/src/helpers/fst/fstapi.c | 526 + gtkwave-3.3.104+really3.3.118/src/helpers/fst/fstapi.h | 8 gtkwave-3.3.104+really3.3.118/src/helpers/fst/lz4.c | 2 gtkwave-3.3.104+really3.3.118/src/helpers/fst/lz4.h | 2 gtkwave-3.3.104+really3.3.118/src/helpers/ghwdump.c | 203 gtkwave-3.3.104+really3.3.118/src/helpers/lxt2_read.c | 96 gtkwave-3.3.104+really3.3.118/src/helpers/vcd2fst.c | 52 gtkwave-3.3.104+really3.3.118/src/helpers/vcd2lxt.c | 69 gtkwave-3.3.104+really3.3.118/src/helpers/vcd2lxt2.c | 69 gtkwave-3.3.104+really3.3.118/src/helpers/vcd2vzt.c | 69 gtkwave-3.3.104+really3.3.118/src/helpers/vzt_read.c | 141 gtkwave-3.3.104+really3.3.118/src/helpers/vzt_write.c | 19 gtkwave-3.3.104+really3.3.118/src/libghw.c | 2241 +++++++ gtkwave-3.3.104+really3.3.118/src/libghw.h | 471 + gtkwave-3.3.104+really3.3.118/src/liblzma/LzmaLib.c | 37 gtkwave-3.3.104+really3.3.118/src/main.c | 7 gtkwave-3.3.104+really3.3.118/src/menu.c | 91 gtkwave-3.3.104+really3.3.118/src/menu.h | 3 gtkwave-3.3.104+really3.3.118/src/mouseover.c | 7 gtkwave-3.3.104+really3.3.118/src/mouseover_sigs.c | 7 gtkwave-3.3.104+really3.3.118/src/ptranslate.c | 2 gtkwave-3.3.104+really3.3.118/src/rc.c | 40 gtkwave-3.3.104+really3.3.118/src/savefile.c | 4 gtkwave-3.3.104+really3.3.118/src/showchange.c | 12 gtkwave-3.3.104+really3.3.118/src/signalwindow.c | 147 gtkwave-3.3.104+really3.3.118/src/tree.c | 1 gtkwave-3.3.104+really3.3.118/src/tree.h | 2 gtkwave-3.3.104+really3.3.118/src/treesearch_gtk2.c | 2 gtkwave-3.3.104+really3.3.118/src/ttranslate.c | 2 gtkwave-3.3.104+really3.3.118/src/vcd.c | 23 gtkwave-3.3.104+really3.3.118/src/vcd_partial.c | 23 gtkwave-3.3.104+really3.3.118/src/vcd_recoder.c | 31 gtkwave-3.3.104+really3.3.118/src/version.h | 4 gtkwave-3.3.104+really3.3.118/src/wavealloca.h | 2 gtkwave-3.3.104+really3.3.118/src/wavewindow.c | 92 83 files changed, 8108 insertions(+), 3726 deletions(-) diff -Nru gtkwave-3.3.104/AUTHORS gtkwave-3.3.104+really3.3.118/AUTHORS --- gtkwave-3.3.104/AUTHORS 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/AUTHORS 2023-12-31 21:11:04.000000000 +0000 @@ -1,13 +1,13 @@ -GTKWave Wave Viewer is Copyright (C) 1999-2020 Tony Bybell. -Windows compatibility and PS/MIF routines are Copyright (C) 1999-2020 Udi Finkelstein. -Context support is Copyright (C) 2007-2020 Kermin Elliott Fleming. -Trace group support is Copyright (C) 2009-2020 Donald Baltus. -GHW and additional GUI support is Copyright (C) 2005-2020 Tristan Gingold. -Analog support is Copyright (C) 2005-2020 Thomas Sailer. -External DnD support is Copyright (C) 2008-2020 Concept Engineering GmbH. -FastLZ is Copyright (C) 2005-2020 Ariya Hidayat. +GTKWave Wave Viewer is Copyright (C) 1999-2021 Tony Bybell. +Windows compatibility and PS/MIF routines are Copyright (C) 1999-2021 Udi Finkelstein. +Context support is Copyright (C) 2007-2021 Kermin Elliott Fleming. +Trace group support is Copyright (C) 2009-2021 Donald Baltus. +GHW and additional GUI support is Copyright (C) 2005-2021 Tristan Gingold. +Analog support is Copyright (C) 2005-2021 Thomas Sailer. +External DnD support is Copyright (C) 2008-2021 Concept Engineering GmbH. +FastLZ is Copyright (C) 2005-2021 Ariya Hidayat. Some public domain clip art by contributors at http://www.sxc.hu/ website. Hierarchy marker icons from the Silk icons set by Mark James found at the http://www.famfamfam.com/lab/icons/silk/ website. Portions of the TCL implementation, tcl_np.c and tcl_np.h are copyrighted by the Regents of the University of California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState Corporation, and other parties. -NSAlert is Copyright (C) 2011-2020 Philipp Mayerhofer. -LZ4 is Copyright (C) 2011-2020 Yann Collet. +NSAlert is Copyright (C) 2011-2021 Philipp Mayerhofer. +LZ4 is Copyright (C) 2011-2021 Yann Collet. diff -Nru gtkwave-3.3.104/ChangeLog gtkwave-3.3.104+really3.3.118/ChangeLog --- gtkwave-3.3.104/ChangeLog 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/ChangeLog 2023-12-31 21:11:04.000000000 +0000 @@ -3,15 +3,15 @@ Added user's manual pdf file to distribution in doc/. Added vertex and rtlbrowse for sourcecode annotation. 3.0.1 09may06 Automatically add extensions to save filenames in gtkwave. - Cygwin compile fixes. Add Cygwin functionality for fork() + Cygwin compile fixes. Add Cygwin functionality for fork() related ops that do in fact work properly. -3.0.2 09may06 More fixes for full function (except pthreads) in Cygwin. +3.0.2 09may06 More fixes for full function (except pthreads) in Cygwin. Requires usage of Cygserver if rtlbrowse is to work. - Fixed fonts for Cygwin to improve readability. + Fixed fonts for Cygwin to improve readability. The Courier font is very bad looking and blitter mangled under cygwin. -3.0.3 29may06 Changed yylineno references in vlex.l in rtlbrowse to - my_yylineno as newer versions of flex automatically define +3.0.3 29may06 Changed yylineno references in vlex.l in rtlbrowse to + my_yylineno as newer versions of flex automatically define this and cause duplicate symbols. Saw there were still problems with courier on debian. Also check for misc-fixed on non-cygwin systems just in case. @@ -35,7 +35,7 @@ dumpfile loaders as the string length is known from the rc of sprintf. Fixed T_SCOPE rule in vcd.c as dotted hierarchies would - throw off the parser as hierarchies themselves are + throw off the parser as hierarchies themselves are (in practice) never really escaped. In tree.c, treenamefix() would recurse more than necessary such that some dotted hierarchies would cause an order of @@ -57,7 +57,7 @@ 3.0.6 14jul06 Added "Real" option for data type display as passing around real numbers in Verilog across modules needs to be done with $realtobits and $bitstoreal. - Added scripting command flag --script in order to allow + Added scripting command flag --script in order to allow autosetup of things that are outside of config file control. This also allows doing things such as automated print jobs. Added --nowm to remove window manager control on most @@ -68,9 +68,9 @@ Added --nomenus to remove menus for the case when used in conjunction with --xid and it is desired to create an embedded wave viewer applet that cannot initiate file I/O - on its own. Note that earlier versions of GTK+ cannot + on its own. Note that earlier versions of GTK+ cannot handle menu events properly from a GtkPlug. - Fixed problem with dead memory allocations for GtkColor + Fixed problem with dead memory allocations for GtkColor structs in color.c as found by Valgrind. Moved .odt version of the user's guide into doc/ rather than the pdf version as this is a sourcecode distribution so the @@ -81,7 +81,7 @@ Found problem with directive-based string embedding in older gcc compiler versions. GTK+-1.2 doesn't handle GtkPlug. -3.0.7 17jul06 Added support for dualview of waveforms using GtkPlug and +3.0.7 17jul06 Added support for dualview of waveforms using GtkPlug and shared memory IPC through use of the "twinwave" front end. Updated documentation to add a section on twinwave. 3.0.8 04aug06 Modified order of flags in twinwave as appending flags @@ -91,7 +91,7 @@ not including getopt.h. Removed unused "bus" element from struct fac. Added interactive loading of vcd files with the routines in - vcd_partial.c. Added shmidcat to the distribition to test + vcd_partial.c. Added shmidcat to the distribition to test this new interactive loading functionality. Added real_parameter vartype (Riviera Aldec 2006.6) in all vcd loaders. @@ -165,7 +165,7 @@ Fixed bug in draw_hptr_trace_vector_analog() that would cause crashes on pure real vectors when zoomed out fully. Added dynamic tooltips on current marker values for both - the left and middle mouse buttons (not tested for Win32 + the left and middle mouse buttons (not tested for Win32 yet so disabled there). Added preliminary support for changing menu accelerators through the rc file with an "accel" statement. @@ -173,7 +173,7 @@ zero in the initial dumpvars. (would be needed anyway for dumpers that for some reason don't as the 1st value change collapses into the second) -3.0.18 28nov06 Fix in vcd saver for when units are in seconds: keeps +3.0.18 28nov06 Fix in vcd saver for when units are in seconds: keeps timescale of "ss" being used instead of just "s". Locale problem in printing of floating point numbers fixed by setting up a local fixer routine in config.h for @@ -181,7 +181,7 @@ Fix in all vcd loaders to handle "port" (along with other keywords) that appear in non-keyword parts of the $VAR declaration sequence. - Fixed long standing LXT bug with integer datatype on + Fixed long standing LXT bug with integer datatype on trivial LXT files. (Overflow in lt_buf decoder buffer.) 3.0.19 21dec06 More locale fixing with LC_ALL. Added user patches from NIIBE Yutaka to remove requirement @@ -196,14 +196,14 @@ reals. 3.0.21 02feb07 Added support for in/out/inout evcd ports generated by dumpports in ModelSim. - Fixed problem with hierarchy being out of order as + Fixed problem with hierarchy being out of order as treegraft needed to be followed by treesort. This mostly impacted recursive hierarchy imports by only allowing two signals to import rather than all of them. Also there was an inconsistency with the signal ordering with VCD vs the database formats because of this. 3.0.22 19feb07 Bumped up hash size from 65519 to 500009 entries for VCD - parsers. + parsers. Bumped up max VCDID fastindex size to 8M entries. Now use gperf for verilog datatypes for some speedup in gtkwave vcd loaders. @@ -218,7 +218,7 @@ PATH_MAX set if not defined in verilog.g for Vertex. Regenerated configure for setenv()/unsetenv() presence which impacts Solaris (use putenv() instead). - Regenerated configure to handle auto detect of -lnsl, + Regenerated configure to handle auto detect of -lnsl, -lrpc, and -lpthread. Added -c to file install in top-level makefile (Solaris). Use _LARGEFILE_SOURCE value from configure with linux @@ -243,15 +243,15 @@ that code was leftover from the vzt2vcd). Updated manpages for vzt2vcd, lxt2vcd, and vztminer. On concatenated vector loads ('#'/':' in savefile), attempts - to do a load of a monolithic vector on fail. This is + to do a load of a monolithic vector on fail. This is somewhat related to the re-coalesce vectors feature above. Implemented reverse of this for monolithic vectors into the '#' bitstrand variants. -3.0.25 10apr07 System Verilog with MTI fix for VCD declarations of form +3.0.25 10apr07 System Verilog with MTI fix for VCD declarations of form $var reg 64 >w #implicit-var###VarElem:ram_di[0.0] [63:0] $end - ...debussy implicitly escapes the varname during loading so + ...debussy implicitly escapes the varname during loading so gtkwave does it too now for all VCD loaders. - More System Verilog with MTI fixes: VCD (parameter) vars of + More System Verilog with MTI fixes: VCD (parameter) vars of length zero are representative of reals with MTI: they don't use real_parameter like Riviera does. Updated vcd_saver.c to handle saving these implicit-var @@ -305,14 +305,14 @@ 3.1.1 20sep07 Fixed crash in hierarchy search reload. (Wrong pointer type introduced from code cleanup.) Adding start of tabbed browsing support. Put in window - select focus switching between tabs (e.g., on + select focus switching between tabs (e.g., on search windows). Added locking in main iteration loop to detect unexpected context switches and fix/report them (wrong operation if it occurs). 3.1.2 24dec07 Compiler warning cleanups from Sun compile logs. Added named parameter support to vermin parser. Added check for gperf back into configure.ac. - Added vlist_spill rc variable to control new + Added vlist_spill rc variable to control new feature of spilling vlists to a tempfile on disk. Fixed vcd loader status bar on files > 2GB. Removed non-growable vlists and also finalize @@ -328,39 +328,39 @@ with the vlist_prepack rc variable. Added --giga option to turn on vlist_spill and vlist_prepack from the command line. -3.1.3 13jan08 Added dynamic keypress detection in the Pattern Search - Requester so users do not need to press enter for search - strings. Likewise, added the rc variable sst_dynamic_filter +3.1.3 13jan08 Added dynamic keypress detection in the Pattern Search + Requester so users do not need to press enter for search + strings. Likewise, added the rc variable sst_dynamic_filter to enable the same type behavior for the signal name filter in the GTK2 signal search tree. - Fixed bug where filtered signal names did not reappear on + Fixed bug where filtered signal names did not reappear on reload. Updated user manual as necessary. - Added "edge" left/right buttons for handy single signal edge + Added "edge" left/right buttons for handy single signal edge detection due to user requests. Fixed long-standing backward edge seek bug in pattern search. (It would miss the preceeding edge if the marker isn't already on one.) - Added use_standard_clicking rc variable in order to enable + Added use_standard_clicking rc variable in order to enable "normal GTK" shift/click semantics in the signal window. - Collapse/uncollapse is now shift-ctrl when + Collapse/uncollapse is now shift-ctrl when use_standard_clicking is active. Added prelim dnd for use_standard_clicking mode. - use_standard_clicking disabled in GTK-1.2 as there are dnd + use_standard_clicking disabled in GTK-1.2 as there are dnd issues. Recalculate signal width on reload as sometimes it was missed. Added input focus capability to signalwindow. Moving menu options to standard GTK accelerator keys. - Added Ctrl-A/Shift-Ctrl-A handler to the treeview so it acts + Added Ctrl-A/Shift-Ctrl-A handler to the treeview so it acts like the signal window. Added left/right scrolling hotkeys in signal window. - Added use_toolbutton_interface environment variable which + Added use_toolbutton_interface environment variable which enables new user interface at the top of screen. - More modifications to handle globals swapping in multi-tab + More modifications to handle globals swapping in multi-tab mode. Update configure.ac to handle library order problem with cygwin in rtlbrowse. - Added scrollwheel support in signal window when focused and + Added scrollwheel support in signal window when focused and standard clicking is active. Added "Use Color" and "Use Black and White" (for screendumps) View menu options from user requests. @@ -431,8 +431,8 @@ calls causing similar problems as necessary. 3.1.9 20apr08 Added missing init_filetrans_data() to reload function. Updated manfiles to get them in line with Debian lintian. -3.1.10 14may08 Added missing adjustment of t->shift in mouseover.c in - order to allow the mouseover on shifted traces to display +3.1.10 14may08 Added missing adjustment of t->shift in mouseover.c in + order to allow the mouseover on shifted traces to display properly. Fixed problem with edgebutton going back two edges on a combined vector. (Cut and paste typo from strace.c.) @@ -445,7 +445,7 @@ 3.1.12 14jul08 Compiler warning fixes. Fixed crash in vcd recoder for b vs 01xz mixups in malformed VCD files. - Fixed abort on VCD load for malformed size vs + Fixed abort on VCD load for malformed size vs [msi:lsi] syntax. NC does this on arrays of wires. Fix to vlist reader with --giga enabled in order to handle reads which go off the end of the file. @@ -466,10 +466,10 @@ for the horizontal scroller in the wavewindow. Added sticky click semantics for clicks in signal window. To do this in the treesearch_gtk2 file - will require some additional future work with + will require some additional future work with view_selection_func() and/or signal handling and trapping. -3.2.0 16feb09 Fix for strings ('s' type) in recoder. +3.2.0 16feb09 Fix for strings ('s' type) in recoder. Added timestart command to savefiles which indicates what the leftmost position should be on reload. Added support for as/zs small timescales as well as @@ -477,12 +477,12 @@ Adding signal name DnD support from external apps. Force open tree nodes on initial .sav file read. Yet more new warning (-Wall) cleanups. - Fixed ExtractNodeSingleBit for vectors which do not + Fixed ExtractNodeSingleBit for vectors which do not have a zero in either the msb or lsb (e.g., [1:9]). Added support for dragging files into the viewer (i.e., dumpfile, savefile, stems file) Added DnD of signal names from RTLBrowse source code - windows directly into gtkwave. + windows directly into gtkwave. GTK1 compiler compatibility fixes. Improved search performance from rtlbrowse initiated DnD searches. @@ -496,7 +496,7 @@ Updated -f argument file handling in vermin. Updated tcl_helper code so that signalwindow drags of bit- blasted vectors are properly re-coalesced for client code - for the drag. + for the drag. Updated task definition in vermin so that identifiers with dots in them can be used as task enable names. Fixed problem in vermin preprocessor where defines in 0x0d0a @@ -549,28 +549,28 @@ Added prelim auto-scrolling code for trace adds/copies. Added support for Tcl repscripts. Removed warnings found when compiling with -Wshadow. - Fix for stack crash in treesort() on dumpfiles with an + Fix for stack crash in treesort() on dumpfiles with an extremely large number of signals (e.g., 5 million). Compile fixes for rtlbrowse in older versions of GTK2. Remove stray tempfiles created by --giga writer under MinGW. Removed stray file descriptor from lxt on reload. Fixed repeat error problem in lxt.c introduced by -Wshadow fix. - Added prelim version of scale_to_time_dimension rc variable and + Added prelim version of scale_to_time_dimension rc variable and appropriate menu options. Beginning to update user manual to reflect new 3.2 features. - Added Partial VCD Dynamic Zoom To End and related + Added Partial VCD Dynamic Zoom To End and related zoom_dynamic_end rc variables. More mingw compile fixes: the whole tarball compiles now. Use old file chooser (for now) in mingw as the new one seems not to be re-sizeable. Added "copy traces" to toolbar in gtkwave as copy function now exists. - Added check for "server" in env var CYGWIN before printing + Added check for "server" in env var CYGWIN before printing warning about using shared memory. Added vpi client lxt/lxt2/vzt writers in contrib/vpi, but these currently are not built. Compatibility fix for gcc 3.x. - Added extload capability which grabs data via popen(). This + Added extload capability which grabs data via popen(). This allows adding loaders for unsupported formats via data mining. Added Tcl command setBaselineMarker. Extload hardening on reload. @@ -602,7 +602,7 @@ order to avoid unnecessary stack pushing. Fixing reloader crashes in vcd_build_symbols(). Adding experimental support for bringing up gtkwave without a - trace like "every other" GUI app. This is currently disabled + trace like "every other" GUI app. This is currently disabled pending more testing. Sort filename lists from DnD in order to allow both a dumpfile and a savefile to be dragged into the viewer and @@ -640,7 +640,7 @@ Warning fixes for printf format strings in lxt2/vzt/ghw. Updated VCD parser to handle names like "a[1] [3:0]". Added VCDNAM_ESCAPE cases in lxt, lxt2, and vzt loaders. - Updated VCD writers so they put spaces before bracketed + Updated VCD writers so they put spaces before bracketed signal ranges. Added extra message for help requester if file type is MISSING_FILE in order to direct users what to do. @@ -693,7 +693,7 @@ Fix to attempt_vecmatch_2 when no suffix encountered. 3.3.0 25dec09 Modified unformat_time() so it can also handle floating- point exponential format. - Integration of a large amount of group handling sourcecode + Integration of a large amount of group handling sourcecode from Don Baltus / Bluespec, Inc. Re-integrated original Simpod repscript handling. Reworked force open tree node and moved to @@ -734,7 +734,7 @@ file support as it is obsolete: all scripts are Tcl scripts now. Integrated user-provided rework of rgb.c. - Removed local lzma library and now use system xz if + Removed local lzma library and now use system xz if available. Old VZT files using -z 2 are no longer readable but can be converted using vzt2vcd from an old version of gtkwave. @@ -745,7 +745,7 @@ In fstapi.c now use tmpfile() to generate tempfiles in order to speed up operation on networked filesystems. Fixed problem in fstapi.c with conflict between off_t - and unsigned longs on some 32-bit systems which cause a + and unsigned longs on some 32-bit systems which cause a "tsec uncompress" failure on reads. Fixed missing dependencies in various Makefile.am files. 3.3.2 05jan10 Emergency fix for ghw.c as it was missing a close comment @@ -792,10 +792,10 @@ force_open_tree_nodes loop (spotted using an alternate allocator). Added optional preliminary Judy array support. - Fixed compiler warnings. + Fixed compiler warnings. Fixed toggle max hier so it toggles back and forth between the most previously set hierarchy depth. - Added ".lxt2" to list of suffixes allowed by gtkwave. + Added ".lxt2" to list of suffixes allowed by gtkwave. Remove name field from struct fac. Added missing hierarchy boundary sort for FST in order to allow compatibility with compressed names (-C flag). @@ -841,7 +841,7 @@ Compiler warning fix in lxt_write.c/fstapi.c for Open Solaris. Added fstWriterGetDumpSizeLimitReached() to fstapi.c. Fixes to Tcl string handling. - Applied user-supplied fixes for null pointer crashes in + Applied user-supplied fixes for null pointer crashes in rtlbrowse. Moved gtk_grab_add() after gtk_widget_show() in order to work with newer versions of GTK. @@ -888,13 +888,13 @@ gtkwave::setCurrentTranslateFile, gtkwave::setCurrentTranslateProc, gtkwave::setCurrentTranslateTransProc, and - gtkwave::setCurrentTranslateEnums to give Tcl access to these + gtkwave::setCurrentTranslateEnums to give Tcl access to these features. Add write combining in fstWriterEmitValueChange to speed up execution on Cygwin. Nested `ifdef fix for Vermin. - Fix for free to non-malloc'd address problem in repscripts - due to context changing in Tcl scripts when reload occurs. + Fix for free to non-malloc'd address problem in repscripts + due to context changing in Tcl scripts when reload occurs. Added gtkwavetcl_setvar() for starting to build a framework to support Tcl variable change callbacks. This can be used to closely monitor how a user manipulates the gtkwave GUI. @@ -936,7 +936,7 @@ 3.3.15 10nov10 Added check in fstapi.c for corner case where fstWriterEmitSectionHeader could make a file unusable if.hier is not present. - Added more checks in fstapi reader to prevent crashes on + Added more checks in fstapi reader to prevent crashes on malformed files. Add config.h #include to the fstapi.c code. Add detection in vcd2fst for Verilog XL-style VCD identifiers @@ -953,7 +953,7 @@ Added Jenkins hash routine to enable dynamic alias detection for when Judy not available. 3.3.17 28nov10 Added sanity check in dynamic alias reconstruct routine in - FST reader and also fixed bug where alias reconstruction in + FST reader and also fixed bug where alias reconstruction in current blocks doesn't overwrite previous, old block data. 3.3.18 24dec10 Added extra allocation in fstWriterEmitValueChange in case users modify the FST_BREAK_ADD_SIZE to a very small value. @@ -961,7 +961,7 @@ into its compile. Fixed x86_64 assembler =q vs =Q problem in lxt.c. Preliminary support for variable length records in FST files. - Added fstUtilityBinToEsc and fstUtilityEscToBin for + Added fstUtilityBinToEsc and fstUtilityEscToBin for conversion of binary data to C-style strings. Now allow escaped strings in VCD files to encode a richer set of data for non-standard "s" VCD records. @@ -1021,7 +1021,7 @@ bug. (Would prevent pattern search from working on 64-bit big-endian architectures.) Fixed broken "replace" signal option. -3.3.24 03aug11 Improve the searching for the TCL libraries (when using +3.3.24 03aug11 Improve the searching for the TCL libraries (when using stubs). Fixed bug where Tcl_GetString was substituted with brace removal preprocessing when unnecessary (would break @@ -1039,7 +1039,7 @@ Fix in lxt2_read.c/.h for negative msb/lsb indices. Fix in vzt_read.c/.h for negative msb/lsb indices. 3.3.26 25sep11 Mac OSX fixes: removed restrictions for twinwave on OSX, - OSX compile fixes for Tcl detection, printf warning + OSX compile fixes for Tcl detection, printf warning fixes (xcode gcc uses stricter warnings). More generic warning fixes from recent feature adds. 3.3.27 20oct11 Fixes of suspicious NULL pointer warnings from scan-build. @@ -1050,7 +1050,7 @@ or will change when files are loaded. Added fix for DnD crash when Quartz is the GDK back-end on Mac OSX. Enable fix with --enable-quartz in configure. - Fixed fstWriterFlushContext() such that invocations + Fixed fstWriterFlushContext() such that invocations outside the fstapi are synced with time changes. Modify main window size for twinwave on Quartz: GtkPlug window does not fit into GtkSocket as with X11. @@ -1067,14 +1067,14 @@ .gtkw itself being able to bring up the original dumpfile. Numerous bug fixes. Preliminary GConf support supporting session ID-based restore. - Preliminary GConf support to emulate OSX "open" + Preliminary GConf support to emulate OSX "open" functionality such that dumpfiles/savefiles can be targeted to an open gtkwave viewer / session ID. << long descriptions >> Fixed size of declaration of render_mutex_renderopt_c_1 as it was one element too short. Added transition code for shifting away from using - GtkItemFactoryEntry (also will help with OSX menubar + GtkItemFactoryEntry (also will help with OSX menubar integration which expects menu shells). Added support for native Quartz menu bars. Removed --enable-quartz as it is auto detected now if @@ -1125,8 +1125,8 @@ Added .gtkw as a new save file extension. When either .sav or .gtkw is encountered, the rest of a tab's session adaptively follows in expecting it as the save file suffix. - Added [savefile] tag to save files. The intended use is to - allow reconstruction of relative paths between dump and save + Added [savefile] tag to save files. The intended use is to + allow reconstruction of relative paths between dump and save file. Fixed --autosavename to use .gtkw as a suffix rather than the .sav suffix. @@ -1134,7 +1134,7 @@ matches gtkwave.icns. Renamed .sav examples to .gtkw. Added relative path comparisons for --save so when dumpfiles - and savefiles move in tandem, a successful load can be + and savefiles move in tandem, a successful load can be attempted. Added [dumpfile_mtime] and [dumpfile_size] tags to save file. Can now specify just an augmented save file at the command @@ -1153,7 +1153,7 @@ Disable analog during mutually incompatible mode selection (binary, filters, etc). Added F/P/T flags to mouseover for the filters. - Fix problem where ungrab doesn't occur if button pressed + + Fix problem where ungrab doesn't occur if button pressed + simultaneous reload accelerator key occurs. Fix combine direction in transaction filter to down. Fix vector analog render/print routine to use skipcnt. @@ -1179,25 +1179,25 @@ args to transaction filters via the args $comment. Added string value of \000 which renders as high-z. Integrated alt_wheel_mode code provided by Tom Browne. - Fixes for some rc file variables to keep them from getting + Fixes for some rc file variables to keep them from getting clobbered on 2nd tab opening. Warning fixes when compiled on Ubuntu. 3.3.33 27feb12 Scan-build fix in vcd_recoder.c. Added $timezero tag to VCD files which allows offsetting all - the values in a trace to provide ability for negative time - values. Currently only VCD, LXT, LXT2, VZT, and FST support + the values in a trace to provide ability for negative time + values. Currently only VCD, LXT, LXT2, VZT, and FST support this. Fix for timescale 10s and 100s. 3.3.34 12mar12 Fix for marker time deltas when $timezero is used. Reduced size of alert requester icons to 64x64 pixels. -3.3.35 04apr12 Polarity fix for vcd_preserve_glitches in rcfile. Default +3.3.35 04apr12 Polarity fix for vcd_preserve_glitches in rcfile. Default is no/off. Use yes in the rcfile to enable (e.g., for viewing interpolated analog waveforms). Added vcd_preserve_glitches support to FST as --optimize uses FST. Added vcd_preserve_glitches_real (for VCD/FST) rcfile variable that turns off deglitching only for real signals. - This removes the need for #define TRACK_AND_HOLD_FIX and + This removes the need for #define TRACK_AND_HOLD_FIX and prevents the case where interpolation of an analog waveform is deformed as significant data points were removed by the VCD or FST loader. @@ -1215,9 +1215,9 @@ introduced in 3.3.19. 3.3.37 10jun12 Added patch for savefile.c that corrects an issue in which the parser for process filter lines assumed the associated id - number was always a single digit. + number was always a single digit. Added patch to bitvec.c catches one more case when locating - bitblasted signals in vcd files created by modelsim. + bitblasted signals in vcd files created by modelsim. Fix that kills stray pipeio_create() processes on pipeio_destroy(). Additions to extload to handle hier types, component types, @@ -1239,7 +1239,7 @@ broken in the GtkSocket/GtkPlug implementation for Win32. 3.3.39 08aug12 Fixed relative pathnames when generated in MinGW and used back on Linux. - Added --output filename option to fst2vcd, vzt2vcd, and + Added --output filename option to fst2vcd, vzt2vcd, and lxt2vcd. Fix crash on OSX if gtk_widget_set_sensitive is called on a separator. @@ -1267,8 +1267,8 @@ Added scrollwheel support to rtlbrowse code windows. Added fseeko() return checking in fstapi.c to prevent errors with dynamically updated files. -3.3.43 26jan13 Fix for rtlbrowse for gtk_adjustment_get_page_increment and - gtk_adjustment_get_step_increment introduced in 2.14. +3.3.43 26jan13 Fix for rtlbrowse for gtk_adjustment_get_page_increment and + gtk_adjustment_get_step_increment introduced in 2.14. Added VPD support via vpd2vcd. To use, specify -o at the command line. (e.g., gtkwave -o test.vpd) Added autodetect for LXT, LXT2, VZT, FST regardless of the @@ -1278,7 +1278,7 @@ Added conditional compile for stat() being available. 3.3.44 16feb13 gdk_draw_layout assertion `GDK_IS_DRAWABLE (drawable)' assertion fix. -3.3.45 28feb13 Fix for VCDNAM_ESCAPE character in treesearch window. This +3.3.45 28feb13 Fix for VCDNAM_ESCAPE character in treesearch window. This sometimes occurs for structure identifiers. 3.3.46 29apr13 Upgraded to autoconf 2.69. Fixed as of yet undetected hdr_incomplete bug when running off @@ -1303,7 +1303,7 @@ FSDB fix for new debug info output style to be parsed. Added generate as scope type to VCD/FST/FSDB. Preliminary add for module port direction for FSDB and FST. - Display signal direction column in SST if not all signals are + Display signal direction column in SST if not all signals are declared as FST_VD_IMPLICIT. Fixed GTK warning when hide_sst is enabled and SST is opened then closed. @@ -1339,14 +1339,14 @@ Fixed ordering of static FSDB libraries for when dynamic ones are not present. Added direction filters to SST name filter search. That is, - adding +I+, +O+, +IO+, +B+, or +L+ before the regular + adding +I+, +O+, +IO+, +B+, or +L+ before the regular expression adds additional filtering criteria. Direction filters are case-insensitive. Relax FSDB loader to allow VHDL and mixed-language files. - Added VHDL hierarchy types to FST, internal VCD loaders and + Added VHDL hierarchy types to FST, internal VCD loaders and also vcdfst/fst2vcd. Added in VHDL to FST (which will also allow other languages): - gtkwave can process these types (e.g., signal + std_ulogic), + gtkwave can process these types (e.g., signal + std_ulogic), but there are currently no simulators supporting them. These are written by using fstWriterCreateVar2(). 3.3.50 15oct13 Limit number of rows that can be displayed in mouseover in @@ -1356,7 +1356,7 @@ Added missing $dumpvars emission in fst2vcd. Added missing atto and zepto time prefix parsing in vcd2fst. Added VHDL package type to FST. - Added red box around 'U' vector values for VHDL similar to + Added red box around 'U' vector values for VHDL similar to 'X' for Verilog. Used FST "attribute name" for variable types if specified. CRLF fix for save file reading on LF-only systems. @@ -1373,13 +1373,13 @@ 3.3.51 27oct13 MAINTAINERS: Please add gedit to the list of dependencies for gtkwave in order to enable new function that Icarus Verilog dumps into FST files. - Fix "/File/Grab To File" on OSX with an OSX patch as the - _gdk_quartz_image_copy_to_image() function in the GTK + Fix "/File/Grab To File" on OSX with an OSX patch as the + _gdk_quartz_image_copy_to_image() function in the GTK toolkit for Quartz is broken. Updated examples/gtkwaverc accel options to reflect the current state of the gtkwave main window main menu. Added "Open Source Definition" and "Open Source Instantiation" - options that invoke .gtkwaverc variable "editor" (or + options that invoke .gtkwaverc variable "editor" (or $GTKWAVE_EDITOR or gedit or open -t [OSX]) on sourcecode when source stems are present in the dumpfile (currently FST only). Fixed timezero in vcd2fst as it was only parsing unsigned @@ -1409,7 +1409,7 @@ Standardized export feature to write vcd using lower case for non 0/1 values. Added perror() on errno-related exits in vcd loaders. - Added experimental wlf2vcd in contrib. It is not currently + Added experimental wlf2vcd in contrib. It is not currently compiled or used. Corrected non-functional typos in documentation. 3.3.54 02jan14 Added LZ4 double compression on hierarchy tree for FST when @@ -1423,9 +1423,9 @@ in some cases on x86_64. 3.3.55 06feb14 Fixed problem with FST_DYNAMIC_ALIAS_DISABLE enabled when Judy arrays are not present. - FST writer performance tweaks for traces with millions of + FST writer performance tweaks for traces with millions of signal declarations. - Keep FSDB_VT_STREAM (FSDB transaction type) traces from + Keep FSDB_VT_STREAM (FSDB transaction type) traces from attempting to be read (for now) as they aren't yet processed. Added more space efficient FST dynamic alias encoding. Tempfile creation fix for Windows. Using tmpnam() is not @@ -1437,7 +1437,7 @@ VCD formatting. Added very fast I/O write capability to fst2vcd. Added support for FSDB_BYTES_PER_BIT_2B (EVCD) in FSDB loader. - Added experimental fsdb2vcd in contrib. It is not currently + Added experimental fsdb2vcd in contrib. It is not currently compiled or used. Fix to treesearch to remove duplicate signal names because of faulty dumpers. @@ -1461,10 +1461,10 @@ Change [1] at end of struct to C99 [] notation with appropriate allocation size modification. System_profiler speed fix for OSX. -3.3.59 26apr14 Use Duff's Device for 8 byte -> 1 byte binary value compression +3.3.59 26apr14 Use Duff's Device for 8 byte -> 1 byte binary value compression algorithm in FST writer. Warnings fixes from cppcheck. - Moved MinGW for FST to using different windows tempfile + Moved MinGW for FST to using different windows tempfile generation instead of tmpfile(). Removed fflush() in FST for MinGW in places that can cause crashes with read only files. @@ -1498,15 +1498,15 @@ -- for example filters all non-ports from search results. Updated LZ4 for version r126. Minor warnings fixes. - Moved TCL_LDADD/TK_LDADD before FSDB_LDADD to avoid stale - Tcl library version conflicts. + Moved TCL_LDADD/TK_LDADD before FSDB_LDADD to avoid stale + Tcl library version conflicts. Removed appending [31:0] to vcd loaded integer names. Reduced recursion depth in GHW signal loader to prevent stack overflow crashes. Added support for synthetic clocks in FST file. Update timetrace marking so it runs quicker for large traces. 3.3.66 05jul15 Faster fsdb initialization. - Fix vcd recoder loader crash for malformed vcd if signal is + Fix vcd recoder loader crash for malformed vcd if signal is declared as bits and a real valued change is encountered for the value change. Fixed crash in vcd2vzt for vcd files with no value changes @@ -1519,7 +1519,7 @@ 3.3.68 18nov15 Update copyright date. Added named markers capability to From: and To: time value input boxes. - Added support for fixed point binary numbers for both signed + Added support for fixed point binary numbers for both signed and unsigned decimal display types. 3.3.69 03feb16 Added missing EXTLOAD_CFLAGS declarations in configure.ac for FSDB detection when only .a files are present (necessary for @@ -1536,8 +1536,8 @@ share/icons/hicolor/scalable/apps/gtkwave.svg directory. Make gtkwave interpret values as double precision FP for plotting when BitsToReal is enabled. Also keeps analog mode - enabled when selecting numerical formats (which allows - enabling/disabling BitsToReal without going out of analog + enabled when selecting numerical formats (which allows + enabling/disabling BitsToReal without going out of analog mode). Disabling analog mode can be done using the existing Analog->Off menu option. Fix broken non-canonical bit ordering (IBM) single bit @@ -1545,7 +1545,7 @@ Fixed gtkwave::gtkwave::addSignalsFromList so it can handle subset and forward/reverse extractions on signals. Remove FST_WRITER_PARALLEL from MinGW CFLAGS as some recent - versions of MinGW have issues with struct timespec when + versions of MinGW have issues with struct timespec when pthread.h is included. Added /Edit/Delete to destroy traces without affecting the existing cut buffer. @@ -1568,7 +1568,7 @@ it is imported to the waveform display as an integer instead of a hex value. This works for dump file formats that show the datatype in the SST window. - Added code that should prevent the primary marker from + Added code that should prevent the primary marker from disappearing unexpectedly as well as dynamic resizing being stuck in the unset marker width. 3.3.75 02aug16 Fix crash when -S and -W are used in tandem. @@ -1576,7 +1576,7 @@ Crash fix in fstapi.c on read value at time accessing of FST files that use new dynamic aliases, FastLZ, or LZ4. This primarily affects rtlbrowse. -3.3.77 03oct16 Updated documentation to include an appendix on FST +3.3.77 03oct16 Updated documentation to include an appendix on FST implementation details. Removed '!A || (A && B)' is equivalent to '!A || B' redundant condition checks where found in source. @@ -1595,14 +1595,14 @@ allow copying values into the clipboard so they can be pasted into text editors, etc. 3.3.81 09jun17 Added max_fsdb_trees environment variable. - Fixed -C option so it is persistent across new tabs. + Fixed -C option so it is persistent across new tabs. Integrated updated GHW reader code. 3.3.82 02jul17 Get sys_fst working with VCS VPI. Added string concatenations for vectors. Added asserts to ghwlib.c to make scan-view clean. 3.3.83 04aug17 Preserve search type for regex search across reloads or close/reopens of regex search widget. - Update local libz to current version. + Update local libz to current version. 3.3.84 03sep17 Updated FSDB reader with experimental FST tree build routines for faster init. Removed warnings found when compiling with -Wshadow. @@ -1616,8 +1616,8 @@ not stored as a string. This then allows bitwise manipulations of integers. 3.3.86 03oct17 Added recurse import function (found before only in the hier - search) into the SST. - Removed obsolete bundle functionality from SST as recurse + search) into the SST. + Removed obsolete bundle functionality from SST as recurse import more accurately imports recursively. Made entrybox taller (using -1) as recent versions of gnome have taller window titlebars and the widget was not @@ -1630,20 +1630,20 @@ Makefile.am. 3.3.88 20feb18 Added --sstexclude command line option to prune unwanted clutter from the SST window. - Updated "/View/Mouseover Copies To Clipboard" menu option to - copying signal names into the clipboard so they can be pasted - into text editors, etc. - Fixed Write Save File to handle getting confused by initial - cancel then retry. + Updated "/View/Mouseover Copies To Clipboard" menu option to + copying signal names into the clipboard so they can be pasted + into text editors, etc. + Fixed Write Save File to handle getting confused by initial + cancel then retry. Updated v2k input/output declarations to handle unpacked arrays. Fix for pattern marks that could overshoot the left marker. 3.3.89 17mar18 Added support for 32-bit conversions in BitsToReal. Crash fix for pattern search with reals using LXT, LXT2, VZT. 3.3.90 08may18 For Cut Traces, fix up scroll position if there are traces - above the current row being cut. - Bits to real crash fix for very large floats. + above the current row being cut. + Bits to real crash fix for very large floats. Fixed gray code conversions that were incomplete for right - justified vectors such that the vector length is not a + justified vectors such that the vector length is not a multiple of the radix size (4 for hex, 3 for oct). Warray-bounds warning fix for 32-bit conversions in BitsToReal. 3.3.91 29may18 Added support for GSettings for when GConf is removed from @@ -1668,46 +1668,46 @@ 3.3.95 07oct18 Added fflush on stdout for help text as fix for possible stdout problem with mingw/msys shells. Added preliminary support for Time datatype. - Warnings fixes for Verilator integration. - Fixed install_proc_filter usage for Tcl invocation. + Warnings fixes for Verilator integration. + Fixed install_proc_filter usage for Tcl invocation. Change integer type to "integer" in SST to differentiate it from sv ints. Premiminary support for enum tables embedded in FST files. 3.3.96 15nov18 Changed to standardized zoom in/out/full hotkeys. Added time backtracking warning (for partial mode) to lxt2vcd. - VCD time backtracking fix (not for interactive mode). + VCD time backtracking fix (not for interactive mode). Added drag_failed handling (can press ESC) to DnD operations. - Prevent missing file in savefile from causing savefile to be - read as VCD by mistake. + Prevent missing file in savefile from causing savefile to be + read as VCD by mistake. Changed to Dinotrace-like 0s/1s rendering for bit vectors so values can be discerned without seeing the full value text. - Removed unneeded pango_layout_get_extents() inside call for - font_engine_draw_string(). + Removed unneeded pango_layout_get_extents() inside call for + font_engine_draw_string(). Changed bsearch_trunc() to run in constant time when monospace fonts are in use. Added missing GDK_SCROLL_MASK to signal area (need for gtk3, but not for other versions for some reason). 3.3.97 23nov18 Need to set menu_wlist entry NULL on gtk_widget_destroy(). - Fix on vtype()/vtype2() to detect 'x' and make the coloration - red on newly-displayed traces. (Bug new from Dinotrace-like - rendering in 3.3.96.) + Fix on vtype()/vtype2() to detect 'x' and make the coloration + red on newly-displayed traces. (Bug new from Dinotrace-like + rendering in 3.3.96.) 3.3.98 27dec18 Removed pccts and vermin. Use xml2stems instead. 3.3.99 09feb19 Added visible single bit glitches as a yellow dot (if enabled with --rcvar 'vcd_preserve_glitches on'). - Fixed print routine broken by bsearch_trunc() optimization in - version 3.3.96. + Fixed print routine broken by bsearch_trunc() optimization in + version 3.3.96. 3.3.100 20mar19 FSDB fix for variable declarations of array of reals. - Added Real, Time, Enum, and Popcnt flags to Edit/Show-Change. + Added Real, Time, Enum, and Popcnt flags to Edit/Show-Change. Ensure Show-Change regenerates analog traces. - Added braces inside Tcl source command to allow spaces in - filenames for Tcl scripts. + Added braces inside Tcl source command to allow spaces in + filenames for Tcl scripts. 3.3.101 08may19 Added gtkwave::getFacDir, gtkwave::getFacVtype, and gtkwave::getFacDtype Tcl accessor functions that function similar to gtkwave::getFacName. Pair $end with $dumpvars in VCD writers. - Make %.16g printing in baseconvert.c more resistant to power + Make %.16g printing in baseconvert.c more resistant to power of 10 roundoff errors. - Remove register keyword where applicable as is deprecated. + Remove register keyword where applicable as is deprecated. Added --saveonexit gtkwave command line option. 3.3.102 21sep19 Remove redundant TREE_VHDL_ST_PACKAGE from SST exclude. Added addCommentTracesFromList tcl command from user patch. @@ -1715,11 +1715,102 @@ Preliminary VHDL support for wlf2vcd. Add missing return value checks on mmap() in FST writer. 3.3.103 03nov19 Fix MAP_FAILED missing for MinGW. - Fix to make the coloration red on 'u' traces. (Bug from - Dinotrace-like rendering in 3.3.96.) - Typo fix on missing group start on vectors. + Fix to make the coloration red on 'u' traces. (Bug from + Dinotrace-like rendering in 3.3.96.) + Typo fix on missing group start on vectors. 3.3.104 24jan20 Added support for loading .vf files (provided FSDB reader libraries are enabled). Added support for dumping variable types in vcd saveer, not just using "wire" for non-reals/strings. Fix for uninitialized values at time 0 for FST, FSDB loaders. +3.3.105 01jul20 Fix bad (void) of is_closing in fstDestroyMmaps when using + Cygwin or MinGW. + Fix left shift overflow in cvt_fpsdec(). + Add in missing file/translate/process filter for reals. + Fix for bitvec merging in GHW so integers arrays can be viewed. + Added Shift-Up/Down highlight with scroll in order to assist + with left/right arrow based transition movement. + Fix Show Wave Highlight so it is not dependent on Show Grid. + Fix negative MSBs on VCD loaders for vectors. + Fix getpwuid() null pointer exception. + Add missing recursion case to treenamefix(). + Fix lock/unlock misuse of pthread mutexes across threads. + Examine env var $HOME for home dir on geteuid failure. +3.3.106 06jul20 Fix for GDK_KEY_* definitions missing in older GDK versions. + Fix Shift-Up/Down highlight to traverse inside groups. + Resync ghwlib to handled unbounded arrays. +3.3.107 30sep20 Fix left shift overflow in cvt_fpsudec for fixed point. + Added Find First One trace type options. + Fixed bug in Show-Change All Highlighted. +3.3.108 30dec20 Fix VZT writer crash when dumpoff is invoked before first + timestep. + Fix convert_ffo() that scanned in wrong direction. + Fix use after free in fstapi.c. +3.3.109 10apr21 gtk_ctree_node_moveto bugfix in SST. + MSVC compiler fix for fstapi. + Update xml2stems and rtlbrowse to support generate. +3.3.110 22may21 Removed ghwdump and ghwdump.1 from the distribution (now + provided with GHDL). + Minor scan-build fixes. +3.3.111 01sep21 Fix in fstapi for read start limit time. + Fix xml2stems when begin blocks are in functions. + Skip over decimal point in timescale in viewer. +3.3.112 04oct22 Bugfix-only release. + VCD reader fixes for unnamed Icarus begin blocks. + String data type crash fix in fst.c. +3.3.113 04oct22 Dummy release to keep in sync with gtk3 version. +3.3.114 23nov22 Buffer overflow fixes in FST reader. +3.3.115 28mar23 Fix VZT reader with -fstrict-aliasing. + Fix use_multi_state condition in vzt_write.c. + Fix for UNDEF vs strings at start of a vzt file. + Fix sleep() time scaling redefine for mingw. + Use MapViewOfFileEx for mmap on Windows (fstapi). + Define FST_DO_MISALIGNED_OPS on AArch64 (fstapi). + Fixed attrbegin short length problem. +3.3.116 27may23 Fix manpage/odt for vcd2fst command switch documentation for + zlibpack. + Changed sprintf to snprintf in fstapi.c. +3.3.117 08aug23 Fix stems reader processing code broken in 3.3.114. +3.3.118 17dec23 Update xml2stems to handle newer "loc" vs "fl" xml tags. + Change preg_regex_c_1 decl to use regex_t* as datatype. + Move gtkwave.appdata.xml to + io.github.gtkwave.GTKWave.metainfo.xml. + Fixed popen security advisories: + TALOS-2023-1786 + Fixed FST security advisories: + TALOS-2023-1777 + TALOS-2023-1783 + TALOS-2023-1785 + TALOS-2023-1789 + TALOS-2023-1790 + TALOS-2023-1791 + TALOS-2023-1792 + TALOS-2023-1793 + TALOS-2023-1797 + TALOS-2023-1798 + Fixed evcd2vcd security advisories: + TALOS-2023-1803 + Fixed VCD security advisories: + TALOS-2023-1804 + TALOS-2023-1805 + TALOS-2023-1806 + TALOS-2023-1807 + Fixed VZT security advisories: + TALOS-2023-1810 + TALOS-2023-1811 + TALOS-2023-1812 + TALOS-2023-1813 + TALOS-2023-1814 + TALOS-2023-1815 + TALOS-2023-1816 + TALOS-2023-1817 + Fixed LXT2 security advisories: + TALOS-2023-1818 + TALOS-2023-1819 + TALOS-2023-1820 + TALOS-2023-1821 + TALOS-2023-1822 + TALOS-2023-1823 + TALOS-2023-1824 + TALOS-2023-1826 + TALOS-2023-1827 diff -Nru gtkwave-3.3.104/LICENSE.TXT gtkwave-3.3.104+really3.3.118/LICENSE.TXT --- gtkwave-3.3.104/LICENSE.TXT 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/LICENSE.TXT 2023-12-31 21:11:04.000000000 +0000 @@ -1,14 +1,14 @@ ########################################################################## -GTKWave 3.3.104 Wave Viewer is Copyright (C) 1999-2020 Tony Bybell. -Portions of GTKWave are Copyright (C) 1999-2020 Udi Finkelstein. -Context support is Copyright (C) 2007-2020 Kermin Elliott Fleming. -Trace group support is Copyright (C) 2009-2020 Donald Baltus. -GHW and additional GUI support is Copyright (C) 2005-2020 Tristan Gingold. -Analog support is Copyright (C) 2005-2020 Thomas Sailer. -External DnD support is Copyright (C) 2008-2020 Concept Engineering GmbH. -FastLZ is Copyright (C) 2005-2020 Ariya Hidayat. -LZ4 is Copyright (C) 2011-2020 Yann Collet. +GTKWave 3.3.118 Wave Viewer is Copyright (C) 1999-2023 Tony Bybell. +Portions of GTKWave are Copyright (C) 1999-2023 Udi Finkelstein. +Context support is Copyright (C) 2007-2023 Kermin Elliott Fleming. +Trace group support is Copyright (C) 2009-2023 Donald Baltus. +GHW and additional GUI support is Copyright (C) 2005-2023 Tristan Gingold. +Analog support is Copyright (C) 2005-2023 Thomas Sailer. +External DnD support is Copyright (C) 2008-2023 Concept Engineering GmbH. +FastLZ is Copyright (C) 2005-2023 Ariya Hidayat. +LZ4 is Copyright (C) 2011-2023 Yann Collet. 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 diff -Nru gtkwave-3.3.104/configure gtkwave-3.3.104+really3.3.118/configure --- gtkwave-3.3.104/configure 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/configure 2023-12-31 21:11:04.000000000 +0000 @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.69 for gtkwave 3.3.104. +# Generated by GNU Autoconf 2.69 for gtkwave 3.3.118. # # Report bugs to . # @@ -580,8 +580,8 @@ # Identity of this package. PACKAGE_NAME='gtkwave' PACKAGE_TARNAME='gtkwave' -PACKAGE_VERSION='3.3.104' -PACKAGE_STRING='gtkwave 3.3.104' +PACKAGE_VERSION='3.3.118' +PACKAGE_STRING='gtkwave 3.3.118' PACKAGE_BUGREPORT='bybell@rocketmail.com' PACKAGE_URL='' @@ -1405,7 +1405,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures gtkwave 3.3.104 to adapt to many kinds of systems. +\`configure' configures gtkwave 3.3.118 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1471,7 +1471,7 @@ if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of gtkwave 3.3.104:";; + short | recursive ) echo "Configuration of gtkwave 3.3.118:";; esac cat <<\_ACEOF @@ -1630,7 +1630,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -gtkwave configure 3.3.104 +gtkwave configure 3.3.118 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. @@ -2274,7 +2274,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by gtkwave $as_me 3.3.104, which was +It was created by gtkwave $as_me 3.3.118, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ @@ -3141,7 +3141,7 @@ # Define the identity of the package. PACKAGE='gtkwave' - VERSION='3.3.104' + VERSION='3.3.118' cat >>confdefs.h <<_ACEOF @@ -11499,7 +11499,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by gtkwave $as_me 3.3.104, which was +This file was extended by gtkwave $as_me 3.3.118, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -11565,7 +11565,7 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -gtkwave config.status 3.3.104 +gtkwave config.status 3.3.118 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" diff -Nru gtkwave-3.3.104/configure.ac gtkwave-3.3.104+really3.3.118/configure.ac --- gtkwave-3.3.104/configure.ac 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/configure.ac 2023-12-31 21:11:04.000000000 +0000 @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT(gtkwave, 3.3.104, bybell@rocketmail.com) +AC_INIT(gtkwave, 3.3.118, bybell@rocketmail.com) AC_CONFIG_SRCDIR([src/vcd.c]) AM_INIT_AUTOMAKE AC_CONFIG_HEADER([config.h]) diff -Nru gtkwave-3.3.104/contrib/bundle_for_osx/Info-gtkwave.plist gtkwave-3.3.104+really3.3.118/contrib/bundle_for_osx/Info-gtkwave.plist --- gtkwave-3.3.104/contrib/bundle_for_osx/Info-gtkwave.plist 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/contrib/bundle_for_osx/Info-gtkwave.plist 2023-12-31 21:11:04.000000000 +0000 @@ -8,7 +8,7 @@ CFBundleExecutable gtkwave CFBundleGetInfoString - 3.3.104, (C) 1999-2020 Tony Bybell http://gtkwave.sourceforge.net + 3.3.118, (C) 1999-2023 Tony Bybell http://gtkwave.sourceforge.net CFBundleIconFile gtkwave.icns CFBundleIdentifier @@ -18,13 +18,13 @@ CFBundlePackageType APPL CFBundleShortVersionString - 3.3.104 + 3.3.118 CFBundleSignature ???? CFBundleVersion - 3.3.104 + 3.3.118 NSHumanReadableCopyright - Copyright 1999 - 2020 Tony Bybell, GNU General Public License. + Copyright 1999 - 2023 Tony Bybell, GNU General Public License. LSMinimumSystemVersion 10.6 diff -Nru gtkwave-3.3.104/contrib/bundle_for_osx/gtkwave.bundle gtkwave-3.3.104+really3.3.118/contrib/bundle_for_osx/gtkwave.bundle --- gtkwave-3.3.104/contrib/bundle_for_osx/gtkwave.bundle 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/contrib/bundle_for_osx/gtkwave.bundle 2023-12-31 21:11:04.000000000 +0000 @@ -26,7 +26,7 @@ - + ${project}/gtk_diff_against_modulesets.patch - -gtkwave.desktop -CC0-1.0 -Electronic waveform viewer for viewing simulation results - -

-GTKWave is a fully featured GTK+ based waveform viewer which reads FST, LXT, LXT2, VZT, and GHW files as well as standard Verilog VCD/EVCD files and allows their viewing. -

-

-The viewer supports both post-mortem viewing of VCD files and interactive viewing of VCD data. Tcl scripting and callback capability allow for remote control by other applications. -

-
-http://gtkwave.sourceforge.net/ - -http://gtkwave.sourceforge.net/gtkwave-appdata.png - -bybell@rocketmail.com -
diff -Nru gtkwave-3.3.104/share/appdata/io.github.gtkwave.GTKWave.metainfo.xml gtkwave-3.3.104+really3.3.118/share/appdata/io.github.gtkwave.GTKWave.metainfo.xml --- gtkwave-3.3.104/share/appdata/io.github.gtkwave.GTKWave.metainfo.xml 1970-01-01 00:00:00.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/share/appdata/io.github.gtkwave.GTKWave.metainfo.xml 2023-12-31 21:11:04.000000000 +0000 @@ -0,0 +1,136 @@ + + + + io.github.gtkwave.GTKWave + CC0-1.0 + GPL-2.0-or-later + GTKWave + Tony Bybell + bybell@rocketmail.com + Electronic waveform viewer for viewing simulation results + +

+ GTKWave is a fully featured GTK+ based waveform viewer which reads FST and + GHW files as well as standard Verilog VCD/EVCD files and allows their viewing. +

+

+ The viewer supports both post-mortem viewing of VCD files and interactive viewing of VCD data. + Tcl scripting and callback capability allow for remote control by other applications. +

+
+ + http://gtkwave.sourceforge.net/ + https://github.com/gtkwave/gtkwave/issues + https://github.com/gtkwave/gtkwave + + + + http://gtkwave.sourceforge.net/gtkwave-appdata.png + + + + + + + + +

+ Changes in 3.3.118: +

+
    +
  • Update xml2stems to handle newer "loc" vs "fl" xml tags
  • +
  • Change preg_regex_c_1 decl to use regex_t* as datatype
  • +
  • Move gtkwave.appdata.xml to io.github.gtkwave.GTKWave.metainfo.xml
  • +
+
+
+ + + +

+ Changes in 3.3.117: +

+
    +
  • Fix stems reader processing code broken in 3.3.114
  • +
+
+
+ + + +

+ Changes in 3.3.116: +

+
    +
  • Fix manpage/odt for vcd2fst command switch documentation for zlibpack
  • +
  • Changed sprintf to snprintf in fstapi.c
  • +
+
+
+ + + +

+ Changes in 3.3.115: +

+
    +
  • Fix VZT reader with -fstrict-aliasing
  • +
  • Fix use_multi_state condition in vzt_write.c
  • +
  • Fix for UNDEF vs strings at start of a vzt file
  • +
  • Fix sleep() time scaling redefine for mingw
  • +
  • Use MapViewOfFileEx for mmap on Windows (fstapi)
  • +
  • Define FST_DO_MISALIGNED_OPS on AArch64 (fstapi)
  • +
  • Fixed attrbegin short length problem
  • +
+
+
+ + + +

+ Changes in 3.3.114: +

+
    +
  • Buffer overflow fixes in FST reader
  • +
+
+
+ + + +

+ Changes in 3.3.113: +

+
    +
  • Dummy release to keep in sync with gtk3 version
  • +
+
+
+ + + +

+ Changes in 3.3.112: +

+
    +
  • Bugfix-only release, no feature adds
  • +
  • VCD reader fixes for unnamed Icarus begin blocks
  • +
  • String data type crash fix in fst.c
  • +
+
+
+ + + +

+ Changes in 3.3.111: +

+
    +
  • Fix in fstapi for read start limit time
  • +
  • Fix xml2stems when begin blocks are in functions
  • +
  • Skip over decimal point in timescale in viewer
  • +
+
+
+
+
diff -Nru gtkwave-3.3.104/src/Makefile.am gtkwave-3.3.104+really3.3.118/src/Makefile.am --- gtkwave-3.3.104/src/Makefile.am 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/Makefile.am 2023-12-31 21:11:05.000000000 +0000 @@ -38,7 +38,7 @@ debug.c debug.h discardbuttons.c edgebuttons.c \ entry.c extload.c extload.h fetchbuttons.c fgetdynamic.c fgetdynamic.h file.c fonts.c fonts.h fst.c fst.h \ gconf.c gconf.h getopt.c \ - getopt1.c ghw.c ghw.h ghwlib.c ghwlib.h gnu-getopt.h gnu_regex.h gtk12compat.h \ + getopt1.c ghw.c ghw.h libghw.c libghw.h gnu-getopt.h gnu_regex.h gtk12compat.h \ hierpack.c hierpack.h jrb.c jrb.h help.c helpers/lxt2_read.c \ helpers/lxt_write.c helpers/vzt_read.c hiersearch.c interp.c \ logfile.c lx2.c lx2.h lxt.c lxt.h main.c main.h markerbox.c menu.c menu.h mouseover.c \ diff -Nru gtkwave-3.3.104/src/Makefile.in gtkwave-3.3.104+really3.3.118/src/Makefile.in --- gtkwave-3.3.104/src/Makefile.in 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/Makefile.in 2023-12-31 21:11:05.000000000 +0000 @@ -98,7 +98,7 @@ entry.$(OBJEXT) extload.$(OBJEXT) fetchbuttons.$(OBJEXT) \ fgetdynamic.$(OBJEXT) file.$(OBJEXT) fonts.$(OBJEXT) \ fst.$(OBJEXT) gconf.$(OBJEXT) getopt.$(OBJEXT) \ - getopt1.$(OBJEXT) ghw.$(OBJEXT) ghwlib.$(OBJEXT) \ + getopt1.$(OBJEXT) ghw.$(OBJEXT) libghw.$(OBJEXT) \ hierpack.$(OBJEXT) jrb.$(OBJEXT) help.$(OBJEXT) \ lxt2_read.$(OBJEXT) lxt_write.$(OBJEXT) vzt_read.$(OBJEXT) \ hiersearch.$(OBJEXT) interp.$(OBJEXT) logfile.$(OBJEXT) \ @@ -434,7 +434,7 @@ debug.c debug.h discardbuttons.c edgebuttons.c \ entry.c extload.c extload.h fetchbuttons.c fgetdynamic.c fgetdynamic.h file.c fonts.c fonts.h fst.c fst.h \ gconf.c gconf.h getopt.c \ - getopt1.c ghw.c ghw.h ghwlib.c ghwlib.h gnu-getopt.h gnu_regex.h gtk12compat.h \ + getopt1.c ghw.c ghw.h libghw.c libghw.h gnu-getopt.h gnu_regex.h gtk12compat.h \ hierpack.c hierpack.h jrb.c jrb.h help.c helpers/lxt2_read.c \ helpers/lxt_write.c helpers/vzt_read.c hiersearch.c interp.c \ logfile.c lx2.c lx2.h lxt.c lxt.h main.c main.h markerbox.c menu.c menu.h mouseover.c \ @@ -574,13 +574,13 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ghw.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ghwlib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/globals.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/help.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hierpack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hiersearch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jrb.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libghw.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/logfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lx2.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxt.Po@am__quote@ diff -Nru gtkwave-3.3.104/src/analyzer.c gtkwave-3.3.104+really3.3.118/src/analyzer.c --- gtkwave-3.3.104/src/analyzer.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/analyzer.c 2023-12-31 21:11:04.000000000 +0000 @@ -223,6 +223,22 @@ } } +void MarkTraceCursor(Trptr t_curs) +{ +if(t_curs) + { + Trptr t=GLOBALS->traces.first; + + while(t) + { + t->is_cursor = 0; + t=t->t_next; + } + + t_curs->is_cursor = 1; + } +} + /* * Add a trace to the display... */ diff -Nru gtkwave-3.3.104/src/analyzer.h gtkwave-3.3.104+really3.3.118/src/analyzer.h --- gtkwave-3.3.104/src/analyzer.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/analyzer.h 2023-12-31 21:11:04.000000000 +0000 @@ -513,6 +513,7 @@ unsigned int t_color; /* trace color index */ unsigned char t_fpdecshift; /* for fixed point decimal */ + unsigned is_cursor : 1; /* set to mark a cursor trace */ unsigned is_alias : 1; /* set when it's an alias (safe to free t->name then) */ unsigned is_depacked : 1; /* set when it's been depacked from a compressed entry (safe to free t->name then) */ unsigned vector : 1; /* 1 if bit vector, 0 if node */ @@ -538,6 +539,8 @@ TR_FPDECSHIFT_B, TR_TIME_B, TR_ENUM_B, + TR_CURSOR_B, + TR_FFO_B, TR_RSVD_B /* for use internally such as temporary caching of highlighting, not for use in traces */ }; @@ -574,6 +577,7 @@ #define TR_REAL2BITS (UINT64_C(1)< gray/popcnt in place + * filters mutually exclusive with file/translate/process filters + */ +static char *lzremoval(char *s) +{ +char *p = s; + +if(*p) + { + while((*p=='0') && *(p+1)) + { + p++; + } + } + +if(p != s) + { + memmove(s, p, strlen(p) + 1); + } + +return(s); +} + +/* + * file/translate/process filters + */ +static char *dofilter(Trptr t, char *s) +{ +GLOBALS->xl_file_filter[t->f_filter] = xl_splay(s, GLOBALS->xl_file_filter[t->f_filter]); + +if(!strcasecmp(s, GLOBALS->xl_file_filter[t->f_filter]->item)) + { + free_2(s); + s = malloc_2(strlen(GLOBALS->xl_file_filter[t->f_filter]->trans) + 1); + strcpy(s, GLOBALS->xl_file_filter[t->f_filter]->trans); + } + +if((*s == '?') && (!GLOBALS->color_active_in_filter)) + { + char *s2a; + char *s2 = strchr(s+1, '?'); + if(s2) + { + s2++; + s2a = malloc_2(strlen(s2)+1); + strcpy(s2a, s2); + free_2(s); + s = s2a; + } + } + +return(s); +} + +static char *edofilter(Trptr t, char *s) +{ +if(t->flags & TR_ENUM) + { + int filt = t->e_filter - 1; + +#ifdef _WAVE_HAVE_JUDY + PPvoid_t pv = JudyHSGet(GLOBALS->xl_enum_filter[filt], s, strlen(s)); + if(pv) + { + free_2(s); + s = malloc_2(strlen(*pv) + 1); + strcpy(s, *pv); + } +#else + GLOBALS->xl_enum_filter[filt] = xl_splay(s, GLOBALS->xl_enum_filter[filt]); + + if(!strcasecmp(s, GLOBALS->xl_enum_filter[filt]->item)) + { + free_2(s); + s = malloc_2(strlen(GLOBALS->xl_enum_filter[filt]->trans) + 1); + strcpy(s, GLOBALS->xl_enum_filter[filt]->trans); + } +#endif + else + { + char *zerofind = s; + char *dst = s, *src; + while(*zerofind == '0') zerofind++; + if(zerofind != s) + { + src = (!*zerofind) ? (zerofind-1) : zerofind; + while(*src) + { + *(dst++) = *(src++); + } + *dst = 0; + } + } + } + +return(s); +} + +static char *pdofilter(Trptr t, char *s) +{ +struct pipe_ctx *p = GLOBALS->proc_filter[t->p_filter]; +char buf[1025]; +int n; + +if(p) + { +#if !defined _MSC_VER && !defined __MINGW32__ + fputs(s, p->sout); + fputc('\n', p->sout); + fflush(p->sout); + + buf[0] = 0; + + n = fgets(buf, 1024, p->sin) ? strlen(buf) : 0; + buf[n] = 0; +#else + { + BOOL bSuccess; + DWORD dwWritten, dwRead; + + WriteFile(p->g_hChildStd_IN_Wr, s, strlen(s), &dwWritten, NULL); + WriteFile(p->g_hChildStd_IN_Wr, "\n", 1, &dwWritten, NULL); + + for(n=0;n<1024;n++) + { + do { + bSuccess = ReadFile(p->g_hChildStd_OUT_Rd, buf+n, 1, &dwRead, NULL); + if((!bSuccess)||(buf[n]=='\n')) + { + goto ex; + } + + } while(buf[n]=='\r'); + } +ex: buf[n] = 0; + } + +#endif + + if(n) + { + if(buf[n-1] == '\n') { buf[n-1] = 0; n--; } + } + + if(buf[0]) + { + free_2(s); + s = malloc_2(n + 1); + strcpy(s, buf); + } + } + +if((*s == '?') && (!GLOBALS->color_active_in_filter)) + { + char *s2a; + char *s2 = strchr(s+1, '?'); + if(s2) + { + s2++; + s2a = malloc_2(strlen(s2)+1); + strcpy(s2a, s2); + free_2(s); + s = s2a; + } + } +return(s); +} + + +/* + * convert binary <=> gray/ffo/popcnt in place */ #define cvt_gray(f,p,n) \ do { \ -if((f)&(TR_GRAYMASK|TR_POPCNT)) \ - { \ - if((f)&TR_BINGRAY) { convert_bingray((p),(n)); } \ - if((f)&TR_GRAYBIN) { convert_graybin((p),(n)); } \ - if((f)&TR_POPCNT) { convert_popcnt((p),(n)); } \ - } \ +if((f)&(TR_GRAYMASK|TR_POPCNT|TR_FFO)) \ + { \ + if((f)&TR_BINGRAY) { convert_bingray((p),(n)); } \ + if((f)&TR_GRAYBIN) { convert_graybin((p),(n)); } \ + if((f)&TR_FFO) { convert_ffo((p),(n)); } \ + if((f)&TR_POPCNT) { convert_popcnt((p),(n)); } \ + } \ } while(0) @@ -168,6 +338,40 @@ } +static void convert_ffo(char *pnt, int nbits) +{ +int i; +int ffo = -1; + +for(i=(nbits-1);i>=0;i--) + { + char ch = pnt[i]; + + if((ch == AN_1) || (ch == AN_H)) + { + ffo = (nbits-1) - i; + break; + } + } + +if(ffo >= 0) + { + for(i=nbits-1;i>=0;i--) /* always requires less number of bits */ + { + pnt[i] = (ffo & 1) ? AN_1 : AN_0; + ffo >>= 1; + } + } + else + { + for(i=nbits-1;i>=0;i--) /* always requires less number of bits */ + { + pnt[i] = AN_X; + } + } +} + + static void dpr_e16(char *str, double d) { char *buf16; @@ -196,7 +400,8 @@ int shamt = t->t_fpdecshift; TimeType lpart = val >> shamt; -TimeType rmsk = (1 << shamt); +TimeType rmsk = (ULLDescriptor(1) << shamt); + TimeType rbit = (val >= 0) ? (val & (rmsk-1)) : ((-val) & (rmsk-1)); double rfrac; int negflag = 0; @@ -245,7 +450,7 @@ { int shamt = t->t_fpdecshift; UTimeType lpart = ((UTimeType)val) >> shamt; -TimeType rmsk = (1 << shamt); +TimeType rmsk = (ULLDescriptor(1) << shamt); TimeType rbit = (val & (rmsk-1)); double rfrac; char dbuf[32]; @@ -466,7 +671,7 @@ if(GLOBALS->show_base) { *(pnt++)='"'; } *(pnt)=0x00; /* scan build : remove dead increment */ } -else if((flags&TR_HEX)||((flags&(TR_DEC|TR_SIGNED))&&(nbits>64)&&(!(flags&TR_POPCNT)))) +else if((flags&TR_HEX)||((flags&(TR_DEC|TR_SIGNED))&&(nbits>64)&&(!(flags&(TR_POPCNT|TR_FFO))))) { char *parse; @@ -896,6 +1101,30 @@ } } +if(t) + { + if(!(t->f_filter|t->p_filter|t->e_filter)) + { + if(GLOBALS->lz_removal) lzremoval(rv); + } + else + { + if(t->e_filter) + { + rv = edofilter(t, rv); + } + else + if(t->f_filter) + { + rv = dofilter(t, rv); + } + else + { + rv = pdofilter(t, rv); + } + } + } + return(rv); } @@ -1215,7 +1444,7 @@ if(GLOBALS->show_base) { *(pnt++)='"'; } *(pnt)=0x00; /* scan build : remove dead increment */ } -else if((flags&TR_HEX)||((flags&(TR_DEC|TR_SIGNED))&&(nbits>64)&&(!(flags&TR_POPCNT)))) +else if((flags&TR_HEX)||((flags&(TR_DEC|TR_SIGNED))&&(nbits>64)&&(!(flags&(TR_POPCNT|TR_FFO))))) { char *parse; @@ -1596,155 +1825,13 @@ } -static char *dofilter(Trptr t, char *s) -{ -GLOBALS->xl_file_filter[t->f_filter] = xl_splay(s, GLOBALS->xl_file_filter[t->f_filter]); - -if(!strcasecmp(s, GLOBALS->xl_file_filter[t->f_filter]->item)) - { - free_2(s); - s = malloc_2(strlen(GLOBALS->xl_file_filter[t->f_filter]->trans) + 1); - strcpy(s, GLOBALS->xl_file_filter[t->f_filter]->trans); - } - -if((*s == '?') && (!GLOBALS->color_active_in_filter)) - { - char *s2a; - char *s2 = strchr(s+1, '?'); - if(s2) - { - s2++; - s2a = malloc_2(strlen(s2)+1); - strcpy(s2a, s2); - free_2(s); - s = s2a; - } - } - -return(s); -} - -static char *edofilter(Trptr t, char *s) -{ -if(t->flags & TR_ENUM) - { - int filt = t->e_filter - 1; - -#ifdef _WAVE_HAVE_JUDY - PPvoid_t pv = JudyHSGet(GLOBALS->xl_enum_filter[filt], s, strlen(s)); - if(pv) - { - free_2(s); - s = malloc_2(strlen(*pv) + 1); - strcpy(s, *pv); - } -#else - GLOBALS->xl_enum_filter[filt] = xl_splay(s, GLOBALS->xl_enum_filter[filt]); - - if(!strcasecmp(s, GLOBALS->xl_enum_filter[filt]->item)) - { - free_2(s); - s = malloc_2(strlen(GLOBALS->xl_enum_filter[filt]->trans) + 1); - strcpy(s, GLOBALS->xl_enum_filter[filt]->trans); - } -#endif - else - { - char *zerofind = s; - char *dst = s, *src; - while(*zerofind == '0') zerofind++; - if(zerofind != s) - { - src = (!*zerofind) ? (zerofind-1) : zerofind; - while(*src) - { - *(dst++) = *(src++); - } - *dst = 0; - } - } - } - -return(s); -} - -static char *pdofilter(Trptr t, char *s) -{ -struct pipe_ctx *p = GLOBALS->proc_filter[t->p_filter]; -char buf[1025]; -int n; - -if(p) - { -#if !defined _MSC_VER && !defined __MINGW32__ - fputs(s, p->sout); - fputc('\n', p->sout); - fflush(p->sout); - - buf[0] = 0; - - n = fgets(buf, 1024, p->sin) ? strlen(buf) : 0; - buf[n] = 0; -#else - { - BOOL bSuccess; - DWORD dwWritten, dwRead; - - WriteFile(p->g_hChildStd_IN_Wr, s, strlen(s), &dwWritten, NULL); - WriteFile(p->g_hChildStd_IN_Wr, "\n", 1, &dwWritten, NULL); - - for(n=0;n<1024;n++) - { - do { - bSuccess = ReadFile(p->g_hChildStd_OUT_Rd, buf+n, 1, &dwRead, NULL); - if((!bSuccess)||(buf[n]=='\n')) - { - goto ex; - } - - } while(buf[n]=='\r'); - } -ex: buf[n] = 0; - } - -#endif - - if(n) - { - if(buf[n-1] == '\n') { buf[n-1] = 0; n--; } - } - - if(buf[0]) - { - free_2(s); - s = malloc_2(n + 1); - strcpy(s, buf); - } - } - -if((*s == '?') && (!GLOBALS->color_active_in_filter)) - { - char *s2a; - char *s2 = strchr(s+1, '?'); - if(s2) - { - s2++; - s2a = malloc_2(strlen(s2)+1); - strcpy(s2a, s2); - free_2(s); - s = s2a; - } - } -return(s); -} - - char *convert_ascii_vec(Trptr t, char *vec) { char *s = convert_ascii_vec_2(t, vec); if(!(t->f_filter|t->p_filter|t->e_filter)) { + if(GLOBALS->lz_removal) lzremoval(s); } else { @@ -1795,6 +1882,7 @@ if(!(t->f_filter|t->p_filter|t->e_filter)) { + if(GLOBALS->lz_removal) lzremoval(s); } else { diff -Nru gtkwave-3.3.104/src/currenttime.c gtkwave-3.3.104+really3.3.118/src/currenttime.c --- gtkwave-3.3.104/src/currenttime.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/currenttime.c 2023-12-31 21:11:05.000000000 +0000 @@ -28,7 +28,38 @@ int i, len; int prefix_idx = 0; -if(*s != '0') return; +if(*s != '0') + { + unsigned char *dot = strchr(s, '.'); + unsigned char *src, *dst; + if(dot) + { + unsigned char *pnt = dot+1; + int alpha_found = 0; + while(*pnt) + { + if(isalpha(*pnt)) + { + alpha_found = 1; + break; + } + pnt++; + } + + if(alpha_found) + { + src = pnt; + dst = dot; + while(*src) + { + *dst = *src; + dst++; src++; + } + *dst = 0; + } + } + return; + } len = strlen(s); for(i=0;i&1", EXTLOAD_PATH, fname); -GLOBALS->extload = popen(sbuff, "r"); +GLOBALS->extload = popen_san(sbuff, "r"); for(;;) { char * rc = fgets(sbuff, 65536, GLOBALS->extload); @@ -1900,7 +1900,7 @@ if(!last_modification_check()) { GLOBALS->extload_already_errored = 1; return(LLDescriptor(0)); } sprintf(sbuff, "%s -hier_tree %s 2>&1", EXTLOAD_PATH, fname); -GLOBALS->extload = popen(sbuff, "r"); +GLOBALS->extload = popen_san(sbuff, "r"); /* do your stuff here..all useful info has been initialized by now */ @@ -2256,7 +2256,7 @@ TimeType tim; sprintf(sbuff, "%s -vc -vidcode %d %s 2>&1", EXTLOAD_PATH, txidx_in_trace, GLOBALS->loaded_file_name); - GLOBALS->extload = popen(sbuff, "r"); + GLOBALS->extload = popen_san(sbuff, "r"); for(;;) { diff -Nru gtkwave-3.3.104/src/fst.c gtkwave-3.3.104+really3.3.118/src/fst.c --- gtkwave-3.3.104/src/fst.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/fst.c 2023-12-31 21:11:05.000000000 +0000 @@ -148,7 +148,7 @@ { struct fstHier *h; const char *pnts; -char *pnt, *pntd, *lb_last = NULL, *col_last = NULL; /* *rb_last = NULL; */ /* scan-build : unused */ +char *pnt, *pntd, *lb_last = NULL, *col_last = NULL, *rb_last = NULL; int acc; char *s; unsigned char ttype; @@ -219,9 +219,11 @@ { if(*pnts != ' ') { - if(*pnts == '[') { lb_last = pntd; col_last = NULL; } - else if(*pnts == ':') { col_last = pntd; } - /* else if(*pnts == ']') { rb_last = pntd; } */ /* scan-build : unused */ + if(*pnts == '[') { lb_last = pntd; col_last = NULL; rb_last = NULL; } + else if(*pnts == ':' && lb_last != NULL && col_last == NULL && rb_last == NULL) { col_last = pntd; } + else if(*pnts == ']' && lb_last != NULL && rb_last == NULL) { rb_last = pntd; } + else if(lb_last != NULL && rb_last == NULL && (isdigit((int)(unsigned char)*pnts) || (*pnts == '-'))) { } + else { lb_last = NULL; col_last = NULL; rb_last = NULL; } *(pntd++) = *pnts; } @@ -229,6 +231,12 @@ } *pntd = 0; *namlen = pntd - s; + if(!rb_last) + { + col_last = NULL; + lb_last = NULL; + } + if(!lb_last) { *msb = *lsb = -1; @@ -1522,7 +1530,7 @@ { if((!strcmp(l2e->histent_curr->v.h_vector, (const char *)value)) && (!GLOBALS->vcd_preserve_glitches)) { - free(s); + free_2(s); return; } } diff -Nru gtkwave-3.3.104/src/ghw.c gtkwave-3.3.104+really3.3.118/src/ghw.c --- gtkwave-3.3.104/src/ghw.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/ghw.c 2023-12-31 21:11:05.000000000 +0000 @@ -20,7 +20,7 @@ #include "globals.h" #include #include "ghw.h" -#include "ghwlib.h" +#include "libghw.h" #include "tree.h" /************************ splay ************************/ @@ -173,42 +173,52 @@ { if(psr) { - char *fstr1 = GLOBALS->facs[i-1]->name; - char *fstr2 = GLOBALS->facs[i]->name; - int p1 = strand_pnt(fstr1); - int p2 = strand_pnt(fstr2); + int ev1 = GLOBALS->facs[i-1]->n->extvals; + int ev2 = GLOBALS->facs[i]->n->extvals; - if(!root) + if(!ev1 && !ev2) { - if((p1>=0)&&(p1==p2)) + char *fstr1 = GLOBALS->facs[i-1]->name; + char *fstr2 = GLOBALS->facs[i]->name; + int p1 = strand_pnt(fstr1); + int p2 = strand_pnt(fstr2); + + if(!root) { - if(!strncmp(fstr1, fstr2, p1)) + if((p1>=0)&&(p1==p2)) { - root = GLOBALS->facs[i-1]; - root->vec_root = root; - root->vec_chain = GLOBALS->facs[i]; - GLOBALS->facs[i]->vec_root = root; + if(!strncmp(fstr1, fstr2, p1)) + { + root = GLOBALS->facs[i-1]; + root->vec_root = root; + root->vec_chain = GLOBALS->facs[i]; + GLOBALS->facs[i]->vec_root = root; + } } } - } - else - { - if((p1>=0)&&(p1==p2)) + else { - if(!strncmp(fstr1, fstr2, p1)) + if((p1>=0)&&(p1==p2)) { - psr->vec_chain = GLOBALS->facs[i]; - GLOBALS->facs[i]->vec_root = root; + if(!strncmp(fstr1, fstr2, p1)) + { + psr->vec_chain = GLOBALS->facs[i]; + GLOBALS->facs[i]->vec_root = root; + } + else + { + root = NULL; + } } else { root = NULL; } } - else - { - root = NULL; - } + } + else + { + root = NULL; } } @@ -233,9 +243,9 @@ int i; int cnt = 1; struct tree **ar; - + while((t2 = t2->next)) { cnt++; } - + ar = malloc_2(cnt * sizeof(struct tree *)); t2 = t; for(i=0;ichild) { recurse_tree_build_whichcache(t2->child); } t2 = t2->next; } - + for(i=cnt-1;i>=0;i--) { t = ar[i]; - if(t->t_which >= 0) + if(t->t_which >= 0) { GLOBALS->gwt_ghw_c_1 = ghw_insert(t, GLOBALS->gwt_ghw_c_1, t->t_which, GLOBALS->facs[t->t_which]); } } - + free_2(ar); } } @@ -266,9 +276,9 @@ int i; int cnt = 1; struct tree **ar; - + while((t2 = t2->next)) { cnt++; } - + ar = malloc_2(cnt * sizeof(struct tree *)); t2 = t; for(i=0;ichild) { recurse_tree_fix_from_whichcache(t2->child); } t2 = t2->next; } - + for(i=cnt-1;i>=0;i--) { t = ar[i]; @@ -285,11 +295,11 @@ { GLOBALS->gwt_ghw_c_1 = ghw_splay(t, GLOBALS->gwt_ghw_c_1); GLOBALS->gwt_corr_ghw_c_1 = ghw_splay(GLOBALS->gwt_ghw_c_1->sym, GLOBALS->gwt_corr_ghw_c_1); /* all facs are in this tree so this is OK */ - + t->t_which = GLOBALS->gwt_corr_ghw_c_1->val_old; } } - + free_2(ar); } } @@ -440,7 +450,8 @@ const char *pfx, struct tree **res, unsigned int **sig) { union ghw_type *idx; - struct ghw_type_array *base = arr->sa.base; + struct ghw_type_array *base = + (struct ghw_type_array *) ghw_get_base_type (arr->sa.base); char *name = NULL; if ((unsigned int)dim == base->nbr_dim) @@ -449,7 +460,7 @@ sprintf (GLOBALS->asbuf, "%s]", pfx); name = strdup_2(GLOBALS->asbuf); - t = build_hierarchy_type (h, base->el, name, sig); + t = build_hierarchy_type (h, arr->sa.el, name, sig); if (*res != NULL) (*res)->next = t; diff -Nru gtkwave-3.3.104/src/ghwlib.c gtkwave-3.3.104+really3.3.118/src/ghwlib.c --- gtkwave-3.3.104/src/ghwlib.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/ghwlib.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,2183 +0,0 @@ -/* GHDL Wavefile reader library. - Copyright (C) 2005 Tristan Gingold - - GHDL 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, or (at your option) any later - version. - - GHDL 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. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. -*/ - -#include -#include -#include -#include -#include - -#include "ghwlib.h" - -/* Reopen H through decompressor DECOMP. */ - -static int -ghw_openz (struct ghw_handler *h, const char *decomp, const char *filename) -{ - int plen = strlen (decomp) + 1 + strlen(filename) + 1; - char *p = malloc (plen); - - snprintf (p, plen, "%s %s", decomp, filename); - fclose (h->stream); - h->stream = popen(p, "r"); - free (p); - - if (h->stream == NULL) - return -1; - - h->stream_ispipe = 1; - - return 0; -} - -int -ghw_open (struct ghw_handler *h, const char *filename) -{ - char hdr[16]; - - h->stream = fopen (filename, "rb"); - if (h->stream == NULL) - return -1; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - - /* Check compression layer. */ - if (!memcmp (hdr, "\x1f\x8b", 2)) - { - if (ghw_openz (h, "gzip -cd", filename) < 0) - return -1; - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - } - else if (!memcmp (hdr, "BZ", 2)) - { - if (ghw_openz (h, "bzip2 -cd", filename) < 0) - return -1; - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - } - else - { - h->stream_ispipe = 0; - } - - /* Check magic. */ - if (memcmp (hdr, "GHDLwave\n", 9) != 0) - return -2; - /* Check version. */ - if (hdr[9] != 16 - || hdr[10] != 0) - return -2; - h->version = hdr[11]; - if (h->version > 1) - return -3; - if (hdr[12] == 1) - h->word_be = 0; - else if (hdr[12] == 2) - h->word_be = 1; - else - return -4; -#if 0 - /* Endianness. */ - { - int endian; - union { unsigned char b[4]; uint32_t i;} v; - v.i = 0x11223344; - if (v.b[0] == 0x11) - endian = 2; - else if (v.b[0] == 0x44) - endian = 1; - else - return -3; - - if (hdr[12] != 1 && hdr[12] != 2) - return -3; - if (hdr[12] != endian) - h->swap_word = 1; - else - h->swap_word = 0; - } -#endif - h->word_len = hdr[13]; - h->off_len = hdr[14]; - - if (hdr[15] != 0) - return -5; - - h->hie = NULL; - return 0; -} - -int32_t -ghw_get_i32 (struct ghw_handler *h, unsigned char *b) -{ - if (h->word_be) - return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0); - else - return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0] << 0); -} - -int64_t -ghw_get_i64 (struct ghw_handler *ghw_h, unsigned char *b) -{ - int l, h; - - if (ghw_h->word_be) - { - h = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0); - l = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | (b[7] << 0); - } - else - { - l = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0] << 0); - h = (b[7] << 24) | (b[6] << 16) | (b[5] << 8) | (b[4] << 0); - } - return (((int64_t)h) << 32) | l; -} - -int -ghw_read_byte (struct ghw_handler *h, unsigned char *res) -{ - int v; - - v = fgetc (h->stream); - if (v == EOF) - return -1; - *res = v; - return 0; -} - -int -ghw_read_uleb128 (struct ghw_handler *h, uint32_t *res) -{ - uint32_t r = 0; - unsigned int off = 0; - - while (1) - { - int v = fgetc (h->stream); - if (v == EOF) - return -1; - r |= (v & 0x7f) << off; - if ((v & 0x80) == 0) - break; - off += 7; - } - *res = r; - return 0; -} - -int -ghw_read_sleb128 (struct ghw_handler *h, int32_t *res) -{ - int32_t r = 0; - unsigned int off = 0; - - while (1) - { - int v = fgetc (h->stream); - if (v == EOF) - return -1; - r |= ((int32_t)(v & 0x7f)) << off; - off += 7; - if ((v & 0x80) == 0) - { - if ((v & 0x40) && off < 32) - r |= ~0U << off; - break; - } - } - *res = r; - return 0; -} - -int -ghw_read_lsleb128 (struct ghw_handler *h, int64_t *res) -{ - static const int64_t r_mask = -1; - int64_t r = 0; - unsigned int off = 0; - - while (1) - { - int v = fgetc (h->stream); - if (v == EOF) - return -1; - r |= ((int64_t)(v & 0x7f)) << off; - off += 7; - if ((v & 0x80) == 0) - { - if ((v & 0x40) && off < 64) - r |= r_mask << off; - break; - } - } - *res = r; - return 0; -} - -int -ghw_read_f64 (struct ghw_handler *h, double *res) -{ - /* FIXME: handle byte order. */ - if (fread (res, sizeof (*res), 1, h->stream) != 1) - return -1; - return 0; -} - -const char * -ghw_read_strid (struct ghw_handler *h) -{ - uint32_t id; - - if (ghw_read_uleb128 (h, &id) != 0) - return NULL; - return h->str_table[id]; -} - -union ghw_type * -ghw_read_typeid (struct ghw_handler *h) -{ - uint32_t id; - - if (ghw_read_uleb128 (h, &id) != 0) - return NULL; - return h->types[id - 1]; -} - -union ghw_range * -ghw_read_range (struct ghw_handler *h) -{ - int t = fgetc (h->stream); - if (t == EOF) - return NULL; - switch (t & 0x7f) - { - case ghdl_rtik_type_b2: - { - struct ghw_range_b2 *r; - r = malloc (sizeof (struct ghw_range_b2)); - r->kind = t & 0x7f; - r->dir = (t & 0x80) != 0; - if (ghw_read_byte (h, &r->left) != 0) - goto err_b2; - if (ghw_read_byte (h, &r->right) != 0) - goto err_b2; - return (union ghw_range *)r; - err_b2: - free (r); - return NULL; - } - case ghdl_rtik_type_e8: - { - struct ghw_range_e8 *r; - r = malloc (sizeof (struct ghw_range_e8)); - r->kind = t & 0x7f; - r->dir = (t & 0x80) != 0; - if (ghw_read_byte (h, &r->left) != 0) - goto err_e8; - if (ghw_read_byte (h, &r->right) != 0) - goto err_e8; - return (union ghw_range *)r; - err_e8: - free (r); - return NULL; - } - case ghdl_rtik_type_i32: - case ghdl_rtik_type_p32: - { - struct ghw_range_i32 *r; - r = malloc (sizeof (struct ghw_range_i32)); - r->kind = t & 0x7f; - r->dir = (t & 0x80) != 0; - if (ghw_read_sleb128 (h, &r->left) != 0) - goto err_i32; - if (ghw_read_sleb128 (h, &r->right) != 0) - goto err_i32; - return (union ghw_range *)r; - err_i32: - free (r); - return NULL; - } - case ghdl_rtik_type_i64: - case ghdl_rtik_type_p64: - { - struct ghw_range_i64 *r; - r = malloc (sizeof (struct ghw_range_i64)); - r->kind = t & 0x7f; - r->dir = (t & 0x80) != 0; - if (ghw_read_lsleb128 (h, &r->left) != 0) - goto err_i64; - if (ghw_read_lsleb128 (h, &r->right) != 0) - goto err_i64; - return (union ghw_range *)r; - err_i64: - free (r); - return NULL; - } - case ghdl_rtik_type_f64: - { - struct ghw_range_f64 *r; - r = malloc (sizeof (struct ghw_range_f64)); - r->kind = t & 0x7f; - r->dir = (t & 0x80) != 0; - if (ghw_read_f64 (h, &r->left) != 0) - goto err_f64; - if (ghw_read_f64 (h, &r->right) != 0) - goto err_f64; - return (union ghw_range *)r; - err_f64: - free (r); - return NULL; - } - default: - fprintf (stderr, "ghw_read_range: type %d unhandled\n", t & 0x7f); - return NULL; - } -} - -int -ghw_read_str (struct ghw_handler *h) -{ - unsigned char hdr[12]; - unsigned i; - char *p; - int prev_len; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - - if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) - return -1; - h->nbr_str = ghw_get_i32 (h, &hdr[4]); - h->nbr_str++; - h->str_size = ghw_get_i32 (h, &hdr[8]); - h->str_table = (char **)malloc ((h->nbr_str + 1) * sizeof (char *)); - h->str_content = (char *)malloc (h->str_size + h->nbr_str + 1); - - if (h->flag_verbose) - { - printf ("Number of strings: %u\n", h->nbr_str - 1); - printf ("String table size: %u\n", h->str_size); - } - - h->str_table[0] = ""; - p = h->str_content; - prev_len = 0; - for (i = 1; i < h->nbr_str; i++) - { - int j; - int c; - char *prev; - int sh; - - h->str_table[i] = p; - prev = h->str_table[i - 1]; - for (j = 0; j < prev_len; j++) - *p++ = prev[j]; - - while (1) - { - c = fgetc (h->stream); - if (c == EOF) - return -1; - if ((c >= 0 && c <= 31) - || (c >= 128 && c <= 159)) - break; - *p++ = c; - } - *p++ = 0; - - if (h->flag_verbose > 1) - printf (" string %u (pl=%d): %s\n", i, prev_len, h->str_table[i]); - - prev_len = c & 0x1f; - sh = 5; - while (c >= 128) - { - c = fgetc (h->stream); - if (c == EOF) - return -1; - prev_len |= (c & 0x1f) << sh; - sh += 5; - } - } - if (fread (hdr, 4, 1, h->stream) != 1) - return -1; - if (memcmp (hdr, "EOS", 4) != 0) - return -1; - return 0; -} - -union ghw_type * -ghw_get_base_type (union ghw_type *t) -{ - switch (t->kind) - { - case ghdl_rtik_type_b2: - case ghdl_rtik_type_e8: - case ghdl_rtik_type_e32: - case ghdl_rtik_type_i32: - case ghdl_rtik_type_i64: - case ghdl_rtik_type_f64: - case ghdl_rtik_type_p32: - case ghdl_rtik_type_p64: - return t; - case ghdl_rtik_subtype_scalar: - return t->ss.base; - case ghdl_rtik_subtype_array: - return (union ghw_type*)(t->sa.base); - default: - fprintf (stderr, "ghw_get_base_type: cannot handle type %d\n", t->kind); - abort (); - } -} - -/* Return -1 for unbounded types. */ -static int -get_nbr_elements (union ghw_type *t) -{ - switch (t->kind) - { - case ghdl_rtik_type_b2: - case ghdl_rtik_type_e8: - case ghdl_rtik_type_e32: - case ghdl_rtik_type_i32: - case ghdl_rtik_type_i64: - case ghdl_rtik_type_f64: - case ghdl_rtik_type_p32: - case ghdl_rtik_type_p64: - case ghdl_rtik_subtype_scalar: - return 1; - case ghdl_rtik_type_array: - return -1; - case ghdl_rtik_subtype_array: - return t->sa.nbr_scalars; - case ghdl_rtik_type_record: - return t->rec.nbr_scalars; - case ghdl_rtik_subtype_record: - return t->sr.nbr_scalars; - default: - fprintf (stderr, "get_nbr_elements: unhandled type %d\n", t->kind); - abort (); - } -} - -int -ghw_get_range_length (union ghw_range *rng) -{ - int res; - - assert (rng != NULL); - - switch (rng->kind) - { - case ghdl_rtik_type_i32: - if (rng->i32.dir) - res = rng->i32.left - rng->i32.right + 1; - else - res = rng->i32.right - rng->i32.left + 1; - break; - case ghdl_rtik_type_b2: - if (rng->b2.dir) - res = rng->b2.left - rng->b2.right + 1; - else - res = rng->b2.right - rng->b2.left + 1; - break; - case ghdl_rtik_type_e8: - if (rng->e8.dir) - res = rng->e8.left - rng->e8.right + 1; - else - res = rng->e8.right - rng->e8.left + 1; - break; - default: - fprintf (stderr, "get_range_length: unhandled kind %d\n", rng->kind); - abort (); - } - /* The length of a null range is 0. */ - return (res <= 0) ? 0 : res; -} - -/* Create an array subtype using BASE and ranges read from H. */ - -struct ghw_subtype_array * -ghw_read_array_subtype (struct ghw_handler *h, struct ghw_type_array *base) -{ - struct ghw_subtype_array *sa; - unsigned j; - int nbr_scalars; - - sa = malloc (sizeof (struct ghw_subtype_array)); - sa->kind = ghdl_rtik_subtype_array; - sa->name = NULL; - sa->base = base; - nbr_scalars = get_nbr_elements (base->el); - sa->rngs = malloc (base->nbr_dim * sizeof (union ghw_range *)); - for (j = 0; j < base->nbr_dim; j++) - { - sa->rngs[j] = ghw_read_range (h); - nbr_scalars *= ghw_get_range_length (sa->rngs[j]); - } - sa->nbr_scalars = nbr_scalars; - return sa; -} - -struct ghw_subtype_record * -ghw_read_record_subtype (struct ghw_handler *h, struct ghw_type_record *base) -{ - struct ghw_subtype_record *sr; - - sr = malloc (sizeof (struct ghw_subtype_record)); - sr->kind = ghdl_rtik_subtype_record; - sr->name = NULL; - sr->base = base; - if (base->nbr_scalars >= 0) - { - /* Record base type is bounded. */ - sr->nbr_scalars = base->nbr_scalars; - sr->els = base->els; - } - else - { - /* Read subtypes. */ - unsigned j; - int nbr_scalars; - - sr->els = malloc (base->nbr_fields * sizeof (struct ghw_record_element)); - nbr_scalars = 0; - for (j = 0; j < base->nbr_fields; j++) - { - union ghw_type *btype = base->els[j].type; - int el_nbr_scalars = get_nbr_elements (btype); - - sr->els[j].name = base->els[j].name; - if (el_nbr_scalars >= 0) - { - /* Element is constrained. */ - sr->els[j].type = btype; - } - else - { - switch (btype->kind) - { - case ghdl_rtik_type_array: - sr->els[j].type = (union ghw_type *) - ghw_read_array_subtype (h, &btype->ar); - break; - case ghdl_rtik_type_record: - sr->els[j].type = (union ghw_type *) - ghw_read_record_subtype (h, &btype->rec); - break; - default: - fprintf - (stderr, "ghw_read_record_subtype: unhandled kind %d\n", - btype->kind); - return NULL; - } - el_nbr_scalars = get_nbr_elements (sr->els[j].type); - } - nbr_scalars += el_nbr_scalars; - } - sr->nbr_scalars = nbr_scalars; - } - return sr; -} - -int -ghw_read_type (struct ghw_handler *h) -{ - unsigned char hdr[8]; - unsigned i; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - - if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) - return -1; - h->nbr_types = ghw_get_i32 (h, &hdr[4]); - h->types = (union ghw_type **) - malloc (h->nbr_types * sizeof (union ghw_type *)); - - for (i = 0; i < h->nbr_types; i++) - { - int t; - - t = fgetc (h->stream); - if (t == EOF) - return -1; - /* printf ("type[%d]= %d\n", i, t); */ - switch (t) - { - case ghdl_rtik_type_b2: - case ghdl_rtik_type_e8: - { - struct ghw_type_enum *e; - unsigned j; - - e = malloc (sizeof (struct ghw_type_enum)); - e->kind = t; - e->wkt = ghw_wkt_unknown; - e->name = ghw_read_strid (h); - if (ghw_read_uleb128 (h, &e->nbr) != 0) - goto err_b2; - e->lits = (const char **) malloc (e->nbr * sizeof (char *)); - if (h->flag_verbose > 1) - printf ("enum %s:", e->name); - for (j = 0; j < e->nbr; j++) - { - e->lits[j] = ghw_read_strid (h); - if (h->flag_verbose > 1) - printf (" %s", e->lits[j]); - } - if (h->flag_verbose > 1) - printf ("\n"); - h->types[i] = (union ghw_type *)e; - break; - err_b2: - free (e); - return -1; - } - break; - case ghdl_rtik_type_i32: - case ghdl_rtik_type_i64: - case ghdl_rtik_type_f64: - { - struct ghw_type_scalar *sc; - - sc = malloc (sizeof (struct ghw_type_scalar)); - sc->kind = t; - sc->name = ghw_read_strid (h); - if (h->flag_verbose > 1) - printf ("scalar: %s\n", sc->name); - h->types[i] = (union ghw_type *)sc; - } - break; - case ghdl_rtik_type_p32: - case ghdl_rtik_type_p64: - { - struct ghw_type_physical *ph; - - ph = malloc (sizeof (struct ghw_type_physical)); - ph->kind = t; - ph->name = ghw_read_strid (h); - ph->units = NULL; - if (h->version == 0) - ph->nbr_units = 0; - else - { - unsigned j; - - if (ghw_read_uleb128 (h, &ph->nbr_units) != 0) - goto err_p32; - ph->units = malloc (ph->nbr_units * sizeof (struct ghw_unit)); - for (j = 0; j < ph->nbr_units; j++) - { - ph->units[j].name = ghw_read_strid (h); - if (ghw_read_lsleb128 (h, &ph->units[j].val) < 0) - goto err_p32; - } - } - if (h->flag_verbose > 1) - printf ("physical: %s\n", ph->name); - h->types[i] = (union ghw_type *)ph; - break; - err_p32: - free (ph->units); - free (ph); - return -1; - } - break; - case ghdl_rtik_subtype_scalar: - { - struct ghw_subtype_scalar *ss; - - ss = malloc (sizeof (struct ghw_subtype_scalar)); - ss->kind = t; - ss->name = ghw_read_strid (h); - ss->base = ghw_read_typeid (h); - ss->rng = ghw_read_range (h); - if (h->flag_verbose > 1) - printf ("subtype scalar: %s\n", ss->name); - h->types[i] = (union ghw_type *)ss; - } - break; - case ghdl_rtik_type_array: - { - struct ghw_type_array *arr; - unsigned j; - - arr = malloc (sizeof (struct ghw_type_array)); - arr->kind = t; - arr->name = ghw_read_strid (h); - arr->el = ghw_read_typeid (h); - if (ghw_read_uleb128 (h, &arr->nbr_dim) != 0) - goto err_array; - arr->dims = (union ghw_type **) - malloc (arr->nbr_dim * sizeof (union ghw_type *)); - for (j = 0; j < arr->nbr_dim; j++) - arr->dims[j] = ghw_read_typeid (h); - if (h->flag_verbose > 1) - printf ("array: %s\n", arr->name); - h->types[i] = (union ghw_type *)arr; - break; - err_array: - free (arr); - return -1; - } - break; - case ghdl_rtik_subtype_array: - { - struct ghw_subtype_array *sa; - const char *name; - struct ghw_type_array *base; - - name = ghw_read_strid (h); - base = (struct ghw_type_array *)ghw_read_typeid (h); - - sa = ghw_read_array_subtype (h, base); - sa->name = name; - h->types[i] = (union ghw_type *)sa; - if (h->flag_verbose > 1) - printf ("subtype array: %s (nbr_scalars=%d)\n", - sa->name, sa->nbr_scalars); - } - break; - case ghdl_rtik_type_record: - { - struct ghw_type_record *rec; - unsigned j; - int nbr_scalars; - - rec = malloc (sizeof (struct ghw_type_record)); - rec->kind = t; - rec->name = ghw_read_strid (h); - rec->els = NULL; - if (ghw_read_uleb128 (h, &rec->nbr_fields) != 0) - goto err_record; - rec->els = malloc - (rec->nbr_fields * sizeof (struct ghw_record_element)); - nbr_scalars = 0; - for (j = 0; j < rec->nbr_fields; j++) - { - rec->els[j].name = ghw_read_strid (h); - rec->els[j].type = ghw_read_typeid (h); - if (nbr_scalars != -1) - { - int field_nbr_scalars = get_nbr_elements (rec->els[j].type); - if (field_nbr_scalars == -1) - nbr_scalars = -1; - else - nbr_scalars += field_nbr_scalars; - } - } - rec->nbr_scalars = nbr_scalars; - if (h->flag_verbose > 1) - printf ("record type: %s (nbr_scalars=%d)\n", - rec->name, rec->nbr_scalars); - h->types[i] = (union ghw_type *)rec; - break; - err_record: - free (rec->els); - free (rec); - return -1; - } - break; - case ghdl_rtik_subtype_record: - { - struct ghw_subtype_record *sr; - const char *name; - struct ghw_type_record *base; - - name = ghw_read_strid (h); - base = (struct ghw_type_record *)ghw_read_typeid (h); - - sr = ghw_read_record_subtype (h, base); - sr->name = name; - h->types[i] = (union ghw_type *)sr; - if (h->flag_verbose > 1) - printf ("subtype record: %s (nbr_scalars=%d)\n", - sr->name, sr->nbr_scalars); - } - break; - default: - fprintf (stderr, "ghw_read_type: unknown type %d\n", t); - return -1; - } - } - if (fgetc (h->stream) != 0) - return -1; - return 0; -} - -int -ghw_read_wk_types (struct ghw_handler *h) -{ - char hdr[4]; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - - if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) - return -1; - - while (1) - { - int t; - union ghw_type *tid; - - t = fgetc (h->stream); - if (t == EOF) - return -1; - else if (t == 0) - break; - - tid = ghw_read_typeid (h); - if (tid->kind == ghdl_rtik_type_b2 - || tid->kind == ghdl_rtik_type_e8) - { - if (h->flag_verbose > 0) - printf ("%s: wkt=%d\n", tid->en.name, t); - tid->en.wkt = t; - } - } - return 0; -} - -void -ghw_disp_typename (struct ghw_handler *h, union ghw_type *t) -{ - (void)h; - printf ("%s", t->common.name); -} - -/* Read a signal composed of severals elements. - Return 0 for success. */ -int -ghw_read_signal (struct ghw_handler *h, unsigned int *sigs, union ghw_type *t) -{ - switch (t->kind) - { - case ghdl_rtik_type_b2: - case ghdl_rtik_type_e8: - case ghdl_rtik_type_e32: - case ghdl_rtik_subtype_scalar: - { - unsigned int sig_el; - - if (ghw_read_uleb128 (h, &sig_el) < 0) - return -1; - *sigs = sig_el; - if (sig_el == 0 || sig_el >= h->nbr_sigs) - return -1; - if (h->sigs[sig_el].type == NULL) - h->sigs[sig_el].type = ghw_get_base_type (t); - } - return 0; - case ghdl_rtik_subtype_array: - { - int i; - int stride; - int len; - - len = t->sa.nbr_scalars; - stride = get_nbr_elements (t->sa.base->el); - - for (i = 0; i < len; i += stride) - if (ghw_read_signal (h, &sigs[i], t->sa.base->el) < 0) - return -1; - } - return 0; - case ghdl_rtik_type_record: - { - struct ghw_type_record *r = &t->rec; - int nbr_fields = r->nbr_fields; - int i; - int off; - - off = 0; - for (i = 0; i < nbr_fields; i++) - { - if (ghw_read_signal (h, &sigs[off], r->els[i].type) < 0) - return -1; - off += get_nbr_elements (r->els[i].type); - } - } - return 0; - case ghdl_rtik_subtype_record: - { - struct ghw_subtype_record *sr = &t->sr; - int nbr_fields = sr->base->nbr_fields; - int i; - int off; - - off = 0; - for (i = 0; i < nbr_fields; i++) - { - if (ghw_read_signal (h, &sigs[off], sr->els[i].type) < 0) - return -1; - off += get_nbr_elements (sr->els[i].type); - } - } - return 0; - default: - fprintf (stderr, "ghw_read_signal: type kind %d unhandled\n", t->kind); - abort (); - } -} - - -int -ghw_read_value (struct ghw_handler *h, - union ghw_val *val, union ghw_type *type) -{ - switch (ghw_get_base_type (type)->kind) - { - case ghdl_rtik_type_b2: - { - int v; - v = fgetc (h->stream); - if (v == EOF) - return -1; - val->b2 = v; - } - break; - case ghdl_rtik_type_e8: - { - int v; - v = fgetc (h->stream); - if (v == EOF) - return -1; - val->e8 = v; - } - break; - case ghdl_rtik_type_i32: - case ghdl_rtik_type_p32: - { - int32_t v; - if (ghw_read_sleb128 (h, &v) < 0) - return -1; - val->i32 = v; - } - break; - case ghdl_rtik_type_f64: - { - double v; - if (ghw_read_f64 (h, &v) < 0) - return -1; - val->f64 = v; - } - break; - case ghdl_rtik_type_p64: - { - int64_t v; - if (ghw_read_lsleb128 (h, &v) < 0) - return -1; - val->i64 = v; - } - break; - default: - fprintf (stderr, "read_value: cannot handle format %d\n", type->kind); - abort (); - } - return 0; -} - -int -ghw_read_hie (struct ghw_handler *h) -{ - unsigned char hdr[16]; - int nbr_scopes; - int nbr_sigs; - unsigned i; - struct ghw_hie *blk; - struct ghw_hie **last; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - - if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) - return -1; - nbr_scopes = ghw_get_i32 (h, &hdr[4]); - /* Number of declared signals (which may be composite). */ - nbr_sigs = ghw_get_i32 (h, &hdr[8]); - /* Number of basic signals. */ - h->nbr_sigs = ghw_get_i32 (h, &hdr[12]); - - if (h->flag_verbose) - printf ("%u scopes, %u signals, %u signal elements\n", - nbr_scopes, nbr_sigs, h->nbr_sigs); - - blk = (struct ghw_hie *)malloc (sizeof (struct ghw_hie)); - blk->kind = ghw_hie_design; - blk->name = NULL; - blk->parent = NULL; - blk->brother = NULL; - blk->u.blk.child = NULL; - - last = &blk->u.blk.child; - h->hie = blk; - - h->nbr_sigs++; - h->skip_sigs = NULL; - h->flag_full_names = 0; - h->sigs = (struct ghw_sig *) malloc (h->nbr_sigs * sizeof (struct ghw_sig)); - memset (h->sigs, 0, h->nbr_sigs * sizeof (struct ghw_sig)); - - while (1) - { - int t; - struct ghw_hie *el; - unsigned int str; - - t = fgetc (h->stream); - if (t == EOF) - return -1; - if (t == 0) - break; - - if (t == ghw_hie_eos) - { - blk = blk->parent; - if (blk->u.blk.child == NULL) - last = &blk->u.blk.child; - else - { - struct ghw_hie *l = blk->u.blk.child; - while (l->brother != NULL) - l = l->brother; - last = &l->brother; - } - - continue; - } - - el = (struct ghw_hie *) malloc (sizeof (struct ghw_hie)); - el->kind = t; - el->parent = blk; - el->brother = NULL; - - /* Link. */ - *last = el; - last = &el->brother; - - /* Read name. */ - if (ghw_read_uleb128 (h, &str) != 0) - return -1; - el->name = h->str_table[str]; - - switch (t) - { - case ghw_hie_eoh: - case ghw_hie_design: - case ghw_hie_eos: - /* Should not be here. */ - abort (); - case ghw_hie_process: - break; - case ghw_hie_block: - case ghw_hie_generate_if: - case ghw_hie_generate_for: - case ghw_hie_instance: - case ghw_hie_generic: - case ghw_hie_package: - /* Create a block. */ - el->u.blk.child = NULL; - - if (t == ghw_hie_generate_for) - { - el->u.blk.iter_type = ghw_read_typeid (h); - el->u.blk.iter_value = malloc (sizeof (union ghw_val)); - if (ghw_read_value (h, el->u.blk.iter_value, - el->u.blk.iter_type) < 0) - return -1; - } - blk = el; - last = &el->u.blk.child; - break; - case ghw_hie_signal: - case ghw_hie_port_in: - case ghw_hie_port_out: - case ghw_hie_port_inout: - case ghw_hie_port_buffer: - case ghw_hie_port_linkage: - /* For a signal, read type. */ - { - int nbr_el; - unsigned int *sigs; - - el->u.sig.type = ghw_read_typeid (h); - nbr_el = get_nbr_elements (el->u.sig.type); - if (nbr_el < 0) - return -1; - sigs = (unsigned int *) malloc - ((nbr_el + 1) * sizeof (unsigned int)); - el->u.sig.sigs = sigs; - /* Last element is NULL. */ - sigs[nbr_el] = 0; - - if (h->flag_verbose > 1) - printf ("signal %s: %d el [", el->name, nbr_el); - if (ghw_read_signal (h, sigs, el->u.sig.type) < 0) - return -1; - if (h->flag_verbose > 1) - { - int j; - for (j = 0; j < nbr_el; j++) - printf (" #%u", sigs[j]); - printf ("]\n"); - } - } - break; - default: - fprintf (stderr, "ghw_read_hie: unhandled kind %d\n", t); - abort (); - } - } - - /* Allocate values. */ - for (i = 0; i < h->nbr_sigs; i++) - if (h->sigs[i].type != NULL) - h->sigs[i].val = (union ghw_val *) malloc (sizeof (union ghw_val)); - return 0; -} - -const char * -ghw_get_hie_name (struct ghw_hie *h) -{ - switch (h->kind) - { - case ghw_hie_eoh: - return "eoh"; - case ghw_hie_design: - return "design"; - case ghw_hie_block: - return "block"; - case ghw_hie_generate_if: - return "generate-if"; - case ghw_hie_generate_for: - return "generate-for"; - case ghw_hie_instance: - return "instance"; - case ghw_hie_package: - return "package"; - case ghw_hie_process: - return "process"; - case ghw_hie_generic: - return "generic"; - case ghw_hie_eos: - return "eos"; - case ghw_hie_signal: - return "signal"; - case ghw_hie_port_in: - return "port-in"; - case ghw_hie_port_out: - return "port-out"; - case ghw_hie_port_inout: - return "port-inout"; - case ghw_hie_port_buffer: - return "port-buffer"; - case ghw_hie_port_linkage: - return "port-linkage"; - default: - return "??"; - } -} - -void -ghw_disp_value (union ghw_val *val, union ghw_type *type); - -static void -print_name (struct ghw_hie *hie, int full_names) -{ - int i; - int depth; - struct ghw_hie *p; - struct ghw_hie **buf; - struct ghw_hie **end; - - /* HIE must be valid. */ - assert (hie->name != NULL); - - if (0 == full_names) - { - printf (" %s: ", hie->name); - return; - } - - p = hie; - depth = 0; - while (p && p->name) - { - p = p->parent; - ++depth; - } - buf = (struct ghw_hie **) malloc (depth * sizeof (struct ghw_hie *)); - - p = hie; - end = depth + buf; - while (p && p->name) - { - *(--end) = p; - p = p->parent; - } - - putchar (' '); - putchar ('/'); - for (i = 0; i < depth; ++i) - { - printf ("%s%s", i ? "/" : "", buf[i]->name); - if (ghw_hie_generate_for == buf[i]->kind) - { - putchar ('('); - ghw_disp_value (buf[i]->u.blk.iter_value, buf[i]->u.blk.iter_type); - putchar (')'); - } - } - putchar (':'); - putchar (' '); - free (buf); -} - -void -ghw_disp_hie (struct ghw_handler *h, struct ghw_hie *top) -{ - int i; - int indent; - struct ghw_hie *hie; - struct ghw_hie *n; - - hie = top; - indent = 0; - - while (1) - { - if (0 == h->flag_full_names) - for (i = 0; i < indent; i++) - fputc (' ', stdout); - printf ("%s", ghw_get_hie_name (hie)); - - switch (hie->kind) - { - case ghw_hie_design: - case ghw_hie_block: - case ghw_hie_generate_if: - case ghw_hie_generate_for: - case ghw_hie_instance: - case ghw_hie_process: - case ghw_hie_package: - if (hie->name) - print_name (hie, h->flag_full_names); - if (hie->kind == ghw_hie_generate_for) - { - printf ("("); - ghw_disp_value (hie->u.blk.iter_value, hie->u.blk.iter_type); - printf (")"); - } - n = hie->u.blk.child; - if (n == NULL) - n = hie->brother; - else - indent++; - break; - case ghw_hie_generic: - case ghw_hie_eos: - abort (); - case ghw_hie_signal: - case ghw_hie_port_in: - case ghw_hie_port_out: - case ghw_hie_port_inout: - case ghw_hie_port_buffer: - case ghw_hie_port_linkage: - { - unsigned int *sigs = hie->u.sig.sigs; - unsigned int k, num; - - print_name (hie, h->flag_full_names); - ghw_disp_subtype_indication (h, hie->u.sig.type); - printf (":"); - k = 0; - assert (sigs[0] != GHW_NO_SIG); - while (1) - { - /* First signal of the range. */ - printf (" #%u", sigs[k]); - for (num = 1; sigs[k + num] != GHW_NO_SIG; num++) - if (sigs[k + num] != sigs[k + num - 1] + 1) - break; - if (num > 1) - printf ("-#%u", sigs[k + num - 1]); - k += num; - /* End of signals ? */ - if (sigs[k] == GHW_NO_SIG) - break; - } - n = hie->brother; - } - break; - default: - abort (); - } - printf ("\n"); - - while (n == NULL) - { - if (hie->parent == NULL) - return; - hie = hie->parent; - indent--; - n = hie->brother; - } - hie = n; - } -} - -int -ghw_read_eoh (struct ghw_handler *h) -{ - (void)h; - return 0; -} - -int -ghw_read_base (struct ghw_handler *h) -{ - unsigned char hdr[4]; - int res; - - while (1) - { - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - if (memcmp (hdr, "STR", 4) == 0) - res = ghw_read_str (h); - else if (memcmp (hdr, "HIE", 4) == 0) - res = ghw_read_hie (h); - else if (memcmp (hdr, "TYP", 4) == 0) - res = ghw_read_type (h); - else if (memcmp (hdr, "WKT", 4) == 0) - res = ghw_read_wk_types (h); - else if (memcmp (hdr, "EOH", 4) == 0) - return 0; - else - { - fprintf (stderr, "ghw_read_base: unknown GHW section %c%c%c%c\n", - hdr[0], hdr[1], hdr[2], hdr[3]); - return -1; - } - if (res != 0) - { - fprintf (stderr, "ghw_read_base: error in section %s\n", hdr); - return res; - } - } -} - -int -ghw_read_signal_value (struct ghw_handler *h, struct ghw_sig *s) -{ - return ghw_read_value (h, s->val, s->type); -} - -int -ghw_read_snapshot (struct ghw_handler *h) -{ - unsigned char hdr[12]; - unsigned i; - struct ghw_sig *s; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - - if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) - return -1; - h->snap_time = ghw_get_i64 (h, &hdr[4]); - if (h->flag_verbose > 1) - printf ("Time is " GHWPRI64 " fs\n", h->snap_time); - - for (i = 0; i < h->nbr_sigs; i++) - { - s = &h->sigs[i]; - if (s->type != NULL) - { - if (h->flag_verbose > 1) - printf ("read type %d for sig %u\n", s->type->kind, i); - if (ghw_read_signal_value (h, s) < 0) - return -1; - } - } - if (fread (hdr, 4, 1, h->stream) != 1) - return -1; - - if (memcmp (hdr, "ESN", 4)) - return -1; - - return 0; -} - -void ghw_disp_values (struct ghw_handler *h); - -int -ghw_read_cycle_start (struct ghw_handler *h) -{ - unsigned char hdr[8]; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - - h->snap_time = ghw_get_i64 (h, hdr); - return 0; -} - -int -ghw_read_cycle_cont (struct ghw_handler *h, int *list) -{ - int i; - int *list_p; - - i = 0; - list_p = list; - while (1) - { - uint32_t d; - - /* Read delta to next signal. */ - if (ghw_read_uleb128 (h, &d) < 0) - return -1; - if (d == 0) - { - /* Last signal reached. */ - break; - } - - /* Find next signal. */ - while (d > 0) - { - i++; - if (h->sigs[i].type != NULL) - d--; - } - - if (ghw_read_signal_value (h, &h->sigs[i]) < 0) - return -1; - if (list_p) - *list_p++ = i; - } - - if (list_p) - *list_p = 0; - return 0; -} - -int -ghw_read_cycle_next (struct ghw_handler *h) -{ - int64_t d_time; - - if (ghw_read_lsleb128 (h, &d_time) < 0) - return -1; - if (d_time == -1) - return 0; - h->snap_time += d_time; - return 1; -} - - -int -ghw_read_cycle_end (struct ghw_handler *h) -{ - char hdr[4]; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - if (memcmp (hdr, "ECY", 4)) - return -1; - - return 0; -} - -static const char * -ghw_get_lit (union ghw_type *type, unsigned e) -{ - if (e >= type->en.nbr) - return "??"; - else - return type->en.lits[e]; -} - -static void -ghw_disp_lit (union ghw_type *type, unsigned e) -{ - printf ("%s (%u)", ghw_get_lit (type, e), e); -} - -void -ghw_disp_value (union ghw_val *val, union ghw_type *type) -{ - switch (ghw_get_base_type (type)->kind) - { - case ghdl_rtik_type_b2: - ghw_disp_lit (type, val->b2); - break; - case ghdl_rtik_type_e8: - ghw_disp_lit (type, val->e8); - break; - case ghdl_rtik_type_i32: - printf (GHWPRI32, val->i32); - break; - case ghdl_rtik_type_p64: - printf (GHWPRI64, val->i64); - break; - case ghdl_rtik_type_f64: - printf ("%g", val->f64); - break; - default: - fprintf (stderr, "ghw_disp_value: cannot handle type %d\n", - type->kind); - abort (); - } -} - -/* Put the ASCII representation of VAL into BUF, whose size if LEN. - A NUL is always written to BUF. -*/ -void -ghw_get_value (char *buf, int len, union ghw_val *val, union ghw_type *type) -{ - union ghw_type *base = ghw_get_base_type (type); - - switch (base->kind) - { - case ghdl_rtik_type_b2: - if (val->b2 <= 1) - { - strncpy (buf, base->en.lits[val->b2], len - 1); - buf[len - 1] = 0; - } - else - { - snprintf (buf, len, "?%d", val->b2); - } - break; - case ghdl_rtik_type_e8: - if (val->b2 <= base->en.nbr) - { - strncpy (buf, base->en.lits[val->e8], len - 1); - buf[len - 1] = 0; - } - else - { - snprintf (buf, len, "?%d", val->e8); - } - break; - case ghdl_rtik_type_i32: - snprintf (buf, len, GHWPRI32, val->i32); - break; - case ghdl_rtik_type_p64: - snprintf (buf, len, GHWPRI64, val->i64); - break; - case ghdl_rtik_type_f64: - snprintf (buf, len, "%g", val->f64); - break; - default: - snprintf (buf, len, "?bad type %d?", type->kind); - } -} - -static char -is_skip_signal (int *signals_to_keep, int nb_signals_to_keep, int signal) -{ - int i; - for (i = 0; i < nb_signals_to_keep; ++i) - { - if (signal == signals_to_keep[i]) - { - return 0; - } - } - return 1; -} - -void -ghw_filter_signals (struct ghw_handler *h, - int *signals_to_keep, int nb_signals_to_keep) -{ - unsigned i; - - if (0 < nb_signals_to_keep && 0 != signals_to_keep) - { - if (0 == h->skip_sigs) - { - h->skip_sigs = (char *) malloc (sizeof (char) * h->nbr_sigs); - } - for (i = 0; i < h->nbr_sigs; ++i) - { - h->skip_sigs[i] = is_skip_signal (signals_to_keep, - nb_signals_to_keep, i); - } - } - else - { - if (0 != h->skip_sigs) - { - free (h->skip_sigs); - h->skip_sigs = 0; - } - } -} - -void -ghw_disp_values (struct ghw_handler *h) -{ - unsigned i; - for (i = 0; i < h->nbr_sigs; i++) - { - struct ghw_sig *s = &h->sigs[i]; - int skip = (0 != h->skip_sigs && (0 != h->skip_sigs[i])); - if (s->type != NULL && !skip) - { - printf ("#%u: ", i); - ghw_disp_value (s->val, s->type); - printf ("\n"); - } - } -} -int -ghw_read_directory (struct ghw_handler *h) -{ - unsigned char hdr[8]; - int nbr_entries; - int i; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - - nbr_entries = ghw_get_i32 (h, &hdr[4]); - - if (h->flag_verbose) - printf ("Directory (%d entries):\n", nbr_entries); - - for (i = 0; i < nbr_entries; i++) - { - unsigned char ent[8]; - int pos; - - if (fread (ent, sizeof (ent), 1, h->stream) != 1) - return -1; - - pos = ghw_get_i32 (h, &ent[4]); - if (h->flag_verbose) - printf (" %s at %d\n", ent, pos); - } - - if (fread (hdr, 4, 1, h->stream) != 1) - return -1; - if (memcmp (hdr, "EOD", 4)) - return -1; - return 0; -} - -int -ghw_read_tailer (struct ghw_handler *h) -{ - unsigned char hdr[8]; - int pos; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - return -1; - - pos = ghw_get_i32 (h, &hdr[4]); - - if (h->flag_verbose) - printf ("Tailer: directory at %d\n", pos); - return 0; -} - -enum ghw_res -ghw_read_sm_hdr (struct ghw_handler *h, int *list) -{ - unsigned char hdr[4]; - int res; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - { - if (feof (h->stream)) - return ghw_res_eof; - else - return ghw_res_error; - } - if (memcmp (hdr, "SNP", 4) == 0) - { - res = ghw_read_snapshot (h); - if (res < 0) - return res; - return ghw_res_snapshot; - } - else if (memcmp (hdr, "CYC", 4) == 0) - { - res = ghw_read_cycle_start (h); - if (res < 0) - return res; - res = ghw_read_cycle_cont (h, list); - if (res < 0) - return res; - - return ghw_res_cycle; - } - else if (memcmp (hdr, "DIR", 4) == 0) - { - res = ghw_read_directory (h); - } - else if (memcmp (hdr, "TAI", 4) == 0) - { - res = ghw_read_tailer (h); - } - else - { - fprintf (stderr, "unknown GHW section %c%c%c%c\n", - hdr[0], hdr[1], hdr[2], hdr[3]); - return -1; - } - if (res != 0) - return res; - return ghw_res_other; -} - -int -ghw_read_sm (struct ghw_handler *h, enum ghw_sm_type *sm) -{ - int res; - - while (1) - { - /* printf ("sm: state = %d\n", *sm); */ - switch (*sm) - { - case ghw_sm_init: - case ghw_sm_sect: - res = ghw_read_sm_hdr (h, NULL); - switch (res) - { - case ghw_res_other: - break; - case ghw_res_snapshot: - *sm = ghw_sm_sect; - return res; - case ghw_res_cycle: - *sm = ghw_sm_cycle; - return res; - default: - return res; - } - break; - case ghw_sm_cycle: - if (0) - printf ("Time is " GHWPRI64 " fs\n", h->snap_time); - if (0) - ghw_disp_values (h); - - res = ghw_read_cycle_next (h); - if (res < 0) - return res; - if (res == 1) - { - res = ghw_read_cycle_cont (h, NULL); - if (res < 0) - return res; - return ghw_res_cycle; - } - res = ghw_read_cycle_end (h); - if (res < 0) - return res; - *sm = ghw_sm_sect; - break; - } - } -} - -int -ghw_read_cycle (struct ghw_handler *h) -{ - int res; - - res = ghw_read_cycle_start (h); - if (res < 0) - return res; - while (1) - { - res = ghw_read_cycle_cont (h, NULL); - if (res < 0) - return res; - - if (0) - printf ("Time is " GHWPRI64 " fs\n", h->snap_time); - if (0) - ghw_disp_values (h); - - - res = ghw_read_cycle_next (h); - if (res < 0) - return res; - if (res == 0) - break; - } - res = ghw_read_cycle_end (h); - return res; -} - -int -ghw_read_dump (struct ghw_handler *h) -{ - unsigned char hdr[4]; - int res; - - while (1) - { - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - { - if (feof (h->stream)) - return 0; - else - return -1; - } - if (memcmp (hdr, "SNP", 4) == 0) - { - res = ghw_read_snapshot (h); - if (0 && res >= 0) - ghw_disp_values (h); - } - else if (memcmp (hdr, "CYC", 4) == 0) - { - res = ghw_read_cycle (h); - } - else if (memcmp (hdr, "DIR", 4) == 0) - { - res = ghw_read_directory (h); - } - else if (memcmp (hdr, "TAI", 4) == 0) - { - res = ghw_read_tailer (h); - } - else - { - fprintf (stderr, "unknown GHW section %c%c%c%c\n", - hdr[0], hdr[1], hdr[2], hdr[3]); - return -1; - } - if (res != 0) - return res; - } -} - -struct ghw_section ghw_sections[] = { - { "\0\0\0", NULL }, - { "STR", ghw_read_str }, - { "HIE", ghw_read_hie }, - { "TYP", ghw_read_type }, - { "WKT", ghw_read_wk_types }, - { "EOH", ghw_read_eoh }, - { "SNP", ghw_read_snapshot }, - { "CYC", ghw_read_cycle }, - { "DIR", ghw_read_directory }, - { "TAI", ghw_read_tailer } -}; - -int -ghw_read_section (struct ghw_handler *h) -{ - unsigned char hdr[4]; - unsigned i; - - if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) - { - if (feof (h->stream)) - return -2; - else - return -1; - } - - for (i = 1; i < sizeof (ghw_sections) / sizeof (*ghw_sections); i++) - if (memcmp (hdr, ghw_sections[i].name, 4) == 0) - return i; - - fprintf (stderr, "ghw_read_section: unknown GHW section %c%c%c%c\n", - hdr[0], hdr[1], hdr[2], hdr[3]); - return 0; -} - -void -ghw_close (struct ghw_handler *h) -{ - if (h->stream) - { - if (h->stream_ispipe) - pclose (h->stream); - else - fclose (h->stream); - - h->stream = NULL; - } -} - -const char * -ghw_get_dir (int is_downto) -{ - return is_downto ? "downto" : "to"; -} - -void -ghw_disp_range (union ghw_type *type, union ghw_range *rng) -{ - switch (rng->kind) - { - case ghdl_rtik_type_b2: - printf ("%s %s %s", ghw_get_lit (type, rng->b2.left), - ghw_get_dir (rng->b2.dir), ghw_get_lit (type, rng->b2.right)); - break; - case ghdl_rtik_type_e8: - printf ("%s %s %s", ghw_get_lit (type, rng->e8.left), - ghw_get_dir (rng->e8.dir), ghw_get_lit (type, rng->e8.right)); - break; - case ghdl_rtik_type_i32: - case ghdl_rtik_type_p32: - printf (GHWPRI32 " %s " GHWPRI32, - rng->i32.left, ghw_get_dir (rng->i32.dir), rng->i32.right); - break; - case ghdl_rtik_type_i64: - case ghdl_rtik_type_p64: - printf (GHWPRI64 " %s " GHWPRI64, - rng->i64.left, ghw_get_dir (rng->i64.dir), rng->i64.right); - break; - case ghdl_rtik_type_f64: - printf ("%g %s %g", - rng->f64.left, ghw_get_dir (rng->f64.dir), rng->f64.right); - break; - default: - printf ("?(%d)", rng->kind); - } -} - -static void -ghw_disp_array_subtype_bounds (struct ghw_subtype_array *a) -{ - unsigned i; - - printf (" ("); - for (i = 0; i < a->base->nbr_dim; i++) - { - if (i != 0) - printf (", "); - ghw_disp_range (a->base->dims[i], a->rngs[i]); - } - printf (")"); -} - -static void -ghw_disp_record_subtype_bounds (struct ghw_subtype_record *sr) -{ - struct ghw_type_record *base = sr->base; - int is_first = 1; - unsigned i; - - for (i = 0; i < base->nbr_fields; i++) - { - if (sr->els[i].type != base->els[i].type) - { - if (is_first) - { - printf ("("); - is_first = 0; - } - else - printf (", "); - printf ("%s", base->els[i].name); - switch (sr->els[i].type->kind) - { - case ghdl_rtik_subtype_array: - ghw_disp_array_subtype_bounds (&sr->els[i].type->sa); - break; - case ghdl_rtik_subtype_record: - ghw_disp_record_subtype_bounds (&sr->els[i].type->sr); - break; - default: - printf ("??? (%d)", sr->els[i].type->kind); - } - } - } - if (!is_first) - printf (")"); -} - -static void -ghw_disp_subtype_definition (struct ghw_handler *h, union ghw_type *t) -{ - switch (t->kind) - { - case ghdl_rtik_subtype_scalar: - { - struct ghw_subtype_scalar *s = &t->ss; - ghw_disp_typename (h, s->base); - printf (" range "); - ghw_disp_range (s->base, s->rng); - } - break; - case ghdl_rtik_subtype_array: - { - struct ghw_subtype_array *a = &t->sa; - - ghw_disp_typename (h, (union ghw_type *)a->base); - ghw_disp_array_subtype_bounds (a); - } - break; - case ghdl_rtik_subtype_record: - { - struct ghw_subtype_record *sr = &t->sr; - - ghw_disp_typename (h, (union ghw_type *)sr->base); - ghw_disp_record_subtype_bounds (sr); - } - break; - default: - printf ("ghw_disp_subtype_definition: unhandled type kind %d\n", - t->kind); - } -} - -static int -ghw_is_anonymous_type (struct ghw_handler *h, union ghw_type *t) -{ - return t->common.name == h->str_table[0]; -} - -void -ghw_disp_subtype_indication (struct ghw_handler *h, union ghw_type *t) -{ - if (ghw_is_anonymous_type (h, t)) - { - /* Anonymous subtype. */ - ghw_disp_subtype_definition (h, t); - } - else - ghw_disp_typename (h, t); -} - -void -ghw_disp_type (struct ghw_handler *h, union ghw_type *t) -{ - switch (t->kind) - { - case ghdl_rtik_type_b2: - case ghdl_rtik_type_e8: - { - struct ghw_type_enum *e = &t->en; - unsigned i; - - printf ("type %s is (", e->name); - for (i = 0; i < e->nbr; i++) - { - if (i != 0) - printf (", "); - printf ("%s", e->lits[i]); - } - printf (");"); - if (e->wkt != ghw_wkt_unknown) - printf (" -- WKT:%d", e->wkt); - printf ("\n"); - } - break; - case ghdl_rtik_type_i32: - case ghdl_rtik_type_f64: - { - struct ghw_type_scalar *s = &t->sc; - printf ("type %s is range <>;\n", s->name); - } - break; - case ghdl_rtik_type_p32: - case ghdl_rtik_type_p64: - { - unsigned i; - - struct ghw_type_physical *p = &t->ph; - printf ("type %s is range <> units\n", p->name); - for (i = 0; i < p->nbr_units; i++) - { - struct ghw_unit *u = &p->units[i]; - printf (" %s = " GHWPRI64 " %s;\n", - u->name, u->val, p->units[0].name); - } - printf ("end units\n"); - } - break; - case ghdl_rtik_type_array: - { - struct ghw_type_array *a = &t->ar; - unsigned i; - - printf ("type %s is array (", a->name); - for (i = 0; i < a->nbr_dim; i++) - { - if (i != 0) - printf (", "); - ghw_disp_typename (h, a->dims[i]); - printf (" range <>"); - } - printf (") of "); - ghw_disp_subtype_indication (h, a->el); - printf (";\n"); - } - break; - case ghdl_rtik_type_record: - { - struct ghw_type_record *r = &t->rec; - unsigned i; - - printf ("type %s is record\n", r->name); - for (i = 0; i < r->nbr_fields; i++) - { - printf (" %s: ", r->els[i].name); - ghw_disp_subtype_indication (h, r->els[i].type); - printf (";\n"); - } - printf ("end record;\n"); - } - break; - case ghdl_rtik_subtype_array: - case ghdl_rtik_subtype_scalar: - case ghdl_rtik_subtype_record: - { - struct ghw_type_common *c = &t->common; - printf ("subtype %s is ", c->name); - ghw_disp_subtype_definition (h, t); - printf (";\n"); - } - break; - default: - printf ("ghw_disp_type: unhandled type kind %d\n", t->kind); - } -} - -void -ghw_disp_types (struct ghw_handler *h) -{ - unsigned i; - - for (i = 0; i < h->nbr_types; i++) - if (h->flag_verbose || !ghw_is_anonymous_type (h, h->types[i])) - ghw_disp_type (h, h->types[i]); -} diff -Nru gtkwave-3.3.104/src/ghwlib.h gtkwave-3.3.104+really3.3.118/src/ghwlib.h --- gtkwave-3.3.104/src/ghwlib.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/ghwlib.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,445 +0,0 @@ -/* GHDL Wavefile reader library. - Copyright (C) 2005-2017 Tristan Gingold - - GHDL 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, or (at your option) any later - version. - - GHDL 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. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. -*/ - - -#ifndef _GHWLIB_H_ -#define _GHWLIB_H_ - -#include -#include - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* The ghwlib uses the standard c99 int32_t and int64_t. They are declared - in stdint.h. Header inttypes.h includes stdint.h and provides macro for - printf and co specifiers. Use it if known to be available. */ - -#if defined(__cplusplus) \ - || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) \ - || defined(HAVE_INTTYPES_H) -/* Use C99 standard header. */ -# include -# define GHWPRI64 "%"PRId64 -# define GHWPRI32 "%"PRId32 -#else -# include -# define GHWPRI64 "%lld" -# define GHWPRI32 "%d" -#endif - -enum ghdl_rtik { - ghdl_rtik_top, /* 0 */ - ghdl_rtik_library, - ghdl_rtik_package, - ghdl_rtik_package_body, - ghdl_rtik_entity, - ghdl_rtik_architecture, /* 5 */ - ghdl_rtik_process, - ghdl_rtik_block, - ghdl_rtik_if_generate, - ghdl_rtik_for_generate, - ghdl_rtik_instance, - ghdl_rtik_constant, - ghdl_rtik_iterator, - ghdl_rtik_variable, - ghdl_rtik_signal, - ghdl_rtik_file, - ghdl_rtik_port, - ghdl_rtik_generic, - ghdl_rtik_alias, - ghdl_rtik_guard, - ghdl_rtik_component, - ghdl_rtik_attribute, - ghdl_rtik_type_b2, /* 22 */ - ghdl_rtik_type_e8, - ghdl_rtik_type_e32, - ghdl_rtik_type_i32, /* 25 */ - ghdl_rtik_type_i64, - ghdl_rtik_type_f64, - ghdl_rtik_type_p32, - ghdl_rtik_type_p64, - ghdl_rtik_type_access, /* 30 */ - ghdl_rtik_type_array, - ghdl_rtik_type_record, - ghdl_rtik_type_file, - ghdl_rtik_subtype_scalar, - ghdl_rtik_subtype_array, /* 35 */ - ghdl_rtik_subtype_array_ptr, /* Obsolete. */ - ghdl_rtik_subtype_unconstrained_array, /* Obsolete. */ - ghdl_rtik_subtype_record, - ghdl_rtik_subtype_access, - ghdl_rtik_type_protected, - ghdl_rtik_element, - ghdl_rtik_unit, - ghdl_rtik_attribute_transaction, - ghdl_rtik_attribute_quiet, - ghdl_rtik_attribute_stable, - ghdl_rtik_error -}; - -/* Well-known types. */ -enum ghw_wkt_type { - ghw_wkt_unknown, - ghw_wkt_boolean, - ghw_wkt_bit, - ghw_wkt_std_ulogic -}; - -struct ghw_range_b2 -{ - enum ghdl_rtik kind : 8; - int dir : 8; /* 0: to, !0: downto. */ - unsigned char left; - unsigned char right; -}; - -struct ghw_range_e8 -{ - enum ghdl_rtik kind : 8; - int dir : 8; /* 0: to, !0: downto. */ - unsigned char left; - unsigned char right; -}; - -struct ghw_range_i32 -{ - enum ghdl_rtik kind : 8; - int dir : 8; /* 0: to, !0: downto. */ - int32_t left; - int32_t right; -}; - -struct ghw_range_i64 -{ - enum ghdl_rtik kind : 8; - int dir : 8; - int64_t left; - int64_t right; -}; - -struct ghw_range_f64 -{ - enum ghdl_rtik kind : 8; - int dir : 8; - double left; - double right; -}; - -union ghw_range -{ - enum ghdl_rtik kind : 8; - struct ghw_range_b2 b2; - struct ghw_range_e8 e8; - struct ghw_range_i32 i32; - struct ghw_range_i64 i64; - struct ghw_range_f64 f64; -}; - -/* Note: the first two fields must be kind and name. */ -union ghw_type; - -struct ghw_type_common -{ - enum ghdl_rtik kind; - const char *name; -}; - -struct ghw_type_enum -{ - enum ghdl_rtik kind; - const char *name; - - enum ghw_wkt_type wkt; - unsigned int nbr; - const char **lits; -}; - -struct ghw_type_scalar -{ - enum ghdl_rtik kind; - const char *name; -}; - -struct ghw_unit -{ - const char *name; - int64_t val; -}; - -struct ghw_type_physical -{ - enum ghdl_rtik kind; - const char *name; - uint32_t nbr_units; - struct ghw_unit *units; -}; - -struct ghw_type_array -{ - enum ghdl_rtik kind; - const char *name; - - unsigned int nbr_dim; - union ghw_type *el; - union ghw_type **dims; -}; - -struct ghw_subtype_array -{ - enum ghdl_rtik kind; - const char *name; - - struct ghw_type_array *base; - int nbr_scalars; - union ghw_range **rngs; -}; - -struct ghw_subtype_scalar -{ - enum ghdl_rtik kind; - const char *name; - - union ghw_type *base; - union ghw_range *rng; -}; - -struct ghw_record_element -{ - const char *name; - union ghw_type *type; -}; - -struct ghw_type_record -{ - enum ghdl_rtik kind; - const char *name; - - unsigned int nbr_fields; - int nbr_scalars; /* Number of scalar elements (ie nbr of signals). */ - struct ghw_record_element *els; -}; - -struct ghw_subtype_record -{ - enum ghdl_rtik kind; - const char *name; - - struct ghw_type_record *base; - int nbr_scalars; /* Number of scalar elements (ie nbr of signals). */ - struct ghw_record_element *els; -}; - -union ghw_type -{ - enum ghdl_rtik kind; - struct ghw_type_common common; - struct ghw_type_enum en; - struct ghw_type_scalar sc; - struct ghw_type_physical ph; - struct ghw_subtype_scalar ss; - struct ghw_subtype_array sa; - struct ghw_subtype_record sr; - struct ghw_type_array ar; - struct ghw_type_record rec; -}; - -union ghw_val -{ - unsigned char b2; - unsigned char e8; - int32_t i32; - int64_t i64; - double f64; -}; - -/* A non-composite signal. */ -struct ghw_sig -{ - union ghw_type *type; - union ghw_val *val; -}; - -enum ghw_hie_kind { - ghw_hie_eoh = 0, - ghw_hie_design = 1, - ghw_hie_block = 3, - ghw_hie_generate_if = 4, - ghw_hie_generate_for = 5, - ghw_hie_instance = 6, - ghw_hie_package = 7, - ghw_hie_process = 13, - ghw_hie_generic = 14, - ghw_hie_eos = 15, - ghw_hie_signal = 16, - ghw_hie_port_in = 17, - ghw_hie_port_out = 18, - ghw_hie_port_inout = 19, - ghw_hie_port_buffer = 20, - ghw_hie_port_linkage = 21 -}; - -#define GHW_NO_SIG 0 - -struct ghw_hie -{ - enum ghw_hie_kind kind; - struct ghw_hie *parent; - const char *name; - struct ghw_hie *brother; - union - { - struct - { - struct ghw_hie *child; - union ghw_type *iter_type; - union ghw_val *iter_value; - } blk; - struct - { - union ghw_type *type; - /* Array of signal elements. - Last element is GHW_NO_SIG (0). */ - unsigned int *sigs; - } sig; - } u; -}; - -struct ghw_handler -{ - FILE *stream; - /* True if STREAM was popen, else was fopen. */ - unsigned char stream_ispipe; - /* True if words are big-endian. */ - unsigned char word_be; - unsigned char word_len; - unsigned char off_len; - /* Minor version. */ - int version; - - /* Set by user. */ - int flag_verbose; - - /* String table. */ - /* Number of strings. */ - unsigned nbr_str; - /* Size of the strings (without nul). */ - unsigned str_size; - /* String table. */ - char **str_table; - /* Array containing strings. */ - char *str_content; - - /* Type table. */ - unsigned nbr_types; - union ghw_type **types; - - /* Non-composite (or basic) signals. */ - unsigned nbr_sigs; - char *skip_sigs; - int flag_full_names; - struct ghw_sig *sigs; - - /* Hierarchy. */ - struct ghw_hie *hie; - - /* Time of the next cycle. */ - int64_t snap_time; -}; - -/* Open a GHW file with H. - Return < 0 in case of error. */ -int ghw_open (struct ghw_handler *h, const char *filename); - -/* Return base type of T. */ -union ghw_type *ghw_get_base_type (union ghw_type *t); - -/* Return length of RNG. */ -int ghw_get_range_length (union ghw_range *rng); - -/* Put the ASCII representation of VAL into BUF, whose size if LEN. - A NUL is always written to BUF. */ -void ghw_get_value (char *buf, int len, - union ghw_val *val, union ghw_type *type); - -const char *ghw_get_hie_name (struct ghw_hie *h); - -void ghw_disp_hie (struct ghw_handler *h, struct ghw_hie *top); - -int ghw_read_base (struct ghw_handler *h); - -void ghw_filter_signals (struct ghw_handler *h, int *signals_to_keep, int nb_signals_to_keep); - -void ghw_disp_values (struct ghw_handler *h); - -int ghw_read_cycle_start (struct ghw_handler *h); - -int ghw_read_cycle_cont (struct ghw_handler *h, int *list); - -int ghw_read_cycle_next (struct ghw_handler *h); - -int ghw_read_cycle_end (struct ghw_handler *h); - -enum ghw_sm_type { - /* At init; - Read section name. */ - ghw_sm_init = 0, - ghw_sm_sect = 1, - ghw_sm_cycle = 2 -}; - -enum ghw_res { - ghw_res_error = -1, - ghw_res_eof = -2, - ghw_res_ok = 0, - ghw_res_snapshot = 1, - ghw_res_cycle = 2, - ghw_res_other = 3 -}; - -int ghw_read_sm (struct ghw_handler *h, enum ghw_sm_type *sm); - -int ghw_read_dump (struct ghw_handler *h); - -struct ghw_section { - const char name[4]; - int (*handler)(struct ghw_handler *h); -}; - -extern struct ghw_section ghw_sections[]; - -int ghw_read_section (struct ghw_handler *h); - -void ghw_close (struct ghw_handler *h); - -const char *ghw_get_dir (int is_downto); - -void ghw_disp_subtype_indication (struct ghw_handler *h, union ghw_type *t); - -/* Note: TYPE must be a base type (used only to display literals). */ -void ghw_disp_range (union ghw_type *type, union ghw_range *rng); - -void ghw_disp_type (struct ghw_handler *h, union ghw_type *t); - -void ghw_disp_types (struct ghw_handler *h); - -enum ghw_res ghw_read_sm_hdr (struct ghw_handler *h, int *list); - -#endif /* _GHWLIB_H_ */ diff -Nru gtkwave-3.3.104/src/globals.c gtkwave-3.3.104+really3.3.118/src/globals.c --- gtkwave-3.3.104/src/globals.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/globals.c 2023-12-31 21:11:05.000000000 +0000 @@ -50,7 +50,7 @@ #include "fsdb_wrapper_api.h" #ifdef __MINGW32__ -#define sleep(x) Sleep(x) +#define sleep(x) Sleep(x * 1000) #endif #if !defined __MINGW32__ && !defined _MSC_VER @@ -854,6 +854,7 @@ NULL, /* toggle3_showchange_c_1 364 */ NULL, /* toggle4_showchange_c_1 364 */ NULL, /* toggle5_showchange_c_1 364 */ +NULL, /* toggle6_showchange_c_1 364 */ NULL, /* window_showchange_c_8 365 */ NULL, /* cleanup_showchange_c_6 366 */ NULL, /* tcache_showchange_c_1 367 */ @@ -1381,6 +1382,7 @@ 0, /* ruler_origin */ 0, /* ruler_step */ 0, /* fill_waveform */ +0, /* lz_removal */ FALSE, /*save_on_exit */ @@ -1902,6 +1904,7 @@ new_globals->display_grid = GLOBALS->display_grid; new_globals->highlight_wavewindow = GLOBALS->highlight_wavewindow; new_globals->fill_waveform = GLOBALS->fill_waveform; + new_globals->lz_removal = GLOBALS->lz_removal; new_globals->use_standard_trace_select = GLOBALS->use_standard_trace_select; new_globals->use_big_fonts = GLOBALS->use_big_fonts; new_globals->use_full_precision = GLOBALS->use_full_precision; @@ -2849,6 +2852,7 @@ GLOBALS->display_grid = g_old->display_grid; GLOBALS->highlight_wavewindow = g_old->highlight_wavewindow; GLOBALS->fill_waveform = g_old->fill_waveform; + GLOBALS->lz_removal = g_old->lz_removal; GLOBALS->use_standard_trace_select = g_old->use_standard_trace_select; GLOBALS->disable_mouseover = g_old->disable_mouseover; GLOBALS->clipboard_mouseover = g_old->clipboard_mouseover; diff -Nru gtkwave-3.3.104/src/globals.h gtkwave-3.3.104+really3.3.118/src/globals.h --- gtkwave-3.3.104/src/globals.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/globals.h 2023-12-31 21:11:05.000000000 +0000 @@ -784,7 +784,7 @@ /* * regex.c */ -struct re_pattern_buffer *preg_regex_c_1; /* from regex.c 339 */ +regex_t *preg_regex_c_1; /* from regex.c 339 */ int *regex_ok_regex_c_1; /* from regex.c 340 */ @@ -857,6 +857,7 @@ GtkWidget *toggle3_showchange_c_1; /* from showchange.c 390 */ GtkWidget *toggle4_showchange_c_1; /* from showchange.c 391 */ GtkWidget *toggle5_showchange_c_1; /* from showchange.c 391 */ +GtkWidget *toggle6_showchange_c_1; /* from showchange.c 391 */ GtkWidget *window_showchange_c_8; /* from showchange.c 392 */ void (*cleanup_showchange_c_6)(void); /* from showchange.c 393 */ struct TraceEnt *tcache_showchange_c_1; /* from showchange.c 394 */ @@ -1370,6 +1371,7 @@ TimeType ruler_origin; TimeType ruler_step; char fill_waveform; +char lz_removal; gboolean save_on_exit; diff -Nru gtkwave-3.3.104/src/helpers/Makefile.am gtkwave-3.3.104+really3.3.118/src/helpers/Makefile.am --- gtkwave-3.3.104/src/helpers/Makefile.am 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/Makefile.am 2023-12-31 21:11:05.000000000 +0000 @@ -8,7 +8,7 @@ AM_CFLAGS= -I$(srcdir)/.. -I$(srcdir)/../.. $(LIBZ_CFLAGS) $(LIBBZ2_CFLAGS) $(LIBLZMA_CFLAGS) $(LIBJUDY_CFLAGS) $(EXTLOAD_CFLAGS) $(RPC_CFLAGS) -I$(srcdir)/fst -I$(srcdir)/../../contrib/rtlbrowse -bin_PROGRAMS= evcd2vcd fst2vcd vcd2fst fstminer ghwdump lxt2miner lxt2vcd \ +bin_PROGRAMS= evcd2vcd fst2vcd vcd2fst fstminer lxt2miner lxt2vcd \ shmidcat vcd2lxt vcd2lxt2 vcd2vzt \ vzt2vcd vztminer @@ -42,6 +42,4 @@ lxt2miner_SOURCES= lxt2miner.c lxt2_read.c lxt2_read.h lxt2miner_LDADD= $(LIBZ_LDADD) -ghwdump_SOURCES= ghwdump.c $(srcdir)/../ghwlib.c - evcd2vcd_SOURCES= evcd2vcd.c $(srcdir)/../../contrib/rtlbrowse/jrb.h $(srcdir)/../../contrib/rtlbrowse/jrb.c diff -Nru gtkwave-3.3.104/src/helpers/Makefile.in gtkwave-3.3.104+really3.3.118/src/helpers/Makefile.in --- gtkwave-3.3.104/src/helpers/Makefile.in 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/Makefile.in 2023-12-31 21:11:05.000000000 +0000 @@ -77,10 +77,9 @@ PRE_UNINSTALL = : POST_UNINSTALL = : bin_PROGRAMS = evcd2vcd$(EXEEXT) fst2vcd$(EXEEXT) vcd2fst$(EXEEXT) \ - fstminer$(EXEEXT) ghwdump$(EXEEXT) lxt2miner$(EXEEXT) \ - lxt2vcd$(EXEEXT) shmidcat$(EXEEXT) vcd2lxt$(EXEEXT) \ - vcd2lxt2$(EXEEXT) vcd2vzt$(EXEEXT) vzt2vcd$(EXEEXT) \ - vztminer$(EXEEXT) + fstminer$(EXEEXT) lxt2miner$(EXEEXT) lxt2vcd$(EXEEXT) \ + shmidcat$(EXEEXT) vcd2lxt$(EXEEXT) vcd2lxt2$(EXEEXT) \ + vcd2vzt$(EXEEXT) vzt2vcd$(EXEEXT) vztminer$(EXEEXT) subdir = src/helpers DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/depcomp @@ -106,9 +105,6 @@ fastlz.$(OBJEXT) fstapi.$(OBJEXT) fstminer_OBJECTS = $(am_fstminer_OBJECTS) fstminer_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) -am_ghwdump_OBJECTS = ghwdump.$(OBJEXT) ghwlib.$(OBJEXT) -ghwdump_OBJECTS = $(am_ghwdump_OBJECTS) -ghwdump_LDADD = $(LDADD) am_lxt2miner_OBJECTS = lxt2miner.$(OBJEXT) lxt2_read.$(OBJEXT) lxt2miner_OBJECTS = $(am_lxt2miner_OBJECTS) lxt2miner_DEPENDENCIES = $(am__DEPENDENCIES_1) @@ -180,15 +176,14 @@ am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(evcd2vcd_SOURCES) $(fst2vcd_SOURCES) $(fstminer_SOURCES) \ - $(ghwdump_SOURCES) $(lxt2miner_SOURCES) $(lxt2vcd_SOURCES) \ + $(lxt2miner_SOURCES) $(lxt2vcd_SOURCES) shmidcat.c \ + $(vcd2fst_SOURCES) $(vcd2lxt_SOURCES) $(vcd2lxt2_SOURCES) \ + $(vcd2vzt_SOURCES) $(vzt2vcd_SOURCES) $(vztminer_SOURCES) +DIST_SOURCES = $(evcd2vcd_SOURCES) $(fst2vcd_SOURCES) \ + $(fstminer_SOURCES) $(lxt2miner_SOURCES) $(lxt2vcd_SOURCES) \ shmidcat.c $(vcd2fst_SOURCES) $(vcd2lxt_SOURCES) \ $(vcd2lxt2_SOURCES) $(vcd2vzt_SOURCES) $(vzt2vcd_SOURCES) \ $(vztminer_SOURCES) -DIST_SOURCES = $(evcd2vcd_SOURCES) $(fst2vcd_SOURCES) \ - $(fstminer_SOURCES) $(ghwdump_SOURCES) $(lxt2miner_SOURCES) \ - $(lxt2vcd_SOURCES) shmidcat.c $(vcd2fst_SOURCES) \ - $(vcd2lxt_SOURCES) $(vcd2lxt2_SOURCES) $(vcd2vzt_SOURCES) \ - $(vzt2vcd_SOURCES) $(vztminer_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ @@ -399,7 +394,6 @@ vztminer_LDADD = $(LIBZ_LDADD) $(LIBBZ2_LDADD) $(LIBLZMA_LDADD) $(RPC_LDADD) lxt2miner_SOURCES = lxt2miner.c lxt2_read.c lxt2_read.h lxt2miner_LDADD = $(LIBZ_LDADD) -ghwdump_SOURCES = ghwdump.c $(srcdir)/../ghwlib.c evcd2vcd_SOURCES = evcd2vcd.c $(srcdir)/../../contrib/rtlbrowse/jrb.h $(srcdir)/../../contrib/rtlbrowse/jrb.c all: all-am @@ -490,10 +484,6 @@ @rm -f fstminer$(EXEEXT) $(AM_V_CCLD)$(LINK) $(fstminer_OBJECTS) $(fstminer_LDADD) $(LIBS) -ghwdump$(EXEEXT): $(ghwdump_OBJECTS) $(ghwdump_DEPENDENCIES) $(EXTRA_ghwdump_DEPENDENCIES) - @rm -f ghwdump$(EXEEXT) - $(AM_V_CCLD)$(LINK) $(ghwdump_OBJECTS) $(ghwdump_LDADD) $(LIBS) - lxt2miner$(EXEEXT): $(lxt2miner_OBJECTS) $(lxt2miner_DEPENDENCIES) $(EXTRA_lxt2miner_DEPENDENCIES) @rm -f lxt2miner$(EXEEXT) $(AM_V_CCLD)$(LINK) $(lxt2miner_OBJECTS) $(lxt2miner_LDADD) $(LIBS) @@ -542,8 +532,6 @@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fst2vcd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fstapi.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fstminer.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ghwdump.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ghwlib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/jrb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxt2_read.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lxt2_write.Po@am__quote@ @@ -634,20 +622,6 @@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o fstapi.obj `if test -f '$(srcdir)/fst/fstapi.c'; then $(CYGPATH_W) '$(srcdir)/fst/fstapi.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/fst/fstapi.c'; fi` -ghwlib.o: $(srcdir)/../ghwlib.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ghwlib.o -MD -MP -MF $(DEPDIR)/ghwlib.Tpo -c -o ghwlib.o `test -f '$(srcdir)/../ghwlib.c' || echo '$(srcdir)/'`$(srcdir)/../ghwlib.c -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ghwlib.Tpo $(DEPDIR)/ghwlib.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../ghwlib.c' object='ghwlib.o' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ghwlib.o `test -f '$(srcdir)/../ghwlib.c' || echo '$(srcdir)/'`$(srcdir)/../ghwlib.c - -ghwlib.obj: $(srcdir)/../ghwlib.c -@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT ghwlib.obj -MD -MP -MF $(DEPDIR)/ghwlib.Tpo -c -o ghwlib.obj `if test -f '$(srcdir)/../ghwlib.c'; then $(CYGPATH_W) '$(srcdir)/../ghwlib.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../ghwlib.c'; fi` -@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ghwlib.Tpo $(DEPDIR)/ghwlib.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$(srcdir)/../ghwlib.c' object='ghwlib.obj' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o ghwlib.obj `if test -f '$(srcdir)/../ghwlib.c'; then $(CYGPATH_W) '$(srcdir)/../ghwlib.c'; else $(CYGPATH_W) '$(srcdir)/$(srcdir)/../ghwlib.c'; fi` - LzmaLib.o: $(srcdir)/../liblzma/LzmaLib.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT LzmaLib.o -MD -MP -MF $(DEPDIR)/LzmaLib.Tpo -c -o LzmaLib.o `test -f '$(srcdir)/../liblzma/LzmaLib.c' || echo '$(srcdir)/'`$(srcdir)/../liblzma/LzmaLib.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/LzmaLib.Tpo $(DEPDIR)/LzmaLib.Po diff -Nru gtkwave-3.3.104/src/helpers/evcd2vcd.c gtkwave-3.3.104+really3.3.118/src/helpers/evcd2vcd.c --- gtkwave-3.3.104/src/helpers/evcd2vcd.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/evcd2vcd.c 2023-12-31 21:11:05.000000000 +0000 @@ -37,6 +37,16 @@ #endif #include +/* + * report abort messages + */ +static void chk_report_abort(const char *s) +{ +fprintf(stderr,"Triggered %s security check, exiting.\n", s); +abort(); +} + + ssize_t getline_replace(char **buf, size_t *len, FILE *f) { char *fgets_rc; @@ -234,6 +244,10 @@ if(!node) { Jval val; + if((len < 0) || (len > 32768)) + { + chk_report_abort("TALOS-2023-1803"); + } jrb_insert_int(vcd_ids, hash, val)->val2.i = len; } diff -Nru gtkwave-3.3.104/src/helpers/fst/CMakeLists.txt gtkwave-3.3.104+really3.3.118/src/helpers/fst/CMakeLists.txt --- gtkwave-3.3.104/src/helpers/fst/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/CMakeLists.txt 2023-12-31 21:11:05.000000000 +0000 @@ -0,0 +1,23 @@ +cmake_minimum_required (VERSION 3.0) + +project (fstlib) + +######################################################################################################################## +# Easiest way to get ZLib on windows is using vcpkg, to load vcpkg: +# cmake -DCMAKE_TOOLCHAIN_FILE=[path to vcpkg]/scripts/buildsystems/vcpkg.cmake +if(CMAKE_TOOLCHAIN_FILE) + message(STATUS "Using VCPKG from ${CMAKE_TOOLCHAIN_FILE}") +endif() +######################################################################################################################## +find_package(ZLIB REQUIRED) + +add_library(fstapi fstapi.c fstapi.h fst_win_unistd.h) +target_link_libraries(fstapi PRIVATE ZLIB::ZLIB) +# hack to avoid creating dummy config.h +target_compile_definitions(fstapi PRIVATE -DFST_CONFIG_INCLUDE="fstapi.h") + +if(MSVC) + # define __MINGW32__ to minimize changes to upstream + target_compile_definitions(fstapi PRIVATE __MINGW32__ _CRT_SECURE_NO_WARNINGS FST_DO_MISALIGNED_OPS) + target_compile_options(fstapi PRIVATE /wd4244 /wd4267 /wd4146 /wd4996) +endif() diff -Nru gtkwave-3.3.104/src/helpers/fst/Makefile.am gtkwave-3.3.104+really3.3.118/src/helpers/fst/Makefile.am --- gtkwave-3.3.104/src/helpers/fst/Makefile.am 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/Makefile.am 2023-12-31 21:11:05.000000000 +0000 @@ -5,6 +5,6 @@ noinst_LIBRARIES= libfst.a -libfst_a_SOURCES= fastlz.c fastlz.h lz4.c lz4.h fstapi.c fstapi.h +libfst_a_SOURCES= fastlz.c fastlz.h lz4.c lz4.h fstapi.c fstapi.h fst_win_unistd.h -EXTRA_DIST= block_format.txt +EXTRA_DIST= block_format.txt CMakeLists.txt diff -Nru gtkwave-3.3.104/src/helpers/fst/Makefile.in gtkwave-3.3.104+really3.3.118/src/helpers/fst/Makefile.in --- gtkwave-3.3.104/src/helpers/fst/Makefile.in 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/Makefile.in 2023-12-31 21:11:05.000000000 +0000 @@ -315,8 +315,8 @@ top_srcdir = @top_srcdir@ AM_CFLAGS = $(LIBZ_CFLAGS) $(LIBJUDY_CFLAGS) noinst_LIBRARIES = libfst.a -libfst_a_SOURCES = fastlz.c fastlz.h lz4.c lz4.h fstapi.c fstapi.h -EXTRA_DIST = block_format.txt +libfst_a_SOURCES = fastlz.c fastlz.h lz4.c lz4.h fstapi.c fstapi.h fst_win_unistd.h +EXTRA_DIST = block_format.txt CMakeLists.txt all: all-am .SUFFIXES: diff -Nru gtkwave-3.3.104/src/helpers/fst/fastlz.c gtkwave-3.3.104+really3.3.118/src/helpers/fst/fastlz.c --- gtkwave-3.3.104/src/helpers/fst/fastlz.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/fastlz.c 2023-12-31 21:11:05.000000000 +0000 @@ -22,6 +22,8 @@ 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. + + SPDX-License-Identifier: MIT */ #include "fastlz.h" diff -Nru gtkwave-3.3.104/src/helpers/fst/fastlz.h gtkwave-3.3.104+really3.3.118/src/helpers/fst/fastlz.h --- gtkwave-3.3.104/src/helpers/fst/fastlz.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/fastlz.h 2023-12-31 21:11:05.000000000 +0000 @@ -22,6 +22,8 @@ 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. + + SPDX-License-Identifier: MIT */ #ifndef FASTLZ_H diff -Nru gtkwave-3.3.104/src/helpers/fst/fst_win_unistd.h gtkwave-3.3.104+really3.3.118/src/helpers/fst/fst_win_unistd.h --- gtkwave-3.3.104/src/helpers/fst/fst_win_unistd.h 1970-01-01 00:00:00.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/fst_win_unistd.h 2023-12-31 21:11:05.000000000 +0000 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2009-2018 Tony Bybell. + * + * 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. + * + * SPDX-License-Identifier: MIT + */ + +#ifndef WIN_UNISTD_H +#define WIN_UNISTD_H + +#include +#ifdef _WIN64 +#include +#else +#include +#endif + +#include + +#define ftruncate _chsize_s +#define unlink _unlink +#define fileno _fileno +#define lseek _lseeki64 + +#ifdef _WIN64 +#define ssize_t __int64 +#define SSIZE_MAX 9223372036854775807i64 +#else +#define ssize_t long +#define SSIZE_MAX 2147483647L +#endif + +#include "stdint.h" + +#endif //WIN_UNISTD_H diff -Nru gtkwave-3.3.104/src/helpers/fst/fstapi.c gtkwave-3.3.104+really3.3.118/src/helpers/fst/fstapi.c --- gtkwave-3.3.104/src/helpers/fst/fstapi.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/fstapi.c 2023-12-31 21:11:05.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2018 Tony Bybell. + * Copyright (c) 2009-2023 Tony Bybell. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -18,6 +18,8 @@ * 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. + * + * SPDX-License-Identifier: MIT */ /* @@ -56,6 +58,7 @@ #endif #ifdef __MINGW32__ +#define WIN32_LEAN_AND_MEAN #include #endif @@ -78,6 +81,12 @@ #define PATH_MAX (4096) #endif +#if defined(_MSC_VER) +typedef int64_t fst_off_t; +#else +typedef off_t fst_off_t; +#endif + /* note that Judy versus Jenkins requires more experimentation: they are */ /* functionally equivalent though it appears Jenkins is slightly faster. */ /* in addition, Jenkins is not bound by the LGPL. */ @@ -123,7 +132,7 @@ #define FST_GZIO_LEN (32768) #define FST_HDR_FOURPACK_DUO_SIZE (4*1024*1024) -#if defined(__i386__) || defined(__x86_64__) || defined(_AIX) +#if defined(__i386__) || defined(__x86_64__) || defined(_AIX) || defined(__aarch64__) #define FST_DO_MISALIGNED_OPS #endif @@ -132,6 +141,10 @@ #include #endif +#if defined(FST_MACOSX) || defined(__MINGW32__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) +#define FST_UNBUFFERED_IO +#endif + #ifdef __GNUC__ /* Boolean expression more often true than false */ #define FST_LIKELY(x) __builtin_expect(!!(x), 1) @@ -153,8 +166,8 @@ #ifdef __MINGW32__ #include #ifndef HAVE_FSEEKO -#define ftello ftell -#define fseeko fseek +#define ftello _ftelli64 +#define fseeko _fseeki64 #endif #endif @@ -180,6 +193,16 @@ /* + * report abort messages + */ +static void chk_report_abort(const char *s) +{ +fprintf(stderr,"Triggered %s security check, exiting.\n", s); +abort(); +} + + +/* * prevent old file overwrite when currently being read */ static FILE *unlink_fopen(const char *nam, const char *mode) @@ -282,7 +305,7 @@ return(fwrite(buf, siz, cnt, fp)); } -static int fstFtruncate(int fd, off_t length) +static int fstFtruncate(int fd, fst_off_t length) { return(ftruncate(fd, length)); } @@ -322,26 +345,22 @@ /* * mmap compatibility */ -#if defined __CYGWIN__ || defined __MINGW32__ +#if defined __MINGW32__ #include #define fstMmap(__addr,__len,__prot,__flags,__fd,__off) fstMmap2((__len), (__fd), (__off)) -#define fstMunmap(__addr,__len) free(__addr) +#define fstMunmap(__addr,__len) UnmapViewOfFile((LPCVOID)__addr) -static void *fstMmap2(size_t __len, int __fd, off_t __off) +static void *fstMmap2(size_t __len, int __fd, fst_off_t __off) { -(void)__off; - -unsigned char *pnt = (unsigned char *)malloc(__len); -off_t cur_offs = lseek(__fd, 0, SEEK_CUR); -size_t i; - -lseek(__fd, 0, SEEK_SET); -for(i=0;i<__len;i+=SSIZE_MAX) - { - read(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i)); - } -lseek(__fd, cur_offs, SEEK_SET); -return(pnt); +HANDLE handle = CreateFileMapping((HANDLE)_get_osfhandle(__fd), NULL, + PAGE_READWRITE, (DWORD)(__len >> 32), + (DWORD)__len, NULL); +if (!handle) { return NULL; } + +void *ptr = MapViewOfFileEx(handle, FILE_MAP_READ | FILE_MAP_WRITE, + 0, (DWORD)__off, (SIZE_T)__len, (LPVOID)NULL); +CloseHandle(handle); +return ptr; } #else #include @@ -541,7 +560,8 @@ static uint32_t fstReaderVarint32(FILE *f) { -unsigned char buf[5]; +int chk_len = 5; /* TALOS-2023-1783 */ +unsigned char buf[chk_len]; unsigned char *mem = buf; uint32_t rc = 0; int ch; @@ -550,7 +570,9 @@ { ch = fgetc(f); *(mem++) = ch; - } while(ch & 0x80); + } while((ch & 0x80) && (--chk_len)); + +if(ch & 0x80) chk_report_abort("TALOS-2023-1783"); mem--; for(;;) @@ -570,7 +592,8 @@ static uint32_t fstReaderVarint32WithSkip(FILE *f, uint32_t *skiplen) { -unsigned char buf[5]; +int chk_len = 5; /* TALOS-2023-1783 */ +unsigned char buf[chk_len]; unsigned char *mem = buf; uint32_t rc = 0; int ch; @@ -579,7 +602,9 @@ { ch = fgetc(f); *(mem++) = ch; - } while(ch & 0x80); + } while((ch & 0x80) && (--chk_len)); + +if(ch & 0x80) chk_report_abort("TALOS-2023-1783"); *skiplen = mem - buf; mem--; @@ -600,7 +625,8 @@ static uint64_t fstReaderVarint64(FILE *f) { -unsigned char buf[16]; +int chk_len = 16; /* TALOS-2023-1783 */ +unsigned char buf[chk_len]; unsigned char *mem = buf; uint64_t rc = 0; int ch; @@ -609,9 +635,12 @@ { ch = fgetc(f); *(mem++) = ch; - } while(ch & 0x80); + } while((ch & 0x80) && (--chk_len)); + +if(ch & 0x80) chk_report_abort("TALOS-2023-1783"); mem--; + for(;;) { rc <<= 7; @@ -732,7 +761,7 @@ unsigned char *vchg_mem; -off_t hier_file_len; +fst_off_t hier_file_len; uint32_t *valpos_mem; unsigned char *curval_mem; @@ -752,7 +781,7 @@ unsigned fastpack : 1; int64_t timezero; -off_t section_header_truncpos; +fst_off_t section_header_truncpos; uint32_t tchn_cnt, tchn_idx; uint64_t curtime; uint64_t firsttime; @@ -760,7 +789,7 @@ uint32_t vchg_alloc_siz; uint32_t secnum; -off_t section_start; +fst_off_t section_start; uint32_t numscopes; double nan; /* nan value for uninitialized doubles */ @@ -792,6 +821,7 @@ pthread_attr_t thread_attr; struct fstWriterContext *xc_parent; #endif +unsigned in_pthread : 1; size_t fst_orig_break_size; size_t fst_orig_break_add_size; @@ -817,7 +847,7 @@ }; -static int fstWriterFseeko(struct fstWriterContext *xc, FILE *stream, off_t offset, int whence) +static int fstWriterFseeko(struct fstWriterContext *xc, FILE *stream, fst_off_t offset, int whence) { int rc = fseeko(stream, offset, whence); @@ -971,20 +1001,32 @@ */ static void fstWriterMmapSanity(void *pnt, const char *file, int line, const char *usage) { -#if !defined(__CYGWIN__) && !defined(__MINGW32__) -if(pnt == MAP_FAILED) +if(pnt == NULL +#ifdef MAP_FAILED + || pnt == MAP_FAILED +#endif + ) { fprintf(stderr, "fstMmap() assigned to %s failed: errno: %d, file %s, line %d.\n", usage, errno, file, line); +#if !defined(__MINGW32__) perror("Why"); +#else + LPSTR mbuf = NULL; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&mbuf, 0, NULL); + fprintf(stderr, "%s", mbuf); + LocalFree(mbuf); +#endif pnt = NULL; } -#endif } static void fstWriterCreateMmaps(struct fstWriterContext *xc) { -off_t curpos = ftello(xc->handle); +fst_off_t curpos = ftello(xc->handle); fflush(xc->hier_handle); @@ -1029,27 +1071,6 @@ fstMunmap(xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t)); xc->valpos_mem = NULL; -#if defined __CYGWIN__ || defined __MINGW32__ -if(xc->curval_mem) - { - if(!is_closing) /* need to flush out for next emulated mmap() read */ - { - unsigned char *pnt = xc->curval_mem; - int __fd = fileno(xc->curval_handle); - off_t cur_offs = lseek(__fd, 0, SEEK_CUR); - size_t i; - size_t __len = xc->maxvalpos; - - lseek(__fd, 0, SEEK_SET); - for(i=0;i<__len;i+=SSIZE_MAX) - { - write(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i)); - } - lseek(__fd, cur_offs, SEEK_SET); - } - } -#endif - fstMunmap(xc->curval_mem, xc->maxvalpos); xc->curval_mem = NULL; } @@ -1277,14 +1298,14 @@ unsigned int i; unsigned char *vchg_mem; FILE *f; -off_t fpos, indxpos, endpos; +fst_off_t fpos, indxpos, endpos; uint32_t prevpos; int zerocnt; unsigned char *scratchpad; unsigned char *scratchpnt; unsigned char *tmem; -off_t tlen; -off_t unc_memreq = 0; /* for reader */ +fst_off_t tlen; +fst_off_t unc_memreq = 0; /* for reader */ unsigned char *packmem; unsigned int packmemlen; uint32_t *vm4ip; @@ -1728,7 +1749,7 @@ unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); - if((rc == Z_OK) && (((off_t)destlen) < tlen)) + if((rc == Z_OK) && (((fst_off_t)destlen) < tlen)) { fstFwrite(dmem, destlen, 1, xc->handle); } @@ -1776,7 +1797,7 @@ xc2->section_header_truncpos = endpos; /* cache in case of need to truncate */ if(xc->dump_size_limit) { - if(endpos >= ((off_t)xc->dump_size_limit)) + if(endpos >= ((fst_off_t)xc->dump_size_limit)) { xc2->skip_writing_section_hdr = 1; xc2->size_limit_locked = 1; @@ -1801,19 +1822,23 @@ static void *fstWriterFlushContextPrivate1(void *ctx) { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; +struct fstWriterContext *xc_parent; +pthread_mutex_lock(&(xc->xc_parent->mutex)); fstWriterFlushContextPrivate2(xc); -pthread_mutex_unlock(&(xc->xc_parent->mutex)); - #ifdef FST_REMOVE_DUPLICATE_VC free(xc->curval_mem); #endif free(xc->valpos_mem); free(xc->vchg_mem); tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); +xc_parent = xc->xc_parent; free(xc); +xc_parent->in_pthread = 0; +pthread_mutex_unlock(&(xc_parent->mutex)); + return(NULL); } @@ -1833,6 +1858,14 @@ xc->xc_parent = xc; memcpy(xc2, xc, sizeof(struct fstWriterContext)); + if(sizeof(size_t) < sizeof(uint64_t)) + { + /* TALOS-2023-1777 for 32b overflow */ + uint64_t chk_64 = xc->maxhandle * 4 * sizeof(uint32_t); + size_t chk_32 = xc->maxhandle * 4 * sizeof(uint32_t); + if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1777"); + } + xc2->valpos_mem = (uint32_t *)malloc(xc->maxhandle * 4 * sizeof(uint32_t)); memcpy(xc2->valpos_mem, xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t)); @@ -1861,7 +1894,15 @@ xc->section_header_only = 0; xc->secnum++; + while (xc->in_pthread) + { + pthread_mutex_lock(&xc->mutex); + pthread_mutex_unlock(&xc->mutex); + }; + pthread_mutex_lock(&xc->mutex); + xc->in_pthread = 1; + pthread_mutex_unlock(&xc->mutex); pthread_create(&xc->thread, &xc->thread_attr, fstWriterFlushContextPrivate1, xc2); } @@ -1914,7 +1955,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) { unsigned char *tmem = NULL; - off_t fixup_offs, tlen, hlen; + fst_off_t fixup_offs, tlen, hlen; xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */ @@ -1943,6 +1984,12 @@ #ifdef FST_WRITER_PARALLEL pthread_mutex_lock(&xc->mutex); pthread_mutex_unlock(&xc->mutex); + + while (xc->in_pthread) + { + pthread_mutex_lock(&xc->mutex); + pthread_mutex_unlock(&xc->mutex); + }; #endif } } @@ -1968,7 +2015,7 @@ unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); - if((rc != Z_OK) || (((off_t)destlen) > tlen)) + if((rc != Z_OK) || (((fst_off_t)destlen) > tlen)) { destlen = tlen; } @@ -1979,7 +2026,7 @@ fstWriterUint64(xc->handle, tlen); /* uncompressed */ /* compressed len is section length - 24 */ fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */ - fstFwrite((((off_t)destlen) != tlen) ? dmem : tmem, destlen, 1, xc->handle); + fstFwrite((((fst_off_t)destlen) != tlen) ? dmem : tmem, destlen, 1, xc->handle); fflush(xc->handle); fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); @@ -1995,7 +2042,7 @@ if(xc->num_blackouts) { uint64_t cur_bl = 0; - off_t bpos, eos; + fst_off_t bpos, eos; uint32_t i; fixup_offs = ftello(xc->handle); @@ -2028,12 +2075,13 @@ if(xc->compress_hier) { - off_t hl, eos; + fst_off_t hl, eos; gzFile zhandle; int zfd; int fourpack_duo = 0; #ifndef __MINGW32__ - char *fnam = (char *)malloc(strlen(xc->filename) + 5 + 1); + int fnam_len = strlen(xc->filename) + 5 + 1; + char *fnam = (char *)malloc(fnam_len); #endif fixup_offs = ftello(xc->handle); @@ -2123,7 +2171,7 @@ fflush(xc->handle); #ifndef __MINGW32__ - sprintf(fnam, "%s.hier", xc->filename); + snprintf(fnam, fnam_len, "%s.hier", xc->filename); unlink(fnam); free(fnam); #endif @@ -2151,7 +2199,7 @@ if(xc->repack_on_close) { FILE *fp; - off_t offpnt, uclen; + fst_off_t offpnt, uclen; int flen = strlen(xc->filename); char *hf = (char *)calloc(1, flen + 5); @@ -2258,7 +2306,7 @@ if(xc) { char s[FST_HDR_DATE_SIZE]; - off_t fpos = ftello(xc->handle); + fst_off_t fpos = ftello(xc->handle); int len = strlen(dat); fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_DATE, SEEK_SET); @@ -2277,7 +2325,7 @@ if(xc && vers) { char s[FST_HDR_SIM_VERSION_SIZE]; - off_t fpos = ftello(xc->handle); + fst_off_t fpos = ftello(xc->handle); int len = strlen(vers); fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_SIM_VERSION, SEEK_SET); @@ -2297,7 +2345,7 @@ { if(/*(filetype >= FST_FT_MIN) &&*/ (filetype <= FST_FT_MAX)) { - off_t fpos = ftello(xc->handle); + fst_off_t fpos = ftello(xc->handle); xc->filetype = filetype; @@ -2438,7 +2486,7 @@ struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - off_t fpos = ftello(xc->handle); + fst_off_t fpos = ftello(xc->handle); fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMESCALE, SEEK_SET); fputc(ts & 255, xc->handle); fflush(xc->handle); @@ -2496,7 +2544,7 @@ struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - off_t fpos = ftello(xc->handle); + fst_off_t fpos = ftello(xc->handle); fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMEZERO, SEEK_SET); fstWriterUint64(xc->handle, (xc->timezero = tim)); fflush(xc->handle); @@ -2802,7 +2850,7 @@ uint32_t i; name_len = strlen(name); - elem_count_len = sprintf(elem_count_buf, "%" PRIu32, elem_count); + elem_count_len = snprintf(elem_count_buf, 16, "%" PRIu32, elem_count); literal_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int)); val_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int)); @@ -3338,7 +3386,7 @@ int64_t timezero; char *filename, *filename_unpacked; -off_t hier_pos; +fst_off_t hier_pos; uint32_t num_blackouts; uint64_t *blackout_times; @@ -3353,10 +3401,10 @@ uint64_t rvat_beg_tim, rvat_end_tim; unsigned char *rvat_frame_data; uint64_t rvat_frame_maxhandle; -off_t *rvat_chain_table; +fst_off_t *rvat_chain_table; uint32_t *rvat_chain_table_lengths; uint64_t rvat_vc_maxhandle; -off_t rvat_vc_start; +fst_off_t rvat_vc_start; uint32_t *rvat_sig_offs; int rvat_packtype; @@ -3379,6 +3427,7 @@ unsigned do_rewind : 1; char str_scope_nam[FST_ID_NAM_SIZ+1]; char str_scope_comp[FST_ID_NAM_SIZ+1]; +char *str_scope_attr; unsigned fseek_failed : 1; @@ -3395,7 +3444,7 @@ }; -int fstReaderFseeko(struct fstReaderContext *xc, FILE *stream, off_t offset, int whence) +int fstReaderFseeko(struct fstReaderContext *xc, FILE *stream, fst_off_t offset, int whence) { int rc = fseeko(stream, offset, whence); @@ -3413,7 +3462,7 @@ #ifndef FST_WRITEX_DISABLE -static void fstWritex(struct fstReaderContext *xc, void *v, int len) +static void fstWritex(struct fstReaderContext *xc, void *v, uint32_t len) /* TALOS-2023-1793: change len to unsigned */ { unsigned char *s = (unsigned char *)v; @@ -3888,11 +3937,12 @@ if(!xc->fh) { - off_t offs_cache = ftello(xc->f); - char *fnam = (char *)malloc(strlen(xc->filename) + 6 + 16 + 32 + 1); + fst_off_t offs_cache = ftello(xc->f); + int fnam_len = strlen(xc->filename) + 6 + 16 + 32 + 1; + char *fnam = (char *)malloc(fnam_len); unsigned char *mem = (unsigned char *)malloc(FST_GZIO_LEN); - off_t hl, uclen; - off_t clen = 0; + fst_off_t hl, uclen; + fst_off_t clen = 0; gzFile zhandle = NULL; int zfd; int htyp = FST_BL_SKIP; @@ -3908,7 +3958,7 @@ htyp = xc->contains_hier_section_lz4duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4; } - sprintf(fnam, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc); + snprintf(fnam, fnam_len, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc); fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); uclen = fstReaderUint64(xc->f); #ifndef __MINGW32__ @@ -4097,26 +4147,35 @@ if(!(isfeof=feof(xc->fh))) { int tag = fgetc(xc->fh); + int cl; switch(tag) { case FST_ST_VCD_SCOPE: xc->hier.htyp = FST_HT_SCOPE; xc->hier.u.scope.typ = fgetc(xc->fh); xc->hier.u.scope.name = pnt = xc->str_scope_nam; + cl = 0; while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + if(cl < FST_ID_NAM_SIZ) + { + pnt[cl++] = ch; + } }; /* scopename */ - *pnt = 0; - xc->hier.u.scope.name_length = pnt - xc->hier.u.scope.name; + pnt[cl] = 0; + xc->hier.u.scope.name_length = cl; xc->hier.u.scope.component = pnt = xc->str_scope_comp; + cl = 0; while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + if(cl < FST_ID_NAM_SIZ) + { + pnt[cl++] = ch; + } }; /* scopecomp */ - *pnt = 0; - xc->hier.u.scope.component_length = pnt - xc->hier.u.scope.component; + pnt[cl] = 0; + xc->hier.u.scope.component_length = cl; break; case FST_ST_VCD_UPSCOPE: @@ -4127,13 +4186,21 @@ xc->hier.htyp = FST_HT_ATTRBEGIN; xc->hier.u.attr.typ = fgetc(xc->fh); xc->hier.u.attr.subtype = fgetc(xc->fh); - xc->hier.u.attr.name = pnt = xc->str_scope_nam; + if(!xc->str_scope_attr) + { + xc->str_scope_attr = (char *)calloc(1, FST_ID_NAM_ATTR_SIZ+1); + } + xc->hier.u.attr.name = pnt = xc->str_scope_attr; + cl = 0; while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; - }; /* scopename */ - *pnt = 0; - xc->hier.u.attr.name_length = pnt - xc->hier.u.scope.name; + if(cl < FST_ID_NAM_ATTR_SIZ) + { + pnt[cl++] = ch; + } + }; /* attrname */ + pnt[cl] = 0; + xc->hier.u.attr.name_length = cl; xc->hier.u.attr.arg = fstReaderVarint64(xc->fh); @@ -4142,7 +4209,7 @@ if((xc->hier.u.attr.subtype == FST_MT_SOURCESTEM)||(xc->hier.u.attr.subtype == FST_MT_SOURCEISTEM)) { int sidx_skiplen_dummy = 0; - xc->hier.u.attr.arg_from_name = fstGetVarint64((unsigned char *)xc->str_scope_nam, &sidx_skiplen_dummy); + xc->hier.u.attr.arg_from_name = fstGetVarint64((unsigned char *)xc->str_scope_attr, &sidx_skiplen_dummy); } } break; @@ -4188,12 +4255,16 @@ xc->hier.u.var.typ = tag; xc->hier.u.var.direction = fgetc(xc->fh); xc->hier.u.var.name = pnt = xc->str_scope_nam; + cl = 0; while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + if(cl < FST_ID_NAM_SIZ) + { + pnt[cl++] = ch; + } }; /* varname */ - *pnt = 0; - xc->hier.u.var.name_length = pnt - xc->hier.u.var.name; + pnt[cl] = 0; + xc->hier.u.var.name_length = cl; xc->hier.u.var.length = fstReaderVarint32(xc->fh); if(tag == FST_VT_VCD_PORT) { @@ -4240,6 +4311,7 @@ int attrtype, subtype; uint64_t attrarg; fstHandle maxhandle_scanbuild; +int cl; if(!xc) return(0); @@ -4322,11 +4394,15 @@ scopetype = fgetc(xc->fh); if((scopetype < FST_ST_MIN) || (scopetype > FST_ST_MAX)) scopetype = FST_ST_VCD_MODULE; pnt = str; + cl = 0; while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + if(cl < FST_ID_NAM_ATTR_SIZ) + { + pnt[cl++] = ch; + } }; /* scopename */ - *pnt = 0; + pnt[cl] = 0; while(fgetc(xc->fh)) { }; /* scopecomp */ if(fv) fprintf(fv, "$scope %s %s $end\n", modtypes[scopetype], str); @@ -4340,11 +4416,15 @@ attrtype = fgetc(xc->fh); subtype = fgetc(xc->fh); pnt = str; + cl = 0; while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + if(cl < FST_ID_NAM_ATTR_SIZ) + { + pnt[cl++] = ch; + } }; /* attrname */ - *pnt = 0; + pnt[cl] = 0; if(!str[0]) { strcpy(str, "\"\""); } @@ -4425,11 +4505,15 @@ vartype = tag; /* vardir = */ fgetc(xc->fh); /* unused in VCD reader, but need to advance read pointer */ pnt = str; + cl = 0; while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + if(cl < FST_ID_NAM_ATTR_SIZ) + { + pnt[cl++] = ch; + } }; /* varname */ - *pnt = 0; + pnt[cl] = 0; len = fstReaderVarint32(xc->fh); alias = fstReaderVarint32(xc->fh); @@ -4512,8 +4596,8 @@ */ int fstReaderInit(struct fstReaderContext *xc) { -off_t blkpos = 0; -off_t endfile; +fst_off_t blkpos = 0; +fst_off_t endfile; uint64_t seclen; int sectype; uint64_t vc_section_count_actual = 0; @@ -4525,21 +4609,23 @@ if(sectype == FST_BL_ZWRAPPER) { FILE *fcomp; - off_t offpnt, uclen; + fst_off_t offpnt, uclen; char gz_membuf[FST_GZIO_LEN]; gzFile zhandle; int zfd; int flen = strlen(xc->filename); char *hf; + int hf_len; seclen = fstReaderUint64(xc->f); uclen = fstReaderUint64(xc->f); if(!seclen) return(0); /* not finished compressing, this is a failed read */ - hf = (char *)calloc(1, flen + 16 + 32 + 1); + hf_len = flen + 16 + 32 + 1; + hf = (char *)calloc(1, hf_len); - sprintf(hf, "%s.upk_%d_%p", xc->filename, getpid(), (void *)xc); + snprintf(hf, hf_len, "%s.upk_%d_%p", xc->filename, getpid(), (void *)xc); fcomp = fopen(hf, "w+b"); if(!fcomp) { @@ -4548,12 +4634,11 @@ if(!fcomp) { tmpfile_close(&fcomp, &xc->f_nam); return(0); } } -#if defined(FST_MACOSX) +#if defined(FST_UNBUFFERED_IO) setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ #endif #ifdef __MINGW32__ - setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ xc->filename_unpacked = hf; #else if(hf) @@ -4851,7 +4936,7 @@ char *hf = (char *)calloc(1, flen + 6); int rc; -#if defined(__MINGW32__) || defined(FST_MACOSX) +#if defined(FST_UNBUFFERED_IO) setvbuf(xc->f, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ #endif @@ -4912,6 +4997,7 @@ free(xc->signal_typs); xc->signal_typs = NULL; free(xc->signal_lens); xc->signal_lens = NULL; free(xc->filename); xc->filename = NULL; + free(xc->str_scope_attr); xc->str_scope_attr = NULL; if(xc->fh) { @@ -4958,15 +5044,13 @@ uint64_t tsec_nitems; unsigned int secnum = 0; int blocks_skipped = 0; -off_t blkpos = 0; +fst_off_t blkpos = 0; uint64_t seclen, beg_tim; -#ifdef FST_DEBUG uint64_t end_tim; -#endif uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle; -off_t vc_start; -off_t indx_pntr, indx_pos; -off_t *chain_table = NULL; +fst_off_t vc_start; +fst_off_t indx_pntr, indx_pos; +fst_off_t *chain_table = NULL; uint32_t *chain_table_lengths = NULL; unsigned char *chain_cmem; unsigned char *pnt; @@ -5004,6 +5088,7 @@ for(;;) { uint32_t *tc_head = NULL; + uint32_t tc_head_items = 0; traversal_mem_offs = 0; fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); @@ -5029,14 +5114,11 @@ if(!seclen) break; beg_tim = fstReaderUint64(xc->f); -#ifdef FST_DEBUG - end_tim = -#endif - fstReaderUint64(xc->f); + end_tim = fstReaderUint64(xc->f); if(xc->limit_range_valid) { - if(beg_tim < xc->limit_range_start) + if(end_tim < xc->limit_range_start) { blocks_skipped++; blkpos += seclen; @@ -5050,12 +5132,12 @@ } - mem_required_for_traversal = fstReaderUint64(xc->f); - mem_for_traversal = (unsigned char *)malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */ + mem_required_for_traversal = fstReaderUint64(xc->f) + 66; /* add in potential fastlz overhead */ + mem_for_traversal = (unsigned char *)malloc(mem_required_for_traversal); #ifdef FST_DEBUG fprintf(stderr, FST_APIMESS "sec: %u seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim, (int)end_tim); - fprintf(stderr, FST_APIMESS "mem_required_for_traversal: %d\n", (int)mem_required_for_traversal); + fprintf(stderr, FST_APIMESS "mem_required_for_traversal: %d\n", (int)mem_required_for_traversal-66); #endif /* process time block */ { @@ -5082,7 +5164,7 @@ destlen = tsec_uclen; sourcelen = tsec_clen; - fstReaderFseeko(xc, xc->f, -24 - ((off_t)tsec_clen), SEEK_CUR); + fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR); if(tsec_uclen != tsec_clen) { @@ -5105,6 +5187,22 @@ } free(time_table); + + if(sizeof(size_t) < sizeof(uint64_t)) + { + /* TALOS-2023-1792 for 32b overflow */ + uint64_t chk_64 = tsec_nitems * sizeof(uint64_t); + size_t chk_32 = ((size_t)tsec_nitems) * sizeof(uint64_t); + if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1792"); + } + else + { + uint64_t chk_64 = tsec_nitems * sizeof(uint64_t); + if((chk_64/sizeof(uint64_t)) != tsec_nitems) + { + chk_report_abort("TALOS-2023-1792"); + } + } time_table = (uint64_t *)calloc(tsec_nitems, sizeof(uint64_t)); tpnt = ucdata; tpval = 0; @@ -5116,7 +5214,23 @@ tpnt += skiplen; } - tc_head = (uint32_t *)calloc(tsec_nitems /* scan-build */ ? tsec_nitems : 1, sizeof(uint32_t)); + tc_head_items = tsec_nitems /* scan-build */ ? tsec_nitems : 1; + if(sizeof(size_t) < sizeof(uint64_t)) + { + /* TALOS-2023-1792 for 32b overflow */ + uint64_t chk_64 = tc_head_items * sizeof(uint32_t); + size_t chk_32 = ((size_t)tc_head_items) * sizeof(uint32_t); + if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1792"); + } + else + { + uint64_t chk_64 = tc_head_items * sizeof(uint32_t); + if((chk_64/sizeof(uint32_t)) != tc_head_items) + { + chk_report_abort("TALOS-2023-1792"); + } + } + tc_head = (uint32_t *)calloc(tc_head_items, sizeof(uint32_t)); free(ucdata); } @@ -5140,16 +5254,16 @@ if(beg_tim) { - if(dumpvars_state == 1) { wx_len = sprintf(wx_buf, "$end\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 2; } - wx_len = sprintf(wx_buf, "#%" PRIu64 "\n", beg_tim); + if(dumpvars_state == 1) { wx_len = snprintf(wx_buf, 32, "$end\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 2; } + wx_len = snprintf(wx_buf, 32, "#%" PRIu64 "\n", beg_tim); fstWritex(xc, wx_buf, wx_len); - if(!dumpvars_state) { wx_len = sprintf(wx_buf, "$dumpvars\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 1; } + if(!dumpvars_state) { wx_len = snprintf(wx_buf, 32, "$dumpvars\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 1; } } if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) { if(beg_tim == xc->blackout_times[cur_blackout]) { - wx_len = sprintf(wx_buf, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); + wx_len = snprintf(wx_buf, 32, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); fstWritex(xc, wx_buf, wx_len); } } @@ -5220,6 +5334,10 @@ { if(value_change_callback) { + if(xc->signal_lens[idx] > xc->longest_signal_value_len) + { + chk_report_abort("TALOS-2023-1797"); + } memcpy(xc->temp_signal_value_buf, mu+sig_offs, xc->signal_lens[idx]); xc->temp_signal_value_buf[xc->signal_lens[idx]] = 0; value_change_callback(user_callback_data_pointer, beg_tim, idx+1, xc->temp_signal_value_buf); @@ -5233,6 +5351,10 @@ vcd_id[0] = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; fstWritex(xc, vcd_id, 1); + if((sig_offs + xc->signal_lens[idx]) > frame_uclen) + { + chk_report_abort("TALOS-2023-1793"); + } fstWritex(xc,mu+sig_offs, xc->signal_lens[idx]); vcd_id[0] = ' '; /* collapse 3 writes into one I/O call */ @@ -5283,7 +5405,7 @@ clone_d[j] = srcdata[7-j]; } } - sprintf((char *)xc->temp_signal_value_buf, "%.16g", d); + snprintf((char *)xc->temp_signal_value_buf, xc->longest_signal_value_len + 1, "%.16g", d); value_change_callback(user_callback_data_pointer, beg_tim, idx+1, xc->temp_signal_value_buf); } } @@ -5311,7 +5433,7 @@ } fstVcdID(vcdid_buf, idx+1); - wx_len = sprintf(wx_buf, "r%.16g %s\n", d, vcdid_buf); + wx_len = snprintf(wx_buf, 64, "r%.16g %s\n", d, vcdid_buf); fstWritex(xc, wx_buf, wx_len); } } @@ -5323,11 +5445,11 @@ } free(mu); - fstReaderFseeko(xc, xc->f, -((off_t)frame_clen), SEEK_CUR); + fstReaderFseeko(xc, xc->f, -((fst_off_t)frame_clen), SEEK_CUR); } } - fstReaderFseeko(xc, xc->f, (off_t)frame_clen, SEEK_CUR); /* skip past compressed data */ + fstReaderFseeko(xc, xc->f, (fst_off_t)frame_clen, SEEK_CUR); /* skip past compressed data */ vc_maxhandle = fstReaderVarint64(xc->f); vc_start = ftello(xc->f); /* points to '!' character */ @@ -5357,7 +5479,44 @@ free(chain_table_lengths); vc_maxhandle_largest = vc_maxhandle; - chain_table = (off_t *)calloc((vc_maxhandle+1), sizeof(off_t)); + + if(!(vc_maxhandle+1)) + { + chk_report_abort("TALOS-2023-1798"); + } + + if(sizeof(size_t) < sizeof(uint64_t)) + { + /* TALOS-2023-1798 for 32b overflow */ + uint64_t chk_64 = (vc_maxhandle+1) * sizeof(fst_off_t); + size_t chk_32 = ((size_t)(vc_maxhandle+1)) * sizeof(fst_off_t); + if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1798"); + } + else + { + uint64_t chk_64 = (vc_maxhandle+1) * sizeof(fst_off_t); + if((chk_64/sizeof(fst_off_t)) != (vc_maxhandle+1)) + { + chk_report_abort("TALOS-2023-1798"); + } + } + chain_table = (fst_off_t *)calloc((vc_maxhandle+1), sizeof(fst_off_t)); + + if(sizeof(size_t) < sizeof(uint64_t)) + { + /* TALOS-2023-1798 for 32b overflow */ + uint64_t chk_64 = (vc_maxhandle+1) * sizeof(uint32_t); + size_t chk_32 = ((size_t)(vc_maxhandle+1)) * sizeof(uint32_t); + if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1798"); + } + else + { + uint64_t chk_64 = (vc_maxhandle+1) * sizeof(uint32_t); + if((chk_64/sizeof(uint32_t)) != (vc_maxhandle+1)) + { + chk_report_abort("TALOS-2023-1798"); + } + } chain_table_lengths = (uint32_t *)calloc((vc_maxhandle+1), sizeof(uint32_t)); } @@ -5401,6 +5560,11 @@ uint64_t val = fstGetVarint32(pnt, &skiplen); fstHandle loopcnt = val >> 1; + if((idx+loopcnt-1) > vc_maxhandle) /* TALOS-2023-1789 */ + { + chk_report_abort("TALOS-2023-1789"); + } + for(i=0;i> 1; + + if((idx+loopcnt-1) > vc_maxhandle) /* TALOS-2023-1789 */ + { + chk_report_abort("TALOS-2023-1789"); + } + for(i=0;i= mem_required_for_traversal) + { + chk_report_abort("TALOS-2023-1785"); + } + if(mc_mem_len < chain_table_lengths[i]) { free(mc_mem); @@ -5522,6 +5697,12 @@ { int destlen = chain_table_lengths[i] - skiplen; unsigned char *mu = mem_for_traversal + traversal_mem_offs; + + if(traversal_mem_offs >= mem_required_for_traversal) + { + chk_report_abort("TALOS-2023-1785"); + } + fstFread(mu, destlen, 1, xc->f); /* data to process is for(j=0;j> 1; } + if(tdelta >= tc_head_items) + { + chk_report_abort("TALOS-2023-1791"); + } + scatterptr[i] = tc_head[tdelta]; tc_head[tdelta] = i+1; } @@ -5576,16 +5762,16 @@ } } - if(dumpvars_state == 1) { wx_len = sprintf(wx_buf, "$end\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 2; } - wx_len = sprintf(wx_buf, "#%" PRIu64 "\n", time_table[i]); + if(dumpvars_state == 1) { wx_len = snprintf(wx_buf, 32, "$end\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 2; } + wx_len = snprintf(wx_buf, 32, "#%" PRIu64 "\n", time_table[i]); fstWritex(xc, wx_buf, wx_len); - if(!dumpvars_state) { wx_len = sprintf(wx_buf, "$dumpvars\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 1; } + if(!dumpvars_state) { wx_len = snprintf(wx_buf, 32, "$dumpvars\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 1; } if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) { if(time_table[i] == xc->blackout_times[cur_blackout]) { - wx_len = sprintf(wx_buf, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); + wx_len = snprintf(wx_buf, 32, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); fstWritex(xc, wx_buf, wx_len); } } @@ -5645,6 +5831,11 @@ shamt = 2 << (vli & 1); tdelta = vli >> shamt; + if((tdelta+i) >= tc_head_items) + { + chk_report_abort("TALOS-2023-1791"); + } + scatterptr[idx] = tc_head[i+tdelta]; tc_head[i+tdelta] = idx+1; } @@ -5678,6 +5869,14 @@ vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); { + if(sizeof(size_t) < sizeof(uint64_t)) + { + /* TALOS-2023-1790 for 32b overflow */ + uint64_t chk_64 = len*4 + 1; + size_t chk_32 = len*4 + 1; + if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1790"); + } + unsigned char *vesc = (unsigned char *)malloc(len*4 + 1); int vlen = fstUtilityBinToEsc(vesc, vdata, len); fstWritex(xc, vesc, vlen); @@ -5703,6 +5902,11 @@ vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); tdelta = vli >> 1; + if((tdelta+i) >= tc_head_items) + { + chk_report_abort("TALOS-2023-1791"); + } + scatterptr[idx] = tc_head[i+tdelta]; tc_head[i+tdelta] = idx+1; } @@ -5719,6 +5923,11 @@ if(xc->signal_typs[idx] != FST_VT_VCD_REAL) { + if(len > xc->longest_signal_value_len) + { + chk_report_abort("TALOS-2023-1797"); + } + if(!(vli & 1)) { int byte = 0; @@ -5766,6 +5975,10 @@ unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; fstWritex(xc, &ch_bp, 1); + if((vdata - mem_for_traversal + len) > mem_required_for_traversal) + { + chk_report_abort("TALOS-2023-1793"); + } fstWritex(xc, vdata, len); } } @@ -5835,7 +6048,7 @@ clone_d[j] = srcdata[7-j]; } } - sprintf((char *)xc->temp_signal_value_buf, "%.16g", d); + snprintf((char *)xc->temp_signal_value_buf, xc->longest_signal_value_len + 1, "%.16g", d); value_change_callback(user_callback_data_pointer, time_table[i], idx+1, xc->temp_signal_value_buf); } } @@ -5861,7 +6074,7 @@ } } - wx_len = sprintf(wx_buf, "r%.16g", d); + wx_len = snprintf(wx_buf, 32, "r%.16g", d); fstWritex(xc, wx_buf, wx_len); } } @@ -5888,6 +6101,11 @@ vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); tdelta = vli >> 1; + if((tdelta+i) >= tc_head_items) + { + chk_report_abort("TALOS-2023-1791"); + } + scatterptr[idx] = tc_head[i+tdelta]; tc_head[i+tdelta] = idx+1; } @@ -5967,7 +6185,7 @@ } } - sprintf((char *)buf, "%.16g", d); + snprintf((char *)buf, 32, "%.16g", d); /* this will write 18 bytes */ } } @@ -5978,7 +6196,7 @@ char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -off_t blkpos = 0, prev_blkpos; +fst_off_t blkpos = 0, prev_blkpos; uint64_t beg_tim, end_tim, beg_tim2, end_tim2; int sectype; unsigned int secnum = 0; @@ -5989,7 +6207,7 @@ #ifdef FST_DEBUG uint64_t mem_required_for_traversal; #endif -off_t indx_pntr, indx_pos; +fst_off_t indx_pntr, indx_pos; long chain_clen; unsigned char *chain_cmem; unsigned char *pnt; @@ -6051,7 +6269,7 @@ { if((tim == end_tim) && (tim != xc->end_time)) { - off_t cached_pos = ftello(xc->f); + fst_off_t cached_pos = ftello(xc->f); fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); sectype = fgetc(xc->f); @@ -6113,7 +6331,7 @@ destlen = tsec_uclen; sourcelen = tsec_clen; -fstReaderFseeko(xc, xc->f, -24 - ((off_t)tsec_clen), SEEK_CUR); +fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR); if(tsec_uclen != tsec_clen) { cdata = (unsigned char *)malloc(tsec_clen); @@ -6198,7 +6416,7 @@ fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET); fstFread(chain_cmem, chain_clen, 1, xc->f); -xc->rvat_chain_table = (off_t *)calloc((xc->rvat_vc_maxhandle+1), sizeof(off_t)); +xc->rvat_chain_table = (fst_off_t *)calloc((xc->rvat_vc_maxhandle+1), sizeof(fst_off_t)); xc->rvat_chain_table_lengths = (uint32_t *)calloc((xc->rvat_vc_maxhandle+1), sizeof(uint32_t)); pnt = chain_cmem; @@ -6559,7 +6777,7 @@ } } - sprintf(buf, "r%.16g", d); + snprintf(buf, 32, "r%.16g", d); /* this will write 19 bytes */ return(buf); } } diff -Nru gtkwave-3.3.104/src/helpers/fst/fstapi.h gtkwave-3.3.104+really3.3.118/src/helpers/fst/fstapi.h --- gtkwave-3.3.104/src/helpers/fst/fstapi.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/fstapi.h 2023-12-31 21:11:05.000000000 +0000 @@ -18,6 +18,8 @@ * 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. + * + * SPDX-License-Identifier: MIT */ #ifndef FST_API_H @@ -33,7 +35,11 @@ #include #include #include -#include +#if defined(_MSC_VER) + #include "fst_win_unistd.h" +#else + #include +#endif #include #define FST_RDLOAD "FSTLOAD | " diff -Nru gtkwave-3.3.104/src/helpers/fst/lz4.c gtkwave-3.3.104+really3.3.118/src/helpers/fst/lz4.c --- gtkwave-3.3.104/src/helpers/fst/lz4.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/lz4.c 2023-12-31 21:11:05.000000000 +0000 @@ -27,6 +27,8 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + SPDX-License-Identifier: BSD-2-Clause + You can contact the author at : - LZ4 source repository : https://github.com/Cyan4973/lz4 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c diff -Nru gtkwave-3.3.104/src/helpers/fst/lz4.h gtkwave-3.3.104+really3.3.118/src/helpers/fst/lz4.h --- gtkwave-3.3.104/src/helpers/fst/lz4.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/fst/lz4.h 2023-12-31 21:11:05.000000000 +0000 @@ -28,6 +28,8 @@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + SPDX-License-Identifier: BSD-2-Clause + You can contact the author at : - LZ4 source repository : https://github.com/Cyan4973/lz4 - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c diff -Nru gtkwave-3.3.104/src/helpers/ghwdump.c gtkwave-3.3.104+really3.3.118/src/helpers/ghwdump.c --- gtkwave-3.3.104/src/helpers/ghwdump.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/ghwdump.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,203 +0,0 @@ -/* Display a GHDL Wavefile for debugging. - Copyright (C) 2005-2008 Tristan Gingold - - GHDL 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, or (at your option) any later - version. - - GHDL 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. - - You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 51 Franklin Street - Suite 500, Boston, MA - 02110-1335, USA. -*/ - -#include -#include -#if HAVE_STDINT_H -#include -#endif -#include -#include -#include - -#include "ghwlib.h" - -#include "wave_locale.h" - -static const char *progname; -void -usage (void) -{ - printf ("usage: %s [OPTIONS] FILEs...\n", progname); - printf ("Options are:\n" - " -t display types\n" - " -h display hierarchy\n" - " -T display time\n" - " -s display signals (and time)\n" - " -l display list of sections\n" - " -v verbose\n"); -} - -int -main (int argc, char **argv) -{ - int i; - int flag_disp_types; - int flag_disp_hierarchy; - int flag_disp_time; - int flag_disp_signals; - int flag_list; - int flag_verbose; - int eof; - enum ghw_sm_type sm; - - progname = argv[0]; - flag_disp_types = 0; - flag_disp_hierarchy = 0; - flag_disp_time = 0; - flag_disp_signals = 0; - flag_list = 0; - flag_verbose = 0; - - WAVE_LOCALE_FIX - - while (1) - { - int c; - - c = getopt (argc, argv, "thTslv"); - if (c == -1) - break; - switch (c) - { - case 't': - flag_disp_types = 1; - break; - case 'h': - flag_disp_hierarchy = 1; - break; - case 'T': - flag_disp_time = 1; - break; - case 's': - flag_disp_signals = 1; - flag_disp_time = 1; - break; - case 'l': - flag_list = 1; - break; - case 'v': - flag_verbose++; - break; - default: - usage (); - exit (2); - } - } - - if (optind >= argc) - { - usage (); - return 1; - } - - for (i = optind; i < argc; i++) - { - struct ghw_handler h; - struct ghw_handler *hp = &h; - - hp->flag_verbose = flag_verbose; - - if (ghw_open (hp, argv[i]) != 0) - { - fprintf (stderr, "cannot open ghw file %s\n", argv[i]); - return 1; - } - if (flag_list) - { - while (1) - { - int section; - - section = ghw_read_section (hp); - if (section == -2) - { - printf ("eof of file\n"); - break; - } - else if (section < 0) - { - printf ("Error in file\n"); - break; - } - else if (section == 0) - { - printf ("Unknown section\n"); - break; - } - printf ("Section %s\n", ghw_sections[section].name); - if ((*ghw_sections[section].handler)(hp) < 0) - break; - } - } - else - { - if (ghw_read_base (hp) < 0) - { - fprintf (stderr, "cannot read ghw file\n"); - return 2; - } - if (0) - { - unsigned ix; - printf ("String table:\n"); - - for (ix = 1; ix < hp->nbr_str; ix++) - printf (" %s\n", hp->str_table[ix]); - } - if (flag_disp_types) - ghw_disp_types (hp); - if (flag_disp_hierarchy) - ghw_disp_hie (hp, hp->hie); - -#if 1 - sm = ghw_sm_init; - eof = 0; - while (!eof) - { - switch (ghw_read_sm (hp, &sm)) - { - case ghw_res_snapshot: - case ghw_res_cycle: - if (flag_disp_time) - printf ("Time is "GHWPRI64" fs\n", hp->snap_time); - if (flag_disp_signals) - ghw_disp_values (hp); - break; - case ghw_res_eof: - eof = 1; - break; - default: - abort (); - } - } - -#else - if (ghw_read_dump (hp) < 0) - { - fprintf (stderr, "error in ghw dump\n"); - return 3; - } -#endif - } - ghw_close (&h); - } - return 0; -} - diff -Nru gtkwave-3.3.104/src/helpers/lxt2_read.c gtkwave-3.3.104+really3.3.118/src/helpers/lxt2_read.c --- gtkwave-3.3.104/src/helpers/lxt2_read.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/lxt2_read.c 2023-12-31 21:11:05.000000000 +0000 @@ -90,6 +90,16 @@ /****************************************************************************/ /* + * report abort messages + */ +static void chk_report_abort(const char *s) +{ +fprintf(stderr,"Triggered %s security check, exiting.\n", s); +abort(); +} + + +/* * fast SWAR ones count for 32 and 64 bits */ #if LXT2_RD_GRANULE_SIZE > 32 @@ -141,6 +151,11 @@ int i; int len2 = len-1; +if(len >= sizeof(s)) + { + chk_report_abort("TALOS-2023-1827"); + } + for(i=0;ilen[idx];i++) { lt->value[idx][i] ^= 1; } break; case LXT2_RD_ENC_LSH0: - case LXT2_RD_ENC_LSH1: memmove(lt->value[idx], lt->value[idx]+1, lt->len[idx]-1); + case LXT2_RD_ENC_LSH1: if(!lt->len[idx]) + { + chk_report_abort("TALOS-2023-1824"); + } + memmove(lt->value[idx], lt->value[idx]+1, lt->len[idx]-1); lt->value[idx][lt->len[idx]-1] = '0'+(vch-LXT2_RD_ENC_LSH0); break; case LXT2_RD_ENC_RSH0: - case LXT2_RD_ENC_RSH1: memmove(lt->value[idx]+1, lt->value[idx], lt->len[idx]-1); + case LXT2_RD_ENC_RSH1: if(!lt->len[idx]) + { + chk_report_abort("TALOS-2023-1824"); + } + memmove(lt->value[idx]+1, lt->value[idx], lt->len[idx]-1); lt->value[idx][0] = '0'+(vch-LXT2_RD_ENC_RSH0); break; @@ -598,7 +621,21 @@ if(b->num_dict_entries) { + { + size_t chk_x = b->num_dict_entries * sizeof(char *); + if((chk_x / sizeof(char *)) != b->num_dict_entries) + { + chk_report_abort("TALOS-2023-1820"); + } + } b->string_pointers = malloc(b->num_dict_entries * sizeof(char *)); + { + size_t chk_x = b->num_dict_entries * sizeof(unsigned int); + if((chk_x / sizeof(unsigned int)) != b->num_dict_entries) + { + chk_report_abort("TALOS-2023-1820"); + } + } b->string_lens = malloc(b->num_dict_entries * sizeof(unsigned int)); pnt = b->dict_start; for(i=0;inum_dict_entries;i++) @@ -662,6 +699,10 @@ /* fprintf(stderr, LXT2_RDLOAD"processing granule %d\n", granule); */ pnt++; lt->num_time_table_entries = lxt2_rd_get_byte(pnt, 0); + if(lt->num_time_table_entries > LXT2_RD_GRANULE_SIZE) + { + chk_report_abort("TALOS-2023-1819"); + } pnt++; for(i=0;inum_time_table_entries;i++) { @@ -884,6 +925,13 @@ lt->zhandle = gzdopen(dup(fileno(lt->handle)), "rb"); t = lt->numfacs * 4 * sizeof(lxtint32_t); + { + size_t chk_x = lt->numfacs * 4 * sizeof(lxtint32_t); + if((chk_x / (4 * sizeof(lxtint32_t))) != lt->numfacs) + { + chk_report_abort("TALOS-2023-1818"); + } + } m=(char *)malloc(t); rc=gzread(lt->zhandle, m, t); gzclose(lt->zhandle); lt->zhandle=NULL; @@ -899,11 +947,25 @@ pos = pos+lt->zfacgeometrysize; + { + size_t chk_x = lt->numfacs * sizeof(lxtint32_t); + if((chk_x / sizeof(lxtint32_t)) != lt->numfacs) + { + chk_report_abort("TALOS-2023-1818"); + } + } lt->rows = malloc(lt->numfacs * sizeof(lxtint32_t)); lt->msb = malloc(lt->numfacs * sizeof(lxtsint32_t)); lt->lsb = malloc(lt->numfacs * sizeof(lxtsint32_t)); lt->flags = malloc(lt->numfacs * sizeof(lxtint32_t)); lt->len = malloc(lt->numfacs * sizeof(lxtint32_t)); + { + size_t chk_x = lt->numfacs * sizeof(char *); + if((chk_x / sizeof(char *)) != lt->numfacs) + { + chk_report_abort("TALOS-2023-1818"); + } + } lt->value = malloc(lt->numfacs * sizeof(char *)); lt->next_radix = malloc(lt->numfacs * sizeof(void *)); @@ -922,6 +984,13 @@ { lt->len[i] = 32; } + if(sizeof(size_t) < sizeof(uint64_t)) + { + /* TALOS-2023-1821 for 32b overflow */ + uint64_t chk_64 = lt->len[i] + 1; + size_t chk_32 = lt->len[i] + 1; + if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1821"); + } lt->value[i] = calloc(lt->len[i] + 1, sizeof(char)); } @@ -1261,12 +1330,24 @@ clone=lxt2_rd_get_16(lt->faccache->n, 0); lt->faccache->n+=2; pnt=lt->faccache->bufcurr; + if(clone > lt->longestname) + { + chk_report_abort("TALOS-2023-1826"); + } + for(j=0;jfaccache->bufprev[j]; } - while((*(pnt++)=lxt2_rd_get_byte(lt->faccache->n++,0))); + do + { + if((pnt - lt->faccache->bufcurr) > lt->longestname) + { + chk_report_abort("TALOS-2023-1826"); + } + } + while((*(pnt++)=lxt2_rd_get_byte(lt->faccache->n++,0))); lt->faccache->old_facidx = facidx; return(lt->faccache->bufcurr); } @@ -1526,6 +1607,11 @@ rcf = fread(&unclen, 4, 1, lt->handle); unclen = rcf ? lxt2_rd_get_32(&unclen,0) : 0; rcf = fread(&iter, 4, 1, lt->handle); iter = rcf ? lxt2_rd_get_32(&iter,0) : 0; + if(unclen > b->uncompressed_siz) + { + chk_report_abort("TALOS-2023-1823"); /* could fix this up with a realloc(), but abort to indicate the file is malformed */ + } + fspos += 12; if((iter==0xFFFFFFFF)||(lt->process_mask_compressed[iter/LXT2_RD_PARTIAL_SIZE])) { @@ -1533,6 +1619,10 @@ { if(zbuff) free(zbuff); zlen = clen * 2; + if(zlen < clen) + { + chk_report_abort("TALOS-2023-1822"); + } zbuff = malloc(zlen ? zlen : 1 /* scan-build */); } diff -Nru gtkwave-3.3.104/src/helpers/vcd2fst.c gtkwave-3.3.104+really3.3.118/src/helpers/vcd2fst.c --- gtkwave-3.3.104/src/helpers/vcd2fst.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/vcd2fst.c 2023-12-31 21:11:05.000000000 +0000 @@ -68,6 +68,43 @@ return(pnt); } +/******************************************************/ + +static FILE *popen_san(const char *command, const char *type) /* TALOS-2023-1786 */ +{ +const char *p = command; +int is_ok = 1; +char ch; + +while(p && (ch = *(p++))) + { + switch(ch) + { + case '&': + case '|': + case ';': + case '\n': + case '`': + case '$': + is_ok = 0; + + default: + break; + } + } + +if(is_ok) + { + return(popen(command, type)); + } +else + { + fprintf(stderr, "GTKWAVE | TALOS-2023-1786: popen() command string '%s' may not be properly sanitized, blocking command.\n", command); + return(NULL); + } +} + +/******************************************************/ /*********************************************************/ /*** vvv extload component type name determination vvv ***/ @@ -281,7 +318,7 @@ void *xc = fstReaderOpenForUtilitiesOnly(); sprintf(sbuff, "%s -info %s 2>&1", EXTLOAD_PATH, fname); -extload = popen(sbuff, "r"); +extload = popen_san(sbuff, "r"); if(extload) { while(get_info(extload)); @@ -295,7 +332,7 @@ } sprintf(sbuff, "%s -tree %s 2>&1", EXTLOAD_PATH, fname); -extload = popen(sbuff, "r"); +extload = popen_san(sbuff, "r"); if(extload) { while(get_scopename(xc, extload)); @@ -482,7 +519,7 @@ if(suffix_check(vname, "."EXTLOAD_SUFFIX) || suffix_check(vname, "."EXTLOAD_SUFFIX".gz") || suffix_check(vname, "."EXTLOAD_SUFFIX".bz2")) { sprintf(bin_fixbuff, EXTCONV_PATH" %s", vname); - f = popen(bin_fixbuff, "r"); + f = popen_san(bin_fixbuff, "r"); is_popen = 1; is_extload = 1; #ifndef _WAVE_HAVE_JUDY @@ -497,7 +534,7 @@ if(suffix_check(vname, "."EXT2LOAD_SUFFIX)) { sprintf(bin_fixbuff, EXT2CONV_PATH" %s", vname); - f = popen(bin_fixbuff, "r"); + f = popen_san(bin_fixbuff, "r"); is_popen = 1; } else @@ -506,7 +543,7 @@ if(suffix_check(vname, "."EXT3LOAD_SUFFIX)) { sprintf(bin_fixbuff, EXT3CONV_PATH" %s", vname); - f = popen(bin_fixbuff, "r"); + f = popen_san(bin_fixbuff, "r"); is_popen = 1; } else @@ -1154,6 +1191,11 @@ { exp+=2; } + else + if(tv == 1000) /* nonstandard */ + { + exp+=3; + } fstWriterSetTimescale(ctx, exp); } diff -Nru gtkwave-3.3.104/src/helpers/vcd2lxt.c gtkwave-3.3.104+really3.3.118/src/helpers/vcd2lxt.c --- gtkwave-3.3.104/src/helpers/vcd2lxt.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/vcd2lxt.c 2023-12-31 21:11:05.000000000 +0000 @@ -139,6 +139,53 @@ /******************************************************************/ +/* + * report abort messages + */ +static void chk_report_abort(const char *s) +{ +fprintf(stderr,"Triggered %s security check, exiting.\n", s); +abort(); +} + +/******************************************************************/ + +static FILE *popen_san(const char *command, const char *type) /* TALOS-2023-1786 */ +{ +const char *p = command; +int is_ok = 1; +char ch; + +while(p && (ch = *(p++))) + { + switch(ch) + { + case '&': + case '|': + case ';': + case '\n': + case '`': + case '$': + is_ok = 0; + + default: + break; + } + } + +if(is_ok) + { + return(popen(command, type)); + } +else + { + fprintf(stderr, "GTKWAVE | TALOS-2023-1786: popen() command string '%s' may not be properly sanitized, blocking command.\n", command); + return(NULL); + } +} + +/******************************************************************/ + static unsigned int vcd_minid = ~0; static unsigned int vcd_maxid = 0; @@ -193,6 +240,8 @@ { return(indexed[hsh-vcd_minid]); } + + return(NULL); /* TALOS-2023-1807 */ } v=(struct vcdsymbol **)bsearch(key, sorted, numsyms, @@ -556,7 +605,16 @@ { if(len==T_MAX_STR) { - yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1); + if(!varsplit) + { + yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1); + } + else /* TALOS-2023-1806 */ + { + int vsplit_len = varsplit - yytext; /* save old len */ + yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1); + varsplit = yytext+vsplit_len; /* reconstruct old len in new buffer */ + } } ch=getch(); @@ -925,7 +983,7 @@ } else { - if(yylen_cachesize) + if(yylen_cache<=v->size) /* TALOS-2023-1804 */ { free_2(vector); vector=malloc_2(v->size+1); @@ -1137,6 +1195,11 @@ int vtok; struct vcdsymbol *v=NULL; + if(header_over) + { + chk_report_abort("TALOS-2023-1805: $var after $enddefinitions"); + } + var_prevch=0; if(varsplit) { @@ -1661,7 +1724,7 @@ str=(char *)wave_alloca(strlen(fname)+dlen+1); strcpy(str,WAVE_DECOMPRESSOR); strcpy(str+dlen,fname); - vcd_handle=popen(str,"r"); + vcd_handle=popen_san(str,"r"); vcd_is_compressed=~0; } else diff -Nru gtkwave-3.3.104/src/helpers/vcd2lxt2.c gtkwave-3.3.104+really3.3.118/src/helpers/vcd2lxt2.c --- gtkwave-3.3.104/src/helpers/vcd2lxt2.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/vcd2lxt2.c 2023-12-31 21:11:05.000000000 +0000 @@ -145,6 +145,53 @@ /******************************************************************/ +/* + * report abort messages + */ +static void chk_report_abort(const char *s) +{ +fprintf(stderr,"Triggered %s security check, exiting.\n", s); +abort(); +} + +/******************************************************************/ + +static FILE *popen_san(const char *command, const char *type) /* TALOS-2023-1786 */ +{ +const char *p = command; +int is_ok = 1; +char ch; + +while(p && (ch = *(p++))) + { + switch(ch) + { + case '&': + case '|': + case ';': + case '\n': + case '`': + case '$': + is_ok = 0; + + default: + break; + } + } + +if(is_ok) + { + return(popen(command, type)); + } +else + { + fprintf(stderr, "GTKWAVE | TALOS-2023-1786: popen() command string '%s' may not be properly sanitized, blocking command.\n", command); + return(NULL); + } +} + +/******************************************************************/ + static unsigned int vcd_minid = ~0; static unsigned int vcd_maxid = 0; @@ -199,6 +246,8 @@ { return(indexed[hsh-vcd_minid]); } + + return(NULL); /* TALOS-2023-1807 */ } v=(struct vcdsymbol **)bsearch(key, sorted, numsyms, @@ -561,7 +610,16 @@ { if(len==T_MAX_STR) { - yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1); + if(!varsplit) + { + yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1); + } + else /* TALOS-2023-1806 */ + { + int vsplit_len = varsplit - yytext; /* save old len */ + yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1); + varsplit = yytext+vsplit_len; /* reconstruct old len in new buffer */ + } } ch=getch(); @@ -930,7 +988,7 @@ } else { - if(yylen_cachesize) + if(yylen_cache<=v->size) /* TALOS-2023-1804 */ { free_2(vector); vector=malloc_2(v->size+1); @@ -1139,6 +1197,11 @@ int vtok; struct vcdsymbol *v=NULL; + if(header_over) + { + chk_report_abort("TALOS-2023-1805: $var after $enddefinitions"); + } + var_prevch=0; if(varsplit) { @@ -1585,7 +1648,7 @@ str=(char *)wave_alloca(strlen(fname)+dlen+1); strcpy(str,WAVE_DECOMPRESSOR); strcpy(str+dlen,fname); - vcd_handle=popen(str,"r"); + vcd_handle=popen_san(str,"r"); vcd_is_compressed=~0; } else diff -Nru gtkwave-3.3.104/src/helpers/vcd2vzt.c gtkwave-3.3.104+really3.3.118/src/helpers/vcd2vzt.c --- gtkwave-3.3.104/src/helpers/vcd2vzt.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/vcd2vzt.c 2023-12-31 21:11:05.000000000 +0000 @@ -147,6 +147,53 @@ /******************************************************************/ +/* + * report abort messages + */ +static void chk_report_abort(const char *s) +{ +fprintf(stderr,"Triggered %s security check, exiting.\n", s); +abort(); +} + +/******************************************************************/ + +static FILE *popen_san(const char *command, const char *type) /* TALOS-2023-1786 */ +{ +const char *p = command; +int is_ok = 1; +char ch; + +while(p && (ch = *(p++))) + { + switch(ch) + { + case '&': + case '|': + case ';': + case '\n': + case '`': + case '$': + is_ok = 0; + + default: + break; + } + } + +if(is_ok) + { + return(popen(command, type)); + } +else + { + fprintf(stderr, "GTKWAVE | TALOS-2023-1786: popen() command string '%s' may not be properly sanitized, blocking command.\n", command); + return(NULL); + } +} + +/******************************************************************/ + static unsigned int vcd_minid = ~0; static unsigned int vcd_maxid = 0; @@ -201,6 +248,8 @@ { return(indexed[hsh-vcd_minid]); } + + return(NULL); /* TALOS-2023-1807 */ } v=(struct vcdsymbol **)bsearch(key, sorted, numsyms, @@ -563,7 +612,16 @@ { if(len==T_MAX_STR) { - yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1); + if(!varsplit) + { + yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1); + } + else /* TALOS-2023-1806 */ + { + int vsplit_len = varsplit - yytext; /* save old len */ + yytext=(char *)realloc_2(yytext, (T_MAX_STR=T_MAX_STR*2)+1); + varsplit = yytext+vsplit_len; /* reconstruct old len in new buffer */ + } } ch=getch(); @@ -932,7 +990,7 @@ } else { - if(yylen_cachesize) + if(yylen_cache<=v->size) /* TALOS-2023-1804 */ { free_2(vector); vector=malloc_2(v->size+1); @@ -1149,6 +1207,11 @@ int vtok; struct vcdsymbol *v=NULL; + if(header_over) + { + chk_report_abort("TALOS-2023-1805: $var after $enddefinitions"); + } + var_prevch=0; if(varsplit) { @@ -1595,7 +1658,7 @@ str=(char *)wave_alloca(strlen(fname)+dlen+1); strcpy(str,WAVE_DECOMPRESSOR); strcpy(str+dlen,fname); - vcd_handle=popen(str,"r"); + vcd_handle=popen_san(str,"r"); vcd_is_compressed=~0; } else diff -Nru gtkwave-3.3.104/src/helpers/vzt_read.c gtkwave-3.3.104+really3.3.118/src/helpers/vzt_read.c --- gtkwave-3.3.104/src/helpers/vzt_read.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/vzt_read.c 2023-12-31 21:11:05.000000000 +0000 @@ -38,6 +38,17 @@ /****************************************************************************/ +/* + * report abort messages + */ +static void chk_report_abort(const char *s) +{ +fprintf(stderr,"Triggered %s security check, exiting.\n", s); +abort(); +} + +/****************************************************************************/ + static int is_big_endian(void) { union @@ -171,19 +182,19 @@ } -static vztint32_t vzt_rd_get_v32(char **mmx) +static vztint32_t vzt_rd_get_v32(unsigned char **mmx) { -signed char *c; -signed char *beg; +unsigned char *c; +unsigned char *beg; vztint32_t val; -signed char **mm = (signed char **)mmx; +unsigned char **mm = mmx; c = *mm; beg = c; -if(*c>=0) +if(!(*c & 0x80)) { - while(*c>=0) c++; + while(!(*c & 0x80)) c++; *mm = c+1; val = (vztint32_t)(*c&0x7f); @@ -202,19 +213,19 @@ return(val); } -static vztint64_t vzt_rd_get_v64(char **mmx) +static vztint64_t vzt_rd_get_v64(unsigned char **mmx) { -signed char *c; -signed char *beg; +unsigned char *c; +unsigned char *beg; vztint64_t val; -signed char **mm = (signed char **)mmx; +unsigned char **mm = mmx; c = *mm; beg = c; -if(*c>=0) +if(!(*c & 0x80)) { - while(*c>=0) c++; + while(!(*c & 0x80)) c++; *mm = c+1; val = (vztint64_t)(*c&0x7f); @@ -314,7 +325,7 @@ vztint32_t *change_dict=NULL; vztint32_t *val_dict=NULL; unsigned int num_time_ticks, num_sections, num_dict_entries; -char *pnt = b->mem; +unsigned char *pnt = b->mem; vztint32_t i, j, m, num_dict_words; /* vztint32_t *block_end = (vztint32_t *)(pnt + b->uncompressed_siz); */ vztint32_t *val_tmp; @@ -326,6 +337,13 @@ if(num_time_ticks != 0) { vztint64_t cur_time; + { + size_t chk_x = num_time_ticks * sizeof(vztint64_t); + if((chk_x / sizeof(vztint64_t)) != num_time_ticks) + { + chk_report_abort("TALOS-2023-1814"); + } + } times = malloc(num_time_ticks * sizeof(vztint64_t)); times[0] = cur_time = vzt_rd_get_v64(&pnt); for(i=1;istart; num_time_ticks = b->end - b->start + 1; + { + size_t chk_x = num_time_ticks * sizeof(vztint64_t); + if((chk_x / sizeof(vztint64_t)) != num_time_ticks) + { + chk_report_abort("TALOS-2023-1814"); + } + } times = malloc(num_time_ticks * sizeof(vztint64_t)); for(i=0;inum_rle_bytes = (num_dict_words = num_sections * num_dict_entries) * sizeof(vztint32_t)); curr_dec_dict = val_dict; @@ -444,7 +483,20 @@ } } +if(num_sections && num_dict_entries) + { + size_t chk_x = (num_sections * num_dict_entries); + size_t chk_y = chk_x * sizeof(vztint32_t); + if((chk_x/num_sections) != num_dict_entries) + { + chk_report_abort("TALOS-2023-1815"); + } + if((chk_y/sizeof(vztint32_t)) != chk_x) + { + chk_report_abort("TALOS-2023-1815"); + } + } num_dict_words = (num_sections * num_dict_entries) * sizeof(vztint32_t); change_dict = malloc(num_dict_words ? num_dict_words : sizeof(vztint32_t)); /* scan-build */ m = 0; @@ -782,7 +834,7 @@ else { unsigned int spnt=vzt_rd_make_sindex(pnt); - char *msg = ((!i)&(!b->prev)) ? "UNDEF" : b->sindex[spnt]; + char *msg = ((!i)&&(b->prev)) ? "UNDEF" : b->sindex[spnt]; lt->value_change_callback(<, &b->times[i], &idx, &msg); } } @@ -857,7 +909,7 @@ else { unsigned int spnt=vzt_rd_make_sindex(pnt); - char *msg = ((!i)&(!b->prev)) ? "UNDEF" : b->sindex[spnt]; + char *msg = ((!i)&&(b->prev)) ? "UNDEF" : b->sindex[spnt]; lt->value_change_callback(<, &b->times[i], &idx, &msg); } } @@ -866,10 +918,17 @@ i2 = vzt_rd_next_value_chg_time(lt, b, i, idx); if(i2) { - struct vzt_ncycle_autosort *t = autosort[i2]; - - autofacs[idx].next = t; - autosort[i2] = autofacs+idx; + if(i2 < b->num_time_ticks) + { + struct vzt_ncycle_autosort *t = autosort[i2]; + + autofacs[idx].next = t; + autosort[i2] = autofacs+idx; + } + else + { + chk_report_abort("TALOS-2023-1817"); + } } else { @@ -908,7 +967,7 @@ else { unsigned int spnt=vzt_rd_make_sindex(pnt); - char *msg = ((!i)&(!b->prev)) ? "UNDEF" : b->sindex[spnt]; + char *msg = ((!i)&&(b->prev)) ? "UNDEF" : b->sindex[spnt]; lt->value_change_callback(<, &b->times[i], &idx, &msg); } } @@ -917,10 +976,17 @@ if(i2!=i) { - struct vzt_ncycle_autosort *ta = autosort[i2]; + if(i2 < b->num_time_ticks) + { + struct vzt_ncycle_autosort *ta = autosort[i2]; - autofacs[idx].next = ta; - autosort[i2] = autofacs+idx; + autofacs[idx].next = ta; + autosort[i2] = autofacs+idx; + } + else + { + chk_report_abort("TALOS-2023-1817"); + } } else { @@ -1131,12 +1197,24 @@ clonecnt=vzt_rd_get_16(lt->faccache->n, 0); lt->faccache->n+=2; pnt=lt->faccache->bufcurr; + if(clonecnt > lt->longestname) + { + chk_report_abort("TALOS-2023-1813"); + } + for(j=0;jfaccache->bufprev[j]; } - while((*(pnt++)=vzt_rd_get_byte(lt->faccache->n++,0))); + char *bufcurr_exceeded = lt->faccache->bufcurr + (lt->longestname+1); + do + { + if(bufcurr_exceeded == pnt) + { + chk_report_abort("TALOS-2023-1813"); + } + } while((*(pnt++)=vzt_rd_get_byte(lt->faccache->n++,0))); lt->faccache->old_facidx = facidx; return(lt->faccache->bufcurr); } @@ -1853,6 +1931,13 @@ pos = pos+lt->zfacgeometrysize; + { + size_t chk_x = lt->numfacs * sizeof(vztint32_t); + if((chk_x / sizeof(vztint32_t)) != lt->numfacs) + { + chk_report_abort("TALOS-2023-1812"); + } + } lt->rows = malloc(lt->numfacs * sizeof(vztint32_t)); lt->msb = malloc(lt->numfacs * sizeof(vztsint32_t)); lt->lsb = malloc(lt->numfacs * sizeof(vztsint32_t)); @@ -1887,6 +1972,14 @@ } } + if(sizeof(size_t) < sizeof(uint64_t)) + { + if(lt->longest_len == 0xffffffff) + { + chk_report_abort("TALOS-2023-1816"); + } + } + vindex_offset = 0; /* offset in value table */ for(lt->numrealfacs=0; lt->numrealfacsnumfacs; lt->numrealfacs++) { diff -Nru gtkwave-3.3.104/src/helpers/vzt_write.c gtkwave-3.3.104+really3.3.118/src/helpers/vzt_write.c --- gtkwave-3.3.104/src/helpers/vzt_write.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/helpers/vzt_write.c 2023-12-31 21:11:05.000000000 +0000 @@ -1259,7 +1259,9 @@ struct vzt_wr_symbol *s = lt->sorted_facs[j]; for(i=0;ilen;i++) { - lt->use_multi_state |= s->chgx[i]; + if (s->chgx[i] != 0) { + lt->use_multi_state = 1; + } t = vzt_wr_dsvzt_splay(s->chgx[i], t); if(!vzt_wr_dsvzt_success) { @@ -1308,7 +1310,9 @@ for(i=0;ilen;i++) { t = s->prevx[i]->child; - lt->use_multi_state |= s->chgx[i]; + if (s->chgx[i] != 0) { + lt->use_multi_state = 1; + } t = vzt_wr_dsvzt_splay(s->chgx[i], t); if(!vzt_wr_dsvzt_success) { @@ -1859,6 +1863,17 @@ msk = (~0U << lt->timepos); msk_n = ~msk; + if(!lt->emitted) + { + vzt_wr_emitfacs(lt); + lt->emitted = 1; + + if(!lt->timeset) + { + vzt_wr_set_time(lt, 0); + } + } + for(j=0;jnumfacs;j++) { struct vzt_wr_symbol *s = lt->sorted_facs[j]; diff -Nru gtkwave-3.3.104/src/libghw.c gtkwave-3.3.104+really3.3.118/src/libghw.c --- gtkwave-3.3.104/src/libghw.c 1970-01-01 00:00:00.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/libghw.c 2023-12-31 21:11:05.000000000 +0000 @@ -0,0 +1,2241 @@ +/* GHDL Wavefile reader library. + Copyright (C) 2005 Tristan Gingold + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include +#include +#include +#include +#include + +#include "libghw.h" +#include "debug.h" + +/* Reopen H through decompressor DECOMP. */ + +static int +ghw_openz (struct ghw_handler *h, const char *decomp, const char *filename) +{ + int plen = strlen (decomp) + 1 + strlen (filename) + 1; + char *p = malloc (plen); + + snprintf (p, plen, "%s %s", decomp, filename); + fclose (h->stream); + h->stream = popen_san (p, "r"); + free (p); + + if (h->stream == NULL) + return -1; + + h->stream_ispipe = 1; + + return 0; +} + +int +ghw_open (struct ghw_handler *h, const char *filename) +{ + char hdr[16]; + + h->stream = fopen (filename, "rb"); + if (h->stream == NULL) + return -1; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + + /* Check compression layer. */ + if (!memcmp (hdr, "\x1f\x8b", 2)) + { + if (ghw_openz (h, "gzip -cd", filename) < 0) + return -1; + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + } + else if (!memcmp (hdr, "BZ", 2)) + { + if (ghw_openz (h, "bzip2 -cd", filename) < 0) + return -1; + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + } + else + { + h->stream_ispipe = 0; + } + + /* Check magic. */ + if (memcmp (hdr, "GHDLwave\n", 9) != 0) + return -2; + /* Check version. */ + if (hdr[9] != 16 || hdr[10] != 0) + return -2; + h->version = hdr[11]; + if (h->version > 1) + return -3; + if (hdr[12] == 1) + h->word_be = 0; + else if (hdr[12] == 2) + h->word_be = 1; + else + return -4; +#if 0 + /* Endianness. */ + { + int endian; + union + { + unsigned char b[4]; + uint32_t i; + } v; + v.i = 0x11223344; + if (v.b[0] == 0x11) + endian = 2; + else if (v.b[0] == 0x44) + endian = 1; + else + return -3; + + if (hdr[12] != 1 && hdr[12] != 2) + return -3; + if (hdr[12] != endian) + h->swap_word = 1; + else + h->swap_word = 0; + } +#endif + h->word_len = hdr[13]; + h->off_len = hdr[14]; + + if (hdr[15] != 0) + return -5; + + h->hie = NULL; + return 0; +} + +int32_t +ghw_get_i32 (struct ghw_handler *h, unsigned char *b) +{ + if (h->word_be) + return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0); + else + return (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0] << 0); +} + +int64_t +ghw_get_i64 (struct ghw_handler *ghw_h, unsigned char *b) +{ + int l, h; + + if (ghw_h->word_be) + { + h = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3] << 0); + l = (b[4] << 24) | (b[5] << 16) | (b[6] << 8) | (b[7] << 0); + } + else + { + l = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | (b[0] << 0); + h = (b[7] << 24) | (b[6] << 16) | (b[5] << 8) | (b[4] << 0); + } + return (((int64_t) h) << 32) | l; +} + +int +ghw_read_byte (struct ghw_handler *h, unsigned char *res) +{ + int v; + + v = fgetc (h->stream); + if (v == EOF) + return -1; + *res = v; + return 0; +} + +int +ghw_read_uleb128 (struct ghw_handler *h, uint32_t * res) +{ + uint32_t r = 0; + unsigned int off = 0; + + while (1) + { + int v = fgetc (h->stream); + if (v == EOF) + return -1; + r |= (v & 0x7f) << off; + if ((v & 0x80) == 0) + break; + off += 7; + } + *res = r; + return 0; +} + +int +ghw_read_sleb128 (struct ghw_handler *h, int32_t * res) +{ + int32_t r = 0; + unsigned int off = 0; + + while (1) + { + int v = fgetc (h->stream); + if (v == EOF) + return -1; + r |= ((int32_t) (v & 0x7f)) << off; + off += 7; + if ((v & 0x80) == 0) + { + if ((v & 0x40) && off < 32) + r |= ~0U << off; + break; + } + } + *res = r; + return 0; +} + +int +ghw_read_lsleb128 (struct ghw_handler *h, int64_t * res) +{ + static const int64_t r_mask = -1; + int64_t r = 0; + unsigned int off = 0; + + while (1) + { + int v = fgetc (h->stream); + if (v == EOF) + return -1; + r |= ((int64_t) (v & 0x7f)) << off; + off += 7; + if ((v & 0x80) == 0) + { + if ((v & 0x40) && off < 64) + r |= r_mask << off; + break; + } + } + *res = r; + return 0; +} + +int +ghw_read_f64 (struct ghw_handler *h, double *res) +{ + /* FIXME: handle byte order. */ + if (fread (res, sizeof (*res), 1, h->stream) != 1) + return -1; + return 0; +} + +const char * +ghw_read_strid (struct ghw_handler *h) +{ + uint32_t id; + + if (ghw_read_uleb128 (h, &id) != 0) + return NULL; + return h->str_table[id]; +} + +union ghw_type * +ghw_read_typeid (struct ghw_handler *h) +{ + uint32_t id; + + if (ghw_read_uleb128 (h, &id) != 0) + return NULL; + return h->types[id - 1]; +} + +union ghw_range * +ghw_read_range (struct ghw_handler *h) +{ + int t = fgetc (h->stream); + if (t == EOF) + return NULL; + switch (t & 0x7f) + { + case ghdl_rtik_type_b2: + { + struct ghw_range_b2 *r; + r = malloc (sizeof (struct ghw_range_b2)); + r->kind = t & 0x7f; + r->dir = (t & 0x80) != 0; + if (ghw_read_byte (h, &r->left) != 0) + goto err_b2; + if (ghw_read_byte (h, &r->right) != 0) + goto err_b2; + return (union ghw_range *) r; + err_b2: + free (r); + return NULL; + } + case ghdl_rtik_type_e8: + { + struct ghw_range_e8 *r; + r = malloc (sizeof (struct ghw_range_e8)); + r->kind = t & 0x7f; + r->dir = (t & 0x80) != 0; + if (ghw_read_byte (h, &r->left) != 0) + goto err_e8; + if (ghw_read_byte (h, &r->right) != 0) + goto err_e8; + return (union ghw_range *) r; + err_e8: + free (r); + return NULL; + } + case ghdl_rtik_type_i32: + case ghdl_rtik_type_p32: + { + struct ghw_range_i32 *r; + r = malloc (sizeof (struct ghw_range_i32)); + r->kind = t & 0x7f; + r->dir = (t & 0x80) != 0; + if (ghw_read_sleb128 (h, &r->left) != 0) + goto err_i32; + if (ghw_read_sleb128 (h, &r->right) != 0) + goto err_i32; + return (union ghw_range *) r; + err_i32: + free (r); + return NULL; + } + case ghdl_rtik_type_i64: + case ghdl_rtik_type_p64: + { + struct ghw_range_i64 *r; + r = malloc (sizeof (struct ghw_range_i64)); + r->kind = t & 0x7f; + r->dir = (t & 0x80) != 0; + if (ghw_read_lsleb128 (h, &r->left) != 0) + goto err_i64; + if (ghw_read_lsleb128 (h, &r->right) != 0) + goto err_i64; + return (union ghw_range *) r; + err_i64: + free (r); + return NULL; + } + case ghdl_rtik_type_f64: + { + struct ghw_range_f64 *r; + r = malloc (sizeof (struct ghw_range_f64)); + r->kind = t & 0x7f; + r->dir = (t & 0x80) != 0; + if (ghw_read_f64 (h, &r->left) != 0) + goto err_f64; + if (ghw_read_f64 (h, &r->right) != 0) + goto err_f64; + return (union ghw_range *) r; + err_f64: + free (r); + return NULL; + } + default: + fprintf (stderr, "ghw_read_range: type %d unhandled\n", t & 0x7f); + return NULL; + } +} + +int +ghw_read_str (struct ghw_handler *h) +{ + unsigned char hdr[12]; + unsigned i; + char *p; + int prev_len; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + + if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) + return -1; + h->nbr_str = ghw_get_i32 (h, &hdr[4]); + h->nbr_str++; + h->str_size = ghw_get_i32 (h, &hdr[8]); + h->str_table = (char **) malloc ((h->nbr_str + 1) * sizeof (char *)); + h->str_content = (char *) malloc (h->str_size + h->nbr_str + 1); + + if (h->flag_verbose) + { + printf ("Number of strings: %u\n", h->nbr_str - 1); + printf ("String table size: %u\n", h->str_size); + } + + h->str_table[0] = ""; + p = h->str_content; + prev_len = 0; + for (i = 1; i < h->nbr_str; i++) + { + int j; + int c; + char *prev; + int sh; + + h->str_table[i] = p; + prev = h->str_table[i - 1]; + for (j = 0; j < prev_len; j++) + *p++ = prev[j]; + + while (1) + { + c = fgetc (h->stream); + if (c == EOF) + return -1; + if ((c >= 0 && c <= 31) || (c >= 128 && c <= 159)) + break; + *p++ = c; + } + *p++ = 0; + + if (h->flag_verbose > 1) + printf (" string %u (pl=%d): %s\n", i, prev_len, h->str_table[i]); + + prev_len = c & 0x1f; + sh = 5; + while (c >= 128) + { + c = fgetc (h->stream); + if (c == EOF) + return -1; + prev_len |= (c & 0x1f) << sh; + sh += 5; + } + } + if (fread (hdr, 4, 1, h->stream) != 1) + return -1; + if (memcmp (hdr, "EOS", 4) != 0) + return -1; + return 0; +} + +union ghw_type * +ghw_get_base_type (union ghw_type *t) +{ + switch (t->kind) + { + case ghdl_rtik_type_b2: + case ghdl_rtik_type_e8: + case ghdl_rtik_type_e32: + case ghdl_rtik_type_i32: + case ghdl_rtik_type_i64: + case ghdl_rtik_type_f64: + case ghdl_rtik_type_p32: + case ghdl_rtik_type_p64: + case ghdl_rtik_type_array: + return t; + case ghdl_rtik_subtype_scalar: + return t->ss.base; + case ghdl_rtik_subtype_array: + return t->sa.base; + case ghdl_rtik_subtype_unbounded_array: + return t->sua.base; + default: + fprintf (stderr, "ghw_get_base_type: cannot handle type %d\n", t->kind); + abort (); + } +} + +/* Return -1 for unbounded types. */ +static int +get_nbr_elements (union ghw_type *t) +{ + switch (t->kind) + { + case ghdl_rtik_type_b2: + case ghdl_rtik_type_e8: + case ghdl_rtik_type_e32: + case ghdl_rtik_type_i32: + case ghdl_rtik_type_i64: + case ghdl_rtik_type_f64: + case ghdl_rtik_type_p32: + case ghdl_rtik_type_p64: + case ghdl_rtik_subtype_scalar: + return 1; + case ghdl_rtik_type_array: + return -1; + case ghdl_rtik_subtype_array: + return t->sa.nbr_scalars; + case ghdl_rtik_type_record: + return t->rec.nbr_scalars; + case ghdl_rtik_subtype_record: + return t->sr.nbr_scalars; + case ghdl_rtik_subtype_unbounded_record: + case ghdl_rtik_subtype_unbounded_array: + return -1; + default: + fprintf (stderr, "get_nbr_elements: unhandled type %d\n", t->kind); + abort (); + } +} + +int +ghw_get_range_length (union ghw_range *rng) +{ + int res; + + assert (rng != NULL); + + switch (rng->kind) + { + case ghdl_rtik_type_i32: + if (rng->i32.dir) + res = rng->i32.left - rng->i32.right + 1; + else + res = rng->i32.right - rng->i32.left + 1; + break; + case ghdl_rtik_type_b2: + if (rng->b2.dir) + res = rng->b2.left - rng->b2.right + 1; + else + res = rng->b2.right - rng->b2.left + 1; + break; + case ghdl_rtik_type_e8: + if (rng->e8.dir) + res = rng->e8.left - rng->e8.right + 1; + else + res = rng->e8.right - rng->e8.left + 1; + break; + default: + fprintf (stderr, "get_range_length: unhandled kind %d\n", rng->kind); + abort (); + } + /* The length of a null range is 0. */ + return (res <= 0) ? 0 : res; +} + +static union ghw_type *ghw_read_type_bounds (struct ghw_handler *h, + union ghw_type *base); + +/* Create an array subtype using BASE and ranges read from H. */ + +struct ghw_subtype_array * +ghw_read_array_subtype (struct ghw_handler *h, union ghw_type *base) +{ + struct ghw_type_array *arr = + (struct ghw_type_array *) ghw_get_base_type (base); + struct ghw_subtype_array *sa; + unsigned j; + int nbr_scalars; + int nbr_els; + + sa = malloc (sizeof (struct ghw_subtype_array)); + sa->kind = ghdl_rtik_subtype_array; + sa->name = NULL; + sa->base = base; + nbr_els = get_nbr_elements (arr->el); + nbr_scalars = 1; + sa->rngs = malloc (arr->nbr_dim * sizeof (union ghw_range *)); + for (j = 0; j < arr->nbr_dim; j++) + { + sa->rngs[j] = ghw_read_range (h); + nbr_scalars *= ghw_get_range_length (sa->rngs[j]); + } + if (nbr_els >= 0) + { + /* Element type is bounded. */ + sa->el = arr->el; + } + else + { + /* Read bounds for the elements. */ + sa->el = ghw_read_type_bounds (h, arr->el); + nbr_els = get_nbr_elements (sa->el); + } + sa->nbr_scalars = nbr_scalars * nbr_els; + return sa; +} + +struct ghw_subtype_record * +ghw_read_record_subtype (struct ghw_handler *h, struct ghw_type_record *base) +{ + struct ghw_subtype_record *sr; + + sr = malloc (sizeof (struct ghw_subtype_record)); + sr->kind = ghdl_rtik_subtype_record; + sr->name = NULL; + sr->base = base; + if (base->nbr_scalars >= 0) + { + /* Record base type is bounded. */ + sr->nbr_scalars = base->nbr_scalars; + sr->els = base->els; + } + else + { + /* Read subtypes. */ + unsigned j; + int nbr_scalars; + + sr->els = + malloc (base->nbr_fields * sizeof (struct ghw_record_element)); + nbr_scalars = 0; + for (j = 0; j < base->nbr_fields; j++) + { + union ghw_type *btype = base->els[j].type; + int el_nbr_scalars = get_nbr_elements (btype); + + sr->els[j].name = base->els[j].name; + if (el_nbr_scalars >= 0) + { + /* Element is constrained. */ + sr->els[j].type = btype; + } + else + { + sr->els[j].type = ghw_read_type_bounds (h, btype); + el_nbr_scalars = get_nbr_elements (sr->els[j].type); + } + nbr_scalars += el_nbr_scalars; + } + sr->nbr_scalars = nbr_scalars; + } + return sr; +} + +/* Read bounds for BASE and create a subtype. */ + +static union ghw_type * +ghw_read_type_bounds (struct ghw_handler *h, union ghw_type *base) +{ + switch (base->kind) + { + case ghdl_rtik_type_array: + case ghdl_rtik_subtype_unbounded_array: + return (union ghw_type *) ghw_read_array_subtype (h, base); + break; + case ghdl_rtik_type_record: + case ghdl_rtik_subtype_unbounded_record: + return (union ghw_type *) ghw_read_record_subtype (h, &base->rec); + break; + default: + fprintf (stderr, "ghw_read_type_bounds: unhandled kind %d\n", + base->kind); + return NULL; + } +} + +int +ghw_read_type (struct ghw_handler *h) +{ + unsigned char hdr[8]; + unsigned i; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + + if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) + return -1; + h->nbr_types = ghw_get_i32 (h, &hdr[4]); + h->types = + (union ghw_type **) malloc (h->nbr_types * sizeof (union ghw_type *)); + + for (i = 0; i < h->nbr_types; i++) + { + int t; + + t = fgetc (h->stream); + if (t == EOF) + return -1; + if (h->flag_verbose > 1) + printf ("type[%d]= %d\n", i, t); + switch (t) + { + case ghdl_rtik_type_b2: + case ghdl_rtik_type_e8: + { + struct ghw_type_enum *e; + unsigned j; + + e = malloc (sizeof (struct ghw_type_enum)); + e->kind = t; + e->wkt = ghw_wkt_unknown; + e->name = ghw_read_strid (h); + if (ghw_read_uleb128 (h, &e->nbr) != 0) + goto err_b2; + e->lits = (const char **) malloc (e->nbr * sizeof (char *)); + if (h->flag_verbose > 1) + printf ("enum %s:", e->name); + for (j = 0; j < e->nbr; j++) + { + e->lits[j] = ghw_read_strid (h); + if (h->flag_verbose > 1) + printf (" %s", e->lits[j]); + } + if (h->flag_verbose > 1) + printf ("\n"); + h->types[i] = (union ghw_type *) e; + break; + err_b2: + free (e); + return -1; + } + break; + case ghdl_rtik_type_i32: + case ghdl_rtik_type_i64: + case ghdl_rtik_type_f64: + { + struct ghw_type_scalar *sc; + + sc = malloc (sizeof (struct ghw_type_scalar)); + sc->kind = t; + sc->name = ghw_read_strid (h); + if (h->flag_verbose > 1) + printf ("scalar: %s\n", sc->name); + h->types[i] = (union ghw_type *) sc; + } break; + case ghdl_rtik_type_p32: + case ghdl_rtik_type_p64: + { + struct ghw_type_physical *ph; + + ph = malloc (sizeof (struct ghw_type_physical)); + ph->kind = t; + ph->name = ghw_read_strid (h); + ph->units = NULL; + if (h->version == 0) + ph->nbr_units = 0; + else + { + unsigned j; + + if (ghw_read_uleb128 (h, &ph->nbr_units) != 0) + goto err_p32; + ph->units = malloc (ph->nbr_units * sizeof (struct ghw_unit)); + for (j = 0; j < ph->nbr_units; j++) + { + ph->units[j].name = ghw_read_strid (h); + if (ghw_read_lsleb128 (h, &ph->units[j].val) < 0) + goto err_p32; + } + } + if (h->flag_verbose > 1) + printf ("physical: %s\n", ph->name); + h->types[i] = (union ghw_type *) ph; + break; + err_p32: + free (ph->units); + free (ph); + return -1; + } + break; + case ghdl_rtik_subtype_scalar: + { + struct ghw_subtype_scalar *ss; + + ss = malloc (sizeof (struct ghw_subtype_scalar)); + ss->kind = t; + ss->name = ghw_read_strid (h); + ss->base = ghw_read_typeid (h); + ss->rng = ghw_read_range (h); + if (h->flag_verbose > 1) + printf ("subtype scalar: %s\n", ss->name); + h->types[i] = (union ghw_type *) ss; + } break; + case ghdl_rtik_type_array: + { + struct ghw_type_array *arr; + unsigned j; + + arr = malloc (sizeof (struct ghw_type_array)); + arr->kind = t; + arr->name = ghw_read_strid (h); + arr->el = ghw_read_typeid (h); + if (ghw_read_uleb128 (h, &arr->nbr_dim) != 0) + goto err_array; + arr->dims = + (union ghw_type **) malloc (arr->nbr_dim * + sizeof (union ghw_type *)); + for (j = 0; j < arr->nbr_dim; j++) + arr->dims[j] = ghw_read_typeid (h); + if (h->flag_verbose > 1) + printf ("array: %s (ndim=%u) of %s\n", arr->name, arr->nbr_dim, + arr->el->common.name); + h->types[i] = (union ghw_type *) arr; + break; + err_array: + free (arr); + return -1; + } + break; + case ghdl_rtik_subtype_array: + { + struct ghw_subtype_array *sa; + const char *name; + union ghw_type *base; + + name = ghw_read_strid (h); + base = ghw_read_typeid (h); + + sa = ghw_read_array_subtype (h, base); + sa->name = name; + h->types[i] = (union ghw_type *) sa; + if (h->flag_verbose > 1) + printf ("subtype array: %s (nbr_scalars=%d)\n", sa->name, + sa->nbr_scalars); + } + break; + case ghdl_rtik_subtype_unbounded_array: + { + struct ghw_subtype_unbounded_array *sua; + + sua = malloc (sizeof (struct ghw_subtype_unbounded_array)); + sua->kind = t; + sua->name = ghw_read_strid (h); + sua->base = ghw_read_typeid (h); + h->types[i] = (union ghw_type *) sua; + if (h->flag_verbose > 1) + printf ("subtype unbounded array: %s\n", sua->name); + } + break; + case ghdl_rtik_type_record: + { + struct ghw_type_record *rec; + unsigned j; + int nbr_scalars; + + rec = malloc (sizeof (struct ghw_type_record)); + rec->kind = t; + rec->name = ghw_read_strid (h); + rec->els = NULL; + if (ghw_read_uleb128 (h, &rec->nbr_fields) != 0) + goto err_record; + rec->els = + malloc (rec->nbr_fields * sizeof (struct ghw_record_element)); + nbr_scalars = 0; + for (j = 0; j < rec->nbr_fields; j++) + { + rec->els[j].name = ghw_read_strid (h); + rec->els[j].type = ghw_read_typeid (h); + if (nbr_scalars != -1) + { + int field_nbr_scalars = + get_nbr_elements (rec->els[j].type); + if (field_nbr_scalars == -1) + nbr_scalars = -1; + else + nbr_scalars += field_nbr_scalars; + } + } + rec->nbr_scalars = nbr_scalars; + if (h->flag_verbose > 1) + printf ("record type: %s (nbr_scalars=%d)\n", rec->name, + rec->nbr_scalars); + h->types[i] = (union ghw_type *) rec; + break; + err_record: + free (rec->els); + free (rec); + return -1; + } + break; + case ghdl_rtik_subtype_record: + { + struct ghw_subtype_record *sr; + const char *name; + struct ghw_type_record *base; + + name = ghw_read_strid (h); + base = (struct ghw_type_record *) ghw_read_typeid (h); + + sr = ghw_read_record_subtype (h, base); + sr->name = name; + h->types[i] = (union ghw_type *) sr; + if (h->flag_verbose > 1) + printf ("subtype record: %s (nbr_scalars=%d)\n", sr->name, + sr->nbr_scalars); + } + break; + case ghdl_rtik_subtype_unbounded_record: + { + struct ghw_subtype_unbounded_record *sur; + + sur = malloc (sizeof (struct ghw_subtype_unbounded_record)); + sur->kind = t; + sur->name = ghw_read_strid (h); + sur->base = (struct ghw_type_record *) ghw_read_typeid (h); + h->types[i] = (union ghw_type *) sur; + if (h->flag_verbose > 1) + printf ("subtype unbounded record: %s\n", sur->name); + } + break; + default: + fprintf (stderr, "ghw_read_type: unknown type %d\n", t); + return -1; + } + } + if (fgetc (h->stream) != 0) + return -1; + return 0; +} + +int +ghw_read_wk_types (struct ghw_handler *h) +{ + char hdr[4]; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + + if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) + return -1; + + while (1) + { + int t; + union ghw_type *tid; + + t = fgetc (h->stream); + if (t == EOF) + return -1; + else if (t == 0) + break; + + tid = ghw_read_typeid (h); + if (tid->kind == ghdl_rtik_type_b2 || tid->kind == ghdl_rtik_type_e8) + { + if (h->flag_verbose > 0) + printf ("%s: wkt=%d\n", tid->en.name, t); + tid->en.wkt = t; + } + } + return 0; +} + +void +ghw_disp_typename (struct ghw_handler *h, union ghw_type *t) +{ + (void) h; + printf ("%s", t->common.name); +} + +/* Read a signal composed of severals elements. + Return 0 for success. */ +int +ghw_read_signal (struct ghw_handler *h, unsigned int *sigs, union ghw_type *t) +{ + switch (t->kind) + { + case ghdl_rtik_type_b2: + case ghdl_rtik_type_e8: + case ghdl_rtik_type_e32: + case ghdl_rtik_subtype_scalar: + { + unsigned int sig_el; + + if (ghw_read_uleb128 (h, &sig_el) < 0) + return -1; + *sigs = sig_el; + if (sig_el == 0 || sig_el >= h->nbr_sigs) + return -1; + if (h->sigs[sig_el].type == NULL) + h->sigs[sig_el].type = ghw_get_base_type (t); + } + return 0; + case ghdl_rtik_subtype_array: + { + int i; + int stride; + int len; + + len = t->sa.nbr_scalars; + stride = get_nbr_elements (t->sa.el); + + for (i = 0; i < len; i += stride) + if (ghw_read_signal (h, &sigs[i], t->sa.el) < 0) + return -1; + } + return 0; + case ghdl_rtik_type_record: + { + struct ghw_type_record *r = &t->rec; + int nbr_fields = r->nbr_fields; + int i; + int off; + + off = 0; + for (i = 0; i < nbr_fields; i++) + { + if (ghw_read_signal (h, &sigs[off], r->els[i].type) < 0) + return -1; + off += get_nbr_elements (r->els[i].type); + } + } + return 0; + case ghdl_rtik_subtype_record: + { + struct ghw_subtype_record *sr = &t->sr; + int nbr_fields = sr->base->nbr_fields; + int i; + int off; + + off = 0; + for (i = 0; i < nbr_fields; i++) + { + if (ghw_read_signal (h, &sigs[off], sr->els[i].type) < 0) + return -1; + off += get_nbr_elements (sr->els[i].type); + } + } + return 0; + default: + fprintf (stderr, "ghw_read_signal: type kind %d unhandled\n", t->kind); + abort (); + } +} + +int +ghw_read_value (struct ghw_handler *h, union ghw_val *val, + union ghw_type *type) +{ + switch (ghw_get_base_type (type)->kind) + { + case ghdl_rtik_type_b2: + { + int v; + v = fgetc (h->stream); + if (v == EOF) + return -1; + val->b2 = v; + } + break; + case ghdl_rtik_type_e8: + { + int v; + v = fgetc (h->stream); + if (v == EOF) + return -1; + val->e8 = v; + } + break; + case ghdl_rtik_type_i32: + case ghdl_rtik_type_p32: + { + int32_t v; + if (ghw_read_sleb128 (h, &v) < 0) + return -1; + val->i32 = v; + } + break; + case ghdl_rtik_type_f64: + { + double v; + if (ghw_read_f64 (h, &v) < 0) + return -1; + val->f64 = v; + } + break; + case ghdl_rtik_type_p64: + { + int64_t v; + if (ghw_read_lsleb128 (h, &v) < 0) + return -1; + val->i64 = v; + } + break; + default: + fprintf (stderr, "read_value: cannot handle format %d\n", type->kind); + abort (); + } + return 0; +} + +int +ghw_read_hie (struct ghw_handler *h) +{ + unsigned char hdr[16]; + int nbr_scopes; + int nbr_sigs; + unsigned i; + struct ghw_hie *blk; + struct ghw_hie **last; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + + if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) + return -1; + nbr_scopes = ghw_get_i32 (h, &hdr[4]); + /* Number of declared signals (which may be composite). */ + nbr_sigs = ghw_get_i32 (h, &hdr[8]); + /* Number of basic signals. */ + h->nbr_sigs = ghw_get_i32 (h, &hdr[12]); + + if (h->flag_verbose) + printf ("%u scopes, %u signals, %u signal elements\n", nbr_scopes, + nbr_sigs, h->nbr_sigs); + + blk = (struct ghw_hie *) malloc (sizeof (struct ghw_hie)); + blk->kind = ghw_hie_design; + blk->name = NULL; + blk->parent = NULL; + blk->brother = NULL; + blk->u.blk.child = NULL; + + last = &blk->u.blk.child; + h->hie = blk; + + h->nbr_sigs++; + h->skip_sigs = NULL; + h->flag_full_names = 0; + h->sigs = (struct ghw_sig *) malloc (h->nbr_sigs * sizeof (struct ghw_sig)); + memset (h->sigs, 0, h->nbr_sigs * sizeof (struct ghw_sig)); + + while (1) + { + int t; + struct ghw_hie *el; + unsigned int str; + + t = fgetc (h->stream); + if (t == EOF) + return -1; + if (t == 0) + break; + + if (t == ghw_hie_eos) + { + blk = blk->parent; + if (blk->u.blk.child == NULL) + last = &blk->u.blk.child; + else + { + struct ghw_hie *l = blk->u.blk.child; + while (l->brother != NULL) + l = l->brother; + last = &l->brother; + } + + continue; + } + + el = (struct ghw_hie *) malloc (sizeof (struct ghw_hie)); + el->kind = t; + el->parent = blk; + el->brother = NULL; + + /* Link. */ + *last = el; + last = &el->brother; + + /* Read name. */ + if (ghw_read_uleb128 (h, &str) != 0) + return -1; + el->name = h->str_table[str]; + + switch (t) + { + case ghw_hie_eoh: + case ghw_hie_design: + case ghw_hie_eos: + /* Should not be here. */ + abort (); + case ghw_hie_process: + el->u.blk.child = NULL; + break; + case ghw_hie_block: + case ghw_hie_generate_if: + case ghw_hie_generate_for: + case ghw_hie_instance: + case ghw_hie_generic: + case ghw_hie_package: + /* Create a block. */ + el->u.blk.child = NULL; + + if (t == ghw_hie_generate_for) + { + el->u.blk.iter_type = ghw_read_typeid (h); + el->u.blk.iter_value = malloc (sizeof (union ghw_val)); + if (ghw_read_value + (h, el->u.blk.iter_value, el->u.blk.iter_type) < 0) + return -1; + } + blk = el; + last = &el->u.blk.child; + break; + case ghw_hie_signal: + case ghw_hie_port_in: + case ghw_hie_port_out: + case ghw_hie_port_inout: + case ghw_hie_port_buffer: + case ghw_hie_port_linkage: + /* For a signal, read type. */ + { + int nbr_el; + unsigned int *sigs; + + el->u.sig.type = ghw_read_typeid (h); + nbr_el = get_nbr_elements (el->u.sig.type); + if (nbr_el < 0) + return -1; + sigs = + (unsigned int *) malloc ((nbr_el + 1) * sizeof (unsigned int)); + el->u.sig.sigs = sigs; + /* Last element is NULL. */ + sigs[nbr_el] = 0; + + if (h->flag_verbose > 1) + printf ("signal %s: %d el [", el->name, nbr_el); + if (ghw_read_signal (h, sigs, el->u.sig.type) < 0) + return -1; + if (h->flag_verbose > 1) + { + int j; + for (j = 0; j < nbr_el; j++) + printf (" #%u", sigs[j]); + printf ("]\n"); + } + } + break; + default: + fprintf (stderr, "ghw_read_hie: unhandled kind %d\n", t); + abort (); + } + } + + /* Allocate values. */ + for (i = 0; i < h->nbr_sigs; i++) + if (h->sigs[i].type != NULL) + h->sigs[i].val = (union ghw_val *) malloc (sizeof (union ghw_val)); + return 0; +} + +const char * +ghw_get_hie_name (struct ghw_hie *h) +{ + switch (h->kind) + { + case ghw_hie_eoh: + return "eoh"; + case ghw_hie_design: + return "design"; + case ghw_hie_block: + return "block"; + case ghw_hie_generate_if: + return "generate-if"; + case ghw_hie_generate_for: + return "generate-for"; + case ghw_hie_instance: + return "instance"; + case ghw_hie_package: + return "package"; + case ghw_hie_process: + return "process"; + case ghw_hie_generic: + return "generic"; + case ghw_hie_eos: + return "eos"; + case ghw_hie_signal: + return "signal"; + case ghw_hie_port_in: + return "port-in"; + case ghw_hie_port_out: + return "port-out"; + case ghw_hie_port_inout: + return "port-inout"; + case ghw_hie_port_buffer: + return "port-buffer"; + case ghw_hie_port_linkage: + return "port-linkage"; + default: + return "??"; + } +} + +void ghw_disp_value (union ghw_val *val, union ghw_type *type); + +static void +print_name (struct ghw_hie *hie, int full_names) +{ + int i; + int depth; + struct ghw_hie *p; + struct ghw_hie **buf; + struct ghw_hie **end; + + /* HIE must be valid. */ + assert (hie->name != NULL); + + if (0 == full_names) + { + printf (" %s: ", hie->name); + return; + } + + p = hie; + depth = 0; + while (p && p->name) + { + p = p->parent; + ++depth; + } + buf = (struct ghw_hie **) malloc (depth * sizeof (struct ghw_hie *)); + + p = hie; + end = depth + buf; + while (p && p->name) + { + *(--end) = p; + p = p->parent; + } + + putchar (' '); + putchar ('/'); + for (i = 0; i < depth; ++i) + { + printf ("%s%s", i ? "/" : "", buf[i]->name); + if (ghw_hie_generate_for == buf[i]->kind) + { + putchar ('('); + ghw_disp_value (buf[i]->u.blk.iter_value, buf[i]->u.blk.iter_type); + putchar (')'); + } + } + putchar (':'); + putchar (' '); + free (buf); +} + +void +ghw_disp_hie (struct ghw_handler *h, struct ghw_hie *top) +{ + int i; + int indent; + struct ghw_hie *hie; + struct ghw_hie *n; + + hie = top; + indent = 0; + + while (1) + { + if (0 == h->flag_full_names) + for (i = 0; i < indent; i++) + fputc (' ', stdout); + printf ("%s", ghw_get_hie_name (hie)); + + switch (hie->kind) + { + case ghw_hie_design: + case ghw_hie_block: + case ghw_hie_generate_if: + case ghw_hie_generate_for: + case ghw_hie_instance: + case ghw_hie_process: + case ghw_hie_package: + if (hie->name) + print_name (hie, h->flag_full_names); + if (hie->kind == ghw_hie_generate_for) + { + printf ("("); + ghw_disp_value (hie->u.blk.iter_value, hie->u.blk.iter_type); + printf (")"); + } + n = hie->u.blk.child; + if (n == NULL) + n = hie->brother; + else + indent++; + break; + case ghw_hie_generic: + case ghw_hie_eos: + abort (); + case ghw_hie_signal: + case ghw_hie_port_in: + case ghw_hie_port_out: + case ghw_hie_port_inout: + case ghw_hie_port_buffer: + case ghw_hie_port_linkage: + { + unsigned int *sigs = hie->u.sig.sigs; + unsigned int k, num; + + print_name (hie, h->flag_full_names); + ghw_disp_subtype_indication (h, hie->u.sig.type); + printf (":"); + k = 0; + /* There can be 0-length signals. */ + while (sigs[k] != GHW_NO_SIG) + { + /* First signal of the range. */ + printf (" #%u", sigs[k]); + for (num = 1; sigs[k + num] != GHW_NO_SIG; num++) + if (sigs[k + num] != sigs[k + num - 1] + 1) + break; + if (num > 1) + printf ("-#%u", sigs[k + num - 1]); + k += num; + } + n = hie->brother; + } + break; + default: + abort (); + } + printf ("\n"); + + while (n == NULL) + { + if (hie->parent == NULL) + return; + hie = hie->parent; + indent--; + n = hie->brother; + } + hie = n; + } +} + +int +ghw_read_eoh (struct ghw_handler *h) +{ + (void) h; + return 0; +} + +int +ghw_read_base (struct ghw_handler *h) +{ + unsigned char hdr[4]; + int res; + + while (1) + { + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + if (memcmp (hdr, "STR", 4) == 0) + res = ghw_read_str (h); + else if (memcmp (hdr, "HIE", 4) == 0) + res = ghw_read_hie (h); + else if (memcmp (hdr, "TYP", 4) == 0) + res = ghw_read_type (h); + else if (memcmp (hdr, "WKT", 4) == 0) + res = ghw_read_wk_types (h); + else if (memcmp (hdr, "EOH", 4) == 0) + return 0; + else + { + fprintf (stderr, "ghw_read_base: unknown GHW section %c%c%c%c\n", + hdr[0], hdr[1], hdr[2], hdr[3]); + return -1; + } + if (res != 0) + { + fprintf (stderr, "ghw_read_base: error in section %s\n", hdr); + return res; + } + } +} + +int +ghw_read_signal_value (struct ghw_handler *h, struct ghw_sig *s) +{ + return ghw_read_value (h, s->val, s->type); +} + +int +ghw_read_snapshot (struct ghw_handler *h) +{ + unsigned char hdr[12]; + unsigned i; + struct ghw_sig *s; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + + if (hdr[0] != 0 || hdr[1] != 0 || hdr[2] != 0 || hdr[3] != 0) + return -1; + h->snap_time = ghw_get_i64 (h, &hdr[4]); + if (h->flag_verbose > 1) + printf ("Time is " GHWPRI64 " fs\n", h->snap_time); + + for (i = 0; i < h->nbr_sigs; i++) + { + s = &h->sigs[i]; + if (s->type != NULL) + { + if (h->flag_verbose > 1) + printf ("read type %d for sig %u\n", s->type->kind, i); + if (ghw_read_signal_value (h, s) < 0) + return -1; + } + } + if (fread (hdr, 4, 1, h->stream) != 1) + return -1; + + if (memcmp (hdr, "ESN", 4)) + return -1; + + return 0; +} + +void ghw_disp_values (struct ghw_handler *h); + +int +ghw_read_cycle_start (struct ghw_handler *h) +{ + unsigned char hdr[8]; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + + h->snap_time = ghw_get_i64 (h, hdr); + return 0; +} + +int +ghw_read_cycle_cont (struct ghw_handler *h, int *list) +{ + int i; + int *list_p; + + i = 0; + list_p = list; + while (1) + { + uint32_t d; + + /* Read delta to next signal. */ + if (ghw_read_uleb128 (h, &d) < 0) + return -1; + if (d == 0) + { + /* Last signal reached. */ + break; + } + + /* Find next signal. */ + while (d > 0) + { + i++; + if (h->sigs[i].type != NULL) + d--; + } + + if (ghw_read_signal_value (h, &h->sigs[i]) < 0) + return -1; + if (list_p) + *list_p++ = i; + } + + if (list_p) + *list_p = 0; + return 0; +} + +int +ghw_read_cycle_next (struct ghw_handler *h) +{ + int64_t d_time; + + if (ghw_read_lsleb128 (h, &d_time) < 0) + return -1; + if (d_time == -1) + return 0; + h->snap_time += d_time; + return 1; +} + +int +ghw_read_cycle_end (struct ghw_handler *h) +{ + char hdr[4]; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + if (memcmp (hdr, "ECY", 4)) + return -1; + + return 0; +} + +static const char * +ghw_get_lit (union ghw_type *type, unsigned e) +{ + if (e >= type->en.nbr) + return "??"; + else + return type->en.lits[e]; +} + +static void +ghw_disp_lit (union ghw_type *type, unsigned e) +{ + printf ("%s (%u)", ghw_get_lit (type, e), e); +} + +void +ghw_disp_value (union ghw_val *val, union ghw_type *type) +{ + switch (ghw_get_base_type (type)->kind) + { + case ghdl_rtik_type_b2: + ghw_disp_lit (type, val->b2); + break; + case ghdl_rtik_type_e8: + ghw_disp_lit (type, val->e8); + break; + case ghdl_rtik_type_i32: + printf (GHWPRI32, val->i32); + break; + case ghdl_rtik_type_p64: + printf (GHWPRI64, val->i64); + break; + case ghdl_rtik_type_f64: + printf ("%g", val->f64); + break; + default: + fprintf (stderr, "ghw_disp_value: cannot handle type %d\n", type->kind); + abort (); + } +} + +/* Put the ASCII representation of VAL into BUF, whose size if LEN. + A NUL is always written to BUF. +*/ +void +ghw_get_value (char *buf, int len, union ghw_val *val, union ghw_type *type) +{ + union ghw_type *base = ghw_get_base_type (type); + + switch (base->kind) + { + case ghdl_rtik_type_b2: + if (val->b2 <= 1) + { + strncpy (buf, base->en.lits[val->b2], len - 1); + buf[len - 1] = 0; + } + else + { + snprintf (buf, len, "?%d", val->b2); + } + break; + case ghdl_rtik_type_e8: + if (val->b2 <= base->en.nbr) + { + strncpy (buf, base->en.lits[val->e8], len - 1); + buf[len - 1] = 0; + } + else + { + snprintf (buf, len, "?%d", val->e8); + } + break; + case ghdl_rtik_type_i32: + snprintf (buf, len, GHWPRI32, val->i32); + break; + case ghdl_rtik_type_p64: + snprintf (buf, len, GHWPRI64, val->i64); + break; + case ghdl_rtik_type_f64: + snprintf (buf, len, "%g", val->f64); + break; + default: + snprintf (buf, len, "?bad type %d?", type->kind); + } +} + +static char +is_skip_signal (int *signals_to_keep, int nb_signals_to_keep, int signal) +{ + int i; + for (i = 0; i < nb_signals_to_keep; ++i) + { + if (signal == signals_to_keep[i]) + { + return 0; + } + } + return 1; +} + +void +ghw_filter_signals (struct ghw_handler *h, int *signals_to_keep, + int nb_signals_to_keep) +{ + unsigned i; + + if (0 < nb_signals_to_keep && 0 != signals_to_keep) + { + if (0 == h->skip_sigs) + { + h->skip_sigs = (char *) malloc (sizeof (char) * h->nbr_sigs); + } + for (i = 0; i < h->nbr_sigs; ++i) + { + h->skip_sigs[i] = + is_skip_signal (signals_to_keep, nb_signals_to_keep, i); + } + } + else + { + if (0 != h->skip_sigs) + { + free (h->skip_sigs); + h->skip_sigs = 0; + } + } +} + +void +ghw_disp_values (struct ghw_handler *h) +{ + unsigned i; + for (i = 0; i < h->nbr_sigs; i++) + { + struct ghw_sig *s = &h->sigs[i]; + int skip = (0 != h->skip_sigs && (0 != h->skip_sigs[i])); + if (s->type != NULL && !skip) + { + printf ("#%u: ", i); + ghw_disp_value (s->val, s->type); + printf ("\n"); + } + } +} + +int +ghw_read_directory (struct ghw_handler *h) +{ + unsigned char hdr[8]; + int nbr_entries; + int i; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + + nbr_entries = ghw_get_i32 (h, &hdr[4]); + + if (h->flag_verbose) + printf ("Directory (%d entries):\n", nbr_entries); + + for (i = 0; i < nbr_entries; i++) + { + unsigned char ent[8]; + int pos; + + if (fread (ent, sizeof (ent), 1, h->stream) != 1) + return -1; + + pos = ghw_get_i32 (h, &ent[4]); + if (h->flag_verbose) + printf (" %s at %d\n", ent, pos); + } + + if (fread (hdr, 4, 1, h->stream) != 1) + return -1; + if (memcmp (hdr, "EOD", 4)) + return -1; + return 0; +} + +int +ghw_read_tailer (struct ghw_handler *h) +{ + unsigned char hdr[8]; + int pos; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + return -1; + + pos = ghw_get_i32 (h, &hdr[4]); + + if (h->flag_verbose) + printf ("Tailer: directory at %d\n", pos); + return 0; +} + +enum ghw_res +ghw_read_sm_hdr (struct ghw_handler *h, int *list) +{ + unsigned char hdr[4]; + int res; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + { + if (feof (h->stream)) + return ghw_res_eof; + else + return ghw_res_error; + } + if (memcmp (hdr, "SNP", 4) == 0) + { + res = ghw_read_snapshot (h); + if (res < 0) + return res; + return ghw_res_snapshot; + } + else if (memcmp (hdr, "CYC", 4) == 0) + { + res = ghw_read_cycle_start (h); + if (res < 0) + return res; + res = ghw_read_cycle_cont (h, list); + if (res < 0) + return res; + + return ghw_res_cycle; + } + else if (memcmp (hdr, "DIR", 4) == 0) + { + res = ghw_read_directory (h); + } + else if (memcmp (hdr, "TAI", 4) == 0) + { + res = ghw_read_tailer (h); + } + else + { + fprintf (stderr, "unknown GHW section %c%c%c%c\n", hdr[0], hdr[1], + hdr[2], hdr[3]); + return -1; + } + if (res != 0) + return res; + return ghw_res_other; +} + +int +ghw_read_sm (struct ghw_handler *h, enum ghw_sm_type *sm) +{ + int res; + + while (1) + { + /* printf ("sm: state = %d\n", *sm); */ + switch (*sm) + { + case ghw_sm_init: + case ghw_sm_sect: + res = ghw_read_sm_hdr (h, NULL); + switch (res) + { + case ghw_res_other: + break; + case ghw_res_snapshot: + *sm = ghw_sm_sect; + return res; + case ghw_res_cycle: + *sm = ghw_sm_cycle; + return res; + default: + return res; + } + break; + case ghw_sm_cycle: + if (0) + printf ("Time is " GHWPRI64 " fs\n", h->snap_time); + if (0) + ghw_disp_values (h); + + res = ghw_read_cycle_next (h); + if (res < 0) + return res; + if (res == 1) + { + res = ghw_read_cycle_cont (h, NULL); + if (res < 0) + return res; + return ghw_res_cycle; + } + res = ghw_read_cycle_end (h); + if (res < 0) + return res; + *sm = ghw_sm_sect; + break; + } + } +} + +int +ghw_read_cycle (struct ghw_handler *h) +{ + int res; + + res = ghw_read_cycle_start (h); + if (res < 0) + return res; + while (1) + { + res = ghw_read_cycle_cont (h, NULL); + if (res < 0) + return res; + + if (0) + printf ("Time is " GHWPRI64 " fs\n", h->snap_time); + if (0) + ghw_disp_values (h); + + res = ghw_read_cycle_next (h); + if (res < 0) + return res; + if (res == 0) + break; + } + res = ghw_read_cycle_end (h); + return res; +} + +int +ghw_read_dump (struct ghw_handler *h) +{ + unsigned char hdr[4]; + int res; + + while (1) + { + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + { + if (feof (h->stream)) + return 0; + else + return -1; + } + if (memcmp (hdr, "SNP", 4) == 0) + { + res = ghw_read_snapshot (h); + if (0 && res >= 0) + ghw_disp_values (h); + } + else if (memcmp (hdr, "CYC", 4) == 0) + { + res = ghw_read_cycle (h); + } + else if (memcmp (hdr, "DIR", 4) == 0) + { + res = ghw_read_directory (h); + } + else if (memcmp (hdr, "TAI", 4) == 0) + { + res = ghw_read_tailer (h); + } + else + { + fprintf (stderr, "unknown GHW section %c%c%c%c\n", hdr[0], hdr[1], + hdr[2], hdr[3]); + return -1; + } + if (res != 0) + return res; + } +} + +struct ghw_section ghw_sections[] = { {"\0\0\0", NULL}, +{"STR", ghw_read_str}, +{"HIE", ghw_read_hie}, +{"TYP", ghw_read_type}, +{"WKT", ghw_read_wk_types}, +{"EOH", ghw_read_eoh}, +{"SNP", ghw_read_snapshot}, +{"CYC", ghw_read_cycle}, +{"DIR", ghw_read_directory}, +{"TAI", ghw_read_tailer} +}; + +int +ghw_read_section (struct ghw_handler *h) +{ + unsigned char hdr[4]; + unsigned i; + + if (fread (hdr, sizeof (hdr), 1, h->stream) != 1) + { + if (feof (h->stream)) + return -2; + else + return -1; + } + + for (i = 1; i < sizeof (ghw_sections) / sizeof (*ghw_sections); i++) + if (memcmp (hdr, ghw_sections[i].name, 4) == 0) + return i; + + fprintf (stderr, "ghw_read_section: unknown GHW section %c%c%c%c\n", hdr[0], + hdr[1], hdr[2], hdr[3]); + return 0; +} + +void +ghw_close (struct ghw_handler *h) +{ + if (h->stream) + { + if (h->stream_ispipe) + pclose (h->stream); + else + fclose (h->stream); + + h->stream = NULL; + } +} + +const char * +ghw_get_dir (int is_downto) +{ + return is_downto ? "downto" : "to"; +} + +void +ghw_disp_range (union ghw_type *type, union ghw_range *rng) +{ + switch (rng->kind) + { + case ghdl_rtik_type_b2: + printf ("%s %s %s", ghw_get_lit (type, rng->b2.left), + ghw_get_dir (rng->b2.dir), ghw_get_lit (type, rng->b2.right)); + break; + case ghdl_rtik_type_e8: + printf ("%s %s %s", ghw_get_lit (type, rng->e8.left), + ghw_get_dir (rng->e8.dir), ghw_get_lit (type, rng->e8.right)); + break; + case ghdl_rtik_type_i32: + case ghdl_rtik_type_p32: + printf (GHWPRI32 " %s " GHWPRI32, rng->i32.left, + ghw_get_dir (rng->i32.dir), rng->i32.right); + break; + case ghdl_rtik_type_i64: + case ghdl_rtik_type_p64: + printf (GHWPRI64 " %s " GHWPRI64, rng->i64.left, + ghw_get_dir (rng->i64.dir), rng->i64.right); + break; + case ghdl_rtik_type_f64: + printf ("%g %s %g", rng->f64.left, ghw_get_dir (rng->f64.dir), + rng->f64.right); + break; + default: + printf ("?(%d)", rng->kind); + } +} + +static void +ghw_disp_array_subtype_bounds (struct ghw_subtype_array *a) +{ + unsigned i; + struct ghw_type_array *base = + (struct ghw_type_array *) ghw_get_base_type (a->base); + + printf (" ("); + for (i = 0; i < base->nbr_dim; i++) + { + if (i != 0) + printf (", "); + ghw_disp_range (base->dims[i], a->rngs[i]); + } + printf (")"); +} + +static void +ghw_disp_record_subtype_bounds (struct ghw_subtype_record *sr) +{ + struct ghw_type_record *base = sr->base; + int is_first = 1; + unsigned i; + + for (i = 0; i < base->nbr_fields; i++) + { + if (sr->els[i].type != base->els[i].type) + { + if (is_first) + { + printf ("("); + is_first = 0; + } + else + printf (", "); + printf ("%s", base->els[i].name); + switch (sr->els[i].type->kind) + { + case ghdl_rtik_subtype_array: + ghw_disp_array_subtype_bounds (&sr->els[i].type->sa); + break; + case ghdl_rtik_subtype_record: + ghw_disp_record_subtype_bounds (&sr->els[i].type->sr); + break; + default: + printf ("??? (%d)", sr->els[i].type->kind); + } + } + } + if (!is_first) + printf (")"); +} + +static void +ghw_disp_subtype_definition (struct ghw_handler *h, union ghw_type *t) +{ + switch (t->kind) + { + case ghdl_rtik_subtype_scalar: + { + struct ghw_subtype_scalar *s = &t->ss; + ghw_disp_typename (h, s->base); + printf (" range "); + ghw_disp_range (s->base, s->rng); + } break; + case ghdl_rtik_subtype_array: + { + struct ghw_subtype_array *a = &t->sa; + + ghw_disp_typename (h, (union ghw_type *) a->base); + ghw_disp_array_subtype_bounds (a); + } break; + case ghdl_rtik_subtype_record: + { + struct ghw_subtype_record *sr = &t->sr; + + ghw_disp_typename (h, (union ghw_type *) sr->base); + ghw_disp_record_subtype_bounds (sr); + } break; + case ghdl_rtik_subtype_unbounded_array: + case ghdl_rtik_subtype_unbounded_record: + { + struct ghw_subtype_unbounded_record *sur = &t->sur; + + ghw_disp_typename (h, (union ghw_type *) sur->base); + } break; + default: + printf ("ghw_disp_subtype_definition: unhandled type kind %d\n", + t->kind); + } +} + +static int +ghw_is_anonymous_type (struct ghw_handler *h, union ghw_type *t) +{ + return t->common.name == h->str_table[0]; +} + +void +ghw_disp_subtype_indication (struct ghw_handler *h, union ghw_type *t) +{ + if (ghw_is_anonymous_type (h, t)) + { + /* Anonymous subtype. */ + ghw_disp_subtype_definition (h, t); + } + else + ghw_disp_typename (h, t); +} + +void +ghw_disp_type (struct ghw_handler *h, union ghw_type *t) +{ + switch (t->kind) + { + case ghdl_rtik_type_b2: + case ghdl_rtik_type_e8: + { + struct ghw_type_enum *e = &t->en; + unsigned i; + + printf ("type %s is (", e->name); + for (i = 0; i < e->nbr; i++) + { + if (i != 0) + printf (", "); + printf ("%s", e->lits[i]); + } + printf (");"); + if (e->wkt != ghw_wkt_unknown) + printf (" -- WKT:%d", e->wkt); + printf ("\n"); + } + break; + case ghdl_rtik_type_i32: + case ghdl_rtik_type_f64: + { + struct ghw_type_scalar *s = &t->sc; + printf ("type %s is range <>;\n", s->name); + } break; + case ghdl_rtik_type_p32: + case ghdl_rtik_type_p64: + { + unsigned i; + + struct ghw_type_physical *p = &t->ph; + printf ("type %s is range <> units\n", p->name); + for (i = 0; i < p->nbr_units; i++) + { + struct ghw_unit *u = &p->units[i]; + printf (" %s = " GHWPRI64 " %s;\n", u->name, u->val, + p->units[0].name); + } + printf ("end units\n"); + } break; + case ghdl_rtik_type_array: + { + struct ghw_type_array *a = &t->ar; + unsigned i; + + printf ("type %s is array (", a->name); + for (i = 0; i < a->nbr_dim; i++) + { + if (i != 0) + printf (", "); + ghw_disp_typename (h, a->dims[i]); + printf (" range <>"); + } + printf (") of "); + ghw_disp_subtype_indication (h, a->el); + printf (";\n"); + } + break; + case ghdl_rtik_type_record: + { + struct ghw_type_record *r = &t->rec; + unsigned i; + + printf ("type %s is record\n", r->name); + for (i = 0; i < r->nbr_fields; i++) + { + printf (" %s: ", r->els[i].name); + ghw_disp_subtype_indication (h, r->els[i].type); + printf (";\n"); + } + printf ("end record;\n"); + } + break; + case ghdl_rtik_subtype_array: + case ghdl_rtik_subtype_scalar: + case ghdl_rtik_subtype_record: + case ghdl_rtik_subtype_unbounded_array: + case ghdl_rtik_subtype_unbounded_record: + { + struct ghw_type_common *c = &t->common; + printf ("subtype %s is ", c->name); + ghw_disp_subtype_definition (h, t); + printf (";\n"); + } break; + default: + printf ("ghw_disp_type: unhandled type kind %d\n", t->kind); + } +} + +void +ghw_disp_types (struct ghw_handler *h) +{ + unsigned i; + + for (i = 0; i < h->nbr_types; i++) + if (h->flag_verbose || !ghw_is_anonymous_type (h, h->types[i])) + ghw_disp_type (h, h->types[i]); +} diff -Nru gtkwave-3.3.104/src/libghw.h gtkwave-3.3.104+really3.3.118/src/libghw.h --- gtkwave-3.3.104/src/libghw.h 1970-01-01 00:00:00.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/libghw.h 2023-12-31 21:11:05.000000000 +0000 @@ -0,0 +1,471 @@ +/* GHDL Wavefile reader library. + Copyright (C) 2005-2017 Tristan Gingold + + 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef _LIBGHW_H_ +#define _LIBGHW_H_ + +#include +#include + +/* To be libraries friendly. */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* The libghw uses the standard c99 int32_t and int64_t. They are declared + in stdint.h. Header inttypes.h includes stdint.h and provides macro for + printf and co specifiers. Use it if known to be available. */ + +#if defined(__cplusplus) || \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(HAVE_INTTYPES_H) +/* Use C99 standard header. */ +#include +#define GHWPRI64 "%" PRId64 +#define GHWPRI32 "%" PRId32 +#else +#include +#define GHWPRI64 "%lld" +#define GHWPRI32 "%d" +#endif + +enum ghdl_rtik +{ + ghdl_rtik_top, /* 0 */ + ghdl_rtik_library, + ghdl_rtik_package, + ghdl_rtik_package_body, + ghdl_rtik_entity, + ghdl_rtik_architecture, /* 5 */ + ghdl_rtik_process, + ghdl_rtik_block, + ghdl_rtik_if_generate, + ghdl_rtik_for_generate, + ghdl_rtik_instance, + ghdl_rtik_constant, + ghdl_rtik_iterator, + ghdl_rtik_variable, + ghdl_rtik_signal, + ghdl_rtik_file, + ghdl_rtik_port, + ghdl_rtik_generic, + ghdl_rtik_alias, + ghdl_rtik_guard, + ghdl_rtik_component, + ghdl_rtik_attribute, + ghdl_rtik_type_b2, /* 22 */ + ghdl_rtik_type_e8, + ghdl_rtik_type_e32, + ghdl_rtik_type_i32, /* 25 */ + ghdl_rtik_type_i64, + ghdl_rtik_type_f64, + ghdl_rtik_type_p32, + ghdl_rtik_type_p64, + ghdl_rtik_type_access, /* 30 */ + ghdl_rtik_type_array, + ghdl_rtik_type_record, + ghdl_rtik_type_file, + ghdl_rtik_subtype_scalar, + ghdl_rtik_subtype_array, /* 35 */ + ghdl_rtik_subtype_array_ptr, /* Obsolete. */ + ghdl_rtik_subtype_unbounded_array, + ghdl_rtik_subtype_record, + ghdl_rtik_subtype_unbounded_record, +#if 0 + ghdl_rtik_subtype_access, /* 40 */ + ghdl_rtik_type_protected, + ghdl_rtik_element, + ghdl_rtik_unit, + ghdl_rtik_attribute_transaction, + ghdl_rtik_attribute_quiet, + ghdl_rtik_attribute_stable, +#endif + ghdl_rtik_error +}; + +/* Well-known types. */ +enum ghw_wkt_type +{ + ghw_wkt_unknown, + ghw_wkt_boolean, + ghw_wkt_bit, + ghw_wkt_std_ulogic +}; + +struct ghw_range_b2 +{ + enum ghdl_rtik kind:8; + int dir:8; /* 0: to, !0: downto. */ + unsigned char left; + unsigned char right; +}; + +struct ghw_range_e8 +{ + enum ghdl_rtik kind:8; + int dir:8; /* 0: to, !0: downto. */ + unsigned char left; + unsigned char right; +}; + +struct ghw_range_i32 +{ + enum ghdl_rtik kind:8; + int dir:8; /* 0: to, !0: downto. */ + int32_t left; + int32_t right; +}; + +struct ghw_range_i64 +{ + enum ghdl_rtik kind:8; + int dir:8; + int64_t left; + int64_t right; +}; + +struct ghw_range_f64 +{ + enum ghdl_rtik kind:8; + int dir:8; + double left; + double right; +}; + +union ghw_range +{ + enum ghdl_rtik kind:8; + struct ghw_range_b2 b2; + struct ghw_range_e8 e8; + struct ghw_range_i32 i32; + struct ghw_range_i64 i64; + struct ghw_range_f64 f64; +}; + +/* Note: the first two fields must be kind and name. */ +union ghw_type; + +struct ghw_type_common +{ + enum ghdl_rtik kind; + const char *name; +}; + +struct ghw_type_enum +{ + enum ghdl_rtik kind; + const char *name; + + enum ghw_wkt_type wkt; + unsigned int nbr; + const char **lits; +}; + +struct ghw_type_scalar +{ + enum ghdl_rtik kind; + const char *name; +}; + +struct ghw_unit +{ + const char *name; + int64_t val; +}; + +struct ghw_type_physical +{ + enum ghdl_rtik kind; + const char *name; + uint32_t nbr_units; + struct ghw_unit *units; +}; + +struct ghw_type_array +{ + enum ghdl_rtik kind; + const char *name; + + unsigned int nbr_dim; + union ghw_type *el; + union ghw_type **dims; +}; + +struct ghw_subtype_unbounded_array +{ + enum ghdl_rtik kind; + const char *name; + + union ghw_type *base; +}; + +struct ghw_subtype_array +{ + enum ghdl_rtik kind; + const char *name; + + union ghw_type *base; + int nbr_scalars; + union ghw_range **rngs; + union ghw_type *el; +}; + +struct ghw_subtype_scalar +{ + enum ghdl_rtik kind; + const char *name; + + union ghw_type *base; + union ghw_range *rng; +}; + +struct ghw_record_element +{ + const char *name; + union ghw_type *type; +}; + +struct ghw_type_record +{ + enum ghdl_rtik kind; + const char *name; + + unsigned int nbr_fields; + int nbr_scalars; /* Number of scalar elements (ie nbr of signals). */ + struct ghw_record_element *els; +}; + +struct ghw_subtype_record +{ + enum ghdl_rtik kind; + const char *name; + + struct ghw_type_record *base; + int nbr_scalars; /* Number of scalar elements (ie nbr of signals). */ + struct ghw_record_element *els; +}; + +struct ghw_subtype_unbounded_record +{ + enum ghdl_rtik kind; + const char *name; + + struct ghw_type_record *base; +}; + +union ghw_type +{ + enum ghdl_rtik kind; + struct ghw_type_common common; + struct ghw_type_enum en; + struct ghw_type_scalar sc; + struct ghw_type_physical ph; + struct ghw_subtype_scalar ss; + struct ghw_type_array ar; + struct ghw_type_record rec; + struct ghw_subtype_array sa; + struct ghw_subtype_unbounded_array sua; + struct ghw_subtype_record sr; + struct ghw_subtype_unbounded_record sur; +}; + +union ghw_val +{ + unsigned char b2; + unsigned char e8; + int32_t i32; + int64_t i64; + double f64; +}; + +/* A non-composite signal. */ +struct ghw_sig +{ + union ghw_type *type; + union ghw_val *val; +}; + +enum ghw_hie_kind +{ + ghw_hie_eoh = 0, + ghw_hie_design = 1, + ghw_hie_block = 3, + ghw_hie_generate_if = 4, + ghw_hie_generate_for = 5, + ghw_hie_instance = 6, + ghw_hie_package = 7, + ghw_hie_process = 13, + ghw_hie_generic = 14, + ghw_hie_eos = 15, + ghw_hie_signal = 16, + ghw_hie_port_in = 17, + ghw_hie_port_out = 18, + ghw_hie_port_inout = 19, + ghw_hie_port_buffer = 20, + ghw_hie_port_linkage = 21 +}; + +#define GHW_NO_SIG 0 + +struct ghw_hie +{ + enum ghw_hie_kind kind; + struct ghw_hie *parent; + const char *name; + struct ghw_hie *brother; + union + { + struct + { + struct ghw_hie *child; + union ghw_type *iter_type; + union ghw_val *iter_value; + } blk; + struct + { + union ghw_type *type; + /* Array of signal elements. + Last element is GHW_NO_SIG (0). */ + unsigned int *sigs; + } sig; + } u; +}; + +struct ghw_handler +{ + FILE *stream; + /* True if STREAM was popen, else was fopen. */ + unsigned char stream_ispipe; + /* True if words are big-endian. */ + unsigned char word_be; + unsigned char word_len; + unsigned char off_len; + /* Minor version. */ + int version; + + /* Set by user. */ + int flag_verbose; + + /* String table. */ + /* Number of strings. */ + unsigned nbr_str; + /* Size of the strings (without nul). */ + unsigned str_size; + /* String table. */ + char **str_table; + /* Array containing strings. */ + char *str_content; + + /* Type table. */ + unsigned nbr_types; + union ghw_type **types; + + /* Non-composite (or basic) signals. */ + unsigned nbr_sigs; + char *skip_sigs; + int flag_full_names; + struct ghw_sig *sigs; + + /* Hierarchy. */ + struct ghw_hie *hie; + + /* Time of the next cycle. */ + int64_t snap_time; +}; + +/* Open a GHW file with H. + Return < 0 in case of error. */ +int ghw_open (struct ghw_handler *h, const char *filename); + +/* Return base type of T. */ +union ghw_type *ghw_get_base_type (union ghw_type *t); + +/* Return length of RNG. */ +int ghw_get_range_length (union ghw_range *rng); + +/* Put the ASCII representation of VAL into BUF, whose size if LEN. + A NUL is always written to BUF. */ +void ghw_get_value (char *buf, int len, union ghw_val *val, + union ghw_type *type); + +const char *ghw_get_hie_name (struct ghw_hie *h); + +void ghw_disp_hie (struct ghw_handler *h, struct ghw_hie *top); + +int ghw_read_base (struct ghw_handler *h); + +void ghw_filter_signals (struct ghw_handler *h, int *signals_to_keep, + int nb_signals_to_keep); + +void ghw_disp_values (struct ghw_handler *h); + +int ghw_read_cycle_start (struct ghw_handler *h); + +int ghw_read_cycle_cont (struct ghw_handler *h, int *list); + +int ghw_read_cycle_next (struct ghw_handler *h); + +int ghw_read_cycle_end (struct ghw_handler *h); + +enum ghw_sm_type +{ + /* At init; + Read section name. */ + ghw_sm_init = 0, + ghw_sm_sect = 1, + ghw_sm_cycle = 2 +}; + +enum ghw_res +{ + ghw_res_error = -1, + ghw_res_eof = -2, + ghw_res_ok = 0, + ghw_res_snapshot = 1, + ghw_res_cycle = 2, + ghw_res_other = 3 +}; + +enum ghw_res ghw_read_sm_hdr (struct ghw_handler *h, int *list); + +int ghw_read_sm (struct ghw_handler *h, enum ghw_sm_type *sm); + +int ghw_read_dump (struct ghw_handler *h); + +struct ghw_section +{ + const char name[4]; + int (*handler) (struct ghw_handler * h); +}; + +extern struct ghw_section ghw_sections[]; + +int ghw_read_section (struct ghw_handler *h); + +void ghw_close (struct ghw_handler *h); + +const char *ghw_get_dir (int is_downto); + +void ghw_disp_subtype_indication (struct ghw_handler *h, union ghw_type *t); + +/* Note: TYPE must be a base type (used only to display literals). */ +void ghw_disp_range (union ghw_type *type, union ghw_range *rng); + +void ghw_disp_type (struct ghw_handler *h, union ghw_type *t); + +void ghw_disp_types (struct ghw_handler *h); +#endif /* _LIBGHW_H_ */ diff -Nru gtkwave-3.3.104/src/liblzma/LzmaLib.c gtkwave-3.3.104+really3.3.118/src/liblzma/LzmaLib.c --- gtkwave-3.3.104/src/liblzma/LzmaLib.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/liblzma/LzmaLib.c 2023-12-31 21:11:05.000000000 +0000 @@ -51,6 +51,16 @@ }; +/* + * report abort messages + */ +static void chk_report_abort(const char *s) +{ +fprintf(stderr,"Triggered %s security check, exiting.\n", s); +abort(); +} + + static void LZMA_write_varint(struct lzma_handle_t *h, size_t v) { size_t nxt; @@ -72,16 +82,22 @@ /* ifdef is warnings fix if XZ is not present */ static size_t LZMA_read_varint(struct lzma_handle_t *h) { -unsigned char buf[16]; +int chk_len = 16; /* TALOS-2023-1811 */ +unsigned char buf[chk_len]; int idx = 0; size_t rc = 0; -for(;;) +while(idxread_cnt += read(h->fd, buf+idx, 1); if(buf[idx++] & 0x80) break; } +if(idx == chk_len) + { + chk_report_abort("TALOS-2023-1811"); + } + do { idx--; @@ -324,6 +340,21 @@ srclen = LZMA_read_varint(h); + if(srclen > h->blksiz) /* TALOS-2023-1810 */ + { + if(h->dmem) + { + free(h->dmem); + } + if(h->mem) + { + free(h->mem); + } + h->blksiz = srclen; + h->mem = malloc(h->blksiz); + h->dmem = malloc(h->blksiz); + } + if(!srclen) { h->read_cnt += (rc = read(h->fd, h->mem, dstlen)); @@ -335,7 +366,7 @@ lzma_stream strm = LZMA_STREAM_INIT; lzma_ret lrc; - h->read_cnt += (rc = read(h->fd, h->dmem, srclen)); + h->read_cnt += (rc = read(h->fd, h->dmem, srclen)); /* TALOS-2023-1810: srclen used here, generally ok as data are compressible */ lrc = lzma_alone_decoder(&strm, LZMA_DECODER_SIZE); if(lrc != LZMA_OK) diff -Nru gtkwave-3.3.104/src/main.c gtkwave-3.3.104+really3.3.118/src/main.c --- gtkwave-3.3.104/src/main.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/main.c 2023-12-31 21:11:05.000000000 +0000 @@ -117,6 +117,7 @@ GLOBALS->display_grid = g_old->display_grid; GLOBALS->highlight_wavewindow = g_old->highlight_wavewindow; GLOBALS->fill_waveform = g_old->fill_waveform; +GLOBALS->lz_removal = g_old->lz_removal; GLOBALS->use_standard_trace_select = g_old->use_standard_trace_select; GLOBALS->disable_mouseover = g_old->disable_mouseover; GLOBALS->clipboard_mouseover = g_old->clipboard_mouseover; @@ -634,6 +635,7 @@ GLOBALS->enable_ghost_marker = old_g->enable_ghost_marker; GLOBALS->enable_horiz_grid = old_g->enable_horiz_grid; GLOBALS->fill_waveform = old_g->fill_waveform; + GLOBALS->lz_removal = old_g->lz_removal; GLOBALS->make_vcd_save_file = old_g->make_vcd_save_file; GLOBALS->enable_vert_grid = old_g->enable_vert_grid; GLOBALS->force_toolbars = old_g->force_toolbars; @@ -649,7 +651,6 @@ GLOBALS->show_base = old_g->show_base; GLOBALS->display_grid = old_g->display_grid; GLOBALS->highlight_wavewindow = old_g->highlight_wavewindow; - GLOBALS->fill_waveform = old_g->fill_waveform; GLOBALS->use_standard_trace_select = old_g->use_standard_trace_select; GLOBALS->use_big_fonts = old_g->use_big_fonts; GLOBALS->use_full_precision = old_g->use_full_precision; @@ -1737,7 +1738,7 @@ str=wave_alloca(strlen(wname)+dlen+1); strcpy(str,WAVE_DECOMPRESSOR); strcpy(str+dlen,wname); - wave=popen(str,"r"); + wave=popen_san(str,"r"); wave_is_compressed=~0; } else @@ -1785,7 +1786,7 @@ if(wave_is_compressed) { pclose(wave); - wave=popen(str,"r"); + wave=popen_san(str,"r"); } else { diff -Nru gtkwave-3.3.104/src/menu.c gtkwave-3.3.104+really3.3.118/src/menu.c --- gtkwave-3.3.104/src/menu.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/menu.c 2023-12-31 21:11:05.000000000 +0000 @@ -4483,12 +4483,12 @@ t=GLOBALS->showchangeall_menu_c_1; if(t) { - flags = t->flags & (TR_NUMMASK | TR_HIGHLIGHT); + flags = t->flags & (TR_NUMMASK | TR_HIGHLIGHT | TR_ATTRIBS); while(t) { if((t->flags&TR_HIGHLIGHT)&&(!(t->flags&(TR_BLANK|TR_ANALOG_BLANK_STRETCH)))&&(t->name)) { - t->flags = (t->flags & ~(TR_NUMMASK | TR_HIGHLIGHT)) | flags; + t->flags = (t->flags & ~(TR_NUMMASK | TR_HIGHLIGHT | TR_ATTRIBS)) | flags; t->minmax_valid = 0; /* force analog traces to regenerate if necessary */ } t=t->t_next; @@ -6771,6 +6771,49 @@ dataformat( ~(TR_POPCNT), 0 ); } +void +menu_dataformat_ffo_on(gpointer null_data, guint callback_action, GtkWidget *widget) +{ +(void)null_data; +(void)callback_action; +(void)widget; + +if(GLOBALS->helpbox_is_active) + { + help_text_bold("\n\nData Format-Find First Rightmost One Index-On"); + help_text( + " will step through all highlighted traces and ensure that" + " bits and vectors with this qualifier will be displayed after" + " going through a right->left FFO index conversion. This is a filter" + " which sits before other Data Format options such as hex, etc." + ); + return; + } + +dataformat( ~(TR_FFO), TR_FFO ); +} + +void +menu_dataformat_ffo_off(gpointer null_data, guint callback_action, GtkWidget *widget) +{ +(void)null_data; +(void)callback_action; +(void)widget; + +if(GLOBALS->helpbox_is_active) + { + help_text_bold("\n\nData Format-Find First Rightmost One Index-Off"); + help_text( + " will step through all highlighted traces and ensure that" + " bits and vectors with this qualifier will be displayed with" + " normal encoding." + ); + return; + } + +dataformat( ~(TR_FFO), 0 ); +} + void menu_dataformat_time(gpointer null_data, guint callback_action, GtkWidget *widget) @@ -7788,6 +7831,42 @@ } /**/ +void menu_lz_removal(gpointer null_data, guint callback_action, GtkWidget *widget) +{ +(void)null_data; +(void)callback_action; +(void)widget; + +if(GLOBALS->helpbox_is_active) + { + help_text_bold("\n\nShow Filled High Values"); + help_text( + " toggles the display of leading zeros on non-filtered traces. This has no effect on filtered traces." + ); + } + else + { +#ifndef WAVE_USE_MLIST_T + GLOBALS->lz_removal=(GLOBALS->lz_removal)?0:~0; +#else + GLOBALS->lz_removal = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_LZ_REMOVAL])); +#endif + if(GLOBALS->signalarea && GLOBALS->wavearea) + { + GLOBALS->signalwindow_width_dirty=1; + MaxSignalLength(); + signalarea_configure_event(GLOBALS->signalarea, NULL); + wavearea_configure_event(GLOBALS->wavearea, NULL); + } + DEBUG(printf("Leading Zero Removal\n")); + } + +#ifndef WAVE_USE_MLIST_T +GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_LZ_REMOVAL].path))->active=(GLOBALS->lz_removal)?TRUE:FALSE; +#endif +} + +/**/ void menu_show_mouseover(gpointer null_data, guint callback_action, GtkWidget *widget) { (void)null_data; @@ -7990,6 +8069,8 @@ WAVE_GTKIFE("/Edit/Data Format/Gray Filters/None", NULL, menu_dataformat_nogray, WV_MENU_GBNONE, ""), WAVE_GTKIFE("/Edit/Data Format/Popcnt/On", NULL, menu_dataformat_popcnt_on, WV_MENU_POPON, ""), WAVE_GTKIFE("/Edit/Data Format/Popcnt/Off", NULL, menu_dataformat_popcnt_off, WV_MENU_POPOFF, ""), + WAVE_GTKIFE("/Edit/Data Format/Find First One/On", NULL, menu_dataformat_ffo_on, WV_MENU_FFOON, ""), + WAVE_GTKIFE("/Edit/Data Format/Find First One/Off", NULL, menu_dataformat_ffo_off, WV_MENU_FFOOFF, ""), WAVE_GTKIFE("/Edit/Data Format/Fixed Point Shift/On", NULL, menu_dataformat_fpshift_on, WV_MENU_FPSHIFTON, ""), WAVE_GTKIFE("/Edit/Data Format/Fixed Point Shift/Off", NULL, menu_dataformat_fpshift_off, WV_MENU_FPSHIFTOFF, ""), WAVE_GTKIFE("/Edit/Data Format/Fixed Point Shift/Specify", NULL, menu_dataformat_fpshift_specify, WV_MENU_FPSHIFTVAL, ""), @@ -8108,6 +8189,7 @@ WAVE_GTKIFE("/View/", NULL, NULL, WV_MENU_SEP9, ""), WAVE_GTKIFE("/View/Show Wave Highlight", NULL, menu_show_wave_highlight, WV_MENU_SHW, ""), WAVE_GTKIFE("/View/Show Filled High Values", NULL, menu_show_filled_high_values, WV_MENU_FILL1, ""), + WAVE_GTKIFE("/View/Leading Zero Removal", NULL, menu_lz_removal, WV_MENU_LZ_REMOVAL, ""), WAVE_GTKIFE("/View/", NULL, NULL, WV_MENU_SEP9B, ""), WAVE_GTKIFE("/View/Show Mouseover", NULL, menu_show_mouseover, WV_MENU_VSMO, ""), #ifdef WAVE_USE_GTK2 @@ -8239,6 +8321,8 @@ GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_FILL1].path))->active=(GLOBALS->fill_waveform)?TRUE:FALSE; +GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_LZ_REMOVAL].path))->active=(GLOBALS->lz_removal)?TRUE:FALSE; + GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1, menu_items[WV_MENU_HSWM].path))->active=(GLOBALS->alt_wheel_mode)?TRUE:FALSE; GTK_CHECK_MENU_ITEM(gtk_item_factory_get_widget(GLOBALS->item_factory_menu_c_1,menu_items[WV_MENU_VSMO].path))->active=(GLOBALS->disable_mouseover)?FALSE:TRUE; @@ -8295,6 +8379,7 @@ gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSG]), GLOBALS->display_grid); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_SHW]), GLOBALS->highlight_wavewindow); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_FILL1]), GLOBALS->fill_waveform); +gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_LZ_REMOVAL]), GLOBALS->lz_removal); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_HSWM]), GLOBALS->alt_wheel_mode); gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(menu_wlist[WV_MENU_VSMO]), !GLOBALS->disable_mouseover); @@ -8696,6 +8781,8 @@ WAVE_GTKIFE("/Data Format/Gray Filters/None", NULL, menu_dataformat_nogray, WV_MENU_GBNONE, ""), WAVE_GTKIFE("/Data Format/Popcnt/On", NULL, menu_dataformat_popcnt_on, WV_MENU_POPON, ""), WAVE_GTKIFE("/Data Format/Popcnt/Off", NULL, menu_dataformat_popcnt_off, WV_MENU_POPOFF, ""), + WAVE_GTKIFE("/Data Format/Find First One/On", NULL, menu_dataformat_ffo_on, WV_MENU_FFOON, ""), + WAVE_GTKIFE("/Data Format/Find First One/Off", NULL, menu_dataformat_ffo_off, WV_MENU_FFOOFF, ""), WAVE_GTKIFE("/Data Format/Fixed Point Shift/On", NULL, menu_dataformat_fpshift_on, WV_MENU_FPSHIFTON, ""), WAVE_GTKIFE("/Data Format/Fixed Point Shift/Off", NULL, menu_dataformat_fpshift_off, WV_MENU_FPSHIFTOFF, ""), WAVE_GTKIFE("/Data Format/Fixed Point Shift/Specify", NULL, menu_dataformat_fpshift_specify, WV_MENU_FPSHIFTVAL, ""), diff -Nru gtkwave-3.3.104/src/menu.h gtkwave-3.3.104+really3.3.118/src/menu.h --- gtkwave-3.3.104/src/menu.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/menu.h 2023-12-31 21:11:05.000000000 +0000 @@ -167,6 +167,8 @@ WV_MENU_GBNONE, WV_MENU_POPON, WV_MENU_POPOFF, +WV_MENU_FFOON, +WV_MENU_FFOOFF, WV_MENU_FPSHIFTON, WV_MENU_FPSHIFTOFF, WV_MENU_FPSHIFTVAL, @@ -264,6 +266,7 @@ WV_MENU_SEP9, WV_MENU_SHW, WV_MENU_FILL1, +WV_MENU_LZ_REMOVAL, WV_MENU_SEP9B, WV_MENU_VSMO, #ifdef WAVE_USE_GTK2 diff -Nru gtkwave-3.3.104/src/mouseover.c gtkwave-3.3.104+really3.3.118/src/mouseover.c --- gtkwave-3.3.104/src/mouseover.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/mouseover.c 2023-12-31 21:11:05.000000000 +0000 @@ -84,16 +84,19 @@ if((flags & TR_TTRANSLATED) != 0) { ch[pos++] = 'T'; } /* [14] */ -if((flags & TR_POPCNT) != 0) { ch[pos++] = 'p'; } +if((flags & TR_FFO) != 0) { ch[pos++] = 'f'; } /* [15] */ +if((flags & TR_POPCNT) != 0) { ch[pos++] = 'p'; } + +/* [16] */ if((flags & TR_FPDECSHIFT) != 0) { int ln = sprintf(ch+pos, "s(%d)", t->t_fpdecshift); pos += ln; } -/* [16+] */ +/* [17+] */ ch[pos] = 0; return(pos); diff -Nru gtkwave-3.3.104/src/mouseover_sigs.c gtkwave-3.3.104+really3.3.118/src/mouseover_sigs.c --- gtkwave-3.3.104/src/mouseover_sigs.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/mouseover_sigs.c 2023-12-31 21:11:05.000000000 +0000 @@ -110,16 +110,19 @@ if((flags & TR_TTRANSLATED) != 0) { ch[pos++] = 'T'; } /* [14] */ -if((flags & TR_POPCNT) != 0) { ch[pos++] = 'p'; } +if((flags & TR_FFO) != 0) { ch[pos++] = 'f'; } /* [15] */ +if((flags & TR_POPCNT) != 0) { ch[pos++] = 'p'; } + +/* [16] */ if((flags & TR_FPDECSHIFT) != 0) { int ln = sprintf(ch+pos, "s(%d)", t->t_fpdecshift); pos += ln; } -/* [16+] */ +/* [17+] */ ch[pos] = 0; if(!t->vector) diff -Nru gtkwave-3.3.104/src/ptranslate.c gtkwave-3.3.104+really3.3.118/src/ptranslate.c --- gtkwave-3.3.104/src/ptranslate.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/ptranslate.c 2023-12-31 21:11:05.000000000 +0000 @@ -133,7 +133,7 @@ #if !defined __MINGW32__ && !defined _MSC_VER cmd = (char *)malloc_2(strlen(exec_name)+6+1); sprintf(cmd, "which %s", exec_name); - stream = popen(cmd, "r"); + stream = popen_san(cmd, "r"); result = fscanf(stream, "%s", abs_path); diff -Nru gtkwave-3.3.104/src/rc.c gtkwave-3.3.104+really3.3.118/src/rc.c --- gtkwave-3.3.104/src/rc.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/rc.c 2023-12-31 21:11:05.000000000 +0000 @@ -280,6 +280,13 @@ return(0); } +int f_lz_removal(char *str) +{ +DEBUG(printf("f_lz_removal(\"%s\")\n",str)); +GLOBALS->lz_removal=atoi_64(str)?1:0; +return(0); +} + int f_fontname_logfile(char *str) { DEBUG(printf("f_fontname_logfile(\"%s\")\n",str)); @@ -942,6 +949,7 @@ { "keep_xz_colors", f_keep_xz_colors }, { "left_justify_sigs", f_left_justify_sigs }, { "lxt_clock_compress_to_z", f_lxt_clock_compress_to_z }, +{ "lz_removal", f_lz_removal }, { "max_fsdb_trees", f_max_fsdb_trees }, { "page_divisor", f_page_divisor }, { "ps_maxveclen", f_ps_maxveclen }, @@ -1098,7 +1106,7 @@ void read_rc_file(char *override_rc) { -FILE *handle; +FILE *handle = NULL; int i; int num_rcitems = sizeof(rcitems)/sizeof(struct rc_entry); @@ -1123,16 +1131,30 @@ #if !defined __MINGW32__ && !defined _MSC_VER if(!(handle=fopen(rcname,"rb"))) { - char *home; - char *rcpath; + struct passwd *pw = NULL; + char *home = NULL; + char *rcpath = NULL; + + pw=getpwuid(geteuid()); + if(pw) + { + home=pw->pw_dir; + } + + if(!home) + { + home = getenv("HOME"); + } - home=getpwuid(geteuid())->pw_dir; - rcpath=(char *)alloca(strlen(home)+1+strlen(rcname)+1); - strcpy(rcpath,home); - strcat(rcpath,"/"); - strcat(rcpath,rcname); + if(home) + { + rcpath=(char *)alloca(strlen(home)+1+strlen(rcname)+1); + strcpy(rcpath,home); + strcat(rcpath,"/"); + strcat(rcpath,rcname); + } - if(!(handle=fopen(rcpath,"rb"))) + if( !rcpath || !(handle=fopen(rcpath,"rb")) ) { #ifdef MAC_INTEGRATION const gchar *bundle_id = gtkosx_application_get_bundle_id(); diff -Nru gtkwave-3.3.104/src/savefile.c gtkwave-3.3.104+really3.3.118/src/savefile.c --- gtkwave-3.3.104/src/savefile.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/savefile.c 2023-12-31 21:11:05.000000000 +0000 @@ -671,7 +671,7 @@ str=wave_alloca(strlen(wname)+5+1); strcpy(str,"zcat "); strcpy(str+5,wname); - wave=popen(str,"r"); + wave=popen_san(str,"r"); wave_is_compressed=~0; } else @@ -808,7 +808,7 @@ if(wave_is_compressed) { pclose(wave); - wave=popen(str,"r"); + wave=popen_san(str,"r"); } else { diff -Nru gtkwave-3.3.104/src/showchange.c gtkwave-3.3.104+really3.3.118/src/showchange.c --- gtkwave-3.3.104/src/showchange.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/showchange.c 2023-12-31 21:11:05.000000000 +0000 @@ -61,6 +61,12 @@ toggle_generic(widget, TR_POPCNT); } +static void toggle6_callback(GtkWidget *widget, GtkWidget *nothing) +{ +(void)nothing; + +toggle_generic(widget, TR_FFO); +} static void enter_callback(GtkWidget *widget, GtkWidget *nothing) { @@ -289,6 +295,12 @@ gtk_widget_show (GLOBALS->toggle5_showchange_c_1); gtkwave_signal_connect (GTK_OBJECT (GLOBALS->toggle5_showchange_c_1), "toggled", GTK_SIGNAL_FUNC(toggle5_callback), NULL); + GLOBALS->toggle6_showchange_c_1=gtk_check_button_new_with_label("Find First One"); + gtk_box_pack_start (GTK_BOX (box1), GLOBALS->toggle6_showchange_c_1, TRUE, TRUE, 0); + if(GLOBALS->flags_showchange_c_1&TR_FFO)gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(GLOBALS->toggle6_showchange_c_1), TRUE); + gtk_widget_show (GLOBALS->toggle6_showchange_c_1); + gtkwave_signal_connect (GTK_OBJECT (GLOBALS->toggle6_showchange_c_1), "toggled", GTK_SIGNAL_FUNC(toggle6_callback), NULL); + gtk_container_add (GTK_CONTAINER (main_vbox), hbox); separator = gtk_hseparator_new (); diff -Nru gtkwave-3.3.104/src/signalwindow.c gtkwave-3.3.104+really3.3.118/src/signalwindow.c --- gtkwave-3.3.104/src/signalwindow.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/signalwindow.c 2023-12-31 21:11:05.000000000 +0000 @@ -20,6 +20,18 @@ #ifndef GDK_KEY_equal #define GDK_KEY_equal GDK_equal #endif +#ifndef GDK_KEY_Up +#define GDK_KEY_Up GDK_Up +#endif +#ifndef GDK_KEY_KP_Up +#define GDK_KEY_KP_Up GDK_KP_Up +#endif +#ifndef GDK_KEY_Down +#define GDK_KEY_Down GDK_Down +#endif +#ifndef GDK_KEY_KP_Down +#define GDK_KEY_KP_Down GDK_KP_Down +#endif #undef FOCUS_DEBUG_MSGS @@ -471,6 +483,7 @@ int which; gint rc = FALSE; int yscroll; +int ud_kill = 0; #ifdef FOCUS_DEBUG_MSGS printf("focus: %d %08x %08x %08x\n", GTK_WIDGET_HAS_FOCUS(GLOBALS->signalarea_event_box), @@ -549,7 +562,128 @@ num_traces_displayable=(GLOBALS->signalarea->allocation.height)/(GLOBALS->fontheight); num_traces_displayable--; /* for the time trace that is always there */ - if(num_traces_displayabletraces.visible) + if(event->state & GDK_SHIFT_MASK) + { + Trptr t = NULL, t2 = NULL; + Trptr tc = NULL, th = NULL; + int num_high = 0; + + if((event->keyval == GDK_KEY_Up) || (event->keyval == GDK_KEY_KP_Up)) + { + ud_kill = 1; + for(t=GLOBALS->traces.first;t;t=t->t_next) + { + if(t->flags&TR_HIGHLIGHT) + { + if(!th) th = t; + num_high++; + } + + if(t->is_cursor) + { + tc = t; + } + } + + if(num_high <= 1) + { + t = th ? GivePrevTrace(th) : GLOBALS->topmost_trace; + } + else + { + t = tc ? GivePrevTrace(tc) : GLOBALS->topmost_trace; + } + + MarkTraceCursor(t); + } + else + if((event->keyval == GDK_KEY_Down) || (event->keyval == GDK_KEY_KP_Down)) + { + ud_kill = 1; + for(t=GLOBALS->traces.first;t;t=t->t_next) + { + if(t->flags&TR_HIGHLIGHT) + { + th = t; + num_high++; + } + if(t->is_cursor) + { + tc = t; + } + } + + if(num_high <= 1) + { + t = th ? GiveNextTrace(th) : GLOBALS->topmost_trace; + } + else + { + if(tc) + { + t = GiveNextTrace(tc); + } + else + { + t = th ? GiveNextTrace(th) : GLOBALS->topmost_trace; + } + } + + MarkTraceCursor(t); + } + + if(t) + { + int top_target = 0; + target = 0; + which=num_traces_displayable-1; + + ClearTraces(); + t->flags |= TR_HIGHLIGHT; + t2 = t; + + for(t=GLOBALS->traces.first;t;t=GiveNextTrace(t)) + { + if(t == GLOBALS->topmost_trace) break; + top_target++; + } + + for(t=GLOBALS->traces.first;t;t=GiveNextTrace(t)) + { + if(t2 == t) break; + target++; + } + + if((target >= top_target) && (target <= top_target+which)) + { + /* nothing */ + } + else + { + if((event->keyval == GDK_KEY_Up) || (event->keyval == GDK_KEY_KP_Up)) + { + if(target<0) target=0; + } + else + if((event->keyval == GDK_KEY_Down) || (event->keyval == GDK_KEY_KP_Down)) + { + target = target - which; + if(target+which>=(GLOBALS->traces.visible-1)) target=GLOBALS->traces.visible-which-1; + } + + wadj->value = target; + } + + if(GLOBALS->cachedwhich_signalwindow_c_1==which) GLOBALS->cachedwhich_signalwindow_c_1=which-1; /* force update */ + + gtk_signal_emit_by_name (GTK_OBJECT (wadj), "changed"); /* force bar update */ + gtk_signal_emit_by_name (GTK_OBJECT (wadj), "value_changed"); /* force text update */ + signalarea_configure_event(GLOBALS->signalarea, NULL); + wavearea_configure_event(GLOBALS->wavearea, NULL); + } + } + + if((num_traces_displayabletraces.visible) && (!ud_kill)) { switch(event->keyval) { @@ -568,6 +702,8 @@ gtk_signal_emit_by_name (GTK_OBJECT (wadj), "changed"); /* force bar update */ gtk_signal_emit_by_name (GTK_OBJECT (wadj), "value_changed"); /* force text update */ + signalarea_configure_event(GLOBALS->signalarea, NULL); + wavearea_configure_event(GLOBALS->wavearea, NULL); break; case GDK_Up: @@ -1228,14 +1364,14 @@ } else { - t->flags ^= TR_HIGHLIGHT; + t->flags ^= TR_HIGHLIGHT; MarkTraceCursor(t); } } } else if((event->state&GDK_SHIFT_MASK)&&(GLOBALS->starting_unshifted_trace)) { - int src = -1, dst = -1; + int src = -1, dst = -1, dsto = -1; int cnt = 0; t2=GLOBALS->traces.first; @@ -1265,6 +1401,7 @@ cnt++; } + dsto = dst; if(src > dst) { int cpy; cpy = src; src = dst; dst = cpy; } cnt = 0; t2=GLOBALS->traces.first; @@ -1275,6 +1412,8 @@ t2->flags |= TR_HIGHLIGHT; } + if(cnt == dsto) { MarkTraceCursor(t2); } + cnt++; t2=t2->t_next; } @@ -1298,7 +1437,7 @@ t2 = t2->t_next; } - if(t) { t->flags |= TR_HIGHLIGHT; } /* scan-build */ + if(t) { t->flags |= TR_HIGHLIGHT; MarkTraceCursor(t); } /* scan-build */ } GLOBALS->standard_trace_dnd_degate = 0; diff -Nru gtkwave-3.3.104/src/tree.c gtkwave-3.3.104+really3.3.118/src/tree.c --- gtkwave-3.3.104/src/tree.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/tree.c 2023-12-31 21:11:05.000000000 +0000 @@ -352,6 +352,7 @@ while(tnext) { + if(tnext->child) treenamefix(tnext->child); if(tnext->name) treenamefix_str(tnext->name); tnext=tnext->next; } diff -Nru gtkwave-3.3.104/src/tree.h gtkwave-3.3.104+really3.3.118/src/tree.h --- gtkwave-3.3.104/src/tree.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/tree.h 2023-12-31 21:11:05.000000000 +0000 @@ -116,7 +116,7 @@ uint32_t t_stem; /* source stem (if >0) for Open Hierarchy Source Def, see stem_struct_t */ uint32_t t_istem; /* source stem (if >0) for Open Hierarchy Source Inst, see stem_struct_t */ -unsigned kind : 7; /* Kind of the leaf: ghwlib reads this as val & 0x7f so only 7 bits needed */ +unsigned kind : 7; /* Kind of the leaf: libghw reads this as val & 0x7f so only 7 bits needed */ unsigned children_in_gui : 1; /* indicates that the child nodes are in the gtk2 tree, but gets borrowed during tree creation for fast judy sort */ char name[]; /* C99 */ }; diff -Nru gtkwave-3.3.104/src/treesearch_gtk2.c gtkwave-3.3.104+really3.3.118/src/treesearch_gtk2.c --- gtkwave-3.3.104/src/treesearch_gtk2.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/treesearch_gtk2.c 2023-12-31 21:11:05.000000000 +0000 @@ -371,7 +371,7 @@ gtk_clist_thaw(GTK_CLIST(ctree)); gtk_ctree_node_moveto(ctree, nodehist[depth-1], - depth /*column*/, + 0, /*column*/ /* was originally depth instead of zero */ 0.5 /*row_align*/, 0.5 /*col_align*/); /* printf("[treeopennode] '%s' ok\n", name); */ diff -Nru gtkwave-3.3.104/src/ttranslate.c gtkwave-3.3.104+really3.3.118/src/ttranslate.c --- gtkwave-3.3.104/src/ttranslate.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/ttranslate.c 2023-12-31 21:11:05.000000000 +0000 @@ -154,7 +154,7 @@ #if !defined __MINGW32__ && !defined _MSC_VER cmd = (char *)malloc_2(strlen(exec_name)+6+1); sprintf(cmd, "which %s", exec_name); - stream = popen(cmd, "r"); + stream = popen_san(cmd, "r"); result = fscanf(stream, "%s", abs_path); diff -Nru gtkwave-3.3.104/src/vcd.c gtkwave-3.3.104+really3.3.118/src/vcd.c --- gtkwave-3.3.104/src/vcd.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/vcd.c 2023-12-31 21:11:05.000000000 +0000 @@ -427,10 +427,10 @@ if(ch<=' ') break; } GLOBALS->yytext_vcd_c_1[len]=0; /* terminator */ +GLOBALS->yylen_vcd_c_1=len; if(is_string) { - GLOBALS->yylen_vcd_c_1=len; return(T_STRING); } @@ -549,7 +549,16 @@ { if(len==GLOBALS->T_MAX_STR_vcd_c_1) { - GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1); + if(!GLOBALS->varsplit_vcd_c_1) + { + GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1); + } + else /* TALOS-2023-1806 */ + { + int vsplit_len = GLOBALS->varsplit_vcd_c_1 - GLOBALS->yytext_vcd_c_1; /* save old len */ + GLOBALS->yytext_vcd_c_1=(char *)realloc_2(GLOBALS->yytext_vcd_c_1, (GLOBALS->T_MAX_STR_vcd_c_1=GLOBALS->T_MAX_STR_vcd_c_1*2)+1); + GLOBALS->varsplit_vcd_c_1 = GLOBALS->yytext_vcd_c_1+vsplit_len; /* reconstruct old len in new buffer */ + } } ch=getch(); @@ -962,7 +971,7 @@ } else { - if(GLOBALS->yylen_cache_vcd_c_1size) + if(GLOBALS->yylen_cache_vcd_c_1<=v->size) /* TALOS-2023-1804 */ { free_2(vector); vector=malloc_2(v->size+1); @@ -1183,7 +1192,7 @@ } T_GET; - if(tok==T_STRING) + if (tok!= T_END && tok != T_EOF) { struct slist *s; s=(struct slist *)calloc_2(1,sizeof(struct slist)); @@ -1245,7 +1254,7 @@ sync_end(NULL); break; case T_VAR: - if((GLOBALS->header_over_vcd_c_1)&&(0)) + if(GLOBALS->header_over_vcd_c_1) /* reinstated because of TALOS-2023-1805 */ { fprintf(stderr,"$VAR encountered after $ENDDEFINITIONS near byte %d. VCD is malformed, exiting.\n", (int)(GLOBALS->vcdbyteno_vcd_c_1+(GLOBALS->vst_vcd_c_1-GLOBALS->vcdbuf_vcd_c_1))); @@ -2213,7 +2222,7 @@ str=(slen>max_slen)?(wave_alloca((max_slen=slen)+32)):(str); /* more than enough */ strcpy(str,v->name); - if(v->msi>=0) + if((v->msi>=0)||(v->msi != v->lsi)) { strcpy(str+slen,GLOBALS->vcd_hier_delimeter); slen++; @@ -2626,7 +2635,7 @@ str=wave_alloca(strlen(fname)+dlen+1); strcpy(str,WAVE_DECOMPRESSOR); strcpy(str+dlen,fname); - GLOBALS->vcd_handle_vcd_c_1=popen(str,"r"); + GLOBALS->vcd_handle_vcd_c_1=popen_san(str,"r"); GLOBALS->vcd_is_compressed_vcd_c_1=~0; } else diff -Nru gtkwave-3.3.104/src/vcd_partial.c gtkwave-3.3.104+really3.3.118/src/vcd_partial.c --- gtkwave-3.3.104/src/vcd_partial.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/vcd_partial.c 2023-12-31 21:11:05.000000000 +0000 @@ -403,10 +403,10 @@ if(ch<=' ') break; } GLOBALS->yytext_vcd_partial_c_2[len]=0; /* terminator */ +GLOBALS->yylen_vcd_partial_c_2=len; if(is_string) { - GLOBALS->yylen_vcd_partial_c_2=len; return(T_STRING); } @@ -525,7 +525,16 @@ { if(len==GLOBALS->T_MAX_STR_vcd_partial_c_2) { - GLOBALS->yytext_vcd_partial_c_2=(char *)realloc_2(GLOBALS->yytext_vcd_partial_c_2, (GLOBALS->T_MAX_STR_vcd_partial_c_2=GLOBALS->T_MAX_STR_vcd_partial_c_2*2)+1); + if(!GLOBALS->varsplit_vcd_partial_c_2) + { + GLOBALS->yytext_vcd_partial_c_2=(char *)realloc_2(GLOBALS->yytext_vcd_partial_c_2, (GLOBALS->T_MAX_STR_vcd_partial_c_2=GLOBALS->T_MAX_STR_vcd_partial_c_2*2)+1); + } + else /* TALOS-2023-1806 */ + { + int vsplit_len = GLOBALS->varsplit_vcd_partial_c_2 - GLOBALS->yytext_vcd_partial_c_2; /* save old len */ + GLOBALS->yytext_vcd_partial_c_2=(char *)realloc_2(GLOBALS->yytext_vcd_partial_c_2, (GLOBALS->T_MAX_STR_vcd_partial_c_2=GLOBALS->T_MAX_STR_vcd_partial_c_2*2)+1); + GLOBALS->varsplit_vcd_partial_c_2 = GLOBALS->yytext_vcd_partial_c_2+vsplit_len; /* reconstruct old len in new buffer */ + } } ch=getch(); @@ -898,7 +907,7 @@ } else { - if(GLOBALS->yylen_cache_vcd_partial_c_2size) + if(GLOBALS->yylen_cache_vcd_partial_c_2<=v->size) /* TALOS-2023-1804 */ { free_2(vector); vector=malloc_2(v->size+1); @@ -1131,7 +1140,7 @@ } } T_GET; - if(tok==T_STRING) + if (tok!= T_END && tok != T_EOF) { struct slist *s; s=(struct slist *)calloc_2(1,sizeof(struct slist)); @@ -1193,11 +1202,11 @@ sync_end(NULL); break; case T_VAR: - if((GLOBALS->header_over_vcd_partial_c_2)&&(0)) + if(GLOBALS->header_over_vcd_partial_c_2) /* reinstated because of TALOS-2023-1805 */ { fprintf(stderr,"$VAR encountered after $ENDDEFINITIONS near byte %d. VCD is malformed, exiting.\n", (int)(GLOBALS->vcdbyteno_vcd_partial_c_2+(GLOBALS->vst_vcd_partial_c_2-GLOBALS->vcdbuf_vcd_partial_c_2))); - exit(0); + exit(255); } else { @@ -2055,7 +2064,7 @@ str=(slen>max_slen)?(wave_alloca((max_slen=slen)+32)):(str); /* more than enough */ strcpy(str,v->name); - if(v->msi>=0) + if((v->msi>=0)||(v->msi != v->lsi)) { strcpy(str+slen,GLOBALS->vcd_hier_delimeter); slen++; diff -Nru gtkwave-3.3.104/src/vcd_recoder.c gtkwave-3.3.104+really3.3.118/src/vcd_recoder.c --- gtkwave-3.3.104/src/vcd_recoder.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/vcd_recoder.c 2023-12-31 21:11:05.000000000 +0000 @@ -932,10 +932,10 @@ if(ch<=' ') break; } GLOBALS->yytext_vcd_recoder_c_3[len]=0; /* terminator */ +GLOBALS->yylen_vcd_recoder_c_3=len; if(is_string) { - GLOBALS->yylen_vcd_recoder_c_3=len; return(T_STRING); } @@ -1054,7 +1054,16 @@ { if(len==GLOBALS->T_MAX_STR_vcd_recoder_c_3) { - GLOBALS->yytext_vcd_recoder_c_3=(char *)realloc_2(GLOBALS->yytext_vcd_recoder_c_3, (GLOBALS->T_MAX_STR_vcd_recoder_c_3=GLOBALS->T_MAX_STR_vcd_recoder_c_3*2)+1); + if(!GLOBALS->varsplit_vcd_recoder_c_3) + { + GLOBALS->yytext_vcd_recoder_c_3=(char *)realloc_2(GLOBALS->yytext_vcd_recoder_c_3, (GLOBALS->T_MAX_STR_vcd_recoder_c_3=GLOBALS->T_MAX_STR_vcd_recoder_c_3*2)+1); + } + else /* TALOS-2023-1806 */ + { + int vsplit_len = GLOBALS->varsplit_vcd_recoder_c_3 - GLOBALS->yytext_vcd_recoder_c_3; /* save old len */ + GLOBALS->yytext_vcd_recoder_c_3=(char *)realloc_2(GLOBALS->yytext_vcd_recoder_c_3, (GLOBALS->T_MAX_STR_vcd_recoder_c_3=GLOBALS->T_MAX_STR_vcd_recoder_c_3*2)+1); + GLOBALS->varsplit_vcd_recoder_c_3 = GLOBALS->yytext_vcd_recoder_c_3+vsplit_len; /* reconstruct old len in new buffer */ + } } ch=getch(); @@ -1525,7 +1534,7 @@ } } T_GET; - if(tok==T_STRING) + if (tok != T_END && tok != T_EOF) { struct slist *s; s=(struct slist *)calloc_2(1,sizeof(struct slist)); @@ -1587,7 +1596,7 @@ sync_end(NULL); break; case T_VAR: - if((GLOBALS->header_over_vcd_recoder_c_3)&&(0)) + if(GLOBALS->header_over_vcd_recoder_c_3) /* reinstated because of TALOS-2023-1805 */ { fprintf(stderr,"$VAR encountered after $ENDDEFINITIONS near byte %d. VCD is malformed, exiting.\n", (int)(GLOBALS->vcdbyteno_vcd_recoder_c_3+(GLOBALS->vst_vcd_recoder_c_3-GLOBALS->vcdbuf_vcd_recoder_c_3))); @@ -2214,11 +2223,11 @@ he->v.h_val=heval; n->curr->next=he; - if(n->curr->v.h_val==heval) - { - n->curr->flags|=HIST_GLITCH; /* set the glitch flag */ - GLOBALS->num_glitch_regions_vcd_recoder_c_4++; - } + if(n->curr->v.h_val==heval) + { + n->curr->flags|=HIST_GLITCH; /* set the glitch flag */ + GLOBALS->num_glitch_regions_vcd_recoder_c_4++; + } n->curr=he; GLOBALS->regions+=regadd; } @@ -2448,7 +2457,7 @@ str=(slen>max_slen)?(wave_alloca((max_slen=slen)+32)):(str); /* more than enough */ strcpy(str,v->name); - if(v->msi>=0) + if((v->msi>=0)||(v->msi != v->lsi)) { strcpy(str+slen,GLOBALS->vcd_hier_delimeter); slen++; @@ -2816,7 +2825,7 @@ str=wave_alloca(strlen(fname)+dlen+1); strcpy(str,WAVE_DECOMPRESSOR); strcpy(str+dlen,fname); - GLOBALS->vcd_handle_vcd_recoder_c_2=popen(str,"r"); + GLOBALS->vcd_handle_vcd_recoder_c_2=popen_san(str,"r"); GLOBALS->vcd_is_compressed_vcd_recoder_c_2=~0; } else diff -Nru gtkwave-3.3.104/src/version.h gtkwave-3.3.104+really3.3.118/src/version.h --- gtkwave-3.3.104/src/version.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/version.h 2023-12-31 21:11:05.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) Tony Bybell 2010-2019. + * Copyright (c) Tony Bybell 2010-2023. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -10,6 +10,6 @@ #ifndef WAVE_VERSION_H #define WAVE_VERSION_H -#define WAVE_VERSION_INFO "GTKWave Analyzer v" PACKAGE_VERSION " (w)1999-2020 BSI" +#define WAVE_VERSION_INFO "GTKWave Analyzer v" PACKAGE_VERSION " (w)1999-2023 BSI" #endif diff -Nru gtkwave-3.3.104/src/wavealloca.h gtkwave-3.3.104+really3.3.118/src/wavealloca.h --- gtkwave-3.3.104/src/wavealloca.h 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/wavealloca.h 2023-12-31 21:11:05.000000000 +0000 @@ -18,6 +18,8 @@ * 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. + * + * SPDX-License-Identifier: MIT */ #ifndef WAVE_ALLOCA_H diff -Nru gtkwave-3.3.104/src/wavewindow.c gtkwave-3.3.104+really3.3.118/src/wavewindow.c --- gtkwave-3.3.104/src/wavewindow.c 2020-02-14 05:07:29.000000000 +0000 +++ gtkwave-3.3.104+really3.3.118/src/wavewindow.c 2023-12-31 21:11:05.000000000 +0000 @@ -3237,19 +3237,17 @@ yu=(_y0+_y1)/2; ytext=yu-(GLOBALS->wavefont->ascent/2)+GLOBALS->wavefont->ascent; +if((GLOBALS->highlight_wavewindow) && (t) && (t->flags & TR_HIGHLIGHT) && (!GLOBALS->black_and_white)&&(!kill_grid)) + { + gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, + TRUE,0, liney - GLOBALS->fontheight, + GLOBALS->wavewidth, GLOBALS->fontheight); + } +else if((GLOBALS->display_grid)&&(GLOBALS->enable_horiz_grid)&&(!kill_grid)) { - if((GLOBALS->highlight_wavewindow) && (t) && (t->flags & TR_HIGHLIGHT) && (!GLOBALS->black_and_white)) - { - gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, - TRUE,0, liney - GLOBALS->fontheight, - GLOBALS->wavewidth, GLOBALS->fontheight); - } - else - { - gdk_draw_line(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, - (GLOBALS->tims.starttims.first)?(GLOBALS->tims.first-GLOBALS->tims.start)*GLOBALS->pxns:0, liney,(GLOBALS->tims.last<=GLOBALS->tims.end)?(GLOBALS->tims.last-GLOBALS->tims.start)*GLOBALS->pxns:GLOBALS->wavewidth-1, liney); - } + gdk_draw_line(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, + (GLOBALS->tims.starttims.first)?(GLOBALS->tims.first-GLOBALS->tims.start)*GLOBALS->pxns:0, liney,(GLOBALS->tims.last<=GLOBALS->tims.end)?(GLOBALS->tims.last-GLOBALS->tims.start)*GLOBALS->pxns:GLOBALS->wavewidth-1, liney); } if((h)&&(GLOBALS->tims.start==h->time)) @@ -3996,31 +3994,33 @@ yu=(_y0+_y1)/2; ytext=yu-(GLOBALS->wavefont->ascent/2)+GLOBALS->wavefont->ascent; +if((GLOBALS->highlight_wavewindow) && (t) && (t->flags & TR_HIGHLIGHT) && (!GLOBALS->black_and_white)) + { + Trptr tn = GiveNextTrace(t); + if((t->flags & TR_ANALOGMASK) && (tn) && (tn->flags & TR_ANALOG_BLANK_STRETCH)) + { + gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, + TRUE,0, liney - GLOBALS->fontheight, + GLOBALS->wavewidth, GLOBALS->fontheight); + } + else + { + gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, + TRUE,0, liney - GLOBALS->fontheight, + GLOBALS->wavewidth, GLOBALS->fontheight); + } + } +else if((GLOBALS->display_grid)&&(GLOBALS->enable_horiz_grid)) { Trptr tn = GiveNextTrace(t); if((t->flags & TR_ANALOGMASK) && (tn) && (tn->flags & TR_ANALOG_BLANK_STRETCH)) { - if((GLOBALS->highlight_wavewindow) && (t) && (t->flags & TR_HIGHLIGHT) && (!GLOBALS->black_and_white)) - { - gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, - TRUE,0, liney - GLOBALS->fontheight, - GLOBALS->wavewidth, GLOBALS->fontheight); - } } else { - if((GLOBALS->highlight_wavewindow) && (t) && (t->flags & TR_HIGHLIGHT) && (!GLOBALS->black_and_white)) - { - gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, - TRUE,0, liney - GLOBALS->fontheight, - GLOBALS->wavewidth, GLOBALS->fontheight); - } - else - { - gdk_draw_line(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, - (GLOBALS->tims.starttims.first)?(GLOBALS->tims.first-GLOBALS->tims.start)*GLOBALS->pxns:0, liney,(GLOBALS->tims.last<=GLOBALS->tims.end)?(GLOBALS->tims.last-GLOBALS->tims.start)*GLOBALS->pxns:GLOBALS->wavewidth-1, liney); - } + gdk_draw_line(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, + (GLOBALS->tims.starttims.first)?(GLOBALS->tims.first-GLOBALS->tims.start)*GLOBALS->pxns:0, liney,(GLOBALS->tims.last<=GLOBALS->tims.end)?(GLOBALS->tims.last-GLOBALS->tims.start)*GLOBALS->pxns:GLOBALS->wavewidth-1, liney); } } @@ -4817,31 +4817,33 @@ yu=(_y0+_y1)/2; ytext=yu-(GLOBALS->wavefont->ascent/2)+GLOBALS->wavefont->ascent; +if((GLOBALS->highlight_wavewindow) && (t) && (t->flags & TR_HIGHLIGHT) && (!GLOBALS->black_and_white)) + { + Trptr tn = GiveNextTrace(t); + if((t->flags & TR_ANALOGMASK) && (tn) && (tn->flags & TR_ANALOG_BLANK_STRETCH)) + { + gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, + TRUE,0, liney - GLOBALS->fontheight, + GLOBALS->wavewidth, GLOBALS->fontheight); + } + else + { + gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, + TRUE,0, liney - GLOBALS->fontheight, + GLOBALS->wavewidth, GLOBALS->fontheight); + } + } +else if((GLOBALS->display_grid)&&(GLOBALS->enable_horiz_grid)) { Trptr tn = GiveNextTrace(t); if((t->flags & TR_ANALOGMASK) && (tn) && (tn->flags & TR_ANALOG_BLANK_STRETCH)) { - if((GLOBALS->highlight_wavewindow) && (t) && (t->flags & TR_HIGHLIGHT) && (!GLOBALS->black_and_white)) - { - gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, - TRUE,0, liney - GLOBALS->fontheight, - GLOBALS->wavewidth, GLOBALS->fontheight); - } } else { - if((GLOBALS->highlight_wavewindow) && (t) && (t->flags & TR_HIGHLIGHT) && (!GLOBALS->black_and_white)) - { - gdk_draw_rectangle(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, - TRUE,0, liney - GLOBALS->fontheight, - GLOBALS->wavewidth, GLOBALS->fontheight); - } - else - { - gdk_draw_line(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, - (GLOBALS->tims.starttims.first)?(GLOBALS->tims.first-GLOBALS->tims.start)*GLOBALS->pxns:0, liney,(GLOBALS->tims.last<=GLOBALS->tims.end)?(GLOBALS->tims.last-GLOBALS->tims.start)*GLOBALS->pxns:GLOBALS->wavewidth-1, liney); - } + gdk_draw_line(GLOBALS->wavepixmap_wavewindow_c_1, GLOBALS->gc.gc_grid_wavewindow_c_1, + (GLOBALS->tims.starttims.first)?(GLOBALS->tims.first-GLOBALS->tims.start)*GLOBALS->pxns:0, liney,(GLOBALS->tims.last<=GLOBALS->tims.end)?(GLOBALS->tims.last-GLOBALS->tims.start)*GLOBALS->pxns:GLOBALS->wavewidth-1, liney); } }