forked from Forth-Standard/forth200x
/
directories-with-prefixes.html
242 lines (172 loc) · 9.18 KB
/
directories-with-prefixes.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
<title>Directories</title>
<h3>Directories</h3>
<pre>
Questions:
- Do you find any of these prefixes acceptable?
Marcel Hendrix: :/ %here%
David Smith doesn't like %here%
- What is your preference among them?
Marcel Hendrix: :/
Stephen Pelc: I do not like any of these!
- Do you have better suggestions for a prefix?
Stephen Pelc: %RelDir%/ (maybe also %id%)
Bernd Paysan: @/
Anton Ertl: ~~/ ^/ %inc%
- Would you use such a facility if it was standarized? How would the
prefixes influence this decision?
Marcel Hendrix: yes.
- Would you implement such a facility if it was standardized? How
would the prefixes influence this decision?
Marcel Hendrix: yes.
Changes:
Added INCLUDE-NAME-ABS.
Added Sections "Which prefix?", "What if there is no currently
including file?", "Isn't specifying "/" as directory separator too
OS-specific?"
Replaced many mentions of "./" with "prefix".
Minor rewrites to make some prose clearer.
Problem:
Summary: How do I refer to another file that is distributed with the
Forth file at hand, in the presence of directories?
Example: Let us assume that the current working directory is /wd/, and
that we have a program installed in directory /prog1/, but on the next
installation it might be installed in /prog2/. The file to be
INCLUDEd by the user is /prog1/prog.fs, and it is supposed to INCLUDE
library.fs and read a data file data.txt residing in the same
directory. How should prog.fs refer to library.fs and data.txt?
Remember that on the next installation they might be in a different
directory than in this installation (but in the same directory as
prog.fs).
As an additional complication, consider the case where prog.fs loads a
library /prog1/lib1/lib.fs, that has been developed independently of
prog.fs, and without knowledge that it would later wind up in
/prog1/lib1; /prog1/lib1/lib.fs refers to another file foo.fs which
resides at /prog1/lib1/foo.fs in this installation. How should Forth
code in the library refer to other files of the library?
Solution outline:
First we need to specify a directory separator. The "/" is supported
in all important OSs (including Windows, except in cmd.exe), so we
specify it for Forth.
Next, we need a way to specify a file name relative to the directory
that contains the Forth source file that contains the file name (as a
string): A special, otherwise unused prefix (e.g., "./", ":/", or
"\/") refers to this directory. For the moment, assume the prefix is
"./". E.g., in the example above, the prog.fs file would contain
references to "./library.fs", "./data" and "./lib1/lib.fs". The
lib.fs file would contain a reference to "./foo.fs".
Finally, how do we expand these filenames to a sourcefile-independent
form? The source file of the string is important for the expansion,
not the source file of the consumer of the string (in the rare cases
where the consumer is not in the same file as the string); so the best
option is probably to have a special filename-string word like F" and
not perform the expansion in the consumer (INCLUDED, OPEN-FILE etc.).
In order to keep the conveniences of the parsing INCLUDE and REQUIRE,
these should expand the string after parsing. In addition, a word
INCLUDE-NAME-ABS for converting a string from an include-relative
filename to an absolute filename is a natural factor of these words
and can be useful in some cases.
Typical usage:
REQUIRE ./lib1/lib.fs
F" ./data.txt" r/o open-file
S\" ./funny\"filename" include-name-abs r/o open-file
Proposal, reference implementation and tests:
Will be done after the solution has solidified after some discussion.
Existing practice and experience:
Gforth uses the ./ prefix in INCLUDED and friends (i.e., in the
consumer, not in the producer, as suggested here). We have had very
good experiences with that (consumer and producer are usually in the
same file).
Modern C compilers like gcc do
#include "bla.h"
relative to the directory of the currently-included file. The
proposed equivalent would be "INCLUDE ./bla.h".
When executing a program or script, the Unix shell searches relative
names like bla.sh in the path (which often does not include "."), but
if you write ./bla.sh, this refers to and only to the bla.sh in the
current working directory (unfortunately not the directory containing
the current file, but the shell offers ways to work around this
shortcoming).
Remarks:
Which prefix?
There was considerable resistance to using the "./" prefix in the
first RfD. Unfortunately, the replacements I and others suggested
(":/", "\/", "%here%") were not met with approval, either.
The prefix should be something which cannot occur in a
portable file name (e.g., ":/" or "\/" cannot occur in Windows file
names), or which normally is redundant (e.g., "./" can be left away).
The prefix "./" has been used in Gforth for many years without
problems or complaints. In other contexts it is a noop, referring to
the current directory relative to some base directory. This is both
its attraction and the reason for resistance against it:
- It is attractive, because the meaning of "require ./lib1/lib.fs" is
intuitively understandable.
- There is resistance against it, because in this context it means
something different than the same file name without "./" (different
Forth systems do different things with prefix-less relative file names
in INCLUDED-style contexts: some search a path, others refer to the
current working directory), and something different than the same
"./"-prefixed name in a different context. However, the Unix shells
are another example where "./" means something different from a
prefix-less relative file name, and while this causes occasional
confusion, it works.
However, I am open to suggestions for other prefixes, especially from
implementors who are prepared to implement that.
What about string macros?
String macro expansion has been proposed as a way to solve the problem
above, and it is implemented by MPEs Forth systems. While I am not
familiar enough with this system to produce a typical-code example for
the example above, it appears to be more cumbersome to use than the
present proposal (at the very least one has to write "%<macro-name>%/"
instead of "./"). Moreover, depending on the exact usage, there might
be problems with name collisions and nesting. Also MPE's systems
currently contain no macro with the needed functionality (%load_path%
was suggested, but does something different in MPE's systems).
That being said, string macros are a general-purpose concept that has
applications in other areas as well as in file names, and is probably
a good candidate for another RfD.
Is the prefix necessary?
It is necessary for use with INCLUDE (and REQUIRE); if we interpreted
prefix-less relative filenames in the way proposed for the prefixed
filenames, some systems would have to be changed in ways that would
break their existing programs; by contrast, it is unlikely that these
legacy programs use prefix in a way that conflicts with the usage
discussed here.
Since F" is new, "./" would not be strictly necessary there (no legacy
programs broken). However, requiring it makes the usage consistent,
and allows putting a standard meaning to an unprefixed relative name,
if there is ever consensus on that.
What about other file names?
How other file names than those starting with "./" are interpreted is
not specified, at least in the first draft: absolute file names are
OS-specific and often user-specific and thus inherently non-portable;
the interpetation of other relative filenames depends on the system
(some do path searching, some perform macro expansion etc.); it is
probably hard to find a consensus here, and these issues are not as
important for writing portable programs (to make using these programs
nicer, it would still be nice if a consensus was found).
Why not use a CD word for this purpose?
While a word for changing the current working directory may have its
uses in Forth, it is usually not a good idea to change the working
directory for loading code. Apart from the usual nesting/unnesting
complications, the user usually sets the working directory to some
directory on purpose, because that's where he is working; the program
or library directory is usually not where he is working. If the user
passes a data file name to the included file, he expects it to be
interpreted in the context of his working directory, not the program's
directory.
What if there is no currently including file?
E.g., if one does "INCLUDE ./foo.fs" from the command line, which file
should be included? I propose to make this an ambiguous condition.
What Gforth currently implements for this situation is to look for
foo.fs in the current working directory.
Isn't specifying "/" as directory separator too OS-specific?
It works in practice, and other approaches don't. E.g., Peter Knaggs
writes <4505c44b$0$2665$ed2619ec@ptn-nntp-reader02.plus.net>:
|Java has a special DirectorySeparator constant you are supposed to use,
|but nobody ever does.
If there is ever a Forth 200x system for an OS that has a different
directory syntax (e.g., VMS), the Forth system can translate the
filename with the slashes into the native directory syntax (I guess
that the POSIX layer for such OSs does the same).
</pre>
<hr><a href="http://www.complang.tuwien.ac.at/anton/">Anton Ertl</a>