Advanced features. 4tH 4tH Forth compiler
Реклама
Реклама
CHAPTER 4. A GUIDED TOUR 51 flush l
Scr # 0
0 ( Conversion from UNIX ASCII files to DOS ASCII files - I)
1
2 : ProcessFile
3
4
5
6
7 begin refill while
0 parse-word type 13 emit 10 emit
8
9 ; repeat
10
11 : test s" code.txt" input open s" out.txt" output open
12 error? rot error? rot or abort" Error!" use use ;
13 test ProcessFile
14
15
^test ProcessFile 13 OK
Seems to be okay. Let’s go back to the main 4tH screen by issuing the ”wq” command. We recompile the source by pressing ”c” and presto: we got a program! Simply hit ”r” to run it. After we’ve run the program we find a file named ”out.txt” in our working directory and examine it with a hex editor:
4261 6445 7865 6375 7465 2028 202d 2d20
2920 2d34 2045 5845 4355 5445 203b 0d0a
3a20 4261 6441 6464 7265 7373 2028 202d
2d20 2920 2d34 2040 2044 524f 5020 3b0d
0a3a 2042 6164 416c 6967 6e20 2820 2d2d
2029 2031 2040 2044 524f 5020 3b0d 0a
It seems our program is working perfectly. However, it doesn’t seem very practical to copy a textfile to your working directory, rename it, start up 4tH, load your program and finally run it. That can be fixed. How? Well, you’ll read that in the next section.
But first we have to stress that you don’t have to use 4tHs editor. You can use any editor you like. Shame you’ve already entered and saved your source. But there is a way out. And you don’t have to go too far. Just start up the editor again and enter:
OK export convert.4th
OK
You’ll find an ordinary file called ”convert.4th” in your working directory hat you can modify with any text editor you like.
4.7
Advanced features
What we actually want is a program we can run from the prompt, something like: convert in.txt out.txt
And if you do not provide the required parameters it has to issue an error message:
CHAPTER 4. A GUIDED TOUR
Usage: convert infile outfile
52
We will get there, but we still have some coding to do. First of all, we have to structure our program. We already have a working word
3 called ”ProcessFile”. It seems like a good idea to define two others, one that opens the files and one that closes the files. And we have to get rid of our ”test” word. So let’s fire up the editor and take care of that right now:
OK
0 list
Scr # 0
0 ( Conversion from UNIX ASCII files to DOS ASCII files - I)
1
2 : ProcessFile
3
4
5
6
7 begin refill while
0 parse-word type 13 emit 10 emit
8
9 ; repeat
10
11 : test s" code.txt" input open s" out.txt" output open
12 error? rot error? rot or abort" Error!" use use ;
13 test ProcessFile
14
15
OK
11 d l
Scr # 0
0 ( Conversion from UNIX ASCII files to DOS ASCII files - I)
1
2 : ProcessFile
3 begin
4
5
6
7
8 refill while
0 parse-word type 13 emit 10 emit repeat
9 ;
10
11 error? rot error? rot or abort" Error!" use use ;
12 test ProcessFile
13
14
15
^( Conversion from UNIX ASCII files to DOS ASCII files - I) 0 OK
You can remove lines with the ”d” command, which stands for ”DELETE”. This will remove the line and move all remaining lines up. Line 15 becomes blank. But there is another way to get rid of unwanted lines:
11 e l
Scr # 0
0 ( Convert UNIX ASCII files to DOS ASCII files - I)
1
2 : ProcessFile
3 begin
3
A subroutine in Forth is called a ”word”, remember?
CHAPTER 4. A GUIDED TOUR 53
4
5
6
7
8
9 ; refill while
0 parse-word type 13 emit 10 emit repeat
10
11
12 test ProcessFile
13
14
15
^( Convert UNIX ASCII files to DOS ASCII files - I) 0 OK
The ”e” command, which stands for ”ERASE”, will leave every line at exactly the same position. It just blanks that line. Let’s finish this:
11 p : Convert OpenFiles ProcessFile ;
OK
12 e
OK
13 p Convert
OK l
Scr # 0
0 ( Convert UNIX ASCII files to DOS ASCII files - I)
1
2 : ProcessFile
3 begin
4 refill
5
6
7
8
9 ; while
0 parse-word type 13 emit 10 emit repeat
10
11 : Convert OpenFiles ProcessFile ;
12
13 Convert
14
15
^( Convert UNIX ASCII files to DOS ASCII files - I) 0 OK
Seems neat enough, but we still haven’t got a ”OpenFiles” word. This has to be defined before ”Convert”, but do we have still have room for that on screen 0? No, we haven’t.
Fortunately, you can insert screens with the 4tH editor
4
. Don’t forget to flush. That is not only a good practice when you’ve visited the bathroom, but also when you’re working with a Forth editor: flush 0 insert
OK
We start our screen with a comment of course. We’ll use the same comment as in our previous screen, so why not copy it?
1 list 0 h 0 list 0 r l
4
Note that this command is usually not available in other Forth editors!
CHAPTER 4. A GUIDED TOUR 54
10
11
12
13
14
5
6
7
8
9
15
Scr # 0
0 ( Convert UNIX ASCII files to DOS ASCII files - I)
1
2
3
4
^( Convert UNIX ASCII files to DOS ASCII files - I) 0 OK
What did we do here? First, we switched to screen 1, which is our previous screen 0. Then we used the ”h”
5 command, which copied line 0 into PAD. PAD is a buffer, which is able to hold the contents of a single line. Note that line 0 of screen 1 remains intact. It is only copied.
Then we switched back to screen 0 and issued the ”r” command, which stands for ”RE-
PLACE”. It replaces whatever is there with the contents of the PAD. Finally, we listed the screen. Let’s play around a little with this PAD thing:
1 r 1 t
^( Convert UNIX ASCII files to DOS ASCII files - I) 1 OK
Yes, the line we copied was still in PAD! We also used the command ”t” to ”TYPE” line 1.
This command is very similar to ”h”, since it copies line 1 to PAD. But is also moves the cursor to the beginning of the line and types it. Let’s see if you can explain this one:
1 d 2 r 2 t
^( Convert UNIX ASCII files to DOS ASCII files - I) 2 OK
Sure, the ”d” command not only deletes the line, it also copies it to PAD. So when the ”r” command is issued, it replaces line 2 with the contents of the line we deleted. Let’s do one final test:
0 i l
Scr # 0
0 ( Convert UNIX ASCII files to DOS ASCII files - I)
1 ( Convert UNIX ASCII files to DOS ASCII files - I)
2
3 ( Convert UNIX ASCII files to DOS ASCII files - I)
4
5
6
7
8
9
10
5
In case you wondered, ”h” stands for ”HOLD”.
CHAPTER 4. A GUIDED TOUR 55
11
12
13
14
15
^ 2 OK
Here we used the ”i” command, which stands for ”INSERT”. It inserted the contents of
PAD at line 0 and moved all the remaining lines down. Note that the cursor didn’t move a bit. That’s enough play for one day, let’s get back to work:
1 e 3 e 2 p : OpenFile
OK
3 p
OK args 2dup 2>r rot open error?
if 4 p
OK
5 p
OK
6 p drop ." Cannot open " 2r> type cr abort else
OK
7 p
OK
8 p
OK
9 p ;
OK l dup use 2r> 2drop then
11
12
13
14
15
5
6
7
8
9 ;
10
Scr # 0
0 ( Conversion from UNIX ASCII files to DOS ASCII files - I)
1
2 : OpenFile
3 args 2dup 2>r rot open error?
4 if drop ." Cannot open " 2r> type cr abort else dup use 2r> 2drop then
^( Conversion from UNIX ASCII files to DOS ASCII files - I) 0 OK
Hmm, it seems like we’re going to need another screen. It is always wise to leave some room for future extensions, so this screen is full enough. But don’t forget the commentline.
We don’t want to enter that one again, so let’s store it in PAD:
0 h flush 1 insert 0 r l
Scr # 1
0 ( Convert UNIX ASCII files to DOS ASCII files - I)
1
2
3
4
5
6
CHAPTER 4. A GUIDED TOUR 56
^
7
8
9
10
11
12
13
14
15
2 OK
Hold the line in PAD, flush the screen, insert screen 1 and replace line 0 with the contents in PAD. But the commentline is not entirely correct, so let’s fix it: top x I)
( Convert UNIX ASCII files to DOS ASCII files - ^ c II)
( Convert UNIX ASCII files to DOS ASCII files - II)^
0 OK
0 OK
The cursor is still on line 2, so we move it to the top again. Then we find and delete ”I)”.
Finally we copy in ”II)”. We can do that since the cursor is at the right position. Now let’s enter our final word:
2 p : OpenFiles
OK
3 p argn 3 < abort" Usage: convert infile outfile"
OK
4 p
OK
5 p
OK input 1 OpenFile output 2 Openfile
6 p ;
OK l
10
11
12
13
14
15
Scr # 1
0 ( Conversion from UNIX ASCII files to DOS ASCII files - II)
1
2 : OpenFiles
3 argn 3 < abort" Usage: convert infile outfile"
4 input 1 OpenFile output 2 Openfile 5
6 ;
7
8
9
^( Conversion from UNIX ASCII files to DOS ASCII files - II) 0 OK
Almost there! We just have to fix the commentline in screen 2: flush 2 list
OK top x I)
CHAPTER 4. A GUIDED TOUR 57
( Convert UNIX ASCII files to DOS ASCII files - ^ c III)
( Convert UNIX ASCII files to DOS ASCII files - III)^
0 OK
0 OK
The current screen is flushed, then screen 2 is listed. We position the cursor at the top, find and delete ”I)” and copy ”III)” in at the cursor position. Done! Let’s leave the editor and see what we have got. It compiles cleanly and when we run it it answers:
Usage: convert infile outfile
Sure, but what we actually want is to convert a file. Well, you can do that too without leaving 4tH. Just press ”a” and enter the filenames, just like you would do at the prompt:
(S)creen file: convert.scr
(O)bject file: out
(E)dit (C)ompile (R)un (A)rguments
(Q)uit (G)enerate (B)uild (D)ecompile
>a
Arguments: code.txt out.txt
When you press ”r” now, the arguments entered will be passed to your 4tH program, just like they would at the prompt. To clear the arguments, press ”a” again and just hit enter when prompted for arguments.
But how do we run it from the prompt? Easy, just press ”o” and enter ”convert.hx” at the prompt. Now press ”b”:
(S)creen file: convert.scr
(O)bject file: convert.hx
(E)dit (C)ompile (R)un (A)rguments
(Q)uit (G)enerate (B)uild (D)ecompile
>b
If 4tH has nothing to complain about, it doesn’t complain, so you can safely assume that everything is okay. Now we can go to the prompt
6 and run it: user@linux:~ > 4th lxq convert.hx code out.txt
Cannot open code user@linux:~ >
That was to be expected. Our file was called ”code.txt”, not ”code”. It is always a good idea to test all exceptions as well. There could be a bug in that code too.
user@linux:~ > 4th lxq convert.hx code.txt out.txt
user@linux:~ >
6
Windows users can do this by starting an MS-DOS session.
CHAPTER 4. A GUIDED TOUR 58
Well, it seems to work.. But what we really want is a standalone program. One that can be run without invoking 4tH and shared with our friends and families. Why this ”.hx” thing? HX-files do have their merits. First of all, it is very small, less than 200 bytes. But most importantly, you can take this file and run it on a Windows NT, MS-DOS or other
Unix machine without modification or recompilation, provided a 4tH is available for that platform.
If you still want a standalone program, startup 4tH and reload ”convert.scr”. Then press
”o” and enter ”convert.c”. Isn’t that the extension of a C-program? Yes, it is. 4tH is able to generate C code. Just press ”g” and you’ve created a C program. You don’t even have to know C. If you know how to compile a C program that’s more than enough
7
. We assume you’ve installed the 4tH library and header files, since those are needed to compile
”convert.c”
8
: user@linux:~ > cc -o convert convert.c -l4th user@linux:~ > convert
Usage: convert infile outfile user@linux:~ >
Is that all? No that’s not all 4tH can do. We have a few surprises left.
4.8
Suspending a program
We’ve entered this program:
9
10
11
12
13
14
15
Scr # 0
0 ." Is everybody in? The ceremony is about to begin.." cr
1 44596 36 base !
2 pause
3 ." Wake up! Do you remember where it was?" cr
4 ." Has this dream stopped? " . cr
5
6
7
8
The first line is simply a string we print to screen. The next line, we push a number on the stack and we change the radix. Then we go to sleep. After that, we wake up again, print a few lines and retrieve the number on the stack. Let’s run it:
(S)creen file: new.scr
(O)bject file: out
(E)dit (C)ompile (R)un (A)rguments
(Q)uit (G)enerate (B)uild (D)ecompile
7
Windows users need to consult the documentation that came with their C compiler. Some Windows compilers may not be able to compile standard C programs. MS-DOS users are encouraged to use the ’DJGPP’ compiler, which is free.
8
Read the ”Developers Guide” if you are not sure how to do this.
CHAPTER 4. A GUIDED TOUR 59
>r
Is everybody in? The ceremony is about to begin..
(S)creen file: new.scr
(O)bject file: out
(E)dit (C)ompile (R)un (A)rguments
(Q)uit (G)enerate (B)uild (D)ecompile
>
At first, it seems like ’PAUSE’ is nothing more than an alias for ’ABORT’, but that is not entirely true. Let’s save the executable and enter ”r” one more time:
>b
(S)creen file: new.scr
(O)bject file: out
(E)dit (C)ompile (R)un (A)rguments
(Q)uit (G)enerate (B)uild (D)ecompile
>r
Wake up! Do you remember where it was?
Has this dream stopped? YES
(S)creen file: new.scr
(O)bject file: out
(E)dit (C)ompile (R)un (A)rguments
(Q)uit (G)enerate (B)uild (D)ecompile
>
Now the second part of the program is run, that is the part after ’PAUSE’. Note that both the stack and the radix have remained intact. Every time ’PAUSE’ is invoked, it will return you to the prompt. When you enter ”r” again, it will continue where it left off, until it meets one of the following three conditions:
1. It encounters another ’PAUSE’; entering ”r” will continue where it left off.
2. It encounters ’ABORT’, ’QUIT’ or ’ABORT”’; entering ”r” will restart the program.
3. There are no more instructions to execute; entering ”r” will restart the program.
But why did we save an executable? We’ll have to go back to the shell to show you: user@linux:~> 4th lxq out
Wake up! Do you remember where it was?
Has this dream stopped? YES user@linux:~>
Entering ”b” during suspension will save the program in its suspended state. When you run the resulting executable, it will behave like you’ve entered ”r”. That’s neat, isn’t it?
Скачать
Реклама