I'm having this error when I enable debug in Raspberry Pi:
"/home/pi/Downloads/flexprop/bin/flexspin" -2 -l -D_BAUD=230400 -O1 -g -I "/home/pi/Downloads/flexprop/include" "/home/pi/Documents/encoder_test_program.spin2"
Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2021 Total Spectrum Software Inc.
Version 5.0.8 Compiled on: Jan 23 2021
Unable to open file `libsys/fmt.c': No such file or directory
encoder_test_program.spin2
child process exited abnormally
Finished at Sat Jan 23 13:29:43 2021
Is there a fix or something I should install to have that file available?
What's in your /home/pi/Downloads/flexprop/include directory? There should be a subdirectory called "libsys", and inside that a file called "fmt.c".
I notice your directory is "Downloads/flexprop". Did you install by downloading a file? Or did you build with "make install"? If the latter, you do have to specify the directory you want to install to -- it defaults to $HOME/flexprop, so to put it somewhere else do:
I'm having this error when I enable debug in Raspberry Pi:
"/home/pi/Downloads/flexprop/bin/flexspin" -2 -l -D_BAUD=230400 -O1 -g -I "/home/pi/Downloads/flexprop/include" "/home/pi/Documents/encoder_test_program.spin2"
Propeller Spin/PASM Compiler 'FlexSpin' (c) 2011-2021 Total Spectrum Software Inc.
Version 5.0.8 Compiled on: Jan 23 2021
Unable to open file `libsys/fmt.c': No such file or directory
encoder_test_program.spin2
child process exited abnormally
Finished at Sat Jan 23 13:29:43 2021
Is there a fix or something I should install to have that file available?
What's in your /home/pi/Downloads/flexprop/include directory? There should be a subdirectory called "libsys", and inside that a file called "fmt.c".
I notice your directory is "Downloads/flexprop". Did you install by downloading a file? Or did you build with "make install"? If the latter, you do have to specify the directory you want to install to -- it defaults to $HOME/flexprop, so to put it somewhere else do:
"make install" failure with latest flexprop source (v5.0.8)... Not sure if this is a macOS (Big Sur 11.1) issue or a recent flexprop sources update issue.
After latest git pull, building with '$ make install', returns this error:
pandoc --metadata-file=pandoc.yml -s --toc -f gfm -t latex -o spin2cpp/Flexspin.pdf spin2cpp/Flexspin.md
pdflatex not found. Please select a different --pdf-engine or install pdflatex
make: *** [spin2cpp/Flexspin.pdf] Error 47
Note: on macOS Big Sur 11.1, pdflatex is located at: /Library/TeX/texbin/
To get this to work, I updated my z-shell PATH environment variable to include the /Library/TeX/texbin directory.
Added the following line to .zshrc and executed '$ source ~/.zshrc':
export PATH=/Library/TeX/texbin:$PATH
This works, but requires the modification to .zshrc, which seems odd, no?
"make install" failure with latest flexprop source (v5.0.8)... Not sure if this is a macOS (Big Sur 11.1) issue or a recent flexprop sources update issue.
It sure sounds like a MacOS configuration problem. The way the documentation is built in flexprop hasn't changed in a long time (siince before 5.0.0 anyway).
@ersmith I ran into this today trying to fix some code written by others. This is usually acceptable (if really UGLY) BASIC syntax but FlexBASIC doesn't like it:
if (zz=1) then print "DONE" else print "NOT DONE"
If you break it up properly with IF and ELSE and END IF on different lines it runs fine but Flex doesn't like an IF/THEN/ELSE all on the same line. Even adding colons between the statements doesn't fix it. Neither does adding an END IF. Or any combo thereof.
I think all this really needs is a mention in the manual because this syntax probably shouldnt be pandered to.
Not the way you probably want it to. Certainly not in FlexProp, and I can't imagine PNut would handle it as expected either. I think both compilers would parse it as:
If ( ($20 <= x) < $7E)
Since ($20<=x) always produces 0 or -1, the expression as a whole will always be TRUE.
The only language I'm aware of that allows that expression to work as one would like is Icon, in which the "false" value is a special thing that can never be confused with a number; there ($20 <= x) produces either x (if true) or the special FALSE value (if false), and FALSE compared with anything is FALSE.
You can also force a garbage collection event to run by calling _gc_collect(). Sometimes when memory is tight and and I want to trigger GC to happen on my own terms, this comes in handy.
@Rayman: For Rogue() you should be able to use the standard C malloc() and free() functions. Make sure you use free() after malloc(), the garbage collector won't re-use malloc'd blocks. Right now there's no way to tell how much memory is free. I should add that.
Ouch, I forgot to add _basic_priint_unsigned() to the list of things that should automatically cause libsys/fmt.c to be included. Mostly everything else is in there though so (for example) printing the newline at the end of a regular print will pull it in. That's why the bug only happens if you put a semicolon at the end of the print statement.
@ersmith : Thanks. What did you mean by "the garbage collector won't re-use malloc'd blocks."? I thought the whole point was to reuse malloc'd blocks that were freed...
@Rayman: I phrased that poorly. I meant the garbage collector won't automatically re-use blocks allocated by malloc(). They must be explicitly freed. This is not true of blocks allocated by _gc_alloc_managed(); for those blocks, the collector tries to figure out on its own whether the block is in use or not. If you forget to free it but there are no longer any references to it then the GC will free it for you when it needs to (when it runs out of memory or when _gc_collect() is called).
The issue for Rogue is in a subroutine that creates lists on the screen, like inventory (add_line() in things.c).
The code creates a new WINDOW object (and sub-object) for each line of text. <-- might be wrong about that..
I am using _gc_alloc_managed() and free() and _gc_collect(), but still run out of heap eventually...
I tried to get around this using statically defined WINDOW objects, but without success so far...
I just thought of another trick to try though... I'll try only calling _gc_alloc_managed() in this routine if the pointers are zero, so it uses the same place in memory every time...
Or, maybe I'll just remove interaction with curses (I see why it has that name now!).
If the pointers that are allocated are always freed with free(), then there's no benefit to using _gc_alloc_managed() instead of malloc(). It might help if this version of Rogue has a memory leak, but that's something tricky to find (maybe using valgrind on Linux or Windows would tell you).
I hadn't thought of running this on Windows... That might be a good idea... Thanks.
I've got another question: Can I "free" a structure in a subroutine that references it? I'm suspicious that this isn't working right...
The original had WINDOW as a class that was too complex...
Anyway, I have a structure destructor that looks like the below.
Does this look like it should work? It deletes some member data members from the heap and then itself.
Also, does free set the pointer to 0 when done?
Also, will free work on something that is going to still be used later?
int delwin(WINDOW* w)
{
//delete w;
if (w->parent == 0)
{//top level windows have data and dirtly, child windows do not
free(w->m_data);
free(w->m_dirty);
}
free(w);
if (w == curscr || w == stdscr)
{//RJA doesn't think we should ever get here...
curscr = 0;
stdscr = 0;
}
return OK;}
You can call free at any time that you are completely done using the pointer. Never try to dereference a pointer after the free. So no, free will definitely not work on something that is going to still be used later!!! Free does not set any pointer to 0, nor can it (C functions can not change the value of their parameters, that's a C++ feature).
Really, you shouldn't have to change any of the malloc/free code in Rogue, unless there's a memory leak (i.e. a bug in the original source code) . Or unless the code is written in C++ instead of C, but then you probably have bigger headaches.
The only thing you'll probably have to do is increase the HEAPSIZE in FlexC. You'll likely have to give it a ridiculously large amount of memory (at least 256K); the code probably expects that it has lots of space available.
Comments
Thank you @ersmith, will test immediately.
Awesome!!! Thank you Eric! It worked!
After latest git pull, building with '$ make install', returns this error: Note: on macOS Big Sur 11.1, pdflatex is located at: /Library/TeX/texbin/
To get this to work, I updated my z-shell PATH environment variable to include the /Library/TeX/texbin directory. This works, but requires the modification to .zshrc, which seems odd, no?
dgately
Using a structure created with malloc doesn't seem to be working... Is that something that should work?
I've used structures created with malloc() all the time, so you're going to have to be more specific about what you're having trouble with.
Thanks. Just wanted to make sure... I probably did something wrong then...
Remember that what malloc() returns is a pointer, so you'll have to use "->" to refer to members rather than ".".
I think that is what I did wrong...
I'm trying to convert some code that used "new" instead...
Is there a trick that lets one take that pointer to a structure and use it like a regular structure, so that it would work like "new"?
That's not how
new
works, either, it just returns a pointer.What you're probably after is reference semantics, which FlexCC (partially?) supports.
Oh wait... I actually need a pointer... Think I see why my code was crashing now... Thanks!
I had the thing I was making defined like this "WINDOW stdscr;" when it should have been like this "WINDOW *stdscr;".
Major blunder there... Things seem to work better now :)
I think all this really needs is a mention in the manual because this syntax probably shouldnt be pandered to.
Eric,
does this syntax work in spin2?
If ($20 <= x < $7E)
...
I'll see if I can figure some way to make it work, it is sometimes convenient to have a simple if/then/else like that.
Not the way you probably want it to. Certainly not in FlexProp, and I can't imagine PNut would handle it as expected either. I think both compilers would parse it as:
If ( ($20 <= x) < $7E)
Since ($20<=x) always produces 0 or -1, the expression as a whole will always be TRUE.
The only language I'm aware of that allows that expression to work as one would like is Icon, in which the "false" value is a special thing that can never be confused with a number; there ($20 <= x) produces either x (if true) or the special FALSE value (if false), and FALSE compared with anything is FALSE.
Thanks Eric. I thought I had seen something similar so I tried it and of course it failed.
FlexSpin seems to have compiled Rogue correctly. That's something! It's a really big program...
I just got to level 4 when malloc failed...
Maybe I need to allocate more heap, or maybe I'm not doing garbage collection correctly...
If malloc fails, should I try again? Or, does garbage collection occur before malloc returns?
Do I just call free() on the pointer from malloc for this to work? Or, is there something else?
You can also force a garbage collection event to run by calling _gc_collect(). Sometimes when memory is tight and and I want to trigger GC to happen on my own terms, this comes in handy.
Also, allocations made with
malloc
do not get garbage collected, use_gc_alloc_managed
for that.Also, the default heap size is only 4K on P2 (256 bytes on P1), you will probably want to increase it (by defining a HEAPSIZE enum constant)
Thanks! I was doing the enum, but not the _gc_alloc.... that might explain it.
Still running out of memory after a while...
Is there any function that tells you how much memory is free?
Guess I need to play around with the heap to see what's going wrong...
Update: I tested out the heap functions and they appear to work.
Added extra heap and can now get further in the game, so hopefully fixed.
@ersmith I'm getting an error when trying to print unsigned longs in FlexBASIC 5.0.8. This code shows it:
The error is: "_gc_:424: error: Undefined symbol _basic_print_unsigned"
Note that if you remove the semi-colon after "PRINT X", it compiles fine.
@Rayman: For Rogue() you should be able to use the standard C malloc() and free() functions. Make sure you use free() after malloc(), the garbage collector won't re-use malloc'd blocks. Right now there's no way to tell how much memory is free. I should add that.
Ouch, I forgot to add _basic_priint_unsigned() to the list of things that should automatically cause libsys/fmt.c to be included. Mostly everything else is in there though so (for example) printing the newline at the end of a regular print will pull it in. That's why the bug only happens if you put a semicolon at the end of the print statement.
@ersmith : Thanks. What did you mean by "the garbage collector won't re-use malloc'd blocks."? I thought the whole point was to reuse malloc'd blocks that were freed...
@Rayman: I phrased that poorly. I meant the garbage collector won't automatically re-use blocks allocated by malloc(). They must be explicitly freed. This is not true of blocks allocated by _gc_alloc_managed(); for those blocks, the collector tries to figure out on its own whether the block is in use or not. If you forget to free it but there are no longer any references to it then the GC will free it for you when it needs to (when it runs out of memory or when _gc_collect() is called).
The issue for Rogue is in a subroutine that creates lists on the screen, like inventory (add_line() in things.c).
The code creates a new WINDOW object (and sub-object) for each line of text.<-- might be wrong about that..I am using _gc_alloc_managed() and free() and _gc_collect(), but still run out of heap eventually...
I tried to get around this using statically defined WINDOW objects, but without success so far...
I just thought of another trick to try though... I'll try only calling _gc_alloc_managed() in this routine if the pointers are zero, so it uses the same place in memory every time...
Or, maybe I'll just remove interaction with curses (I see why it has that name now!).
If the pointers that are allocated are always freed with free(), then there's no benefit to using _gc_alloc_managed() instead of malloc(). It might help if this version of Rogue has a memory leak, but that's something tricky to find (maybe using valgrind on Linux or Windows would tell you).
I hadn't thought of running this on Windows... That might be a good idea... Thanks.
I've got another question: Can I "free" a structure in a subroutine that references it? I'm suspicious that this isn't working right...
The original had WINDOW as a class that was too complex...
Anyway, I have a structure destructor that looks like the below.
Does this look like it should work? It deletes some member data members from the heap and then itself.
Also, does free set the pointer to 0 when done?
Also, will free work on something that is going to still be used later?
You can call free at any time that you are completely done using the pointer. Never try to dereference a pointer after the free. So no, free will definitely not work on something that is going to still be used later!!! Free does not set any pointer to 0, nor can it (C functions can not change the value of their parameters, that's a C++ feature).
Really, you shouldn't have to change any of the malloc/free code in Rogue, unless there's a memory leak (i.e. a bug in the original source code) . Or unless the code is written in C++ instead of C, but then you probably have bigger headaches.
The only thing you'll probably have to do is increase the HEAPSIZE in FlexC. You'll likely have to give it a ridiculously large amount of memory (at least 256K); the code probably expects that it has lots of space available.