Making Hugo Programs

This is a discussion / support forum for the Hugo programming language by Kent Tessman. Hugo is a powerful programming language for making text games / interactive fiction with multimedia support.

Hugo download links: https://www.generalcoffee.com/hugo
Roody Yogurt's Hugo Blog: https://notdeadhugo.blogspot.com
The Hugor interpreter by RealNC: http://ifwiki.org/index.php/Hugor

Moderators: Ice Cream Jonsey, joltcountry

ICJ

Post by ICJ »

Hm, didn't see your note till just now. I actually hopped on my Mac, did a make and tried to compile Cyberganked.

I get this:

➜ cyberganked2 git:(master) ✗ ./hc cyberganked.hug
[1] 41939 abort ./hc cyberganked.hug

Just putting this here for now.

bruce
Posts: 2544
Joined: Tue Jun 04, 2002 10:43 pm

Post by bruce »

So how about making with the source?

I can compile Colossal Cave and start it and play to releasing the bird at the snake (all on my Mac) and it seems to be fine.

User avatar
Ice Cream Jonsey
Posts: 28877
Joined: Sat Apr 27, 2002 2:44 pm
Location: Colorado
Contact:

Post by Ice Cream Jonsey »

Hmm. Bet it has something to do with the long file names in the WIP. Well, not long file names, but the subdirectories and filenames blew up the Unix version 'fore I fixed it.

Sent you an invitation to your f*s*f address. Through bitbucket. Thanks, man.
the dark and gritty...Ice Cream Jonsey!

bruce
Posts: 2544
Joined: Tue Jun 04, 2002 10:43 pm

Post by bruce »

Well, a little dicking around (Mavericks doesn't include gdb anymore, so I needed to switch compiler to clang and then run under lldb) shows where it's crashing:

Code: Select all

(lldb) bt
* thread #1: tid = 0x7e19f, 0x00007fff9034e286 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
  * frame #0: 0x00007fff9034e286 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff9247542f libsystem_pthread.dylib`pthread_kill + 90
    frame #2: 0x00007fff8cb65b53 libsystem_c.dylib`abort + 129
    frame #3: 0x00007fff8cb65cca libsystem_c.dylib`abort_report_np + 181
    frame #4: 0x00007fff8cb8bdb0 libsystem_c.dylib`__chk_fail + 48
    frame #5: 0x00007fff8cb8bdc0 libsystem_c.dylib`__chk_fail_overlap + 16
    frame #6: 0x00007fff8cb8bde2 libsystem_c.dylib`__chk_overlap + 34
    frame #7: 0x00007fff8cb8c117 libsystem_c.dylib`__strcat_chk + 81
    frame #8: 0x0000000100016cf9 hc`CompilerMem + 217 at hccomp.c:332
    frame #9: 0x0000000100017766 hc`Pass1 + 422 at hcpass.c:91
    frame #10: 0x0000000100000dbb hc`main(argc=2, argv=0x00007fff5fbffb50) + 171 at hc.c:64
    frame #11: 0x00007fff8ca9f5c9 libdyld.dylib`start + 1
So then we go to hccomp.c:

Code: Select all

                        strcpy(buffer, word[1]);
                        strcat(buffer, word[2]);
                        strcat(buffer, word[3]);
                        word[1] = buffer;
                        words = 1;
It's that first strcat.

buffer is defined as extern char[] in hcheader.h.

There is no definition of buffer in hccomp.c.

So I guess it's getting implicitly initialized to some fixed size by strcpy? And then you're immediately appending to it, and the compiler is getting nervous?

So we simply declare buffer as char[256] at the top of CompilerMem.

Compilation now succeeds. And running the game in Hugor looks like it works. But still, let's see what else we find in the CLI tools.

Now he fails in the same way.

Code: Select all

    frame #7: 0x00007fff8cb8bfbf libsystem_c.dylib`__strcpy_chk + 64
    frame #8: 0x000000010001a8e1 he`hugo_splitpath(path=0x00007fff5fbffc48, drive=0x00007fff5fbff9f0, dir=0x00007fff5fbff8f0, fname=0x00007fff5fbff7f0, ext=0x00007fff5fbff6f0) + 849 at hegcc.c:165
....which is....

Code: Select all

        if (strcmp(dir, "") && fname[0]=='/') strcpy(fname, fname+1);
man strcpy tells us:

Code: Select all

     The source and destination strings should not overlap, as the behavior is undefined.
Apparently gcc on Linux lets you get away with that.

So let's replace that with a cheesy strcpy implementation instead.

Code: Select all

        if (strcmp(dir, "") && fname[0]=='/') {
          int i = 0;
          while(1) {
            fname[i]=fname[++i];
            if (fname[i] == '\0') break;
          }
        }
And now he also runs cyberganked.hex.

Moral of the story: string handling in C blows.

bruce
Posts: 2544
Joined: Tue Jun 04, 2002 10:43 pm

Post by bruce »

Does Kent read this forum?

Here are the patches. No idea if 256 bytes is really right for the buffer, or if we're really guaranteed that fname is null-terminated, but hey. You get what you pay for.

Code: Select all

--- hegcc.orig	2014-11-26 20:03:42.000000000 -0600
+++ hegcc.c	2014-11-26 20:11:15.000000000 -0600
@@ -162,7 +162,13 @@
         }
         else strcpy(fname,file);
 
-        if (strcmp(dir, "") && fname[0]=='/') strcpy(fname, fname+1);
+        if (strcmp(dir, "") && fname[0]=='/') {
+	  int i = 0;
+	  while(1) {
+	    fname[i]=fname[++i];
+	    if (fname[i] == '\0') break;
+	  }
+	}
 }

Code: Select all

--- hccomp.c.orig	2014-11-26 19:42:06.000000000 -0600
+++ hccomp.c	2014-11-26 19:53:39.000000000 -0600
@@ -317,6 +317,7 @@
 void CompilerMem(void)
 {
 	char e[64];
+	char buffer[256];
 
 	strcpy(e, "");

User avatar
Ice Cream Jonsey
Posts: 28877
Joined: Sat Apr 27, 2002 2:44 pm
Location: Colorado
Contact:

Post by Ice Cream Jonsey »

It's the bees knees.

^_____________^

I just wrote Kent on the mud to seeing about getting this patched officially. I will test it on my Mac when I go to work next.

Thanks, man. You have saved an entire race of people with this.
the dark and gritty...Ice Cream Jonsey!

Roody_Yogurt
Posts: 2179
Joined: Mon Apr 29, 2002 6:23 pm
Location: Milwaukee

Post by Roody_Yogurt »

Awesome, bruce!

User avatar
Ice Cream Jonsey
Posts: 28877
Joined: Sat Apr 27, 2002 2:44 pm
Location: Colorado
Contact:

Post by Ice Cream Jonsey »

Posting this link as the download locations are included:

http://www.joltcountry.com/phpBB2/viewtopic.php?t=9511
the dark and gritty...Ice Cream Jonsey!

Post Reply