Implement FILE-STATUS
[pforth] / fth / file.fth
CommitLineData
593eb738
HE
1\ READ-LINE and WRITE-LINE
2\
938d9dba 3\ This code is part of pForth.
593eb738 4\
938d9dba
HE
5\ The pForth software code is dedicated to the public domain,
6\ and any third party may reproduce, distribute and modify
7\ the pForth software code or any derivative works thereof
8\ without any compensation or license. The pForth software
9\ code is provided on an "as is" basis without any warranty
10\ of any kind, including, without limitation, the implied
11\ warranties of merchantability and fitness for a particular
12\ purpose and their equivalents under the laws of any jurisdiction.
593eb738
HE
13
14private{
15
938d9dba
HE
1610 constant \N
1713 constant \R
593eb738
HE
18
19\ Unread one char from file FILEID.
938d9dba
HE
20: UNREAD { fileid -- ior }
21 fileid file-position ( ud ior )
593eb738
HE
22 ?dup
23 IF nip nip \ IO error
938d9dba 24 ELSE 1 s>d d- fileid reposition-file
593eb738
HE
25 THEN
26;
27
28\ Read the next available char from file FILEID and if it is a \n then
29\ skip it; otherwise unread it. IOR is non-zero if an error occured.
938d9dba
HE
30\ C-ADDR is a buffer that can hold at least one char.
31: SKIP-\N { c-addr fileid -- ior }
32 c-addr 1 fileid read-file ( u ior )
aad4537d
HE
33 ?dup
34 IF \ Read error?
35 nip
36 ELSE ( u )
37 0=
38 IF \ End of file?
39 0
40 ELSE
938d9dba 41 c-addr c@ \n = ( is-it-a-\n? )
aad4537d 42 IF 0
938d9dba 43 ELSE fileid unread
aad4537d
HE
44 THEN
45 THEN
46 THEN
593eb738
HE
47;
48
49\ This is just s\" \n" but s\" isn't yet available.
50create (LINE-TERMINATOR) \n c,
51: LINE-TERMINATOR ( -- c-addr u ) (line-terminator) 1 ;
52
662a735a
HE
53\ Standard throw code
54\ See: http://lars.nocrew.org/forth2012/exception.html#table:throw
6f3de396
HE
55-72 constant THROW_RENAME_FILE
56
662a735a
HE
57\ Copy the string C-ADDR/U1 to C-ADDR2 and append a NUL.
58: PLACE-CSTR ( c-addr1 u1 c-addr2 -- )
59 2dup 2>r ( c-addr1 u1 c-addr2 ) ( r: u1 c-addr2 )
60 swap cmove ( ) ( r: u1 c-addr2 )
61 0 2r> + c! ( )
62;
63
fe6f537b
HE
64: MULTI-LINE-COMMENT ( "comment<rparen>" -- )
65 BEGIN
66 >in @ ')' parse ( >in c-addr len )
67 nip + >in @ = ( delimiter-not-found? )
68 WHILE ( )
69 refill 0= IF EXIT THEN ( )
70 REPEAT
fe6f537b
HE
71;
72
593eb738
HE
73}private
74
593eb738
HE
75\ This treats \n, \r\n, and \r as line terminator. Reading is done
76\ one char at a time with READ-FILE hence READ-FILE should probably do
77\ some form of buffering for good efficiency.
78: READ-LINE ( c-addr u1 fileid -- u2 flag ior )
aad4537d
HE
79 { a u f }
80 u 0 ?DO
81 a i chars + 1 f read-file ( u ior' )
82 ?dup IF nip i false rot UNLOOP EXIT THEN \ Read error? ( u )
938d9dba 83 0= IF i i 0<> 0 UNLOOP EXIT THEN \ End of file? ( )
aad4537d
HE
84 a i chars + c@
85 CASE
86 \n OF i true 0 UNLOOP EXIT ENDOF
87 \r OF
88 \ Detect \r\n
938d9dba 89 a i chars + f skip-\n ( ior )
aad4537d
HE
90 ?dup IF i false rot UNLOOP EXIT THEN \ IO Error? ( )
91 i true 0 UNLOOP EXIT
92 ENDOF
93 ENDCASE
94 LOOP
95 \ Line doesn't fit in buffer
96 u true 0
593eb738
HE
97;
98
99: WRITE-LINE ( c-addr u fileid -- ior )
aad4537d
HE
100 { f }
101 f write-file ( ior )
102 ?dup
103 IF \ IO error
104 ELSE line-terminator f write-file
105 THEN
593eb738
HE
106;
107
6f3de396
HE
108: RENAME-FILE ( c-addr1 u1 c-addr2 u2 -- ior )
109 { a1 u1 a2 u2 | new }
662a735a
HE
110 \ Convert the file-names to C-strings by copying them after HERE.
111 a1 u1 here place-cstr
6f3de396 112 here u1 1+ chars + to new
662a735a 113 a2 u2 new place-cstr
6f3de396
HE
114 here new (rename-file) 0=
115 IF 0
116 ELSE throw_rename_file
117 THEN
118;
119
fe6f537b
HE
120: ( ( "comment<rparen>" -- )
121 source-id
122 CASE
123 -1 OF postpone ( ENDOF
124 0 OF postpone ( ENDOF
646bd2a8 125 \ for input from files
fe6f537b
HE
126 multi-line-comment
127 ENDCASE
128; immediate
129
8d2c2052
HE
130\ We basically try to open the file in read-only mode. That seems to
131\ be the best that we can do with ANSI C. If we ever want to do
132\ something more sophisticated, like calling access(2), we must create
133\ a proper primitive. (OTOH, portable programs can't assume much
134\ about FILE-STATUS and non-portable programs could create a custom
135\ function for access(2).)
136: FILE-STATUS ( c-addr u -- x ior )
137 r/o bin open-file ( fileid ior1 )
138 ?dup
139 IF ( fileid ior1 )
140 ELSE close-file 0 swap ( 0 ior2 )
141 THEN
142;
143
593eb738 144privatize