4

As a first project I have been writing a short program to render the Mandelbrot fractal. I have got to the point of trying to output my results to a file ( e.g. .bmp or .ppm ) and got stuck.

I have not really found any examples of exactly what I am trying to do, but I have found two examples of code to copy from one file to another.

The examples in the Gforth documentation ( Section 3.27 ) did not work for me ( winXP ) in fact they seemed to open and create files but not write to files properly.

This is the Gforth documentation example that copies the contents of one file to another:

0 Value fd-in
0 Value fd-out
: open-input ( addr u -- )  r/o open-file throw to fd-in ;
: open-output ( addr u -- )  w/o create-file throw to fd-out ;

s" foo.in" open-input
s" foo.out" open-output

: copy-file ( -- )
  begin
      line-buffer max-line fd-in read-line throw
  while
      line-buffer swap fd-out write-line throw
  repeat ;

I found this example ( http://rosettacode.org/wiki/File_IO#Forth ) which does work. The main problem is that I can't isolate the part that writes to a file and have it still work. The main confusion is that >r doesn't seem to consume TOS as I might expect.

: copy-file2 ( a1 n1 a2 n2 -- )
    r/o open-file throw >r
    w/o create-file throw r>
    begin
        pad maxstring  2 pick  read-file throw
    ?dup while
        pad swap  3 pick  write-file throw
    repeat
    close-file throw
    close-file throw ;

\ Invoke it like this:
    s" output.txt" s" input.txt" copy-file

I would be very grateful if someone could explain exactly how the open, create read and write -file words actually work, as my investigation keeps resulting in somewhat bizarre stacks.

Any clues as to why the Gforth examples do not work might help too.

In summary, I want to output from Gforth to a file and so far have been thwarted. Can anyone offer any help?


Thank you Vijay, I think that I understand the example that you gave. However when I try to use something like this ( which I think is similar ):

0 value test-file

: write-test
    s" testfile.out" w/o create-file throw to test-file
    s" test text" test-file write-line ;

I get ok but nothing is put into the file, have I made a mistake?


It seems that the problem was due to not flushing the relevant buffers or explicitly closing the file. Adding something like

test-file flush-file throw

or

test-file close-file throw

between write-line and ; makes it work. Consequently the Gforth documentation example would have worked had I followed the instructions.

Thanks again Vijay for helping.

sheepez
  • 986
  • 1
  • 10
  • 26
  • You should specify the length of the string as the second element on the stack: `s" test text" 9 test-file write-line` – Vijay Mathew Dec 21 '10 at 05:32
  • I think that `s" test text" ` leaves the starting address of the string in memory on the stack and then the length of the string. The example that you give give and Invalid Memory address error as the arguments to write-line are ` 9 9 `. – sheepez Dec 21 '10 at 15:06
  • do not add an answer inside your question. Just add a separate answer yourself. – Albert van der Horst Jul 12 '18 at 14:04

2 Answers2

1

I will try to explain how write-line works with this simple example. Here we have a buffer that contains the string " hello", and we want to write that to a file opened with open-output.

buffer 5 fd-out write-line

5 is the length of the buffer. fd-out is the open file handle. A call to write-line will leave an integer result on the stack, the value of which is implementation dependent. More information on the file I/O words could be found in File Access words.

Calling the word throw is optional. It will check the integer value on the top of the stack and based on that value either pops the topmost exception frame from the exception stack or call abort or display an implementation-dependent message giving information about the condition associated with the integer. (Exact details on how throw works could be found in THROW).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vijay Mathew
  • 26,737
  • 4
  • 62
  • 93
  • I have added an addendum to my original question, mainly because I couldn't format it properly in a comment. – sheepez Dec 20 '10 at 15:11
0

You program is incomplete, which makes the question hard to answer.

With prepending

 1024 CONSTANT max-line
 CREATE line-buffer max-line 3 + ALLOT

and postpending

copy-file
fd-in close-file  throw
fd-out close-file  throw

and after creating a testfile foo.in gforth the first program works flawlessly on Debian.

Probably your problem is caused by not properly closing the file after writing.