This introduces a RESIZE-FILE-LIMIT
[pforth] / fth / file.fth
... / ...
CommitLineData
1\ READ-LINE and WRITE-LINE
2\
3\ This code is part of pForth.
4\
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.
13
14private{
15
1610 constant \N
1713 constant \R
18
19\ Unread one char from file FILEID.
20: UNREAD { fileid -- ior }
21 fileid file-position ( ud ior )
22 ?dup
23 IF nip nip \ IO error
24 ELSE 1 s>d d- fileid reposition-file
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.
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 )
33 ?dup
34 IF \ Read error?
35 nip
36 ELSE ( u )
37 0=
38 IF \ End of file?
39 0
40 ELSE
41 c-addr c@ \n = ( is-it-a-\n? )
42 IF 0
43 ELSE fileid unread
44 THEN
45 THEN
46 THEN
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
53\ Standard throw code
54\ See: http://lars.nocrew.org/forth2012/exception.html#table:throw
55-72 constant THROW_RENAME_FILE
56
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
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
71;
72
73}private
74
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 )
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 )
83 0= IF i i 0<> 0 UNLOOP EXIT THEN \ End of file? ( )
84 a i chars + c@
85 CASE
86 \n OF i true 0 UNLOOP EXIT ENDOF
87 \r OF
88 \ Detect \r\n
89 a i chars + f skip-\n ( ior )
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
97;
98
99: WRITE-LINE ( c-addr u fileid -- ior )
100 { f }
101 f write-file ( ior )
102 ?dup
103 IF \ IO error
104 ELSE line-terminator f write-file
105 THEN
106;
107
108: RENAME-FILE ( c-addr1 u1 c-addr2 u2 -- ior )
109 { a1 u1 a2 u2 | new }
110 \ Convert the file-names to C-strings by copying them after HERE.
111 a1 u1 here place-cstr
112 here u1 1+ chars + to new
113 a2 u2 new place-cstr
114 here new (rename-file) 0=
115 IF 0
116 ELSE throw_rename_file
117 THEN
118;
119
120\ A limit used to perform a sanity check on the size argument for
121\ RESIZE-FILE.
1222variable RESIZE-FILE-LIMIT
12310000000 0 resize-file-limit 2! \ 10MB is somewhat arbitrarily chosen
124
125: RESIZE-FILE ( ud fileid -- ior )
126 -rot 2dup resize-file-limit 2@ d> ( fileid ud big? )
127 IF
128 ." Argument (" 0 d.r ." ) is larger then RESIZE-FILE-LIMIT." cr
129 ." (You can increase RESIZE-FILE-LIMIT with 2!)" cr
130 abort
131 ELSE
132 rot (resize-file)
133 THEN
134;
135
136: ( ( "comment<rparen>" -- )
137 source-id
138 CASE
139 -1 OF postpone ( ENDOF
140 0 OF postpone ( ENDOF
141 \ for input from files
142 multi-line-comment
143 ENDCASE
144; immediate
145
146privatize