1

I am using Ubuntu 20.04.2 LTS via VMWare on macOS BigSur. I have the latest versions of tcl, tcl-dev, tk and tk-dev installed - version 8.6. I want to compile the source code for the Architecture lab project. The source code is from 2016 and located in the self-study handout. Compilation fails [with error messages detailed below], possibly due to the source code relying of tcl8.5 instead of the latest version. Would installing versions 8.5 of these packages solve the problem?

To make the GUIs work, in the project Makefile I need to assign one variable [which I have done] and update two more so that gcc can find the relevant libraries [libtcl.so and libtk.so] and header files [tcl.h and tk.h].

# ******* variable 1 **********

# Assigning GUIMODE=-DHAS_GUI causes the necessary GUI support code in the simulator sources to be included.
GUIMODE=-DHAS_GUI

# ******* variable 2 **********

# Modify the following line so that gcc can find the libtcl.so and
# libtk.so libraries on your system. You may need to use the -L option
# to tell gcc which directory to look in. Comment this out if you
# don't have Tcl/Tk.

# TKLIBS variable tells gcc where to look for the libtcl.so and libtk.so libraries.
# TKLIBS=-L/usr/lib -ltk -ltcl

# ******* variable 3 **********

# Modify the following line so that gcc can find the tcl.h and tk.h
# header files on your system. Comment this out if you don't have
# Tcl/Tk.

# TKINC variable tells gcc where to find the tcl.h and tk.h header files.
# TKINC=-isystem /usr/include/tcl8.5

##################################################
# You shouldn't need to modify anything below here
##################################################

# Use this rule (make all) to build the Y86-64 tools. The variables you've
# assigned to GUIMODE, TKLIBS, and TKINC will override the values that
# are currently assigned in seq/Makefile and pipe/Makefile.
all:
        (cd misc; make all)
        (cd pipe; make all GUIMODE=$(GUIMODE) TKLIBS="$(TKLIBS)" TKINC="$(TKINC)")
        (cd seq; make all GUIMODE=$(GUIMODE) TKLIBS="$(TKLIBS)" TKINC="$(TKINC)")
        (cd y86-code; make all)

clean:
        rm -f *~ core
        (cd misc; make clean)
        (cd pipe; make clean)
        (cd seq; make clean)
        (cd y86-code; make clean)
        (cd ptest; make clean)

Based on

$ locate libtcl.so
/usr/lib/x86_64-linux-gnu/libtcl.so

$ locate libtk.so
/usr/lib/x86_64-linux-gnu/libtk.so

I updated TKLIBS to

TKLIBS=-L/usr/lib/x86_64-linux-gnu -ltk -ltcl

The tcl.h and tk.h header files are in:

$ locate tcl.h
/usr/include/tcl8.6/tcl.h
/usr/include/tcl8.6/tcl-private/generic/tcl.h

$ locate tk.h
/usr/include/tcl8.6/tk.h
/usr/include/tcl8.6/tk-private/generic/tk.h
/And many other folders, but only these two locations also have tcl.h

When I update TKINC to

TKINC=-isystem /usr/include/tcl8.6

I get the following errors.

az@ubuntu:~/Desktop/archlab-handout/sim$ make clean; make
rm -f *~ core
(cd misc; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/misc'
rm -f *.o *.yo *.exe yis yas hcl2c mux4 *~ core.* 
rm -f hcl.tab.c hcl.tab.h lex.yy.c yas-grammar.c
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/misc'
(cd pipe; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/pipe'
rm -f psim pipe-*.c *.o *.exe *~ 
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/pipe'
(cd seq; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/seq'
rm -f ssim ssim+ seq*-*.c *.o *~ *.exe *.yo *.ys
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/seq'
(cd y86-code; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/y86-code'
rm -f *.o *.yis *~ *.yo *.pipe *.seq *.seq+ core
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/y86-code'
(cd ptest; make clean)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/ptest'
rm -f *.o *~ *.yo *.ys
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/ptest'
(cd misc; make all)
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/misc'
gcc -Wall -O1 -g -c yis.c
gcc -Wall -O1 -g -c isa.c
gcc -Wall -O1 -g yis.o isa.o -o yis
gcc -Wall -O1 -g -c yas.c
flex yas-grammar.lex
mv lex.yy.c yas-grammar.c
gcc -O1 -c yas-grammar.c
gcc -Wall -O1 -g yas-grammar.o yas.o isa.o -lfl -o yas
bison -d hcl.y
flex hcl.lex
gcc -O1 node.c lex.yy.c hcl.tab.c outgen.c -o hcl2c
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/misc'
(cd pipe; make all GUIMODE=-DHAS_GUI TKLIBS="-L/usr/lib/x86_64-linux-gnu -ltk -ltcl" TKINC="-isystem /usr/include/tcl8.6")
make[1]: Entering directory '/home/az/Desktop/archlab-handout/sim/pipe'
# Building the pipe-std.hcl version of PIPE
../misc/hcl2c -n pipe-std.hcl < pipe-std.hcl > pipe-std.c
gcc -Wall -O2 -isystem /usr/include/tcl8.6 -I../misc -DHAS_GUI -o psim psim.c pipe-std.c \
    ../misc/isa.c -L/usr/lib/x86_64-linux-gnu -ltk -ltcl -lm
psim.c: In function ‘simResetCmd’:
psim.c:853:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  853 |  interp->result = "No arguments allowed";
      |        ^~
psim.c:861:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  861 |     interp->result = stat_name(STAT_AOK);
      |           ^~
psim.c: In function ‘simLoadCodeCmd’:
psim.c:872:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  872 |  interp->result = "One argument required";
      |        ^~
psim.c:878:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  878 |  interp->result = tcl_msg;
      |        ^~
psim.c:885:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  885 |     interp->result = tcl_msg;
      |           ^~
psim.c: In function ‘simLoadDataCmd’:
psim.c:895:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  895 |     interp->result = "Not implemented";
      |           ^~
psim.c:901:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  901 |  interp->result = "One argument required";
      |        ^~
psim.c:907:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  907 |  interp->result = tcl_msg;
      |        ^~
psim.c:911:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  911 |     interp->result = tcl_msg;
      |           ^~
psim.c: In function ‘simRunCmd’:
psim.c:925:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  925 |  interp->result = "At most one argument allowed";
      |        ^~
psim.c:932:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  932 |  interp->result = tcl_msg;
      |        ^~
psim.c:936:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  936 |     interp->result = stat_name(status);
      |           ^~
psim.c: In function ‘simModeCmd’:
psim.c:945:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  945 |  interp->result = "One argument required";
      |        ^~
psim.c:948:11: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  948 |     interp->result = argv[1];
      |           ^~
psim.c:957:8: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  957 |  interp->result = tcl_msg;
      |        ^~
psim.c: In function ‘signal_register_update’:
psim.c:994:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
  994 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘create_memory_display’:
psim.c:1005:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1005 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c:1020:60: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1020 |      fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                            ^~
psim.c: In function ‘set_memory’:
psim.c:1055:60: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1055 |      fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                            ^~
psim.c: In function ‘show_cc’:
psim.c:1069:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1069 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘show_stat’:
psim.c:1081:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1081 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘show_cpi’:
psim.c:1096:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1096 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘signal_sources’:
psim.c:1110:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1110 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘signal_register_clear’:
psim.c:1120:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1120 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘report_line’:
psim.c:1134:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1134 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘report_pc’:
psim.c:1190:56: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1190 |  fprintf(stderr, "Error Message was '%s'\n", sim_interp->result);
      |                                                        ^~
psim.c: In function ‘report_state’:
psim.c:1204:58: error: ‘Tcl_Interp’ {aka ‘struct Tcl_Interp’} has no member named ‘result’
 1204 |  fprintf(stderr, "\tError Message was '%s'\n", sim_interp->result);
      |                                                          ^~
make[1]: *** [Makefile:44: psim] Error 1
make[1]: Leaving directory '/home/az/Desktop/archlab-handout/sim/pipe'
make: *** [Makefile:30: all] Error 2

psim.c has 1000+ lines of code and the part that causes the first error is on line 853:

/******************************************************************************
 *      tcl command definitions
 ******************************************************************************/

/* Implement command versions of the simulation functions */
int simResetCmd(ClientData clientData, Tcl_Interp *interp,
                int argc, char *argv[])
{
    sim_interp = interp;
    if (argc != 1) {
        interp->result = "No arguments allowed";
        return TCL_ERROR;
    }
    sim_reset();
    if (post_load_mem) {
        free_mem(mem);
        mem = copy_mem(post_load_mem);
    }
    interp->result = stat_name(STAT_AOK);
    return TCL_OK;
}

Could this be due the different tcl/tk versions? I wonder if version 8.5 would help as hinted by the default value of the TKINC variable in the Makefile.

How can I install versions 8.5 and ensure that gcc uses that version?

Thanks.

azxz
  • 13
  • 3
  • Access to the internals of that structure is now rather strongly deprecated. It was bad practice even in 8.5 and hasn't in fact been a recommended thing since 8.0 was released, which is over 20 years ago. I guess some people just don't update their code very often! – Donal Fellows Feb 23 '21 at 12:40

1 Answers1

2

Direct access to the Tcl_Interp struct has for long been deprecated. Given that this is a single source file (psim.c), you might want to patch it to properly use:

  • Tcl_SetResult(), for example: Change interp->result = "No arguments allowed"; to Tcl_SetResult(interp, "No arguments allowed", TCL_STATIC);
  • Tcl_GetStringResult(), for example: Change fprintf(stderr, "Error Message was '%s'\n", sim_interp->result); to fprintf(stderr, "Error Message was '%s'\n", Tcl_GetStringResult(sim_interp));

This is backwards compatible.


Not recommended, but doable: Set the macro

#define USE_INTERP_RESULT

See also Deprecated Interfaces / Direct access to interp->result.

mrcalvin
  • 3,291
  • 12
  • 18
  • Note that setting `USE_INTERP_RESULT` is very much an “Aaargh! I need to build this code now!” workaround, and not something that people can expect to be supported going forward; it _particularly_ has no chance at all of working in 9.0 when that's released. – Donal Fellows Feb 23 '21 at 12:42
  • @mrcalvin. I have now updated psim.c with the patch as you outlined. Compilation now does not raise any of the errors mentioned in my original message. However, some errors persist which I suspect are unrelated to tcl, but where my variable TKLIBS looks for libtcl.so and libtk.so libraries. The errors follow this comment: "undefined reference to `matherr' " – azxz Feb 23 '21 at 14:55
  • Yes, `matherr` is a symbol that is not available anymore in modern glibc. See, for example, https://stackoverflow.com/questions/52903488/fail-to-build-y86-64-simulator-from-sources – mrcalvin Feb 23 '21 at 15:24
  • 1
    References to matherr removed from psim.c and ssim.c. Compilation completes without errors and initial trials show that the GUI simulators work fine. – azxz Feb 24 '21 at 09:59